ShellPilot.psd1
|
# # Module manifest for module 'ShellPilot' # # Generated by: raandree # # Generated on: 6/6/2026 # @{ # Script module or binary module file associated with this manifest. RootModule = 'ShellPilot.psm1' # Version number of this module. ModuleVersion = '0.4.0' # Supported PSEditions # CompatiblePSEditions = @() # ID used to uniquely identify this module GUID = 'd2a14b3e-8f6e-4a07-9c2d-1e5a6e3b9c01' # Author of this module Author = 'raandree' # Company or vendor of this module CompanyName = 'raandree' # Copyright statement for this module Copyright = '(c) raandree. All rights reserved.' # Description of the functionality provided by this module Description = 'GitHub Copilot in your PowerShell terminal: device-flow auth, model listing, chat and agentic tool-calling with usage and cost.' # Minimum version of the PowerShell engine required by this module PowerShellVersion = '7.0' # Name of the PowerShell host required by this module # PowerShellHostName = '' # Minimum version of the PowerShell host required by this module # PowerShellHostVersion = '' # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. # DotNetFrameworkVersion = '' # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. # ClrVersion = '' # Processor architecture (None, X86, Amd64) required by this module # ProcessorArchitecture = '' # Modules that must be imported into the global environment prior to importing this module RequiredModules = @() # Assemblies that must be loaded prior to importing this module # RequiredAssemblies = @() # Script files (.ps1) that are run in the caller's environment prior to importing this module. # ScriptsToProcess = @() # Type files (.ps1xml) to be loaded when importing this module # TypesToProcess = @() # Format files (.ps1xml) to be loaded when importing this module FormatsToProcess = @('ShellPilot.Format.ps1xml') # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess # NestedModules = @() # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @('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') # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() # Variables to export from this module VariablesToExport = @() # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. AliasesToExport = @() # DSC resources to export from this module DscResourcesToExport = @() # List of all modules packaged with this module # ModuleList = @() # List of all files packaged with this module # FileList = @() # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. PrivateData = @{ PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. Tags = @('GitHubCopilot', 'Copilot', 'AI', 'LLM', 'Chat', 'Agent', 'PSEdition_Core') # A URL to the license for this module. LicenseUri = 'https://github.com/raandree/ShellPilot/blob/main/LICENSE' # A URL to the main website for this project. ProjectUri = 'https://github.com/raandree/ShellPilot' # A URL to an icon representing this module. IconUri = 'https://raw.githubusercontent.com/raandree/ShellPilot/main/assets/shellpilot-icon.png' # ReleaseNotes of this module ReleaseNotes = '## [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 ' # Prerelease string of this module Prerelease = 'preview0005' # Flag to indicate whether the module requires explicit user acceptance for install/update/save # RequireLicenseAcceptance = $false # External dependent modules of this module # ExternalModuleDependencies = @() } # End of PSData hashtable } # End of PrivateData hashtable # HelpInfo URI of this module # HelpInfoURI = '' # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. # DefaultCommandPrefix = '' } |