@earendil-works/pi-coding-agent 0.80.3 → 0.80.5

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.
Files changed (158) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +1 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +2 -2
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/config-selector.d.ts +4 -2
  7. package/dist/cli/config-selector.d.ts.map +1 -1
  8. package/dist/cli/config-selector.js +1 -1
  9. package/dist/cli/config-selector.js.map +1 -1
  10. package/dist/core/agent-session.d.ts +20 -4
  11. package/dist/core/agent-session.d.ts.map +1 -1
  12. package/dist/core/agent-session.js +95 -22
  13. package/dist/core/agent-session.js.map +1 -1
  14. package/dist/core/auth-storage.d.ts.map +1 -1
  15. package/dist/core/auth-storage.js +13 -5
  16. package/dist/core/auth-storage.js.map +1 -1
  17. package/dist/core/cache-stats.d.ts +49 -0
  18. package/dist/core/cache-stats.d.ts.map +1 -0
  19. package/dist/core/cache-stats.js +101 -0
  20. package/dist/core/cache-stats.js.map +1 -0
  21. package/dist/core/compaction/compaction.d.ts +1 -2
  22. package/dist/core/compaction/compaction.d.ts.map +1 -1
  23. package/dist/core/compaction/compaction.js +56 -81
  24. package/dist/core/compaction/compaction.js.map +1 -1
  25. package/dist/core/extensions/index.d.ts +1 -1
  26. package/dist/core/extensions/index.d.ts.map +1 -1
  27. package/dist/core/extensions/index.js.map +1 -1
  28. package/dist/core/extensions/loader.d.ts.map +1 -1
  29. package/dist/core/extensions/loader.js +6 -0
  30. package/dist/core/extensions/loader.js.map +1 -1
  31. package/dist/core/extensions/runner.d.ts +5 -3
  32. package/dist/core/extensions/runner.d.ts.map +1 -1
  33. package/dist/core/extensions/runner.js +38 -0
  34. package/dist/core/extensions/runner.js.map +1 -1
  35. package/dist/core/extensions/types.d.ts +31 -4
  36. package/dist/core/extensions/types.d.ts.map +1 -1
  37. package/dist/core/extensions/types.js.map +1 -1
  38. package/dist/core/index.d.ts +1 -1
  39. package/dist/core/index.d.ts.map +1 -1
  40. package/dist/core/index.js.map +1 -1
  41. package/dist/core/keybindings.d.ts.map +1 -1
  42. package/dist/core/keybindings.js +3 -6
  43. package/dist/core/keybindings.js.map +1 -1
  44. package/dist/core/model-registry.d.ts +3 -0
  45. package/dist/core/model-registry.d.ts.map +1 -1
  46. package/dist/core/model-registry.js +16 -2
  47. package/dist/core/model-registry.js.map +1 -1
  48. package/dist/core/model-resolver.d.ts +10 -0
  49. package/dist/core/model-resolver.d.ts.map +1 -1
  50. package/dist/core/model-resolver.js +14 -17
  51. package/dist/core/model-resolver.js.map +1 -1
  52. package/dist/core/package-manager.d.ts +4 -1
  53. package/dist/core/package-manager.d.ts.map +1 -1
  54. package/dist/core/package-manager.js +68 -26
  55. package/dist/core/package-manager.js.map +1 -1
  56. package/dist/core/provider-attribution.d.ts.map +1 -1
  57. package/dist/core/provider-attribution.js +0 -10
  58. package/dist/core/provider-attribution.js.map +1 -1
  59. package/dist/core/resource-loader.d.ts +2 -2
  60. package/dist/core/resource-loader.d.ts.map +1 -1
  61. package/dist/core/resource-loader.js +6 -7
  62. package/dist/core/resource-loader.js.map +1 -1
  63. package/dist/core/sdk.d.ts +1 -1
  64. package/dist/core/sdk.d.ts.map +1 -1
  65. package/dist/core/sdk.js +8 -1
  66. package/dist/core/sdk.js.map +1 -1
  67. package/dist/core/session-manager.d.ts +20 -1
  68. package/dist/core/session-manager.d.ts.map +1 -1
  69. package/dist/core/session-manager.js +97 -68
  70. package/dist/core/session-manager.js.map +1 -1
  71. package/dist/core/settings-manager.d.ts +5 -0
  72. package/dist/core/settings-manager.d.ts.map +1 -1
  73. package/dist/core/settings-manager.js +8 -0
  74. package/dist/core/settings-manager.js.map +1 -1
  75. package/dist/core/slash-commands.d.ts +1 -0
  76. package/dist/core/slash-commands.d.ts.map +1 -1
  77. package/dist/core/slash-commands.js +3 -3
  78. package/dist/core/slash-commands.js.map +1 -1
  79. package/dist/core/tools/bash.d.ts.map +1 -1
  80. package/dist/core/tools/bash.js +20 -5
  81. package/dist/core/tools/bash.js.map +1 -1
  82. package/dist/core/tools/edit.d.ts.map +1 -1
  83. package/dist/core/tools/edit.js +2 -2
  84. package/dist/core/tools/edit.js.map +1 -1
  85. package/dist/index.d.ts +3 -2
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +2 -1
  88. package/dist/index.js.map +1 -1
  89. package/dist/main.d.ts +2 -2
  90. package/dist/main.d.ts.map +1 -1
  91. package/dist/main.js +1 -0
  92. package/dist/main.js.map +1 -1
  93. package/dist/modes/interactive/components/config-selector.d.ts +34 -3
  94. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  95. package/dist/modes/interactive/components/config-selector.js +280 -25
  96. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  97. package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
  98. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
  99. package/dist/modes/interactive/components/custom-entry.js +52 -0
  100. package/dist/modes/interactive/components/custom-entry.js.map +1 -0
  101. package/dist/modes/interactive/components/footer.d.ts +4 -0
  102. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  103. package/dist/modes/interactive/components/footer.js +1 -1
  104. package/dist/modes/interactive/components/footer.js.map +1 -1
  105. package/dist/modes/interactive/components/oauth-selector.d.ts +3 -1
  106. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  107. package/dist/modes/interactive/components/oauth-selector.js +17 -6
  108. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  109. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  110. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  111. package/dist/modes/interactive/components/settings-selector.js +10 -0
  112. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  113. package/dist/modes/interactive/interactive-mode.d.ts +15 -3
  114. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  115. package/dist/modes/interactive/interactive-mode.js +302 -61
  116. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  117. package/dist/modes/print-mode.d.ts.map +1 -1
  118. package/dist/modes/print-mode.js +1 -1
  119. package/dist/modes/print-mode.js.map +1 -1
  120. package/dist/modes/rpc/rpc-client.d.ts +6 -6
  121. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  122. package/dist/modes/rpc/rpc-client.js +3 -3
  123. package/dist/modes/rpc/rpc-client.js.map +1 -1
  124. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  125. package/dist/modes/rpc/rpc-mode.js +4 -1
  126. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  127. package/dist/package-manager-cli.d.ts +2 -2
  128. package/dist/package-manager-cli.d.ts.map +1 -1
  129. package/dist/package-manager-cli.js +71 -17
  130. package/dist/package-manager-cli.js.map +1 -1
  131. package/dist/utils/clipboard-image.d.ts.map +1 -1
  132. package/dist/utils/clipboard-image.js +1 -1
  133. package/dist/utils/clipboard-image.js.map +1 -1
  134. package/docs/extensions.md +74 -17
  135. package/docs/models.md +4 -4
  136. package/docs/packages.md +2 -2
  137. package/docs/rpc.md +13 -3
  138. package/docs/sdk.md +50 -0
  139. package/docs/session-format.md +18 -8
  140. package/docs/settings.md +1 -0
  141. package/docs/usage.md +1 -1
  142. package/examples/extensions/README.md +1 -0
  143. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  144. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  145. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  146. package/examples/extensions/entry-renderer.ts +41 -0
  147. package/examples/extensions/gondolin/package-lock.json +2 -2
  148. package/examples/extensions/gondolin/package.json +1 -1
  149. package/examples/extensions/question.ts +1 -0
  150. package/examples/extensions/reload-runtime.ts +2 -2
  151. package/examples/extensions/sandbox/package-lock.json +2 -2
  152. package/examples/extensions/sandbox/package.json +1 -1
  153. package/examples/extensions/with-deps/package-lock.json +2 -2
  154. package/examples/extensions/with-deps/package.json +1 -1
  155. package/examples/sdk/12-full-control.ts +1 -1
  156. package/examples/sdk/README.md +1 -1
  157. package/npm-shrinkwrap.json +12 -12
  158. package/package.json +4 -4
