specpi 0.18.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.18.1 - 2026-09-07
4
+
5
+ - Restore Pi's cached model catalogs during delegation setup so switching to catalog-added or updated models resumes workers without a manual toggle or restart. Catalog network refresh stays disabled; exact-model checks, safety revocations and spent quotas remain enforced.
6
+
7
+ - SpecPi Chat 0.4.1 replaces the persistent Delegates panel with a compact live-only activity strip and opens workspace image links in the validated image viewer instead of the text editor. Chat is packaged separately; update the harness for the model-switch fix and Chat for the UI fixes.
8
+
3
9
  ## 0.18.0 - 2026-09-07
4
10
 
5
11
  - Start Command Guard off in RPC sessions, including new SpecPi Chat conversations. Explicit `/guard guard` and `/guard strict` still enable protection for the current session; the terminal startup chooser is unchanged.
package/README.md CHANGED
@@ -48,7 +48,7 @@ specpi doctor
48
48
 
49
49
  Preview the changes, confirm the install, then check the setup. Restart Pi when finished.
50
50
 
51
- To pin this release, use `npm install --global specpi@0.18.0`.
51
+ To pin this release, use `npm install --global specpi@0.18.1`.
52
52
 
53
53
  Delegation is enabled at startup. Use `/delegate off` to turn it off.
54
54
 
@@ -62,7 +62,7 @@ Chat beside your code, attach files, and switch conversations.
62
62
 
63
63
  In VS Code, find **SpecPi Chat** by **tannermidd** in Extensions and install it. Open **SpecPi** in the Activity Bar, then **Connect Pi**.
64
64
 
65
- Chat 0.4.0 adds live delegate progress and worker Stop controls, plus compact tags for attached files. With SpecPi 0.18.0, new Chat sessions start with Guard off; use `/guard guard` or `/guard strict` to enable it. Update the harness and use **Restart Pi** to load these changes.
65
+ Chat 0.4.1 shows a compact delegation strip only while workers run or settle, and opens workspace image links in the image viewer. SpecPi 0.18.1 fixes delegation after switching models in the same chat. Update both packages, reload VS Code for the Chat update, and use **Restart Pi** to load the harness update. Later model switches do not require a restart. New Chat sessions start with Guard off; use `/guard guard` or `/guard strict` to enable it.
66
66
 
67
67
  ## Go further
68
68
 
package/SECURITY_MODEL.md CHANGED
@@ -35,7 +35,7 @@ not a new provider-disclosure boundary.
35
35
 
36
36
  Delegation is a native extension discovered through the ordinary Pi package and SpecPi lifecycle. Start `pi` normally; delegation is enabled by default at the first session start of each Pi process, including TUI, RPC, print and JSON modes, after settings, host and Guard checks. Startup launches no workers or model inference, but Pi-owned authentication/OAuth preparation may occur. The model-facing schema is present only while dispatch is enabled. It adds no launcher, separate host process, service or trust override. Parent Pi retains normal resource discovery, trust decisions and proxy policy. Delegation checks required public SDK capabilities, not exact version identifiers. Missing session/runtime/settings/thinking APIs prevent activation; session construction and every request still enforce the tool, model and resource policy. API presence is not proof of every future SDK behavior or a passing integration receipt. Normal installation's minimum Pi version and 0.84.4 bootstrap pin are separate contracts.
37
37
 
38
- Each worker is an SDK `createAgentSession` instance with in-memory session storage. Pi owns its model/tool loop. A fresh Pi `ModelRuntime` uses standard authentication, environment and `models.json` resolution. Child transport and thinking budgets come from configured global settings; project settings are not loaded. Parent model/thinking are explicit with Pi's supported-level clamping. SpecPi does not extract credentials, copy authentication state or inspect private runtime fields. Preflight rejects runtime-only authentication, selected extension-registered provider overrides, model-specific headers, startup proxy configuration and mismatched safe model descriptors because those routes cannot be faithfully reconstructed. These rejections leave parent configuration unchanged.
38
+ Each worker is an SDK `createAgentSession` instance with in-memory session storage. Pi owns its model/tool loop. A fresh Pi `ModelRuntime` uses standard authentication, environment and `models.json` resolution, restoring Pi's persisted model catalogs with catalog network refresh disabled. Child transport and thinking budgets come from configured global settings; project settings are not loaded. Parent model/thinking are explicit with Pi's supported-level clamping. SpecPi does not extract credentials, copy authentication state or inspect private runtime fields. Preflight rejects runtime-only authentication, selected extension-registered provider overrides, model-specific headers, startup proxy configuration and mismatched safe model descriptors because those routes cannot be faithfully reconstructed. These rejections leave parent configuration unchanged.
39
39
 
40
40
  This is not full parent inference parity: parent request hooks, ephemeral runtime settings and session affinity are not automatically inherited. Keep delegation disabled if those inherited controls are required for every request. Children load no ambient extensions, skills, AGENTS files or parent transcript. Their only tools are selected-source list/read/literal-search; shell, write, arbitrary plugin, live-web and nested delegation tools are absent. Trusted parent extensions remain privileged in the same process. This is an application boundary, not an OS sandbox against malicious extensions.
