ShellPilot
0.4.0-preview0005
GitHub Copilot in your PowerShell terminal: device-flow auth, model listing, chat and agentic tool-calling with usage and cost.
Minimum PowerShell version
7.0
See the version list below for details.
Installation Options
Owners
Copyright
(c) raandree. All rights reserved.
Package Details
Author(s)
- raandree
Tags
GitHubCopilot Copilot AI LLM Chat Agent
Functions
Clear-ShpChat Clear-ShpContext Clear-ShpUsage ConvertTo-ShpTokenCount Get-ShpChat Get-ShpContext Get-ShpCosineSimilarity Get-ShpCostEstimate Get-ShpDefault Get-ShpModel Get-ShpModelName Get-ShpTool Get-ShpUsage Initialize-Shp Invoke-Shp Invoke-ShpBatch Register-ShpTool Request-ShpEmbedding Resolve-ShpError Select-ShpModel Set-ShpContext Start-ShpChat Unregister-ShpTool
PSEditions
Dependencies
This module has no dependencies.
Release Notes
## [0.4.0-preview0005] - 2026-08-11
### Added
- `Get-ShpUsage` now records calls that **failed**, not only the ones that
succeeded. A failed call carries `Success` `$false` and the failure message on
`Error`, plus whatever spend its completed round-trips had already incurred.
Both halves of that matter: a success rate computed from the old log was 100%
by construction, because only successes were in it; and a turn is a loop of
billable round-trips, so a turn refused on its third round-trip really was
charged for the first two and reported nothing. Only a call that reached the
API is recorded - a parameter combination rejected before any request was
never a call. `Invoke-ShpBatch` inherits this, so a failed batch item now
shows up in `Get-ShpUsage` too.
See [specs/016-failed-call-usage-accounting.md](specs/016-failed-call-usage-accounting.md).
- `Get-ShpUsage -Summary` gained `Succeeded`, `Failed`, `TotalDurationMs`,
`MeanDurationMs`, `FirstCall`, `LastCall` and `ElapsedMs`, and the `ByModel`
breakdown gained `Succeeded`, `Failed` and `DurationMs`. `ElapsedMs` is
wall-clock between the first and last call and is deliberately *not* the sum
of `DurationMs`: under `Invoke-ShpBatch` the calls overlap, so the sum can far
exceed the elapsed time and the ratio between them is the speed-up the batch
bought.
- `Get-ShpUsage -Since` and `-Before` filter by time window, so one phase of a
run can be summarised without clearing the log between phases. Both apply to
the records and to `-Summary`. There is deliberately no `-GroupBy`:
`Get-ShpUsage` returns the records, so `Group-Object` already groups by any
field, and `ByModel` is pre-aggregated only because that split is the common
case.
- `Invoke-ShpBatch` runs many independent prompts concurrently and returns one
`ShellPilot.BatchResult` per input, carrying the answer, that item's usage and
cost, and - when the call failed - the error. `-ThrottleLimit` bounds how many
calls are in flight (default 4, deliberately conservative), and prompts can be
piped in as plain strings or as objects with `Prompt` and an optional `Id`.
Three guarantees are the point of it. Every item is stateless: a batch never
reads or writes the session conversation, so it cannot reproduce the
accumulation that makes a serial loop of `Invoke-Shp` calls grow until the
model refuses it with `model_max_prompt_tokens_exceeded`. Failures are
isolated: one failed call never aborts the batch and nothing is written to the
error stream, because an error raised from a worker obeys the caller's
`$ErrorActionPreference` and would destroy every result under `Stop`; check
`Success` and `Error` on the results, and a single summary warning names how
many did not complete. And identity is carried: results arrive in completion
order, so every one has `Index`, `Id` and the original `InputObject`.
`-MaxBatchBudgetUSD` caps the whole run as a gate on dispatch - calls already
in flight are never cancelled. Streaming, `ask_user` and progress events are
off for every item, for reasons the help gives. The model, sampling
parameters, `-ResponseFormat` / `-JsonSchema`, `-SkillPath`,
`-InstructionRoot`, the isolation switches and the connection options are all
forwarded, and per-item usage is merged into `Get-ShpUsage`.
See [specs/015-batch-execution.md](specs/015-batch-execution.md).
- `Invoke-Shp -MaxContextWindowTokens` and `Set-ShpContext
-MaxContextWindowTokens` set the token budget above which a turn elides its
oldest tool results, with the usual precedence of explicit parameter, then
session context, then the built-in default. The built-in 900000 is a fallback
rather than any model's real window - `claude-haiku-4.5` is 136000 - so the
guard could never fire for a smaller model; set this from the model's own
`MaxContextWindowTokens` (see `Get-ShpModel`) to make it fire when it should.
`0` disables the guard. The default is unchanged, so existing calls behave
exactly as before. Note this bounds tool results only: the session
conversation is never elided, so a long loop of calls still needs
`Clear-ShpChat` or `-History`.
- `Invoke-Shp` now explains a rejection it cannot recover from. A service reply
of `model_max_prompt_tokens_exceeded` is emitted as a warning naming the real
cause - every `-Prompt` call continues the session conversation, so a loop of
calls grows until it no longer fits - and the two remedies. Left unexplained
this reads as a bare 400 and gets mistaken for rate limiting.
- `Invoke-Shp -Temperature`, `-TopP` and `-Seed` control the model's sampling,
so a call that has to be reproducible (grading or judging in an evaluation
harness) can pin itself with `-Temperature 0` and a variance measurement can
fix its operating point instead of inheriting the backend default. Each field
is omitted from the request body entirely when the parameter is not passed, so
existing calls are unchanged. `-Temperature` is validated against 0..2 and
`-TopP` against 0..1 before the request is sent, and a model that rejects a
field fails the call rather than having the field silently dropped.
The values used are reported on the result as `Temperature`, `TopP` and
`Seed`. See [specs/014-sampling-parameters.md](specs/014-sampling-parameters.md).
- `Invoke-Shp` and `Get-ShpCostEstimate` results carry `Priced` and
`PriceTableKey`, so a call the price table cannot cost is no longer
indistinguishable from a free one. `PriceTableKey` stays populated even when
nothing matched, naming the key that was looked up and missed, and the first
call for an unpriced model warns once per session rather than once per tool
iteration. `CostUSD` and `Credits` are unchanged and still `null` - never `0` -
when no rate is found. `Priced` is also recorded on each `Get-ShpUsage` entry.
- `Resolve-ShpError` explains the last error in the session and suggests a fix.
It takes an error record (`$Error[0]` by default, or from the pipeline), sends
the message, exception type, category, target, failing command line and script
stack trace to the model, and returns the usual `Invoke-Shp` result. Every
tool is disabled unless `-EnableTools` is passed, so diagnosing an error
cannot touch the machine.
- `Invoke-Shp` supports `ShouldProcess`. `-WhatIf` dry-runs a whole agent turn -
the model still plans and calls tools, but `write_file`, `create_directory`,
`run_command` and user-registered tools are skipped and told they were not
approved - and `-Confirm` prompts before each of those calls. Default
behaviour is unchanged.
- `Invoke-Shp -MaxBudgetUSD` stops the tool-calling loop once the turn's
estimated spend passes the cap, and the result carries a new `BudgetExceeded`
flag.
- `Invoke-Shp -AppendSystemPrompt` adds inline system instructions in either
parameter set, so a file-driven system prompt can still be topped up for a
single call.
- `Invoke-Shp -AllowPrivateNetwork` opts the `fetch_url` tool back in to
loopback, link-local and private addresses.
- `Start-ShpChat` gained the `/models`, `/history`, `/retry` and `/usage`
commands. `/retry` drops the last exchange and resends the previous prompt.
- The price table supports a long-context tier. An entry may carry a
`LongContext` block with a `Threshold` in input tokens plus its own rates, and
the cost breakdown now reports `Tier` and `TiersUsed`.
### Changed
- **`Get-ShpUsage -Summary`'s `Calls` and `CostUSD` will report different
numbers for a session in which something failed.** `Calls` now counts calls
*attempted*; it previously counted records, and only successes were recorded,
so it meant "calls that succeeded". Read `Succeeded` for the old number.
`CostUSD` now includes the spend of turns that failed after one or more
billable round-trips, which was previously dropped. Both are corrections
rather than regressions - that money was really spent, and those calls were
really made - but a caller reading `Calls` as a success count must move to
`Succeeded`. Nothing changes for a session in which nothing failed.
- The HTTP retry backoff is now jittered: half the exponential delay plus a
random amount up to the other half. A purely deterministic backoff
synchronises under concurrency - several `Invoke-ShpBatch` workers refused by
the same 429 would sleep identical durations and re-fire together, recreating
the burst that caused the refusal. A `RetryDelaySec` of `0` still yields
exactly `0`, so no existing call path changes.
### Fixed
- Streamed `Invoke-Shp` requests now use the same retry wrapper as buffered
requests. HTTP 429/5xx responses are bounded by `MaxRetryCount`, and a true
no-response transport failure uses `NetworkOutageToleranceSec`. The classifier
reads the streaming sender's structured `StatusCode` before its bare
`HttpRequestException` type, so a permanent 400 fails after one attempt instead
of burning the network-outage budget. If reading an error body itself fails,
the known status is preserved and both response and request are still disposed.
- `Invoke-Shp -History @()` now genuinely starts from nothing. `-History` is
documented as stateless, but an empty array is falsy and the check tested
truthiness, so an explicitly empty history silently fell through to seeding
the call from the session conversation - the opposite of what was asked for.
Binding is now the test, matching the module's rule for every other optional
value whose type has a meaningful default.
- The streaming sender now carries the same structured error as the buffered
one. Streaming is the `Invoke-Shp` default, so this was the common path on
which a caller still had to match substrings in an exception message. A
non-success status from `Invoke-ShpStreamRequest` now raises an ErrorRecord
with the body on `ErrorDetails.Message` and a `ShellPilot.HttpErrorDetail` on
`TargetObject`, which is also the only
FileList
- ShellPilot.nuspec
- ShellPilot.psm1
- ShellPilot.psd1
- en-US\about_ShellPilot.help.txt
- data\PriceTable.psd1
- ShellPilot.Format.ps1xml
- en-US\ShellPilot-help.xml
Version History
| Version | Downloads | Last updated |
|---|---|---|
| 0.4.0-previe... | 3 | 8/19/2026 |
| 0.4.0-previe... | 5 | 8/12/2026 |
| 0.4.0-previe... | 7 | 8/12/2026 |
| 0.4.0-previe... (current version) | 5 | 8/11/2026 |
| 0.4.0-previe... | 3 | 8/11/2026 |
| 0.4.0-previe... | 10 | 8/6/2026 |
| 0.4.0-previe... | 10 | 7/28/2026 |
| 0.4.0-previe... | 3 | 7/28/2026 |
| 0.3.1 | 54 | 7/23/2026 |
| 0.3.1-previe... | 3 | 7/23/2026 |
| 0.3.0-previe... | 8 | 7/12/2026 |
| 0.3.0-previe... | 7 | 7/9/2026 |
| 0.3.0-previe... | 4 | 7/9/2026 |
| 0.3.0-previe... | 7 | 7/9/2026 |
| 0.2.1-previe... | 8 | 7/8/2026 |
| 0.2.0 | 37 | 7/8/2026 |
| 0.2.0-previe... | 6 | 7/8/2026 |
| 0.2.0-previe... | 4 | 7/8/2026 |
| 0.2.0-previe... | 31 | 6/12/2026 |