@codex-infinity/pi-infinity 0.63.2 → 0.64.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +2 -2
  3. package/dist/core/agent-session.d.ts +5 -0
  4. package/dist/core/agent-session.d.ts.map +1 -1
  5. package/dist/core/agent-session.js +49 -34
  6. package/dist/core/agent-session.js.map +1 -1
  7. package/dist/core/extensions/runner.d.ts +1 -0
  8. package/dist/core/extensions/runner.d.ts.map +1 -1
  9. package/dist/core/extensions/runner.js +4 -0
  10. package/dist/core/extensions/runner.js.map +1 -1
  11. package/dist/core/extensions/types.d.ts +7 -0
  12. package/dist/core/extensions/types.d.ts.map +1 -1
  13. package/dist/core/extensions/types.js.map +1 -1
  14. package/dist/core/keybindings.d.ts +10 -0
  15. package/dist/core/keybindings.d.ts.map +1 -1
  16. package/dist/core/keybindings.js +10 -0
  17. package/dist/core/keybindings.js.map +1 -1
  18. package/dist/core/model-registry.d.ts +3 -1
  19. package/dist/core/model-registry.d.ts.map +1 -1
  20. package/dist/core/model-registry.js +7 -1
  21. package/dist/core/model-registry.js.map +1 -1
  22. package/dist/core/sdk.d.ts +1 -1
  23. package/dist/core/sdk.d.ts.map +1 -1
  24. package/dist/core/sdk.js +2 -2
  25. package/dist/core/sdk.js.map +1 -1
  26. package/dist/core/session-manager.d.ts +3 -0
  27. package/dist/core/session-manager.d.ts.map +1 -1
  28. package/dist/core/session-manager.js +13 -6
  29. package/dist/core/session-manager.js.map +1 -1
  30. package/dist/core/tools/edit-diff.d.ts +3 -3
  31. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  32. package/dist/core/tools/edit-diff.js.map +1 -1
  33. package/dist/core/tools/edit.d.ts +7 -17
  34. package/dist/core/tools/edit.d.ts.map +1 -1
  35. package/dist/core/tools/edit.js +32 -103
  36. package/dist/core/tools/edit.js.map +1 -1
  37. package/dist/core/tools/index.d.ts +5 -10
  38. package/dist/core/tools/index.d.ts.map +1 -1
  39. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  40. package/dist/core/tools/tool-definition-wrapper.js +2 -0
  41. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  42. package/dist/main.d.ts.map +1 -1
  43. package/dist/main.js +1 -1
  44. package/dist/main.js.map +1 -1
  45. package/dist/modes/interactive/components/assistant-message.d.ts +3 -1
  46. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  47. package/dist/modes/interactive/components/assistant-message.js +13 -3
  48. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  49. package/dist/modes/interactive/components/tree-selector.d.ts +4 -2
  50. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  51. package/dist/modes/interactive/components/tree-selector.js +48 -15
  52. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  53. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  54. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  55. package/dist/modes/interactive/interactive-mode.js +24 -3
  56. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  57. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  58. package/dist/modes/rpc/rpc-mode.js +3 -0
  59. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  60. package/docs/compaction.md +4 -2
  61. package/docs/extensions.md +94 -0
  62. package/docs/json.md +5 -2
  63. package/docs/keybindings.md +2 -0
  64. package/docs/rpc.md +21 -7
  65. package/docs/sdk.md +20 -12
  66. package/docs/tree.md +5 -2
  67. package/examples/extensions/README.md +1 -0
  68. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  69. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  70. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  71. package/examples/extensions/custom-provider-qwen-cli/package.json +1 -1
  72. package/examples/extensions/hidden-thinking-label.ts +57 -0
  73. package/examples/extensions/sandbox/index.ts +4 -0
  74. package/examples/extensions/with-deps/package-lock.json +2 -2
  75. package/examples/extensions/with-deps/package.json +1 -1
  76. package/examples/sdk/02-custom-model.ts +1 -1
  77. package/examples/sdk/09-api-keys-and-oauth.ts +3 -3
  78. package/examples/sdk/12-full-control.ts +1 -1
  79. package/examples/sdk/README.md +3 -3
  80. package/package.json +4 -4