41
41
 
@@ -195,7 +195,7 @@ The sidebar uses Pi's documented JSONL RPC protocol. Pi owns provider authentica
195
195
 
196
196
  Chat allows up to 90 seconds for an initial read-only RPC readiness probe before sending normal requests. This accommodates the 30-second startup fallback in older installed Guard versions without extending later request deadlines. Dialogs arriving before readiness receive cancellation only, never an approval or mode selection; the sidebar explains the limitation and retains a notice after connection. An extension with an unbounded startup dialog can still prevent readiness. Chat times out with recovery guidance instead of bypassing that extension or changing the user's installed harness.
197
197
 
198
- The webview loads only packaged scripts/styles under a strict content security policy, forbids network resources, and renders model/tool/file text without interpreting embedded HTML. Images use validated data URLs under `img-src data:`; remote image URLs are never fetched by the webview. HTTP(S) links, including external image links, require a human click and pass through VS Code's external-link API. Clicked code references use a separate host action: paths are parsed, checked against the selected workspace, canonicalized, and restricted to regular non-sensitive files before VS Code opens the file and reveals a clamped line/range. Clicked workspace Markdown image references use the same path boundary and the image validator before a preview is returned. Arbitrary command and URI handlers are not executed. Raw paths preserve literal percent signs; Markdown link destinations and explicit local file URLs are decoded once before filesystem validation.
198
+ The webview loads only packaged scripts/styles under a strict content security policy, forbids network resources, and renders model/tool/file text without interpreting embedded HTML. Images use validated data URLs under `img-src data:`; remote image URLs are never fetched by the webview. HTTP(S) links, including external image links, require a human click and pass through VS Code's external-link API. Clicked code references use a separate host action: paths are parsed, checked against the selected workspace, canonicalized, and restricted to regular non-sensitive files before VS Code opens the file and reveals a clamped line/range. Clicked workspace Markdown image references, and ordinary file links or inline references ending in PNG, JPEG, GIF or WebP extensions, use the same path boundary and the image validator before a preview is returned. The extension suffix chooses the viewer, not whether the file is safe or valid. Arbitrary command and URI handlers are not executed. Raw paths preserve literal percent signs; Markdown link destinations and explicit local file URLs are decoded once before filesystem validation.
199
199
 
200
200
  Text/code context requires an explicit file/selection action, is size-bounded, rejects binary and known sensitive paths, and checks canonical workspace containment. Workspace file suggestions enumerate a bounded set of names; choosing a suggestion invokes the same attachment validation before reading contents. Dropped workspace URIs are validated independently of their browser representation. Native image selection, clipboard images, and dropped image files are explicit attachment actions and may supply images from outside the selected workspace; filesystem image sources still require ordinary files and pass sensitive-path checks. Pi-state names such as `auth`, `trust`, `sessions`, `missions`, and `history` are reserved inside `.pi`, Chat-owned storage, and the configured Pi agent directory (including its canonical target), not arbitrary source directories. Global credential/key patterns remain blocked, including `auth.json`. Relative `PI_CODING_AGENT_DIR` overrides retain conservative name blocking because they resolve in the child workspace; use an absolute path or `~/…` to obtain directory-scoped filtering. These filename checks and format validators are not content-based secret detectors. Manually typed messages, ordinary files, and images may contain sensitive content, and the extension does not promise image metadata removal. Prompts and attachments are sent to the provider selected in Pi when the user sends them.
201
201
 
@@ -209,7 +209,7 @@ Pi persists chats, including sent image blocks, in a workspace-specific director
209
209
 
210
210
  Conversation edits select entries from the active Pi tree, revalidate the selection before mutation, and fork before the chosen user prompt. Exact original text and validated image blocks are captured before forking because Pi's fork response returns text only. The original conversation is retained, restored drafts require another send action, and conversation forks/clones do not restore or checkpoint workspace files. Actions are scoped to the active workspace, connection, and session revision. Export opens an unsaved Markdown document and Copy Conversation writes the visible Markdown to the OS clipboard only on explicit request. Both omit image bytes and represent images as placeholders; they do not reconstruct truncated or hidden history. Usage displays report Pi measurements, preserving unavailable values rather than inventing totals. The separate provider Limits row projects bounded strings from the known Codex Usage and pi-usage status keys, strips terminal/control sequences, and inserts text only. It does not parse numeric quotas, combine budgets with conversation cost, read provider credentials or usage-cache files, or add provider requests. Reports stay with their live connection and are cleared on disconnect, exit, and reconnect; refreshing and cache age remain upstream plugin responsibilities. Opening the details has no RPC or provider side effect. Existing `/usage` notifications and exact confirmation dialogs continue through the normal UI protocol; no automatic reset consumption or terminal-footer emulation is added.
211
211
 
