Public/New-KritOpenApiAgenticSidecar.ps1
|
function New-KritOpenApiAgenticSidecar { <# .SYNOPSIS Emit an agentic-sidecar companion script for a Krit.<Brand>OpenApi module. .DESCRIPTION Per WAVE-5079 design: each generated OpenAPI client module ships with a companion sidecar that lets an off-to-the-side agent (claude / codex / cowork) connect, prove and report end-to-end without the main session orchestrating step-by-step. The sidecar exposes: - Test-<Brand>ApiConnectivity : single-call health probe (auth + base URI + one read-only GET against a canary endpoint). Returns structured { ok, latencyMs, baseUri, authShape, error }. - Resolve-<Brand>AgentTask : takes a natural-language task hint plus a dictionary of inputs, routes to the most-likely module verb, invokes it, and returns the structured result. Caller agent then decides next step. v0.1.0 emits a template skeleton; the matchmaker logic in Resolve-<Brand>AgentTask is a stub that the consuming agent fills with domain heuristics (or replaces with an LLM-routing call). .PARAMETER Spec OpenAPI spec — used to enumerate available verbs the sidecar exposes. .PARAMETER Brand Pascal-cased brand. .PARAMETER OutFile Output .ps1 path (sidecar is a single script that dot-sources alongside the generated module). .EXAMPLE New-KritOpenApiAgenticSidecar -Spec ./pax8-openapi.json -Brand Pax8 ` -OutFile ./Krit.Pax8OpenApi.AgenticSidecar.ps1 #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][string]$Spec, [Parameter(Mandatory)][string]$Brand, [Parameter(Mandatory)][string]$OutFile ) if (-not (Test-Path -LiteralPath $Spec)) { throw "Spec not found: $Spec" } $doc = Get-Content -LiteralPath $Spec -Raw | ConvertFrom-Json -Depth 100 $baseUri = if ($doc.servers -and $doc.servers.Count -gt 0) { $doc.servers[0].url } else { 'http://127.0.0.1:80' } # First GET path = canary $canary = $null foreach ($p in $doc.paths.PSObject.Properties.Name) { if ($doc.paths.$p.PSObject.Properties.Name -contains 'get') { $canary = $p; break } } if (-not $canary) { $canary = '/' } $verbsCsv = ($doc.paths.PSObject.Properties.Name | Select-Object -First 20) -join "', '" $tpl = @" # ────────────────────────────────────────────────────────────────────────── # Krit.${Brand}OpenApi — Agentic Sidecar (auto-generated WAVE-5105) # ────────────────────────────────────────────────────────────────────────── # Dot-source this script alongside Krit.${Brand}OpenApi.psm1 to expose two # operator-callable functions that let an off-to-the-side agent connect, # prove, and route tasks against the upstream without main-session help. # ────────────────────────────────────────────────────────────────────────── function Test-${Brand}ApiConnectivity { [CmdletBinding()] param( [string]`$BaseUri = '$baseUri', [string]`$CanaryPath = '$canary' ) `$startUtc = [DateTime]::UtcNow try { `$resp = Invoke-RestMethod -Method GET -Uri (`$BaseUri.TrimEnd('/') + `$CanaryPath) -TimeoutSec 15 [pscustomobject]@{ Ok = `$true LatencyMs = [int]([DateTime]::UtcNow - `$startUtc).TotalMilliseconds BaseUri = `$BaseUri Canary = `$CanaryPath Sample = `$resp | Select-Object -First 1 Error = `$null AtUtc = `$startUtc.ToString('o') } } catch { [pscustomobject]@{ Ok = `$false LatencyMs = [int]([DateTime]::UtcNow - `$startUtc).TotalMilliseconds BaseUri = `$BaseUri Canary = `$CanaryPath Sample = `$null Error = `$_.Exception.Message AtUtc = `$startUtc.ToString('o') } } } function Resolve-${Brand}AgentTask { <# .SYNOPSIS Route a natural-language task hint to the most-likely Krit.${Brand}OpenApi verb. .PARAMETER TaskHint Free-text task description from the calling agent. .PARAMETER Inputs Hashtable of named parameters to pass to the chosen verb. .PARAMETER DryRun Plan-only: returns the chosen verb + inputs without invoking. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][string]`$TaskHint, [hashtable]`$Inputs = @{}, [switch]`$DryRun ) # Stub matchmaker — replace with LLM router OR domain-specific heuristics. # Lists the first 20 paths the spec exposed at sidecar-gen time so the # calling agent can see what's reachable. `$availablePaths = @('$verbsCsv') `$candidate = `$availablePaths | Where-Object { `$_ -match (`$TaskHint -replace '[^\w]','.*') } | Select-Object -First 1 `$plan = [pscustomobject]@{ TaskHint = `$TaskHint ChosenPath = `$candidate Inputs = `$Inputs AvailablePaths = `$availablePaths DryRun = `$DryRun.IsPresent AtUtc = (Get-Date).ToUniversalTime().ToString('o') } if (`$DryRun) { return `$plan } # Real-invocation hook: caller fills in mapping path -> Get-Command verb. Write-Warning "Resolve-${Brand}AgentTask: real-invocation logic not implemented in v0.1.0 sidecar. Returning plan only." `$plan } "@ if ($PSCmdlet.ShouldProcess($OutFile, "Emit Krit.${Brand}OpenApi agentic sidecar")) { $tpl | Set-Content -LiteralPath $OutFile -Encoding UTF8 [pscustomobject]@{ OutFile = (Resolve-Path -LiteralPath $OutFile).Path Brand = $Brand BaseUri = $baseUri CanaryPath = $canary GeneratedAt = (Get-Date).ToUniversalTime().ToString('o') } } } |