package/docs/sdk.md CHANGED
@@ -20,7 +20,7 @@ import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "
20
20
 
21
21
  // Set up credential storage and model registry
22
22
  const authStorage = AuthStorage.create();
23
- const modelRegistry = new ModelRegistry(authStorage);
23
+ const modelRegistry = ModelRegistry.create(authStorage);
24
24
 
25
25
  const { session } = await createAgentSession({
26
26
  sessionManager: SessionManager.inMemory(),
@@ -171,10 +171,15 @@ const state = session.agent.state;
171
171
  // state.model: Model - current model
172
172
  // state.thinkingLevel: ThinkingLevel - current thinking level
173
173
  // state.systemPrompt: string - system prompt
174
- // state.tools: Tool[] - available tools
174
+ // state.tools: AgentTool[] - available tools
175
+ // state.streamingMessage?: AgentMessage - current partial assistant message
176
+ // state.errorMessage?: string - latest assistant error
175
177
 
176
- // Replace messages (useful for branching, restoration)
177
- session.agent.replaceMessages(messages);
178
+ // Replace messages (useful for branching or restoration)
179
+ session.agent.state.messages = messages; // copies the top-level array
180
+
181
+ // Replace tools
182
+ session.agent.state.tools = tools; // copies the top-level array
178
183
 
179
184
  // Wait for agent to finish processing
180
185
  await session.agent.waitForIdle();
@@ -232,9 +237,12 @@ session.subscribe((event) => {
232
237
  // event.toolResults: tool results from this turn
233
238
  break;
234
239
 
235
- // Session events (auto-compaction, retry)
236
- case "auto_compaction_start":
237
- case "auto_compaction_end":
240
+ // Session events (queue, compaction, retry)
241
+ case "queue_update":
242
+ console.log(event.steering, event.followUp);
243
+ break;
244
+ case "compaction_start":
245
+ case "compaction_end":
238
246
  case "auto_retry_start":
239
247
  case "auto_retry_end":
240
248
  break;
@@ -286,7 +294,7 @@ import { getModel } from "@mariozechner/pi-ai";
286
294
  import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
287
295
 
288
296
  const authStorage = AuthStorage.create();
289
- const modelRegistry = new ModelRegistry(authStorage);
297
+ const modelRegistry = ModelRegistry.create(authStorage);
290
298
 
291
299
  // Find specific built-in model (doesn't check if API key exists)
292
300
  const opus = getModel("anthropic", "claude-opus-4-5");
@@ -334,7 +342,7 @@ import { AuthStorage, ModelRegistry } from "@mariozechner/pi-coding-agent";
334
342
 
335
343
  // Default: uses ~/.pi/agent/auth.json and ~/.pi/agent/models.json
336
344
  const authStorage = AuthStorage.create();
337
- const modelRegistry = new ModelRegistry(authStorage);
345
+ const modelRegistry = ModelRegistry.create(authStorage);
338
346
 
339
347
  const { session } = await createAgentSession({
340
348
  sessionManager: SessionManager.inMemory(),
@@ -347,7 +355,7 @@ authStorage.setRuntimeApiKey("anthropic", "sk-my-temp-key");
347
355
 
348
356
  // Custom auth storage location
349
357
  const customAuth = AuthStorage.create("/my/app/auth.json");
350
- const customRegistry = new ModelRegistry(customAuth, "/my/app/models.json");
358
+ const customRegistry = ModelRegistry.create(customAuth, "/my/app/models.json");
351
359
 
352
360
  const { session } = await createAgentSession({
353
361
  sessionManager: SessionManager.inMemory(),
@@ -356,7 +364,7 @@ const { session } = await createAgentSession({
356
364
  });
357
365
 
358
366
  // No custom models.json (built-in models only)
359
- const simpleRegistry = new ModelRegistry(authStorage);
367
+ const simpleRegistry = ModelRegistry.inMemory(authStorage);
360
368
  ```
361
369
 
362
370
  > See [examples/sdk/09-api-keys-and-oauth.ts](../examples/sdk/09-api-keys-and-oauth.ts)
@@ -785,7 +793,7 @@ if (process.env.MY_KEY) {
785
793
  }
786
794
 
787
795
  // Model registry (no custom models.json)
788
- const modelRegistry = new ModelRegistry(authStorage);
796
+ const modelRegistry = ModelRegistry.create(authStorage);
789
797
 
790
798
  // Inline tool
791
799
  const statusTool: ToolDefinition = {
package/docs/tree.md CHANGED
@@ -35,6 +35,8 @@ Sessions are stored as trees where each entry has an `id` and `parentId`. The "l
35
35
  | ↑/↓ | Navigate (depth-first order) |
36
36
  | ←/→ | Page up/down |
37
37
  | Ctrl+←/Ctrl+→ or Alt+←/Alt+→ | Fold/unfold and jump between branch segments |
38
+ | Shift+L | Set or clear a label on the selected node |
39
+ | Shift+T | Toggle label timestamps |
38
40
  | Enter | Select node |
39
41
  | Escape/Ctrl+C | Cancel |
40
42
  | Ctrl+U | Toggle: user messages only |
@@ -49,11 +51,12 @@ Sessions are stored as trees where each entry has an `id` and `parentId`. The "l
49
51
  - Height: half terminal height
50
52
  - Current leaf marked with `← active`
51
53
  - Labels shown inline: `[label-name]`
54
+ - `Shift+T` shows the latest label-change timestamp next to labeled nodes
52
55
  - Foldable branch starts show `⊟` in the connector. Folded branches show `⊞`
53
56
  - Active path marker `•` appears after the fold indicator when applicable
54
57
  - Search and filter changes reset all folds
55
58
  - Default filter hides `label` and `custom` entries (shown in Ctrl+O mode)
56
- - Children sorted by timestamp (oldest first)
59
+ - At each branch point, the active subtree is shown first; other sibling branches are sorted by timestamp (oldest first)
57
60
 
58
61
  ## Selection Behavior
59
62
 
@@ -141,7 +144,7 @@ Flow:
141
144
  4. Fire `session_before_tree` event (hook can cancel or provide summary)
142
145
  5. Run default summarizer if needed
143
146
  6. Switch leaf via `branch()` or `branchWithSummary()`
144
- 7. Update agent: `agent.replaceMessages(sessionManager.buildSessionContext().messages)`
147
+ 7. Update agent: `agent.state.messages = sessionManager.buildSessionContext().messages`
145
148
  8. Fire `session_tree` event
146
149
  9. Notify custom tools via session event
147
150
  10. Return result with `editorText` if user message was selected
@@ -52,6 +52,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
52
52
  | `qna.ts` | Extracts questions from last response into editor via `ctx.ui.setEditorText()` |
53
53
  | `status-line.ts` | Shows turn progress in footer via `ctx.ui.setStatus()` with themed colors |
54
54
  | `widget-placement.ts` | Shows widgets above and below the editor via `ctx.ui.setWidget()` placement |
55
+ | `hidden-thinking-label.ts` | Customizes the collapsed thinking label via `ctx.ui.setHiddenThinkingLabel()` |
55
56
  | `model-status.ts` | Shows model changes in status bar via `model_select` hook |
56
57
  | `snake.ts` | Snake game with custom UI, keyboard handling, and session persistence |
57
58
  | `send-user-message.ts` | Demonstrates `pi.sendUserMessage()` for sending user messages from extensions |
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "1.14.2",
3
+ "version": "1.15.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "1.14.2",
9
+ "version": "1.15.1",
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": "1.14.2",
4
+ "version": "1.15.1",
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": "1.14.2",
4
+ "version": "1.15.1",
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-qwen-cli",
3
3
  "private": true,
4
- "version": "1.13.2",
4
+ "version": "1.14.1",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Hidden Thinking Label Extension
3
+ *
4
+ * Demonstrates `ctx.ui.setHiddenThinkingLabel()` for customizing the label shown
5
+ * when thinking blocks are hidden.
6
+ *
7
+ * Usage:
8
+ * pi --extension examples/extensions/hidden-thinking-label.ts
9
+ *
10
+ * Test:
11
+ * 1. Load this extension
12
+ * 2. Hide thinking blocks with Ctrl+T
13
+ * 3. Ask for something that produces reasoning output
14
+ * 4. The collapsed thinking block label will show the custom text
15
+ *
16
+ * Commands:
17
+ * /thinking-label <text> Set a custom hidden thinking label
18
+ * /thinking-label Reset to the default label
19
+ */
20
+
21
+ import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
22
+
23
+ const DEFAULT_LABEL = "Pondering...";
24
+
25
+ export default function (pi: ExtensionAPI) {
26
+ let label = DEFAULT_LABEL;
27
+
28
+ const applyLabel = (ctx: ExtensionContext) => {
29
+ ctx.ui.setHiddenThinkingLabel(label);
30
+ };
31
+
32
+ pi.on("session_start", async (_event, ctx) => {
33
+ applyLabel(ctx);
34
+ });
35
+
36
+ pi.on("session_switch", async (_event, ctx) => {
37
+ applyLabel(ctx);
38
+ });
39
+
40
+ pi.registerCommand("thinking-label", {
41
+ description: "Set the hidden thinking label. Use without args to reset.",
42
+ handler: async (args, ctx) => {
43
+ const nextLabel = args.trim();
44
+
45
+ if (!nextLabel) {
46
+ label = DEFAULT_LABEL;
47
+ ctx.ui.setHiddenThinkingLabel();
48
+ ctx.ui.notify(`Hidden thinking label reset to: ${DEFAULT_LABEL}`);
49
+ return;
50
+ }
51
+
52
+ label = nextLabel;
53
+ ctx.ui.setHiddenThinkingLabel(label);
54
+ ctx.ui.notify(`Hidden thinking label set to: ${label}`);
55
+ },
56
+ });
57
+ }
@@ -5,6 +5,10 @@
5
5
  * restrictions on bash commands at the OS level (sandbox-exec on macOS,
6
6
  * bubblewrap on Linux).
7
7
  *
8
+ * Note: this example intentionally overrides the built-in `bash` tool to show
9
+ * how built-in tools can be replaced. Alternatively, you could sandbox `bash`
10
+ * via `tool_call` input mutation without replacing the tool.
11
+ *
8
12
  * Config files (merged, project takes precedence):
9
13
  * - ~/.pi/agent/sandbox.json (global)
10
14
  * - <cwd>/.pi/sandbox.json (project-local)
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "1.27.2",
3
+ "version": "1.28.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "1.27.2",
9
+ "version": "1.28.1",
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": "1.27.2",
4
+ "version": "1.28.1",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -9,7 +9,7 @@ import { AuthStorage, createAgentSession, ModelRegistry } from "@mariozechner/pi
9
9
 
10
10
  // Set up auth storage and model registry
11
11
  const authStorage = AuthStorage.create();
12
- const modelRegistry = new ModelRegistry(authStorage);
12
+ const modelRegistry = ModelRegistry.create(authStorage);
13
13
 
14
14
  // Option 1: Find a specific built-in model by provider/id
15
15
  const opus = getModel("anthropic", "claude-opus-4-5");
@@ -9,7 +9,7 @@ import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "
9
9
  // Default: AuthStorage uses ~/.pi/agent/auth.json
10
10
  // ModelRegistry loads built-in + custom models from ~/.pi/agent/models.json
11
11
  const authStorage = AuthStorage.create();
12
- const modelRegistry = new ModelRegistry(authStorage);
12
+ const modelRegistry = ModelRegistry.create(authStorage);
13
13
 
14
14
  await createAgentSession({
15
15
  sessionManager: SessionManager.inMemory(),
@@ -20,7 +20,7 @@ console.log("Session with default auth storage and model registry");
20
20
 
21
21
  // Custom auth storage location
22
22
  const customAuthStorage = AuthStorage.create("/tmp/my-app/auth.json");
23
- const customModelRegistry = new ModelRegistry(customAuthStorage, "/tmp/my-app/models.json");
23
+ const customModelRegistry = ModelRegistry.create(customAuthStorage, "/tmp/my-app/models.json");
24
24
 
25
25
  await createAgentSession({
26
26
  sessionManager: SessionManager.inMemory(),
@@ -39,7 +39,7 @@ await createAgentSession({
39
39
  console.log("Session with runtime API key override");
40
40
 
41
41
  // No models.json - only built-in models
42
- const simpleRegistry = new ModelRegistry(authStorage); // null = no models.json
42
+ const simpleRegistry = ModelRegistry.inMemory(authStorage);
43
43
  await createAgentSession({
44
44
  sessionManager: SessionManager.inMemory(),
45
45
  authStorage,
@@ -30,7 +30,7 @@ if (process.env.MY_ANTHROPIC_KEY) {
30
30
  }
31
31
 
32
32
  // Model registry with no custom models.json
33
- const modelRegistry = new ModelRegistry(authStorage);
33
+ const modelRegistry = ModelRegistry.inMemory(authStorage);
34
34
 
35
35
  const model = getModel("anthropic", "claude-sonnet-4-20250514");
36
36
  if (!model) throw new Error("Model not found");
@@ -44,7 +44,7 @@ import {
44
44
 
45
45
  // Auth and models setup
46
46
  const authStorage = AuthStorage.create();
47
- const modelRegistry = new ModelRegistry(authStorage);
47
+ const modelRegistry = ModelRegistry.create(authStorage);
48
48
 
49
49
  // Minimal
50
50
  const { session } = await createAgentSession({ authStorage, modelRegistry });
@@ -73,7 +73,7 @@ const { session } = await createAgentSession({
73
73
  // Full control
74
74
  const customAuth = AuthStorage.create("/my/app/auth.json");
75
75
  customAuth.setRuntimeApiKey("anthropic", process.env.MY_KEY!);
76
- const customRegistry = new ModelRegistry(customAuth);
76
+ const customRegistry = ModelRegistry.create(customAuth);
77
77
 
78
78
  const resourceLoader = new DefaultResourceLoader({
79
79
  systemPromptOverride: () => "You are helpful.",
@@ -109,7 +109,7 @@ await session.prompt("Hello");
109
109
  | Option | Default | Description |
110
110
  |--------|---------|-------------|
111
111
  | `authStorage` | `AuthStorage.create()` | Credential storage |
112
- | `modelRegistry` | `new ModelRegistry(authStorage)` | Model registry |
112
+ | `modelRegistry` | `ModelRegistry.create(authStorage)` | Model registry |
113
113
  | `cwd` | `process.cwd()` | Working directory |
114
114
  | `agentDir` | `~/.pi/agent` | Config directory |
115
115
  | `model` | From settings/first available | Model to use |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codex-infinity/pi-infinity",
3
- "version": "0.63.2",
3
+ "version": "0.64.1",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -40,9 +40,9 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@mariozechner/jiti": "^2.6.2",
43
- "@mariozechner/pi-agent-core": "^0.63.2",
44
- "@mariozechner/pi-ai": "^0.63.2",
45
- "@mariozechner/pi-tui": "^0.63.2",
43
+ "@mariozechner/pi-agent-core": "^0.64.1",
44
+ "@mariozechner/pi-ai": "^0.64.1",
45
+ "@mariozechner/pi-tui": "^0.64.1",
46
46
  "@silvia-odwyer/photon-node": "^0.3.4",
47
47
  "ajv": "^8.17.1",
48
48
  "chalk": "^5.5.0",