212
- The Delegates panel consumes the known `specpi-delegation-v1` RPC widget key, with one versioned JSON record of at most 32 KiB and eight projected worker rows. Public identities, shortened task labels, states, elapsed times, call counts and code-owned diagnostics are text-only; snapshots, full prompts, raw provider errors and child transcripts are not sent through the live widget. A single extension-side timer samples existing counters while slots are occupied; it makes no provider or source requests and is disposed on shutdown/rebinding. Invalidated-generation jobs contribute only to occupied-slot counts, not cross-session task labels; replaced same-generation stopping jobs remain visible until settlement. Chat clears live state on disconnect, exit and runtime session replacement and keeps at most 32 connection-local completion summaries for refresh; it adds no child journal or webview persistence. Existing delegate tool receipts are projected into readable advisory reports without changing their model/session content. Stop actions require a trusted workspace, foreground conversation, matching context and an observed running/queued batch/job/attempt. Pi rechecks that exact attempt before its human command cancels it. Worker Stop does not submit draft text/images, clear parent queues, approve tools, change quotas or claim remote termination. The widget is an integration contract with trusted installed extensions, not protection against a malicious extension in Pi's process.
212
+ The delegate activity strip consumes the known `specpi-delegation-v1` RPC widget key, with one versioned JSON record of at most 32 KiB and eight projected worker rows. It appears only while workers run or retain unsettled requests, starts collapsed, and excludes settled results; reports remain in the conversation. Queued jobs are shown only alongside live work. Unsettled requests without current-generation job metadata show only a stopping count, never prior task labels. Public identities, shortened task labels, states, elapsed times, call counts and code-owned diagnostics are text-only; snapshots, full prompts, raw provider errors and child transcripts are not sent through the live widget. A single extension-side timer samples existing counters while slots are occupied; it makes no provider or source requests and is disposed on shutdown/rebinding. Invalidated-generation jobs contribute only to occupied-slot counts, not cross-session task labels; replaced same-generation stopping jobs remain visible until settlement. Chat clears live state on disconnect, exit and runtime session replacement and keeps at most 32 connection-local completion summaries for refresh; it adds no child journal or webview persistence. Existing delegate tool receipts are projected into readable advisory reports without changing their model/session content. Stop actions require a trusted workspace, foreground conversation, matching context and an observed running/queued batch/job/attempt. Pi rechecks that exact attempt before its human command cancels it. Worker Stop does not submit draft text/images, clear parent queues, approve tools, change quotas or claim remote termination. The widget is an integration contract with trusted installed extensions, not protection against a malicious extension in Pi's process.
213
213
 
214
214
  Native change review reads VS Code's Git API, validates selected workspace paths, and opens the corresponding working-tree or staged view through the built-in diff/editor actions. It does not execute a shell command, stage, commit, discard, or restore files. Git integration availability and the filesystem race boundary still apply. The sidebar coordinator keeps independent Pi connections for explicitly opened conversations. Switching conversations or folders only changes the selected view. Stop and Disconnect target the selected process; extension-host shutdown stops all owned processes. User-initiated parallel conversations share their workspace files and are not isolated worktrees. Branching uses Pi's pre-runtime `--fork` to copy into a new owned session before extensions can write, then performs any active-branch or prompt selection there; the original process and session remain unchanged.
215
215
 
@@ -7,7 +7,7 @@ import { DelegationError } from "./errors.mjs";
7
7
  import { createTimeoutStore } from "./settings.mjs";
8
8
 
9
9
  const stateKey = Symbol.for("specpi.delegation.native.v1");
10
- const revision = 9;
10
+ const revision = 10;
11
11
 
12
12
  export async function withPiCompatibility(sdk, loadCompatibility) {
13
13
  if (typeof sdk.clampThinkingLevel === "function") {
@@ -325,7 +325,8 @@ export function createNativePiHost(ctx, { id, isCurrent, sdk, thinkingLevel } =
325
325
  check();
326
326
  initialization ??= (async () => {
327
327
  // Pi owns normal configuration and credential access. No credential object is
328
- // requested, copied, or exposed. Static catalogs avoid refresh I/O.
328
+ // requested, copied, or exposed. Restore Pi's persisted catalogs without
329
+ // network refresh; skipping initialization also skips cached model overlays.
329
330
  const configured = sdk.SettingsManager.create(ctx.cwd, undefined, { projectTrusted: false });
330
331
  if (
331
332
  configured.getGlobalSettings().httpProxy ||
@@ -343,7 +344,7 @@ export function createNativePiHost(ctx, { id, isCurrent, sdk, thinkingLevel } =
343
344
  compaction: { enabled: false },
344
345
  retry: { enabled: false, maxRetries: 0, provider: { maxRetries: 0 } },
345
346
  };
346
- const runtime = await sdk.ModelRuntime.create({ allowModelNetwork: false, refreshOnCreate: false });
347
+ const runtime = await sdk.ModelRuntime.create({ allowModelNetwork: false });
347
348
  check();
348
349
  const childModel = runtime.getModel(model.provider, model.id);
349
350
  if (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specpi",
3
- "version": "0.18.0",
3
+ "version": "0.18.1",
4
4
  "description": "An explicit, privacy-conscious, self-improving harness for the Pi coding agent",
5
5
  "author": "Tanner Middleton",
6
6
  "repository": {