@counterposition/skill-pi 0.80.3 → 0.80.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@counterposition/skill-pi",
3
- "version": "0.80.3",
3
+ "version": "0.80.9",
4
4
  "description": "Pi coding agent reference skill — extensions, settings, providers, SDK/RPC, packages, and .pi/ config",
5
5
  "keywords": [
6
6
  "ai-skill",
@@ -90,13 +90,15 @@ Useful agent events:
90
90
  - `input` — carries `event.streamingBehavior` (`"steer" | "followUp" | undefined`) so handlers can distinguish idle prompts, mid-stream steers, and queued follow-ups; return `{ action: "transform" | "handled" | "continue" }`
91
91
  - `before_agent_start` — receives `event.systemPromptOptions` (a `BuildSystemPromptOptions`) so handlers can inspect the structured inputs feeding the system prompt
92
92
  - `agent_start`
93
- - `agent_end`
93
+ - `agent_end` — one low-level run; Pi may still auto-retry, auto-compact and retry, or continue with queued follow-ups
94
+ - `agent_settled` (Pi 0.80.4) — fired when no retry/compaction/follow-up remains; use for status integrations that need to know Pi will not continue automatically (`ctx.isIdle()` is true here unless another extension started a new run)
94
95
  - `turn_start`
95
96
  - `turn_end`
96
97
  - `message_start`
97
98
  - `message_update`
98
99
  - `message_end` — return a replacement message to override usage/cost or rewrite the finalized assistant message
99
100
  - `context`
101
+ - `before_provider_headers` (Pi 0.80.4) — mutate `event.headers` in place after outgoing HTTP headers are assembled: set a key to a string to add/override, `null` to delete. Runs once per provider request; retries reuse the same headers
100
102
  - `before_provider_request`
101
103
  - `after_provider_response` — inspect the provider HTTP status and headers before stream consumption
102
104
  - `model_select`
@@ -121,8 +123,8 @@ Tool results may include `terminate: true` to end the current tool batch without
121
123
  - `ctx.ui` for interactive UI hooks
122
124
  - `ctx.mode` — `"tui" | "rpc" | "json" | "print"`; gate terminal-only features on `ctx.mode === "tui"`
123
125
  - `ctx.cwd`
124
- - `ctx.sessionManager` (read-only)
125
- - `ctx.modelRegistry` / `ctx.model`
126
+ - `ctx.sessionManager` (read-only; `buildContextEntries()` returns active-branch entries with compaction applied, Pi 0.80.4)
127
+ - `ctx.modelRegistry` / `ctx.model` — `ctx.modelRegistry` is the synchronous extension-facing facade; its `refresh()` became `Promise<void>` in Pi 0.80.8 (await it before synchronous registry reads)
126
128
  - `ctx.hasUI` — `true` in TUI and RPC modes
127
129
  - `ctx.signal` — the active agent abort signal (or `undefined` when idle); pass it to `fetch`/model calls for abort-aware nested work
128
130
  - `ctx.isIdle()` / `ctx.hasPendingMessages()`
@@ -171,6 +173,19 @@ Important rules:
171
173
  4. Use the file-mutation queue for write/edit style tools.
172
174
  5. Put reconstructable state in `details`; it persists in session history.
173
175
 
176
+ ## Dynamic Tool Loading
177
+
178
+ Pi 0.80.7 lets an extension register many tools while keeping only a small initial set active, then add more during execution — cache-friendly on models with native deferred loading. Lifecycle:
179
+
180
+ 1. Register every tool with `pi.registerTool()` (all appear in `pi.getAllTools()`).
181
+ 2. Keep a loader tool (e.g. `search_tools`) active; leave searchable tools inactive — e.g. on `session_start`, `pi.setActiveTools()` to the filtered set.
182
+ 3. During loader execution, call `pi.setActiveTools([...pi.getActiveTools(), ...matches])`. The change must be purely additive; unknown names are ignored.
183
+ 4. Pi records the added tools on that tool result and exposes their definitions before the next model response.
184
+
185
+ Native deferred loading preserves the cached prompt prefix on Anthropic Sonnet/Opus/Fable ≥ 4.5 (not Haiku) and OpenAI `gpt-5.4`+; Kimi K3 works via `compat.deferredToolsMode: "kimi"` (Pi 0.80.9). For verified custom models/proxies, enable `compat.supportsToolReferences: true` (`anthropic-messages`) or `compat.supportsToolSearch: true` (`openai-responses`/`openai-codex-responses`). All other models fall back to sending the full active tool list on the next request — activation still works, but may invalidate the provider's cached prefix. Non-additive changes (removals/replacements) always use the fallback.
186
+
187
+ Cache tips: keep the loader active for the whole session; add rather than replace. Activating a tool that has `promptSnippet`/`promptGuidelines` rebuilds the system prompt and can invalidate the prefix even with native support — lazily loaded tools should rely on their `description` alone.
188
+
174
189
  ## UI Methods
175
190
 
176
191
  Check `ctx.hasUI` first. Non-interactive modes may not support UI.
@@ -240,6 +255,15 @@ Store extension state with custom session entries:
240
255
  pi.appendEntry("my-extension-state", { key: "value" });
241
256
  ```
242
257
 
258
+ Custom entries never participate in LLM context. Since Pi 0.80.4 they can also render in the interactive transcript via `pi.registerEntryRenderer(customType, renderer)` — the TUI-only counterpart to `pi.registerMessageRenderer()` (whose custom messages DO enter LLM context via `pi.sendMessage()`):
259
+
260
+ ```typescript
261
+ pi.registerEntryRenderer("status-card", (entry, { expanded }, theme) => {
262
+ return new Text(theme.fg("accent", JSON.stringify(entry.data)));
263
+ });
264
+ pi.appendEntry("status-card", { title: "Indexed files", count: 17 });
265
+ ```
266
+
243
267
  Use lifecycle hooks to restore it:
244
268
 
245
269
  ```typescript
@@ -280,12 +304,16 @@ pi.registerProvider("anthropic", { baseUrl: "https://proxy.example.com" });
280
304
  pi.unregisterProvider("my-provider");
281
305
  ```
282
306
 
307
+ Dynamic providers can implement `refreshModels(context)` (Pi 0.80.8) for model discovery: Pi calls it during catalog refresh (`/model`, `pi update --models`) and publishes the returned list; its models replace extension-provided `models`. Persist results through the scoped `context.store` only when they should survive restarts — live servers like llama.cpp can ignore it.
308
+
283
309
  If you need auth for a specific model request, use:
284
310
 
285
311
  ```typescript
286
312
  const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
287
313
  ```
288
314
 
315
+ (Still supported for extensions in Pi 0.80.8+; SDK code should use `ModelRuntime.getAuth()` — see `references/sdk.md`.)
316
+
289
317
  Pass `shouldStopAfterTurn` via the SDK to exit the agent loop gracefully after a completed turn. See `references/sdk.md` and `references/providers.md` for the full provider/model schema.
290
318
 
291
319
  ## Handy Patterns
@@ -19,9 +19,11 @@ pi list
19
19
  pi update # update pi only (changed in Pi 0.79.7)
20
20
  pi update --all # update pi + packages, reconcile pinned git refs
21
21
  pi update --extensions # update packages only
22
+ pi update --models # refresh model catalogs only (Pi 0.80.8)
22
23
  pi update --self # update pi only
23
24
  pi update <source> # update one package
24
- pi config
25
+ pi config # starts in global settings; Tab switches scope
26
+ pi config -l # start in project overrides (.pi/settings.json)
25
27
  ```
26
28
 
27
29
  By default, `install` and `remove` write to user settings (`~/.pi/agent/settings.json`). Use `-l` to write to project settings (`.pi/settings.json`) instead. `pi update` installs the exact version returned by the update check.
@@ -129,6 +131,6 @@ Rules:
129
131
 
130
132
  ## Scope and Deduplication
131
133
 
132
- - Project settings override global settings for the same package identity
134
+ - Project settings override global settings for the same package identity — unless the project entry has `autoload: false`, in which case it is applied as a delta over the global entry (Pi 0.80.4)
133
135
  - Identity is package name for npm, repo URL for git, and resolved absolute path for local sources
134
- - `pi config` can enable or disable package resources after installation
136
+ - `pi config` can enable or disable package resources after installation; since Pi 0.80.4 it manages global vs project-local scopes (Tab to switch, `pi config -l` to start in project mode with inherited global resources dimmed)
@@ -9,8 +9,12 @@ Use `/login` in interactive mode, then select a provider. The `/login` selector
9
9
  - Anthropic Claude Pro / Max — third-party usage draws from extra usage and is billed per token (suppress the warning via `warnings.anthropicExtraUsage`)
10
10
  - OpenAI ChatGPT Plus / Pro (Codex) — `/login` defaults to browser auth but can use a device-code flow for headless environments
11
11
  - GitHub Copilot
12
+ - xAI (Grok/X subscription, Pi 0.80.8) — `/login xai` then **Use a subscription** (device-code OAuth); `XAI_API_KEY` remains available via **Use an API key**
13
+ - Radius (Pi 0.80.8) — a dynamic `pi-messages` gateway; `/login radius` stores OAuth tokens, and custom Radius gateways can be declared in `models.json` with `"oauth": "radius"` plus a gateway `baseUrl`
12
14
 
13
- Use `/logout` to clear stored OAuth credentials. Pi 0.71.0 removed built-in Google Gemini CLI and Google Antigravity providers.
15
+ `/login <provider>` with autocomplete works since Pi 0.80.4, and login methods are provider-owned since 0.80.8 (registered pi-ai providers expose their own auth options and status in `/login`). Use `/logout` to clear stored OAuth credentials. Pi 0.71.0 removed built-in Google Gemini CLI and Google Antigravity providers.
16
+
17
+ Since Pi 0.80.8, built-in catalogs are complemented by dynamic ones: `/model` refreshes configured providers in the background, `pi update --models` forces an immediate refresh, and refreshed catalogs are cached in `~/.pi/agent/models-store.json` for offline use.
14
18
 
15
19
  ## API Key Providers
16
20
 
@@ -35,6 +39,8 @@ Use `/logout` to clear stored OAuth credentials. Pi 0.71.0 removed built-in Goog
35
39
  | ZAI Coding Plan (China) | `ZAI_CODING_CN_API_KEY` | `zai-coding-cn` |
36
40
  | OpenCode Zen | `OPENCODE_API_KEY` | `opencode` |
37
41
  | OpenCode Go | `OPENCODE_API_KEY` | `opencode-go` |
42
+ | Amazon Bedrock | `AWS_BEARER_TOKEN_BEDROCK` | `amazon-bedrock` |
43
+ | Radius | `RADIUS_API_KEY` | `radius` |
38
44
  | Hugging Face | `HF_TOKEN` | `huggingface` |
39
45
  | Fireworks | `FIREWORKS_API_KEY` | `fireworks` |
40
46
  | Together AI | `TOGETHER_API_KEY` | `together` |
@@ -99,7 +105,7 @@ export AZURE_OPENAI_DEPLOYMENT_NAME_MAP=gpt-4o=my-gpt4o
99
105
 
100
106
  ### Amazon Bedrock
101
107
 
102
- Pi supports standard AWS auth flows:
108
+ `/login amazon-bedrock` stores a Bedrock API key (Pi 0.80.7). Ambient AWS credential flows also work — these keep using SigV4 authentication:
103
109
 
104
110
  - `AWS_PROFILE`
105
111
  - `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY`
@@ -182,10 +188,14 @@ Common `api` values:
182
188
 
183
189
  ### Model & Compatibility Knobs
184
190
 
185
- - `thinkingLevelMap` (Pi 0.72) replaces `compat.reasoningEffortMap`. Map pi levels (`off`/`minimal`/`low`/`medium`/`high`/`xhigh`) to provider values; use `null` to hide a level.
191
+ - `thinkingLevelMap` (Pi 0.72) replaces `compat.reasoningEffortMap`. Map pi levels (`off`/`minimal`/`low`/`medium`/`high`/`xhigh`/`max`) to provider values; use `null` to hide a level. Maps may contain holes (Pi 0.80.6) — e.g. expose `high` and `max` without `xhigh`. When a key is omitted, standard levels through `high` use the provider default mapping, but the extended `xhigh`/`max` levels are unsupported.
192
+ - `cost` supports request-wide input pricing tiers (Pi 0.80.6): a `tiers` array where each tier supplies a complete alternate rate set and applies to the whole request when total input usage (`input + cacheRead + cacheWrite`) exceeds `inputTokensAbove`; the highest matching threshold wins. Also usable in `modelOverrides` and extension-registered providers.
193
+ - `modelOverrides` applies to built-in and (since Pi 0.80.4) extension-registered provider models; per-model fields: `name`, `reasoning`, `thinkingLevelMap`, `input`, `cost` (partial), `contextWindow`, `maxTokens`, `headers`, `compat`.
186
194
  - `openRouterRouting` is forwarded as-is in the OpenRouter `provider` field (fallbacks, ZDR, ignore lists, throughput/latency).
187
195
  - `compat.thinkingFormat` supports OpenAI-compatible reasoning variants: `openrouter` sends `reasoning: { effort }`, `together` sends `reasoning: { enabled }` plus `reasoning_effort` when supported, `qwen-chat-template` targets local Qwen-compatible servers that read `chat_template_kwargs.enable_thinking`, and `chat-template` (Pi 0.79.9) sends configurable `chat_template_kwargs` via `compat.chatTemplateKwargs` — e.g. `{ "thinking": { "$var": "thinking.enabled" } }` for DeepSeek models behind vLLM/Hugging Face chat templates (`"$var"` accepts `"thinking.enabled"` or `"thinking.effort"`).
188
- - Advanced `compat` flags exist for proxy quirks (`cacheControlFormat`, `supportsReasoningEffort`, `supportsLongCacheRetention`, `supportsEagerToolInputStreaming`, `sendSessionIdHeader`, `sendSessionAffinityHeaders`). See [Pi `docs/models.md`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/models.md) when a proxy rejects pi's defaults.
196
+ - **Breaking (Pi 0.80.7):** `compat.sendSessionIdHeader` was removed. Session affinity is now controlled by `compat.sessionAffinityFormat` (`"openai"` sends `session_id`/`x-client-request-id`, `"openai-nosession"` omits the underscore-containing `session_id` header, `"openrouter"` sends `x-session-id`; default auto-detected). Replace `sendSessionIdHeader: false` with `sessionAffinityFormat: "openai-nosession"`. `sendSessionAffinityHeaders` still gates the behavior for `openai-completions`.
197
+ - `compat.deferredToolsMode: "kimi"` (Pi 0.80.9) enables Kimi's deferred tool serialization; `compat.supportsToolReferences` / `compat.supportsToolSearch` enable native dynamic tool loading on verified custom endpoints (see `references/extensions.md`).
198
+ - Advanced `compat` flags exist for proxy quirks (`cacheControlFormat`, `supportsReasoningEffort`, `supportsLongCacheRetention`, `supportsEagerToolInputStreaming`, `supportsStrictMode`). See [Pi `docs/models.md`](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/models.md) when a proxy rejects pi's defaults.
189
199
 
190
200
  ### Context Overflow Recovery
191
201
 
@@ -219,7 +229,7 @@ pi.registerProvider("anthropic", { baseUrl: "https://proxy.example.com" });
219
229
 
220
230
  ## SDK / Extension Auth Lookup
221
231
 
222
- If extension or SDK code needs auth for a specific model request, use `getApiKeyAndHeaders(model)` rather than the removed `getApiKey(model)`:
232
+ If extension code needs auth for a specific model request, use `getApiKeyAndHeaders(model)` rather than the removed `getApiKey(model)`:
223
233
 
224
234
  ```typescript
225
235
  const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
@@ -228,4 +238,4 @@ if (!auth.ok) throw new Error(auth.error);
228
238
  const { apiKey, headers } = auth;
229
239
  ```
230
240
 
231
- This matters for providers whose headers or auth values resolve dynamically on every request.
241
+ This matters for providers whose headers or auth values resolve dynamically on every request. In SDK code, use `ModelRuntime.getAuth(providerOrModel)` instead (Pi 0.80.8) — passing a model also resolves built-in, `models.json`, and extension model headers; see `references/sdk.md`.
@@ -12,19 +12,16 @@ npm install @earendil-works/pi-coding-agent
12
12
 
13
13
  ```typescript
14
14
  import {
15
- AuthStorage,
16
15
  createAgentSession,
17
- ModelRegistry,
16
+ ModelRuntime,
18
17
  SessionManager,
19
18
  } from "@earendil-works/pi-coding-agent";
20
19
 
21
- const authStorage = AuthStorage.create();
22
- const modelRegistry = ModelRegistry.create(authStorage);
20
+ const modelRuntime = await ModelRuntime.create();
23
21
 
24
22
  const { session } = await createAgentSession({
25
23
  sessionManager: SessionManager.inMemory(),
26
- authStorage,
27
- modelRegistry,
24
+ modelRuntime,
28
25
  });
29
26
 
30
27
  session.subscribe((event) => {
@@ -38,17 +35,16 @@ await session.prompt("What files are in the current directory?");
38
35
 
39
36
  Run with `npx tsx my-script.ts`.
40
37
 
41
- **Important:** `ModelRegistry` no longer has a public constructor. Use `ModelRegistry.create(authStorage, modelsJsonPath?)` for file-backed registries or `ModelRegistry.inMemory(authStorage)` for built-in models only.
38
+ **Breaking (Pi 0.80.8):** `ModelRuntime` replaced the old `AuthStorage`/`ModelRegistry` pair as the SDK model/auth facade. `CreateAgentSessionOptions.authStorage` and `modelRegistry` are gone — pass the async `modelRuntime` instead. `AuthStorage` is no longer exported; use `ModelRuntime` (or a custom pi-ai `CredentialStore`), or `readStoredCredential()` for one-off reads of `auth.json`. `ModelRegistry` still exists only as the synchronous extension-facing compatibility facade, and its `refresh()` is now `Promise<void>`.
42
39
 
43
40
  ## Key Imports
44
41
 
45
42
  ```typescript
46
43
  import {
47
- AuthStorage,
48
44
  createAgentSession,
49
45
  DefaultResourceLoader,
50
46
  defineTool,
51
- ModelRegistry,
47
+ ModelRuntime,
52
48
  SessionManager,
53
49
  } from "@earendil-works/pi-coding-agent";
54
50
  import { getBuiltinModel } from "@earendil-works/pi-ai/providers/all";
@@ -60,16 +56,14 @@ import { getBuiltinModel } from "@earendil-works/pi-ai/providers/all";
60
56
 
61
57
  ```typescript
62
58
  const cwd = "/path/to/project";
63
- const authStorage = AuthStorage.create();
64
- const modelRegistry = ModelRegistry.create(authStorage);
59
+ const modelRuntime = await ModelRuntime.create();
65
60
 
66
61
  const { session } = await createAgentSession({
67
62
  cwd,
68
63
  agentDir: "~/.pi/agent",
69
- authStorage,
70
- modelRegistry,
64
+ modelRuntime,
71
65
  model: getBuiltinModel("anthropic", "claude-opus-4-8"),
72
- thinkingLevel: "medium",
66
+ thinkingLevel: "medium", // off | minimal | low | medium | high | xhigh | max
73
67
  scopedModels: [
74
68
  { model: getBuiltinModel("anthropic", "claude-opus-4-8"), thinkingLevel: "high" },
75
69
  ],
@@ -90,6 +84,50 @@ Notes:
90
84
  - `DefaultResourceLoader` loads extensions, skills, prompt templates, themes, and context files. Replace it to drive resource discovery from custom sources (and it must implement `loadProjectContextFiles()` if you want `AGENTS.md`/`CLAUDE.md` discovery; that helper is also exported standalone).
91
85
  - Pass `shouldStopAfterTurn(state) => boolean` (Pi 0.72.0) to exit the agent loop gracefully after a completed turn.
92
86
 
87
+ ## Models & Auth (`ModelRuntime`)
88
+
89
+ `ModelRuntime` (Pi 0.80.8) implements the pi-ai `Models` interface and owns credential storage. Auth resolution priority: runtime overrides (`setRuntimeApiKey`, not persisted) → stored credentials in `auth.json` → environment variables → fallback resolver for `models.json` keys.
90
+
91
+ ```typescript
92
+ import { InMemoryCredentialStore } from "@earendil-works/pi-ai";
93
+ import { ModelRuntime } from "@earendil-works/pi-coding-agent";
94
+
95
+ // Default: ~/.pi/agent/auth.json and ~/.pi/agent/models.json
96
+ const modelRuntime = await ModelRuntime.create();
97
+
98
+ // Model lookup (use pi-ai Models methods directly; the old
99
+ // getAll()/find()/getSnapshot() projections were removed)
100
+ const model = modelRuntime.getModel("my-provider", "my-model");
101
+ const available = await modelRuntime.getAvailable(); // only models with valid auth
102
+
103
+ // Provider-owned auth methods and current status
104
+ for (const provider of modelRuntime.getProviders()) {
105
+ const status = await modelRuntime.checkAuth(provider.id);
106
+ }
107
+
108
+ modelRuntime.setRuntimeApiKey("anthropic", "sk-my-temp-key");
109
+
110
+ // Custom locations, or inject any pi-ai CredentialStore
111
+ const custom = await ModelRuntime.create({ authPath: "/my/auth.json", modelsPath: "/my/models.json" });
112
+ const inMemory = await ModelRuntime.create({ credentials: new InMemoryCredentialStore() });
113
+ ```
114
+
115
+ `ModelRuntime.getAuth(providerOrModel)` assembles final request auth (replacing `ModelRegistry.getApiKeyAndHeaders()` on the SDK side); passing a model also resolves built-in, `models.json`, and extension model headers. Dynamic provider catalogs refresh via async `ModelRuntime.refresh()` and are cached in `~/.pi/agent/models-store.json`.
116
+
117
+ To match CLI model parsing, use the exported resolver helpers (Pi 0.80.4):
118
+
119
+ ```typescript
120
+ import { resolveCliModel, resolveModelScopeWithDiagnostics } from "@earendil-works/pi-coding-agent";
121
+
122
+ const cliModel = resolveCliModel({ cliModel: "anthropic/claude-opus-4-8:high", modelRuntime });
123
+ const { scopedModels, diagnostics } = await resolveModelScopeWithDiagnostics(
124
+ ["anthropic/*:high", "gpt-5"],
125
+ modelRuntime,
126
+ );
127
+ ```
128
+
129
+ `resolveCliModel()` resolves against all registered models (so `--api-key`-style first-time setup works before stored auth exists); `resolveModelScopeWithDiagnostics()` matches `--models`/`enabledModels` semantics and returns warnings instead of printing.
130
+
93
131
  ## Prompting & Queueing
94
132
 
95
133
  ```typescript
@@ -193,7 +231,8 @@ session.subscribe((event) => {
193
231
  case "tool_execution_update":
194
232
  case "tool_execution_end":
195
233
  case "agent_start":
196
- case "agent_end":
234
+ case "agent_end": // one low-level run; may be followed by retry/compaction/queued follow-ups
235
+ case "agent_settled": // fully settled — no automatic continuation left (Pi 0.80.4)
197
236
  case "turn_start":
198
237
  case "turn_end":
199
238
  case "queue_update":
@@ -212,6 +251,7 @@ session.subscribe((event) => {
212
251
 
213
252
  `pi --mode rpc` speaks newline-delimited JSON over stdio. Additions since Pi 0.79:
214
253
 
254
+ - `agent_settled` event (Pi 0.80.4) fires when a run is fully settled — no automatic retry, compaction retry, or queued continuation remains; `agent_end` now carries `willRetry`. `set_thinking_level` accepts `"max"` where the model supports it.
215
255
  - `get_entries` / `get_tree` (Pi 0.80.3) read session entries and tree snapshots over RPC.
216
256
  - `@earendil-works/pi-coding-agent/rpc-entry` (Pi 0.80.3) launches Pi directly in RPC mode from an importing process.
217
257
  - RPC extension UI request/response types are exported from the public API (Pi 0.79.0).
@@ -227,6 +267,20 @@ session.subscribe((event) => {
227
267
  - Add custom skills or prompt templates without touching disk
228
268
  - Share an event bus between the host app and loaded extensions
229
269
 
270
+ To name an inline factory in the startup Extensions list (instead of `<inline:1>`), wrap it in an `InlineExtension` (Pi 0.80.4):
271
+
272
+ ```typescript
273
+ import type { InlineExtension } from "@earendil-works/pi-coding-agent";
274
+
275
+ const myProvider: InlineExtension = {
276
+ name: "my-provider",
277
+ factory: (pi) => { /* ... */ },
278
+ };
279
+ const loader = new DefaultResourceLoader({ extensionFactories: [myProvider] });
280
+ ```
281
+
282
+ Bare factory functions are still accepted.
283
+
230
284
  ## Standalone Custom Tools
231
285
 
232
286
  Use `defineTool()` when you want a reusable custom tool definition outside `pi.registerTool(...)`:
@@ -17,6 +17,7 @@ Edit JSON directly or use `/settings` for common interactive options.
17
17
  "defaultModel": "claude-sonnet-4-20250514",
18
18
  "defaultThinkingLevel": "medium",
19
19
  "hideThinkingBlock": false,
20
+ "showCacheMissNotices": false,
20
21
  "thinkingBudgets": {
21
22
  "minimal": 1024,
22
23
  "low": 4096,
@@ -26,8 +27,9 @@ Edit JSON directly or use `/settings` for common interactive options.
26
27
  }
27
28
  ```
28
29
 
29
- - Thinking levels: `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`
30
+ - Thinking levels: `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"`, `"max"` — `max` (Pi 0.80.6) is an opt-in level above `xhigh`, exposed only when the selected model supports it (some models, e.g. GPT-5.6, expose both). Custom themes can define `thinkingMax`; existing themes fall back to `thinkingXhigh`.
30
31
  - `hideThinkingBlock` hides visible thinking output in the UI
32
+ - `showCacheMissNotices` (Pi 0.80.4) shows transcript notices for significant prompt-cache misses
31
33
 
32
34
  ## UI & Display
33
35
 
@@ -125,6 +127,7 @@ Notes:
125
127
  }
126
128
  ```
127
129
 
130
+ - `shellPath` supports a leading `~` for the home directory (Pi 0.80.6).
128
131
  - `npmCommand` is argv-style and is used for npm lookup/install operations, including git-package installs. User-scoped npm packages install under `~/.pi/agent/npm/`; project-scoped npm packages install under `.pi/npm/`.
129
132
  - `terminal.showTerminalProgress` (default `false` since Pi 0.70.0) toggles OSC 9;4 progress reporting in supporting terminals (iTerm2, WezTerm, Windows Terminal, Kitty).
130
133
  - `terminal.imageWidthCells` (Pi 0.68.1) caps inline tool-output image width in terminal cells.
@@ -236,7 +239,7 @@ pi [options] [@files...] [messages...]
236
239
  --provider <name> e.g. anthropic, openai, google
237
240
  --model <pattern> supports provider/id and optional :<thinking>
238
241
  --api-key <key>
239
- --thinking off|minimal|low|medium|high|xhigh
242
+ --thinking off|minimal|low|medium|high|xhigh|max
240
243
  --models <patterns> Ctrl+P cycling allowlist
241
244
  --list-models [search]
242
245