package/docs/models.md CHANGED
@@ -139,7 +139,7 @@ Set `api` at provider level (default for all models) or model level (override pe
139
139
  | `headers` | Custom headers (see value resolution below) |
140
140
  | `authHeader` | Set `true` to add `Authorization: Bearer <apiKey>` automatically |
141
141
  | `models` | Array of model configurations |
142
- | `modelOverrides` | Per-model overrides for built-in models on this provider |
142
+ | `modelOverrides` | Per-model overrides for built-in or extension-registered models on this provider |
143
143
 
144
144
  For providers with `models`, non-built-in provider configs need `baseUrl` and an `api` value at either provider or model level. `apiKey` is not required to load the file: models become available when auth is configured through `/login`/`auth.json`, CLI `--api-key`, or provider `apiKey`. If no auth is configured, the models load but stay unavailable in `/model` and `--list-models`.
145
145
 
@@ -293,7 +293,7 @@ Merge semantics:
293
293
 
294
294
  ## Per-model Overrides
295
295
 
296
- Use `modelOverrides` to customize specific built-in models without replacing the provider's full model list.
296
+ Use `modelOverrides` to customize built-in models and matching extension-registered models without replacing the provider's full model list.
297
297
 
298
298
  ```json
299
299
  {
@@ -314,10 +314,10 @@ Use `modelOverrides` to customize specific built-in models without replacing the
314
314
  }
315
315
  ```
316
316
 
317
- `modelOverrides` supports these fields per model: `name`, `reasoning`, `input`, `cost` (partial), `contextWindow`, `maxTokens`, `headers`, `compat`.
317
+ `modelOverrides` supports these fields per model: `name`, `reasoning`, `thinkingLevelMap`, `input`, `cost` (partial), `contextWindow`, `maxTokens`, `headers`, `compat`.
318
318
 
319
319
  Behavior notes:
320
- - `modelOverrides` are applied to built-in provider models.
320
+ - `modelOverrides` are applied to built-in provider models and matching extension-registered provider models.
321
321
  - Unknown model IDs are ignored.
322
322
  - You can combine provider-level `baseUrl`/`headers` with `modelOverrides`.
323
323
  - Overriding `name` changes model matching and secondary detail text only; the footer and primary model lists continue to show the model `id`.
package/docs/packages.md CHANGED
@@ -216,11 +216,11 @@ Filter what a package loads using the object form in settings:
216
216
 
217
217
  ## Enable and Disable Resources
218
218
 
219
- Use `pi config` to enable or disable extensions, skills, prompt templates, and themes from installed packages and local directories. Works for both global (`~/.pi/agent`) and project (`.pi/`) scopes.
219
+ Use `pi config` to enable or disable extensions, skills, prompt templates, and themes from installed packages and local directories. `pi config` starts in global settings (`~/.pi/agent/settings.json`); press Tab to switch between global and project-local modes. Use `pi config -l` to start in project overrides (`.pi/settings.json`) with inherited global resources dimmed.
220
220
 
221
221
  ## Scope and Deduplication
222
222
 
223
- Packages can appear in both global and project settings. If the same package appears in both, the project entry wins. Identity is determined by:
223
+ Packages can appear in both global and project settings. If the same package appears in both, the project entry wins unless the project entry has `autoload: false`, in which case it is applied as a delta over the global entry. Identity is determined by:
224
224
 
225
225
  - npm: package name
226
226
  - git: repository URL without ref
package/docs/rpc.md CHANGED
@@ -808,7 +808,8 @@ Events are streamed to stdout as JSON lines during agent operation. Events do NO
808
808
  | Event | Description |
809
809
  |-------|-------------|
810
810
  | `agent_start` | Agent begins processing |
811
- | `agent_end` | Agent completes (includes all generated messages) |
811
+ | `agent_end` | One low-level agent run completes (may still be followed by retry, compaction, or queued continuations) |
812
+ | `agent_settled` | Agent run is fully settled; no automatic retry, compaction retry, or queued continuation remains |
812
813
  | `turn_start` | New turn begins |
813
814
  | `turn_end` | Turn completes (includes assistant message and tool results) |
814
815
  | `message_start` | Message begins |
@@ -834,15 +835,24 @@ Emitted when the agent begins processing a prompt.
834
835
 
835
836
  ### agent_end
836
837
 
837
- Emitted when the agent completes. Contains all messages generated during this run.
838
+ Emitted when one low-level agent run completes. Contains all messages generated during this run. If `willRetry` is true, an automatic retry will follow.
838
839
 
839
840
  ```json
840
841
  {
841
842
  "type": "agent_end",
842
- "messages": [...]
843
+ "messages": [...],
844
+ "willRetry": false
843
845
  }
844
846
  ```
845
847
 
848
+ ### agent_settled
849
+
850
+ Emitted after the full session-level run settles. At this point Pi will not continue automatically through retry, compaction retry, or queued follow-up messages.
851
+
852
+ ```json
853
+ {"type": "agent_settled"}
854
+ ```
855
+
846
856
  ### turn_start / turn_end
847
857
 
848
858
  A turn consists of one assistant response plus any resulting tool calls and results.
package/docs/sdk.md CHANGED
@@ -405,6 +405,32 @@ If no model is provided:
405
405
  2. Uses default from settings
406
406
  3. Falls back to first available model
407
407
 
408
+ To match CLI model parsing, use the exported resolver helpers:
409
+
410
+ ```typescript
411
+ import {
412
+ resolveCliModel,
413
+ resolveModelScopeWithDiagnostics,
414
+ } from "@earendil-works/pi-coding-agent";
415
+
416
+ const cliModel = resolveCliModel({
417
+ cliModel: "anthropic/claude-opus-4-5:high",
418
+ modelRegistry,
419
+ });
420
+ if (cliModel.error) throw new Error(cliModel.error);
421
+ if (cliModel.warning) console.warn(cliModel.warning);
422
+
423
+ const { scopedModels, diagnostics } = await resolveModelScopeWithDiagnostics(
424
+ ["anthropic/*:high", "gpt-5"],
425
+ modelRegistry,
426
+ );
427
+ for (const diagnostic of diagnostics) {
428
+ console.warn(diagnostic.message);
429
+ }
430
+ ```
431
+
432
+ `resolveCliModel()` uses all registered models so `--api-key` style first-time setup can resolve a model before stored auth exists. `resolveModelScopeWithDiagnostics()` matches `--models` and `enabledModels` semantics while returning warnings instead of printing them.
433
+
408
434
  > See [examples/sdk/02-custom-model.ts](../examples/sdk/02-custom-model.ts)
409
435
 
410
436
  ### API Keys and OAuth
@@ -578,6 +604,27 @@ const { session } = await createAgentSession({ resourceLoader: loader });
578
604
 
579
605
  Extensions can register tools, subscribe to events, add commands, and more. See [extensions.md](extensions.md) for the full API.
580
606
 
607
+ **Named inline extensions:** By default, inline factories display as `<inline:1>`, `<inline:2>`, etc. in the startup Extensions list. To show a descriptive name instead, wrap the factory:
608
+
609
+ ```typescript
610
+ import type { InlineExtension } from "@earendil-works/pi-coding-agent";
611
+
612
+ const myProvider: InlineExtension = {
613
+ name: "my-provider",
614
+ factory: (pi) => {
615
+ pi.on("agent_start", () => {
616
+ console.log("[my-provider] Agent starting");
617
+ });
618
+ },
619
+ };
620
+
621
+ const loader = new DefaultResourceLoader({
622
+ extensionFactories: [myProvider],
623
+ });
624
+ ```
625
+
626
+ This displays as `<inline:my-provider>` instead of `<inline:1>`. Bare factory functions are still accepted for backward compatibility.
627
+
581
628
  **Event Bus:** Extensions can communicate via `pi.events`. Pass a shared `eventBus` to `DefaultResourceLoader` if you need to emit or listen from outside:
582
629
 
583
630
  ```typescript
@@ -1104,6 +1151,8 @@ AgentSessionRuntime
1104
1151
  // Auth and Models
1105
1152
  AuthStorage
1106
1153
  ModelRegistry
1154
+ resolveCliModel
1155
+ resolveModelScopeWithDiagnostics
1107
1156
 
1108
1157
  // Resource loading
1109
1158
  DefaultResourceLoader
@@ -1133,6 +1182,7 @@ createGrepTool, createFindTool, createLsTool
1133
1182
  type CreateAgentSessionOptions
1134
1183
  type CreateAgentSessionResult
1135
1184
  type ExtensionFactory
1185
+ type InlineExtension
1136
1186
  type ExtensionAPI
1137
1187
  type ToolDefinition
1138
1188
  type Skill
@@ -255,7 +255,7 @@ Extension state persistence. Does NOT participate in LLM context.
255
255
  {"type":"custom","id":"h8i9j0k1","parentId":"g7h8i9j0","timestamp":"2024-12-03T14:20:00.000Z","customType":"my-extension","data":{"count":42}}
256
256
  ```
257
257
 
258
- Use `customType` to identify your extension's entries on reload.
258
+ Use `customType` to identify your extension's entries on reload. Interactive mode can render custom entries via `pi.registerEntryRenderer(customType, renderer)`, but they still do not participate in LLM context.
259
259
 
260
260
  ### CustomMessageEntry
261
261
 
@@ -306,15 +306,24 @@ Entries form a tree:
306
306
 
307
307
  ## Context Building
308
308
 
309
- `buildSessionContext()` walks from the current leaf to the root, producing the message list for the LLM:
309
+ `buildContextEntries()` walks from the current leaf to the root, producing the active entry list while honoring compaction:
310
310
 
311
311
  1. Collects all entries on the path
312
- 2. Extracts current model and thinking level settings
313
- 3. If a `CompactionEntry` is on the path:
314
- - Emits the summary first
315
- - Then messages from `firstKeptEntryId` to compaction
316
- - Then messages after compaction
317
- 4. Converts `BranchSummaryEntry` and `CustomMessageEntry` to appropriate message formats
312
+ 2. If a `CompactionEntry` is on the path:
313
+ - Includes the compaction entry first
314
+ - Then entries from `firstKeptEntryId` to compaction
315
+ - Then entries after compaction
316
+ 3. Preserves non-message entries in the selected range so interactive mode can render them
317
+
318
+ `buildSessionContext()` builds on that entry list to produce the message list for the LLM:
319
+
320
+ 1. Extracts current model and thinking level settings from the full path
321
+ 2. Converts selected entries to messages:
322
+ - `message` -> stored `AgentMessage`
323
+ - `compaction` -> `compactionSummary`
324
+ - `branch_summary` -> `branchSummary`
325
+ - `custom_message` -> `CustomMessage`
326
+ - `custom` -> no context message
318
327
 
319
328
  ## Parsing Example
320
329
 
@@ -401,6 +410,7 @@ Key methods for working with sessions programmatically.
401
410
  - `branchWithSummary(entryId, summary, details?, fromHook?)` - Branch with context summary
402
411
 
403
412
  ### Instance Methods - Context & Info
413
+ - `buildContextEntries()` - Get active branch entries with compaction applied
404
414
  - `buildSessionContext()` - Get messages, thinkingLevel, and model for LLM
405
415
  - `getEntries()` - All entries (excluding header)
406
416
  - `getHeader()` - Session header metadata
package/docs/settings.md CHANGED
@@ -31,6 +31,7 @@ Use `/trust` in interactive mode to save a project trust decision for future ses
31
31
  | `defaultModel` | string | - | Default model ID |
32
32
  | `defaultThinkingLevel` | string | - | `"off"`, `"minimal"`, `"low"`, `"medium"`, `"high"`, `"xhigh"` |
33
33
  | `hideThinkingBlock` | boolean | `false` | Hide thinking blocks in output |
34
+ | `showCacheMissNotices` | boolean | `false` | Show transcript notices for significant prompt-cache misses |
34
35
  | `thinkingBudgets` | object | - | Custom token budgets per thinking level |
35
36
 
36
37
  #### thinkingBudgets
package/docs/usage.md CHANGED
@@ -52,7 +52,7 @@ Type `/` in the editor to open command completion. Extensions can register custo
52
52
  | `/export [file]` | Export session to HTML or JSONL |
53
53
  | `/import <file>` | Import and resume a session from a JSONL file |
54
54
  | `/share` | Upload as private GitHub gist with shareable HTML link |
55
- | `/reload` | Reload keybindings, extensions, skills, prompts, and context files |
55
+ | `/reload` | Reload keybindings, extensions, skills, prompts, themes, and context files |
56
56
  | `/hotkeys` | Show all keyboard shortcuts |
57
57
  | `/changelog` | Display version history |
58
58
  | `/quit` | Quit pi |
@@ -112,6 +112,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
112
112
  | Extension | Description |
113
113
  |-----------|-------------|
114
114
  | `message-renderer.ts` | Custom message rendering with colors and expandable details via `registerMessageRenderer` |
115
+ | `entry-renderer.ts` | TUI-only session entry rendering via `appendEntry` and `registerEntryRenderer` |
115
116
  | `event-bus.ts` | Inter-extension communication via `pi.events` |
116
117
 
117
118
  ### Session Metadata
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "0.80.3",
3
+ "version": "0.80.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "0.80.3",
9
+ "version": "0.80.5",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "0.80.3",
4
+ "version": "0.80.5",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "0.80.3",
4
+ "version": "0.80.5",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Custom entry rendering example.
3
+ *
4
+ * Shows how to render durable extension data inside the chat without sending it
5
+ * to the LLM. Custom entries are stored in the session via pi.appendEntry() and
6
+ * rendered in interactive mode via pi.registerEntryRenderer().
7
+ *
8
+ * Usage: /status-card [message]
9
+ */
10
+
11
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
12
+ import { Box, Text } from "@earendil-works/pi-tui";
13
+
14
+ interface StatusCardData {
15
+ message: string;
16
+ timestamp: number;
17
+ }
18
+
19
+ export default function (pi: ExtensionAPI) {
20
+ pi.registerEntryRenderer<StatusCardData>("status-card", (entry, { expanded }, theme) => {
21
+ const data = entry.data ?? { message: "No data", timestamp: Date.now() };
22
+ const box = new Box(1, 1, (text) => theme.bg("customMessageBg", text));
23
+ box.addChild(new Text(`${theme.fg("accent", "[status]")} ${data.message}`, 0, 0));
24
+
25
+ if (expanded) {
26
+ box.addChild(new Text(theme.fg("dim", new Date(data.timestamp).toLocaleString()), 0, 0));
27
+ }
28
+
29
+ return box;
30
+ });
31
+
32
+ pi.registerCommand("status-card", {
33
+ description: "Render a durable status card that is not sent to the LLM",
34
+ handler: async (args) => {
35
+ pi.appendEntry<StatusCardData>("status-card", {
36
+ message: args.trim() || "Status card",
37
+ timestamp: Date.now(),
38
+ });
39
+ },
40
+ });
41
+ }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
- "version": "0.80.3",
3
+ "version": "0.80.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-gondolin",
9
- "version": "0.80.3",
9
+ "version": "0.80.5",
10
10
  "dependencies": {
11
11
  "@earendil-works/gondolin": "0.12.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
3
  "private": true,
4
- "version": "0.80.3",
4
+ "version": "0.80.5",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -47,6 +47,7 @@ export default function question(pi: ExtensionAPI) {
47
47
  label: "Question",
48
48
  description: "Ask the user a question and let them pick from options. Use when you need user input to proceed.",
49
49
  parameters: QuestionParams,
50
+ executionMode: "sequential",
50
51
 
51
52
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
52
53
  if (ctx.mode !== "tui") {
@@ -12,7 +12,7 @@ export default function (pi: ExtensionAPI) {
12
12
  // Command entrypoint for reload.
13
13
  // Treat reload as terminal for this handler.
14
14
  pi.registerCommand("reload-runtime", {
15
- description: "Reload extensions, skills, prompts, and themes",
15
+ description: "Reload extensions, skills, prompts, themes, and context files",
16
16
  handler: async (_args, ctx) => {
17
17
  await ctx.reload();
18
18
  return;
@@ -24,7 +24,7 @@ export default function (pi: ExtensionAPI) {
24
24
  pi.registerTool({
25
25
  name: "reload_runtime",
26
26
  label: "Reload Runtime",
27
- description: "Reload extensions, skills, prompts, and themes",
27
+ description: "Reload extensions, skills, prompts, themes, and context files",
28
28
  parameters: Type.Object({}),
29
29
  async execute() {
30
30
  pi.sendUserMessage("/reload-runtime", { deliverAs: "followUp" });
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
- "version": "1.10.3",
3
+ "version": "1.10.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-sandbox",
9
- "version": "1.10.3",
9
+ "version": "1.10.5",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sandbox-runtime": "^0.0.26"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
3
  "private": true,
4
- "version": "1.10.3",
4
+ "version": "1.10.5",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "0.80.3",
3
+ "version": "0.80.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "0.80.3",
9
+ "version": "0.80.5",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
3
  "private": true,
4
- "version": "0.80.3",
4
+ "version": "0.80.5",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -26,7 +26,7 @@ if (process.env.MY_ANTHROPIC_KEY) {
26
26
  // Model registry with no custom models.json
27
27
  const modelRegistry = ModelRegistry.inMemory(authStorage);
28
28
 
29
- const model = getModel("anthropic", "claude-sonnet-4-20250514");
29
+ const model = getModel("anthropic", "claude-sonnet-4-5");
30
30
  if (!model) throw new Error("Model not found");
31
31
 
32
32
  // In-memory settings with overrides
@@ -116,7 +116,7 @@ await session.prompt("Hello");
116
116
  | `thinkingLevel` | From settings/"off" | off, low, medium, high |
117
117
  | `tools` | `["read", "bash", "edit", "write"]` built-ins | Allowlist tool names across built-in, extension, and custom tools |
118
118
  | `customTools` | `[]` | Additional tool definitions |
119
- | `resourceLoader` | DefaultResourceLoader | Resource loader for extensions, skills, prompts, themes |
119
+ | `resourceLoader` | DefaultResourceLoader | Resource loader for extensions, skills, prompts, themes, and context files |
120
120
  | `sessionManager` | `SessionManager.create(cwd)` | Persistence |
121
121
  | `settingsManager` | `SettingsManager.create(cwd, agentDir)` | Settings overrides |
122
122
 
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-coding-agent",
3
- "version": "0.80.3",
3
+ "version": "0.80.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@earendil-works/pi-coding-agent",
9
- "version": "0.80.3",
9
+ "version": "0.80.5",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@earendil-works/pi-agent-core": "^0.80.3",
13
- "@earendil-works/pi-ai": "^0.80.3",
14
- "@earendil-works/pi-tui": "^0.80.3",
12
+ "@earendil-works/pi-agent-core": "^0.80.5",
13
+ "@earendil-works/pi-ai": "^0.80.5",
14
+ "@earendil-works/pi-tui": "^0.80.5",
15
15
  "@silvia-odwyer/photon-node": "0.3.4",
16
16
  "chalk": "5.6.2",
17
17
  "cross-spawn": "7.0.6",
@@ -474,11 +474,11 @@
474
474
  }
475
475
  },
476
476
  "node_modules/@earendil-works/pi-agent-core": {
477
- "version": "0.80.3",
478
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.80.3.tgz",
477
+ "version": "0.80.5",
478
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.80.5.tgz",
479
479
  "license": "MIT",
480
480
  "dependencies": {
481
- "@earendil-works/pi-ai": "^0.80.3",
481
+ "@earendil-works/pi-ai": "^0.80.5",
482
482
  "ignore": "7.0.5",
483
483
  "typebox": "1.1.38",
484
484
  "yaml": "2.9.0"
@@ -488,8 +488,8 @@
488
488
  }
489
489
  },
490
490
  "node_modules/@earendil-works/pi-ai": {
491
- "version": "0.80.3",
492
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.80.3.tgz",
491
+ "version": "0.80.5",
492
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.80.5.tgz",
493
493
  "license": "MIT",
494
494
  "dependencies": {
495
495
  "@anthropic-ai/sdk": "0.91.1",
@@ -512,8 +512,8 @@
512
512
  }
513
513
  },
514
514
  "node_modules/@earendil-works/pi-tui": {
515
- "version": "0.80.3",
516
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.80.3.tgz",
515
+ "version": "0.80.5",
516
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.80.5.tgz",
517
517
  "license": "MIT",
518
518
  "dependencies": {
519
519
  "get-east-asian-width": "1.6.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-coding-agent",
3
- "version": "0.80.3",
3
+ "version": "0.80.5",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -39,9 +39,9 @@
39
39
  "prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap"
40
40
  },
41
41
  "dependencies": {
42
- "@earendil-works/pi-agent-core": "^0.80.3",
43
- "@earendil-works/pi-ai": "^0.80.3",
44
- "@earendil-works/pi-tui": "^0.80.3",
42
+ "@earendil-works/pi-agent-core": "^0.80.5",
43
+ "@earendil-works/pi-ai": "^0.80.5",
44
+ "@earendil-works/pi-tui": "^0.80.5",
45
45
  "@silvia-odwyer/photon-node": "0.3.4",
46
46
  "chalk": "5.6.2",
47
47
  "cross-spawn": "7.0.6",