@astralyn/pi 0.82.7 → 0.83.0

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 (127) hide show
  1. package/CHANGELOG.md +34 -5099
  2. package/README.md +12 -111
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +9 -2
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/cli/credential-print.d.ts +23 -0
  7. package/dist/cli/credential-print.d.ts.map +1 -0
  8. package/dist/cli/credential-print.js +116 -0
  9. package/dist/cli/credential-print.js.map +1 -0
  10. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  11. package/dist/core/agent-session-runtime.js +3 -0
  12. package/dist/core/agent-session-runtime.js.map +1 -1
  13. package/dist/core/agent-session.d.ts +1 -1
  14. package/dist/core/agent-session.d.ts.map +1 -1
  15. package/dist/core/agent-session.js +13 -6
  16. package/dist/core/agent-session.js.map +1 -1
  17. package/dist/core/extensions/runner.d.ts +1 -0
  18. package/dist/core/extensions/runner.d.ts.map +1 -1
  19. package/dist/core/extensions/runner.js +7 -0
  20. package/dist/core/extensions/runner.js.map +1 -1
  21. package/dist/core/extensions/types.d.ts +7 -0
  22. package/dist/core/extensions/types.d.ts.map +1 -1
  23. package/dist/core/extensions/types.js.map +1 -1
  24. package/dist/core/footer-data-provider.d.ts +10 -0
  25. package/dist/core/footer-data-provider.d.ts.map +1 -1
  26. package/dist/core/footer-data-provider.js +1 -1
  27. package/dist/core/footer-data-provider.js.map +1 -1
  28. package/dist/core/model-runtime.d.ts +2 -0
  29. package/dist/core/model-runtime.d.ts.map +1 -1
  30. package/dist/core/model-runtime.js.map +1 -1
  31. package/dist/core/package-manager.d.ts.map +1 -1
  32. package/dist/core/package-manager.js +13 -6
  33. package/dist/core/package-manager.js.map +1 -1
  34. package/dist/core/resource-loader.d.ts +15 -0
  35. package/dist/core/resource-loader.d.ts.map +1 -1
  36. package/dist/core/resource-loader.js +70 -9
  37. package/dist/core/resource-loader.js.map +1 -1
  38. package/dist/core/tools/find.d.ts.map +1 -1
  39. package/dist/core/tools/find.js +34 -4
  40. package/dist/core/tools/find.js.map +1 -1
  41. package/dist/core/trust-manager.d.ts.map +1 -1
  42. package/dist/core/trust-manager.js +48 -9
  43. package/dist/core/trust-manager.js.map +1 -1
  44. package/dist/extensions/index.d.ts.map +1 -1
  45. package/dist/extensions/index.js +0 -2
  46. package/dist/extensions/index.js.map +1 -1
  47. package/dist/extensions/llama/provider.d.ts.map +1 -1
  48. package/dist/extensions/llama/provider.js +1 -1
  49. package/dist/extensions/llama/provider.js.map +1 -1
  50. package/dist/main.d.ts.map +1 -1
  51. package/dist/main.js +43 -0
  52. package/dist/main.js.map +1 -1
  53. package/dist/modes/interactive/components/extension-selector.d.ts +1 -1
  54. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  55. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  56. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  57. package/dist/modes/interactive/components/model-selector.js +4 -1
  58. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  59. package/dist/modes/interactive/external-editor.d.ts.map +1 -1
  60. package/dist/modes/interactive/external-editor.js +40 -3
  61. package/dist/modes/interactive/external-editor.js.map +1 -1
  62. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  63. package/dist/modes/interactive/interactive-mode.js +20 -6
  64. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  65. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  66. package/dist/modes/rpc/rpc-mode.js +13 -0
  67. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  68. package/dist/utils/paths.d.ts +2 -3
  69. package/dist/utils/paths.d.ts.map +1 -1
  70. package/dist/utils/paths.js +2 -3
  71. package/dist/utils/paths.js.map +1 -1
  72. package/docs/bundled/README.md +13 -16
  73. package/docs/bundled/themes.md +1 -1
  74. package/docs/compaction.md +25 -30
  75. package/docs/custom-provider.md +298 -583
  76. package/docs/docs.json +0 -8
  77. package/docs/extensions.md +112 -116
  78. package/docs/index.md +18 -74
  79. package/docs/json.md +20 -14
  80. package/docs/models.md +193 -151
  81. package/docs/providers.md +2 -1
  82. package/docs/quickstart.md +3 -3
  83. package/docs/rpc.md +165 -123
  84. package/docs/sdk.md +119 -178
  85. package/docs/security.md +1 -1
  86. package/docs/session-format.md +139 -119
  87. package/docs/skills.md +0 -1
  88. package/docs/themes.md +2 -2
  89. package/docs/tui.md +411 -549
  90. package/docs/usage.md +3 -11
  91. package/examples/README.md +6 -1
  92. package/examples/extensions/README.md +13 -33
  93. package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
  94. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  95. package/examples/extensions/truncated-tool.ts +2 -2
  96. package/examples/sdk/12-full-control.ts +2 -0
  97. package/npm-shrinkwrap.json +21 -21
  98. package/package.json +5 -5
  99. package/dist/extensions/plan/constants.d.ts +0 -68
  100. package/dist/extensions/plan/constants.d.ts.map +0 -1
  101. package/dist/extensions/plan/constants.js +0 -100
  102. package/dist/extensions/plan/constants.js.map +0 -1
  103. package/dist/extensions/plan/index.d.ts +0 -30
  104. package/dist/extensions/plan/index.d.ts.map +0 -1
  105. package/dist/extensions/plan/index.js +0 -429
  106. package/dist/extensions/plan/index.js.map +0 -1
  107. package/dist/extensions/plan/schema.d.ts +0 -20
  108. package/dist/extensions/plan/schema.d.ts.map +0 -1
  109. package/dist/extensions/plan/schema.js +0 -13
  110. package/dist/extensions/plan/schema.js.map +0 -1
  111. package/dist/extensions/plan/state.d.ts +0 -38
  112. package/dist/extensions/plan/state.d.ts.map +0 -1
  113. package/dist/extensions/plan/state.js +0 -96
  114. package/dist/extensions/plan/state.js.map +0 -1
  115. package/dist/extensions/plan/storage.d.ts +0 -26
  116. package/dist/extensions/plan/storage.d.ts.map +0 -1
  117. package/dist/extensions/plan/storage.js +0 -83
  118. package/dist/extensions/plan/storage.js.map +0 -1
  119. package/dist/extensions/plan/view.d.ts +0 -44
  120. package/dist/extensions/plan/view.d.ts.map +0 -1
  121. package/dist/extensions/plan/view.js +0 -149
  122. package/dist/extensions/plan/view.js.map +0 -1
  123. package/docs/bundled/extensions/README.md +0 -19
  124. package/docs/bundled/extensions/plan.md +0 -34
  125. package/examples/extensions/plan-mode/README.md +0 -66
  126. package/examples/extensions/plan-mode/index.ts +0 -390
  127. package/examples/extensions/plan-mode/utils.ts +0 -168
package/docs/usage.md CHANGED
@@ -85,15 +85,7 @@ pi --session <path|id> # Use a specific session file or session ID
85
85
  pi --fork <path|id> # Fork a session into a new session file
86
86
  ```
87
87
 
88
- Useful session commands:
89
-
90
- - `/session` shows the current session file and ID.
91
- - `/tree` navigates the in-file session tree and can summarize abandoned branches.
92
- - `/fork` creates a new session from an earlier user message.
93
- - `/clone` duplicates the current active branch into a new session file.
94
- - `/compact` summarizes older messages to free context.
95
-
96
- See [Sessions](sessions.md) and [Compaction](compaction.md) for details.
88
+ See [Sessions](sessions.md) and [Compaction](compaction.md) for session commands and behavior.
97
89
 
98
90
  ## Context Files
99
91
 
@@ -159,7 +151,7 @@ pi list # List installed packages
159
151
  pi config # Enable/disable package resources
160
152
  ```
161
153
 
162
- These commands manage pi packages and `pi update` can update the pi CLI installation. To uninstall pi itself, see [Quickstart](quickstart.md#uninstall). `pi config` and project package commands accept `--approve`/`--no-approve` to trust or ignore project-local settings for one command. `pi update` never prompts for project trust.
154
+ To uninstall pi itself, see [Quickstart](quickstart.md#uninstall). `pi config` and project package commands accept `--approve`/`--no-approve` to trust or ignore project-local settings for one command. `pi update` never prompts for project trust.
163
155
 
164
156
  See [Pi Packages](packages.md) for package sources and security notes.
165
157
 
@@ -293,6 +285,6 @@ pi --exclude-tools ask_question
293
285
 
294
286
  Pi keeps the core small and pushes workflow-specific behavior into extensions, skills, prompt templates, and packages.
295
287
 
296
- This distribution ships selected workflows as hidden built-in extensions, including plan mode, sub-agents, and to-dos. It does not include built-in MCP, permission popups, or background bash. You can build or install additional workflows as extensions or packages, or use external tools such as containers and tmux.
288
+ This distribution ships selected workflows as hidden built-in extensions, including sub-agents and to-dos. It does not include built-in MCP, permission popups, or background bash. You can build or install additional workflows as extensions or packages, or use external tools such as containers and tmux.
297
289
 
298
290
  For the full rationale, read the [blog post](https://mariozechner.at/posts/2025-11-30-pi-coding-agent/).
@@ -1,6 +1,11 @@
1
1
  # Examples
2
2
 
3
- Example code for pi-coding-agent SDK and extensions.
3
+ Example code for the `@astralyn/pi` SDK and extensions.
4
+
5
+ ## Standalone
6
+
7
+ ### [rpc-extension-ui.ts](rpc-extension-ui.ts)
8
+ A lightweight RPC chat client that handles extension UI requests; pair it with [the RPC demo extension](extensions/rpc-demo.ts).
4
9
 
5
10
  ## Directories
6
11
 
@@ -1,6 +1,6 @@
1
1
  # Extension Examples
2
2
 
3
- Example extensions for pi-coding-agent.
3
+ Example extensions for `@astralyn/pi`.
4
4
 
5
5
  ## Usage
6
6
 
@@ -35,6 +35,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
35
35
  | `question.ts` | Demonstrates `ctx.ui.select()` for asking the user questions with custom UI |
36
36
  | `questionnaire.ts` | Multi-question input with tab bar navigation between questions |
37
37
  | `tool-override.ts` | Override built-in tools (e.g., add logging/access control to `read`) |
38
+ | `bash-spawn-hook.ts` | Wraps bash to adjust the command, cwd, and environment before execution |
38
39
  | `dynamic-tools.ts` | Register tools after startup (`session_start`) and at runtime via command, with prompt snippets and tool-specific prompt guidelines |
39
40
  | `kimi-deferred-tools.ts` | Search for and progressively activate tools for Kimi's deferred-tool loading protocol |
40
41
  | `structured-output.ts` | Final structured-output tool that returns `terminate: true` so the agent can end on the tool call |
@@ -48,17 +49,20 @@ cp permission-gate.ts ~/.pi/agent/extensions/
48
49
  | Extension | Description |
49
50
  |-----------|-------------|
50
51
  | `preset.ts` | Named presets for model, thinking level, tools, and instructions via `--preset` flag and `/preset` command |
51
- | `plan-mode/` | Claude Code-style plan mode for read-only exploration with `/plan` command and step tracking |
52
52
  | `tools.ts` | Interactive `/tools` command to enable/disable tools with session persistence |
53
53
  | `handoff.ts` | Transfer context to a new focused session via `/handoff <goal>` |
54
+ | `commands.ts` | Lists available slash commands, optionally filtered by source |
54
55
  | `qna.ts` | Extracts questions from last response into editor via `ctx.ui.setEditorText()` |
55
56
  | `status-line.ts` | Shows turn progress in footer via `ctx.ui.setStatus()` with themed colors |
57
+ | `border-status-editor.ts` | Custom editor borders with working state, model, context, cwd, and Git branch |
56
58
  | `github-issue-autocomplete.ts` | Adds `#1234` issue completions by stacking a custom autocomplete provider that preloads open issues from `gh issue list` |
57
59
  | `widget-placement.ts` | Shows widgets above and below the editor via `ctx.ui.setWidget()` placement |
58
60
  | `hidden-thinking-label.ts` | Customizes the collapsed thinking label via `ctx.ui.setHiddenThinkingLabel()` |
59
61
  | `working-indicator.ts` | Customizes the streaming working indicator via `ctx.ui.setWorkingIndicator()` |
62
+ | `working-message-test.ts` | Tests custom working-message and indicator persistence across loader recreation |
60
63
  | `model-status.ts` | Shows model changes in status bar via `model_select` hook |
61
64
  | `snake.ts` | Snake game with custom UI, keyboard handling, and session persistence |
65
+ | `space-invaders.ts` | Space Invaders game with keyboard controls and session persistence |
62
66
  | `tic-tac-toe.ts` | Tic-tac-toe vs the agent with `executionMode: "sequential"` tools to prevent race conditions on shared cursor state |
63
67
  | `send-user-message.ts` | Demonstrates `pi.sendUserMessage()` for sending user messages from extensions |
64
68
  | `timed-confirm.ts` | Demonstrates AbortSignal for auto-dismissing `ctx.ui.confirm()` and `ctx.ui.select()` dialogs |
@@ -77,6 +81,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
77
81
  | `reload-runtime.ts` | Adds `/reload-runtime` and `reload_runtime` tool showing safe reload flow |
78
82
  | `interactive-shell.ts` | Run interactive commands (vim, htop) with full terminal via `user_bash` hook |
79
83
  | `inline-bash.ts` | Expands `!{command}` patterns in prompts via `input` event transformation |
84
+ | `input-transform.ts` | Transforms or handles typed input through the `input` event |
80
85
  | `input-transform-streaming.ts` | Skips expensive input preprocessing for mid-stream steering via `streamingBehavior` |
81
86
 
82
87
  ### Git Integration
@@ -84,6 +89,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
84
89
  | Extension | Description |
85
90
  |-----------|-------------|
86
91
  | `git-checkpoint.ts` | Creates git stash checkpoints at each turn for code restoration on fork |
92
+ | `git-merge-and-resolve.ts` | Fetches and merges the upstream branch after turns, then sends conflicts for resolution |
87
93
  | `auto-commit-on-exit.ts` | Auto-commits on exit using last assistant message for commit message |
88
94
 
89
95
  ### System Prompt & Compaction
@@ -91,7 +97,9 @@ cp permission-gate.ts ~/.pi/agent/extensions/
91
97
  | Extension | Description |
92
98
  |-----------|-------------|
93
99
  | `pirate.ts` | Demonstrates `systemPromptAppend` to dynamically modify system prompt |
100
+ | `prompt-customizer.ts` | Adds context-aware guidance based on active tools and skills |
94
101
  | `claude-rules.ts` | Scans `.claude/rules/` folder and lists rules in system prompt |
102
+ | `system-prompt-header.ts` | Shows the effective system-prompt length in the status area |
95
103
  | `custom-compaction.ts` | Custom compaction that summarizes entire conversation |
96
104
  | `trigger-compact.ts` | Triggers compaction when context usage exceeds 100k tokens and adds `/trigger-compact` command |
97
105
 
@@ -128,6 +136,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
128
136
  |-----------|-------------|
129
137
  | `custom-provider-anthropic/` | Custom Anthropic provider with OAuth support and custom streaming implementation |
130
138
  | `custom-provider-gitlab-duo/` | GitLab Duo provider using pi-ai's built-in Anthropic/OpenAI streaming via proxy |
139
+ | `provider-payload.ts` | Logs provider request payloads and response headers to `.pi/provider-payload.log` |
131
140
 
132
141
  ### External Dependencies
133
142
 
@@ -142,39 +151,10 @@ See [docs/extensions.md](../../docs/extensions.md) for full documentation.
142
151
 
143
152
  ```typescript
144
153
  import type { ExtensionAPI } from "@astralyn/pi";
145
- import { Type } from "typebox";
146
154
 
147
155
  export default function (pi: ExtensionAPI) {
148
- // Subscribe to lifecycle events
149
- pi.on("tool_call", async (event, ctx) => {
150
- if (event.toolName === "bash" && event.input.command?.includes("rm -rf")) {
151
- const ok = await ctx.ui.confirm("Dangerous!", "Allow rm -rf?");
152
- if (!ok) return { block: true, reason: "Blocked by user" };
153
- }
154
- });
155
-
156
- // Register custom tools
157
- pi.registerTool({
158
- name: "greet",
159
- label: "Greeting",
160
- description: "Generate a greeting",
161
- parameters: Type.Object({
162
- name: Type.String({ description: "Name to greet" }),
163
- }),
164
- async execute(toolCallId, params, signal, onUpdate, ctx) {
165
- return {
166
- content: [{ type: "text", text: `Hello, ${params.name}!` }],
167
- details: {},
168
- };
169
- },
170
- });
171
-
172
- // Register commands
173
- pi.registerCommand("hello", {
174
- description: "Say hello",
175
- handler: async (args, ctx) => {
176
- ctx.ui.notify("Hello!", "info");
177
- },
156
+ pi.on("session_start", (_event, ctx) => {
157
+ ctx.ui.notify("Extension loaded!", "info");
178
158
  });
179
159
  }
180
160
  ```
@@ -153,7 +153,7 @@ async function refreshAnthropicToken(credentials: OAuthCredentials): Promise<OAu
153
153
  }
154
154
 
155
155
  // =============================================================================
156
- // Streaming Implementation (simplified from packages/ai/src/api/anthropic-messages.ts)
156
+ // Streaming Implementation Using Public @earendil-works/pi-ai Exports
157
157
  // =============================================================================
158
158
 
159
159
  // Claude Code tool names for OAuth stealth mode
@@ -353,7 +353,7 @@ function streamCustomAnthropic(
353
353
  totalTokens: 0,
354
354
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
355
355
  },
356
- stopReason: "stop",
356
+ stopReason: "pending",
357
357
  timestamp: Date.now(),
358
358
  };
359
359
 
@@ -546,8 +546,14 @@ function streamCustomAnthropic(
546
546
  if (options?.signal?.aborted) {
547
547
  throw new Error("Request was aborted");
548
548
  }
549
+ if (output.stopReason === "pending") {
550
+ throw new Error("Anthropic stream ended without a stop reason");
551
+ }
552
+ if (output.stopReason === "error" || output.stopReason === "aborted") {
553
+ throw new Error(output.errorMessage || "An unknown error occurred");
554
+ }
549
555
 
550
- stream.push({ type: "done", reason: output.stopReason as "stop" | "length" | "toolUse", message: output });
556
+ stream.push({ type: "done", reason: output.stopReason, message: output });
551
557
  stream.end();
552
558
  } catch (error) {
553
559
  for (const block of output.content) delete (block as any).index;
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://raw.githubusercontent.com/ming-kang/pi/main/src/modes/interactive/theme/theme-schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3
3
  "name": "dynamic-resources",
4
4
  "vars": {
5
5
  "cyan": "#00d7ff",
@@ -10,8 +10,8 @@
10
10
  * 3. Inform the LLM where to find the complete output
11
11
  * 4. Custom rendering of tool calls and results
12
12
  *
13
- * The `rg` tool here wraps ripgrep with proper truncation. Compare this to the
14
- * built-in `grep` tool in src/core/tools/grep.ts for a more complete implementation.
13
+ * The `rg` tool here wraps ripgrep with proper truncation. For Pi's built-in
14
+ * implementation, use the published `createGrepTool` export from `@astralyn/pi`.
15
15
  */
16
16
 
17
17
  import { mkdtemp, writeFile } from "node:fs/promises";
@@ -41,7 +41,9 @@ const resourceLoader: ResourceLoader = {
41
41
  getAgentsFiles: () => ({ agentsFiles: [] }),
42
42
  getSystemPrompt: () => `You are a minimal assistant.
43
43
  Available: read, bash. Be concise.`,
44
+ getSystemPromptSource: () => undefined,
44
45
  getAppendSystemPrompt: () => [],
46
+ getAppendSystemPromptSources: () => [],
45
47
  extendResources: () => {},
46
48
  reload: async () => {},
47
49
  };
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@astralyn/pi",
3
- "version": "0.82.7",
3
+ "version": "0.83.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@astralyn/pi",
9
- "version": "0.82.7",
9
+ "version": "0.83.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@earendil-works/pi-agent-core": "0.82.1",
13
- "@earendil-works/pi-ai": "0.82.1",
14
- "@earendil-works/pi-tui": "0.82.1",
12
+ "@earendil-works/pi-agent-core": "0.83.0",
13
+ "@earendil-works/pi-ai": "0.83.0",
14
+ "@earendil-works/pi-tui": "0.83.0",
15
15
  "@silvia-odwyer/photon-node": "0.3.4",
16
16
  "chalk": "5.6.2",
17
17
  "cross-spawn": "7.0.6",
@@ -24,7 +24,7 @@
24
24
  "minimatch": "10.2.5",
25
25
  "proper-lockfile": "4.1.2",
26
26
  "semver": "7.8.0",
27
- "typebox": "1.1.38",
27
+ "typebox": "1.3.7",
28
28
  "undici": "8.5.0",
29
29
  "yaml": "2.9.0"
30
30
  },
@@ -716,15 +716,15 @@
716
716
  }
717
717
  },
718
718
  "node_modules/@earendil-works/pi-agent-core": {
719
- "version": "0.82.1",
720
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.82.1.tgz",
721
- "integrity": "sha512-Z3kloziJIE2dmrisRckZX8zDca/gIv9/YdFAzeoqpHiLV2wsni6bL4hInNSjVKLbqT+4kqLIkph2JQLKvSepjg==",
719
+ "version": "0.83.0",
720
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.83.0.tgz",
721
+ "integrity": "sha512-RorGp9OH5l3ElpuC5a5ZQ2eWcchZGXflXRzVGkV99y3y6tT+LLNyxoYIdVKvTKWEObwhExeQbTH0fI2tE4iX4g==",
722
722
  "license": "MIT",
723
723
  "dependencies": {
724
- "@earendil-works/pi-ai": "^0.82.1",
724
+ "@earendil-works/pi-ai": "^0.83.0",
725
725
  "diff": "8.0.4",
726
726
  "ignore": "7.0.5",
727
- "typebox": "1.1.38",
727
+ "typebox": "1.3.7",
728
728
  "yaml": "2.9.0"
729
729
  },
730
730
  "engines": {
@@ -732,9 +732,9 @@
732
732
  }
733
733
  },
734
734
  "node_modules/@earendil-works/pi-ai": {
735
- "version": "0.82.1",
736
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.82.1.tgz",
737
- "integrity": "sha512-3WFYRhEp3lQB3444EhPMBcM7zSaEUE3eJgHOR7s4081NLqbw/FsWilIKWXSua0Gv3sRr7m9xMidR3pPDE7jI/A==",
735
+ "version": "0.83.0",
736
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.83.0.tgz",
737
+ "integrity": "sha512-m3IZD4g3er0V8TC9+Vpgw/sjTKqcJlkcIBy/JvsgRubuuik3tAVzyugUg4rVrShIkkOT69mEd34NEqKUIsl6JQ==",
738
738
  "license": "MIT",
739
739
  "dependencies": {
740
740
  "@anthropic-ai/sdk": "0.91.1",
@@ -747,7 +747,7 @@
747
747
  "https-proxy-agent": "7.0.6",
748
748
  "openai": "6.26.0",
749
749
  "partial-json": "0.1.7",
750
- "typebox": "1.1.38"
750
+ "typebox": "1.3.7"
751
751
  },
752
752
  "bin": {
753
753
  "pi-ai": "dist/cli.js"
@@ -777,9 +777,9 @@
777
777
  }
778
778
  },
779
779
  "node_modules/@earendil-works/pi-tui": {
780
- "version": "0.82.1",
781
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.82.1.tgz",
782
- "integrity": "sha512-9yN8hALfKaxZq7n54EMxqhFCWnMi6LHkraMJ/1YjHiATq75XrI6XDMVppn9EDtiK7Fks8hUe1SDXUTrIvwRWfQ==",
780
+ "version": "0.83.0",
781
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.83.0.tgz",
782
+ "integrity": "sha512-IoYrb0rORjELmEpNtoCA/U8je3KopMkRAVJRdSzvXRvgb+Huo1gNh8Q5CSZvNOiYtDxJdj2tYZZHZ4B3+IN3hA==",
783
783
  "license": "MIT",
784
784
  "dependencies": {
785
785
  "get-east-asian-width": "1.6.0",
@@ -4332,9 +4332,9 @@
4332
4332
  }
4333
4333
  },
4334
4334
  "node_modules/typebox": {
4335
- "version": "1.1.38",
4336
- "resolved": "https://registry.npmjs.org/typebox/-/typebox-1.1.38.tgz",
4337
- "integrity": "sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==",
4335
+ "version": "1.3.7",
4336
+ "resolved": "https://registry.npmjs.org/typebox/-/typebox-1.3.7.tgz",
4337
+ "integrity": "sha512-meKuifc33Pccx0O6PdIzYMq3Og8zvP4TIi/a+Bw3AEMZMxOD0+RHGQvpglEe6Zdy3wZ8nqn/j95h8LUZLk/6Hg==",
4338
4338
  "license": "MIT"
4339
4339
  },
4340
4340
  "node_modules/typescript": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astralyn/pi",
3
- "version": "0.82.7",
3
+ "version": "0.83.0",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -48,9 +48,9 @@
48
48
  "prepublishOnly": "npm run clean && npm run build"
49
49
  },
50
50
  "dependencies": {
51
- "@earendil-works/pi-agent-core": "0.82.1",
52
- "@earendil-works/pi-ai": "0.82.1",
53
- "@earendil-works/pi-tui": "0.82.1",
51
+ "@earendil-works/pi-agent-core": "0.83.0",
52
+ "@earendil-works/pi-ai": "0.83.0",
53
+ "@earendil-works/pi-tui": "0.83.0",
54
54
  "@silvia-odwyer/photon-node": "0.3.4",
55
55
  "chalk": "5.6.2",
56
56
  "cross-spawn": "7.0.6",
@@ -63,7 +63,7 @@
63
63
  "minimatch": "10.2.5",
64
64
  "proper-lockfile": "4.1.2",
65
65
  "semver": "7.8.0",
66
- "typebox": "1.1.38",
66
+ "typebox": "1.3.7",
67
67
  "undici": "8.5.0",
68
68
  "yaml": "2.9.0"
69
69
  },
@@ -1,68 +0,0 @@
1
- /**
2
- * plan/constants.ts — tool identity, command names, and prompt copy.
3
- *
4
- * Name/label/command live here so `index.ts` only assembles the extension,
5
- * matching the todo/question constants.ts pattern. Prompt copy is the
6
- * model-facing contract; keep it stable.
7
- */
8
- import type { SelectOption } from "../../core/extensions/types.ts";
9
- export declare const EXIT_PLAN_TOOL_NAME = "exit_plan";
10
- export declare const EXIT_PLAN_TOOL_LABEL = "Exit Plan";
11
- export declare const PLAN_COMMAND_NAME = "plan";
12
- export declare const PLAN_FLAG_NAME = "plan";
13
- export declare const PLAN_ENTRY_TYPE = "plan-mode";
14
- export declare const PLAN_STATUS_KEY = "plan-mode";
15
- /**
16
- * customType of the post-compaction kickoff message. Sent via sendMessage so
17
- * the LLM receives the full plan while the TUI renders a collapsed card.
18
- */
19
- export declare const PLAN_KICKOFF_MESSAGE_TYPE = "plan-kickoff";
20
- /**
21
- * Tools blocked while planning: edit/write grant write access directly.
22
- * bash stays available and is constrained to read-only inspection via the
23
- * plan-mode system prompt (same contract as the explorer subagent), and
24
- * subagent stays available but is limited to the built-in explorer profile
25
- * by the tool_call guard. Other extension tools (question, todo, deepwiki,
26
- * ...) stay available.
27
- */
28
- export declare const PLAN_BLOCKED_TOOLS: ReadonlySet<string>;
29
- /**
30
- * Exploration tools activated on entry. Mirrors the explorer subagent's
31
- * EXPLORER_TOOLS (kept as a separate constant so plan does not depend on the
32
- * subagent extension): the standalone search tools plus bash for read-only
33
- * inspection. grep/find/ls are registered but not active in the default
34
- * session tool set, so plan mode must activate them explicitly.
35
- */
36
- export declare const PLAN_EXPLORE_TOOLS: readonly string[];
37
- /** Only subagent profile allowed while planning (read-only exploration). */
38
- export declare const PLAN_ALLOWED_SUBAGENT = "explorer";
39
- /** Name of the subagent extension tool, for the plan-mode tool_call guard. */
40
- export declare const PLAN_SUBAGENT_TOOL_NAME = "subagent";
41
- /** Max characters of plan markdown echoed into the post-compaction kickoff message. */
42
- export declare const PLAN_EMBED_MAX_CHARS = 24000;
43
- export declare const MENU_EXECUTE = "Start executing";
44
- export declare const MENU_COMPACT_EXECUTE = "Compact context, then execute";
45
- export declare const MENU_KEEP_PLANNING = "Keep planning";
46
- /**
47
- * Approval choices. The label is the decision, the description is the
48
- * trade-off, so the three options can be told apart without reading to the
49
- * end of a sentence. select() resolves to the label.
50
- */
51
- export declare const EXIT_PLAN_MENU_OPTIONS: readonly SelectOption[];
52
- /** Esc maps to "keep planning", so the dismiss hint must not read as "discard". */
53
- export declare const EXIT_PLAN_CANCEL_HINT = "keep planning";
54
- /**
55
- * /plan panel (shown when the command runs while planning): exit is the first
56
- * option, saved plans follow. Esc keeps planning with no side effects.
57
- */
58
- export declare const PLAN_PANEL_TITLE = "Plan mode";
59
- export declare const PLAN_PANEL_EXIT = "Exit plan mode";
60
- export declare const PLAN_PANEL_EXIT_DESCRIPTION = "restore full tool access";
61
- export declare const PLAN_PANEL_CANCEL_HINT = "keep planning";
62
- export declare const PLAN_PANEL_MAX_FILES = 20;
63
- export declare const EXIT_PLAN_TOOL_DESCRIPTION = "Submit the finished plan and ask the user to approve leaving plan mode. Present the complete plan as normal response text first, then call this tool with a short title and the same plan markdown; on approval the plan is saved to disk. The user chooses between executing with full context, compacting the context before executing, or continuing to plan. Only available while plan mode is active.";
64
- export declare const EXIT_PLAN_PROMPT_SNIPPET = "Submit the finished plan for user approval and leave plan mode";
65
- export declare const EXIT_PLAN_PROMPT_GUIDELINES: string[];
66
- /** Build the plan-mode system prompt block, listing plans already saved for this branch. */
67
- export declare function buildPlanModePrompt(planFiles: string[]): string;
68
- //# sourceMappingURL=constants.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/extensions/plan/constants.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAC/C,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAChD,eAAO,MAAM,iBAAiB,SAAS,CAAC;AACxC,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,eAAO,MAAM,eAAe,cAAc,CAAC;AAC3C,eAAO,MAAM,eAAe,cAAc,CAAC;AAE3C;;;GAGG;AACH,eAAO,MAAM,yBAAyB,iBAAiB,CAAC;AAExD;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAA8B,CAAC;AAElF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAA2C,CAAC;AAE5F,4EAA4E;AAC5E,eAAO,MAAM,qBAAqB,aAAa,CAAC;AAEhD,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,aAAa,CAAC;AAElD,uFAAuF;AACvF,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C,eAAO,MAAM,YAAY,oBAAoB,CAAC;AAC9C,eAAO,MAAM,oBAAoB,kCAAkC,CAAC;AACpE,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,SAAS,YAAY,EAIzD,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AAErD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAC5C,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAChD,eAAO,MAAM,2BAA2B,6BAA6B,CAAC;AACtE,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AACtD,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,eAAO,MAAM,0BAA0B,+YACsW,CAAC;AAE9Y,eAAO,MAAM,wBAAwB,mEAAmE,CAAC;AAEzG,eAAO,MAAM,2BAA2B,UAGvC,CAAC;AAoBF,4FAA4F;AAC5F,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ/D","sourcesContent":["/**\n * plan/constants.ts — tool identity, command names, and prompt copy.\n *\n * Name/label/command live here so `index.ts` only assembles the extension,\n * matching the todo/question constants.ts pattern. Prompt copy is the\n * model-facing contract; keep it stable.\n */\n\nimport type { SelectOption } from \"../../core/extensions/types.ts\";\n\nexport const EXIT_PLAN_TOOL_NAME = \"exit_plan\";\nexport const EXIT_PLAN_TOOL_LABEL = \"Exit Plan\";\nexport const PLAN_COMMAND_NAME = \"plan\";\nexport const PLAN_FLAG_NAME = \"plan\";\nexport const PLAN_ENTRY_TYPE = \"plan-mode\";\nexport const PLAN_STATUS_KEY = \"plan-mode\";\n\n/**\n * customType of the post-compaction kickoff message. Sent via sendMessage so\n * the LLM receives the full plan while the TUI renders a collapsed card.\n */\nexport const PLAN_KICKOFF_MESSAGE_TYPE = \"plan-kickoff\";\n\n/**\n * Tools blocked while planning: edit/write grant write access directly.\n * bash stays available and is constrained to read-only inspection via the\n * plan-mode system prompt (same contract as the explorer subagent), and\n * subagent stays available but is limited to the built-in explorer profile\n * by the tool_call guard. Other extension tools (question, todo, deepwiki,\n * ...) stay available.\n */\nexport const PLAN_BLOCKED_TOOLS: ReadonlySet<string> = new Set([\"edit\", \"write\"]);\n\n/**\n * Exploration tools activated on entry. Mirrors the explorer subagent's\n * EXPLORER_TOOLS (kept as a separate constant so plan does not depend on the\n * subagent extension): the standalone search tools plus bash for read-only\n * inspection. grep/find/ls are registered but not active in the default\n * session tool set, so plan mode must activate them explicitly.\n */\nexport const PLAN_EXPLORE_TOOLS: readonly string[] = [\"read\", \"grep\", \"find\", \"ls\", \"bash\"];\n\n/** Only subagent profile allowed while planning (read-only exploration). */\nexport const PLAN_ALLOWED_SUBAGENT = \"explorer\";\n\n/** Name of the subagent extension tool, for the plan-mode tool_call guard. */\nexport const PLAN_SUBAGENT_TOOL_NAME = \"subagent\";\n\n/** Max characters of plan markdown echoed into the post-compaction kickoff message. */\nexport const PLAN_EMBED_MAX_CHARS = 24_000;\n\nexport const MENU_EXECUTE = \"Start executing\";\nexport const MENU_COMPACT_EXECUTE = \"Compact context, then execute\";\nexport const MENU_KEEP_PLANNING = \"Keep planning\";\n\n/**\n * Approval choices. The label is the decision, the description is the\n * trade-off, so the three options can be told apart without reading to the\n * end of a sentence. select() resolves to the label.\n */\nexport const EXIT_PLAN_MENU_OPTIONS: readonly SelectOption[] = [\n\t{ label: MENU_EXECUTE, description: \"keep full context\" },\n\t{ label: MENU_COMPACT_EXECUTE, description: \"best for long tasks\" },\n\t{ label: MENU_KEEP_PLANNING, description: \"refine before running\" },\n];\n\n/** Esc maps to \"keep planning\", so the dismiss hint must not read as \"discard\". */\nexport const EXIT_PLAN_CANCEL_HINT = \"keep planning\";\n\n/**\n * /plan panel (shown when the command runs while planning): exit is the first\n * option, saved plans follow. Esc keeps planning with no side effects.\n */\nexport const PLAN_PANEL_TITLE = \"Plan mode\";\nexport const PLAN_PANEL_EXIT = \"Exit plan mode\";\nexport const PLAN_PANEL_EXIT_DESCRIPTION = \"restore full tool access\";\nexport const PLAN_PANEL_CANCEL_HINT = \"keep planning\";\nexport const PLAN_PANEL_MAX_FILES = 20;\n\nexport const EXIT_PLAN_TOOL_DESCRIPTION =\n\t\"Submit the finished plan and ask the user to approve leaving plan mode. Present the complete plan as normal response text first, then call this tool with a short title and the same plan markdown; on approval the plan is saved to disk. The user chooses between executing with full context, compacting the context before executing, or continuing to plan. Only available while plan mode is active.\";\n\nexport const EXIT_PLAN_PROMPT_SNIPPET = \"Submit the finished plan for user approval and leave plan mode\";\n\nexport const EXIT_PLAN_PROMPT_GUIDELINES = [\n\t\"Call `exit_plan` only after presenting the complete plan as response text; make it the only tool call in that step and stop after it returns.\",\n\t\"`exit_plan` results are authoritative for plan-mode state: follow them even when the plan-mode system prompt block is still present later in the run.\",\n];\n\nconst PLAN_MODE_PROMPT = `[PLAN MODE]\nYou are in plan mode: a read-only phase for exploring the codebase and agreeing on a plan with the user before any changes are made.\n\nRestrictions:\n- edit and write are unavailable; do not attempt changes or workarounds.\n- bash is for read-only inspection only: git log/diff/blame/show/status, ls, wc, head, tail, cat, and similar. Never run anything that modifies state: no file creation or deletion, no redirect (>, >>) or heredoc writes, no temp files, no git commands that write (add, commit, checkout, restore, stash, clean), no installs, no network access.\n- subagent is limited to the read-only explorer profile: always pass agent: \"${PLAN_ALLOWED_SUBAGENT}\"; other profiles are blocked while planning.\n- Explore with read, grep, find, ls, read-only bash, and explorer subagents.\n\nWorking style:\n- Answer questions from the code, not from the user: explore before asking.\n- When product intent, scope, or risk tolerance is unclear, interview the user with the question tool. Focus on one decision per exchange (batch only tightly coupled decisions) and always include your recommendation and the trade-offs.\n- Skip the interview for small, clear tasks. Pick sensible defaults for low-risk details and state them in the plan.\n\nDelivering the plan:\n- When the plan is ready, present it in full as normal response text (goal, steps, verification criteria) so the user can read it, then call exit_plan with a short title and the same markdown as the plan parameter.\n- The exit_plan tool result is authoritative for mode state: this block can outlive plan mode within a run, so if the result says plan mode has ended, it has ended.`;\n\n/** Build the plan-mode system prompt block, listing plans already saved for this branch. */\nexport function buildPlanModePrompt(planFiles: string[]): string {\n\tif (!planFiles.length) return PLAN_MODE_PROMPT;\n\tconst listing = planFiles.map((path) => `- ${path}`).join(\"\\n\");\n\treturn `${PLAN_MODE_PROMPT}\n\nPlans already saved for this session (read them with the read tool):\n${listing}\nWhen revising a saved plan, read the latest one first, account for work already completed, and produce a revision that states what changed and why; set the revises parameter to the file name of the plan being revised.`;\n}\n"]}
@@ -1,100 +0,0 @@
1
- /**
2
- * plan/constants.ts — tool identity, command names, and prompt copy.
3
- *
4
- * Name/label/command live here so `index.ts` only assembles the extension,
5
- * matching the todo/question constants.ts pattern. Prompt copy is the
6
- * model-facing contract; keep it stable.
7
- */
8
- export const EXIT_PLAN_TOOL_NAME = "exit_plan";
9
- export const EXIT_PLAN_TOOL_LABEL = "Exit Plan";
10
- export const PLAN_COMMAND_NAME = "plan";
11
- export const PLAN_FLAG_NAME = "plan";
12
- export const PLAN_ENTRY_TYPE = "plan-mode";
13
- export const PLAN_STATUS_KEY = "plan-mode";
14
- /**
15
- * customType of the post-compaction kickoff message. Sent via sendMessage so
16
- * the LLM receives the full plan while the TUI renders a collapsed card.
17
- */
18
- export const PLAN_KICKOFF_MESSAGE_TYPE = "plan-kickoff";
19
- /**
20
- * Tools blocked while planning: edit/write grant write access directly.
21
- * bash stays available and is constrained to read-only inspection via the
22
- * plan-mode system prompt (same contract as the explorer subagent), and
23
- * subagent stays available but is limited to the built-in explorer profile
24
- * by the tool_call guard. Other extension tools (question, todo, deepwiki,
25
- * ...) stay available.
26
- */
27
- export const PLAN_BLOCKED_TOOLS = new Set(["edit", "write"]);
28
- /**
29
- * Exploration tools activated on entry. Mirrors the explorer subagent's
30
- * EXPLORER_TOOLS (kept as a separate constant so plan does not depend on the
31
- * subagent extension): the standalone search tools plus bash for read-only
32
- * inspection. grep/find/ls are registered but not active in the default
33
- * session tool set, so plan mode must activate them explicitly.
34
- */
35
- export const PLAN_EXPLORE_TOOLS = ["read", "grep", "find", "ls", "bash"];
36
- /** Only subagent profile allowed while planning (read-only exploration). */
37
- export const PLAN_ALLOWED_SUBAGENT = "explorer";
38
- /** Name of the subagent extension tool, for the plan-mode tool_call guard. */
39
- export const PLAN_SUBAGENT_TOOL_NAME = "subagent";
40
- /** Max characters of plan markdown echoed into the post-compaction kickoff message. */
41
- export const PLAN_EMBED_MAX_CHARS = 24_000;
42
- export const MENU_EXECUTE = "Start executing";
43
- export const MENU_COMPACT_EXECUTE = "Compact context, then execute";
44
- export const MENU_KEEP_PLANNING = "Keep planning";
45
- /**
46
- * Approval choices. The label is the decision, the description is the
47
- * trade-off, so the three options can be told apart without reading to the
48
- * end of a sentence. select() resolves to the label.
49
- */
50
- export const EXIT_PLAN_MENU_OPTIONS = [
51
- { label: MENU_EXECUTE, description: "keep full context" },
52
- { label: MENU_COMPACT_EXECUTE, description: "best for long tasks" },
53
- { label: MENU_KEEP_PLANNING, description: "refine before running" },
54
- ];
55
- /** Esc maps to "keep planning", so the dismiss hint must not read as "discard". */
56
- export const EXIT_PLAN_CANCEL_HINT = "keep planning";
57
- /**
58
- * /plan panel (shown when the command runs while planning): exit is the first
59
- * option, saved plans follow. Esc keeps planning with no side effects.
60
- */
61
- export const PLAN_PANEL_TITLE = "Plan mode";
62
- export const PLAN_PANEL_EXIT = "Exit plan mode";
63
- export const PLAN_PANEL_EXIT_DESCRIPTION = "restore full tool access";
64
- export const PLAN_PANEL_CANCEL_HINT = "keep planning";
65
- export const PLAN_PANEL_MAX_FILES = 20;
66
- export const EXIT_PLAN_TOOL_DESCRIPTION = "Submit the finished plan and ask the user to approve leaving plan mode. Present the complete plan as normal response text first, then call this tool with a short title and the same plan markdown; on approval the plan is saved to disk. The user chooses between executing with full context, compacting the context before executing, or continuing to plan. Only available while plan mode is active.";
67
- export const EXIT_PLAN_PROMPT_SNIPPET = "Submit the finished plan for user approval and leave plan mode";
68
- export const EXIT_PLAN_PROMPT_GUIDELINES = [
69
- "Call `exit_plan` only after presenting the complete plan as response text; make it the only tool call in that step and stop after it returns.",
70
- "`exit_plan` results are authoritative for plan-mode state: follow them even when the plan-mode system prompt block is still present later in the run.",
71
- ];
72
- const PLAN_MODE_PROMPT = `[PLAN MODE]
73
- You are in plan mode: a read-only phase for exploring the codebase and agreeing on a plan with the user before any changes are made.
74
-
75
- Restrictions:
76
- - edit and write are unavailable; do not attempt changes or workarounds.
77
- - bash is for read-only inspection only: git log/diff/blame/show/status, ls, wc, head, tail, cat, and similar. Never run anything that modifies state: no file creation or deletion, no redirect (>, >>) or heredoc writes, no temp files, no git commands that write (add, commit, checkout, restore, stash, clean), no installs, no network access.
78
- - subagent is limited to the read-only explorer profile: always pass agent: "${PLAN_ALLOWED_SUBAGENT}"; other profiles are blocked while planning.
79
- - Explore with read, grep, find, ls, read-only bash, and explorer subagents.
80
-
81
- Working style:
82
- - Answer questions from the code, not from the user: explore before asking.
83
- - When product intent, scope, or risk tolerance is unclear, interview the user with the question tool. Focus on one decision per exchange (batch only tightly coupled decisions) and always include your recommendation and the trade-offs.
84
- - Skip the interview for small, clear tasks. Pick sensible defaults for low-risk details and state them in the plan.
85
-
86
- Delivering the plan:
87
- - When the plan is ready, present it in full as normal response text (goal, steps, verification criteria) so the user can read it, then call exit_plan with a short title and the same markdown as the plan parameter.
88
- - The exit_plan tool result is authoritative for mode state: this block can outlive plan mode within a run, so if the result says plan mode has ended, it has ended.`;
89
- /** Build the plan-mode system prompt block, listing plans already saved for this branch. */
90
- export function buildPlanModePrompt(planFiles) {
91
- if (!planFiles.length)
92
- return PLAN_MODE_PROMPT;
93
- const listing = planFiles.map((path) => `- ${path}`).join("\n");
94
- return `${PLAN_MODE_PROMPT}
95
-
96
- Plans already saved for this session (read them with the read tool):
97
- ${listing}
98
- When revising a saved plan, read the latest one first, account for work already completed, and produce a revision that states what changed and why; set the revises parameter to the file name of the plan being revised.`;
99
- }
100
- //# sourceMappingURL=constants.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/extensions/plan/constants.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,CAAC,MAAM,mBAAmB,GAAG,WAAW,CAAC;AAC/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAC;AAChD,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AACxC,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC;AACrC,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAC3C,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAE3C;;;GAGG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,cAAc,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAElF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAE5F,4EAA4E;AAC5E,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAC;AAEhD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,uBAAuB,GAAG,UAAU,CAAC;AAElD,uFAAuF;AACvF,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAE3C,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAC9C,MAAM,CAAC,MAAM,oBAAoB,GAAG,+BAA+B,CAAC;AACpE,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAElD;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAA4B;IAC9D,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACzD,EAAE,KAAK,EAAE,oBAAoB,EAAE,WAAW,EAAE,qBAAqB,EAAE;IACnE,EAAE,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,uBAAuB,EAAE;CACnE,CAAC;AAEF,mFAAmF;AACnF,MAAM,CAAC,MAAM,qBAAqB,GAAG,eAAe,CAAC;AAErD;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC;AAC5C,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAAC;AAChD,MAAM,CAAC,MAAM,2BAA2B,GAAG,0BAA0B,CAAC;AACtE,MAAM,CAAC,MAAM,sBAAsB,GAAG,eAAe,CAAC;AACtD,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEvC,MAAM,CAAC,MAAM,0BAA0B,GACtC,4YAA4Y,CAAC;AAE9Y,MAAM,CAAC,MAAM,wBAAwB,GAAG,gEAAgE,CAAC;AAEzG,MAAM,CAAC,MAAM,2BAA2B,GAAG;IAC1C,+IAA+I;IAC/I,uJAAuJ;CACvJ,CAAC;AAEF,MAAM,gBAAgB,GAAG;;;;;;+EAMsD,qBAAqB;;;;;;;;;;qKAUiE,CAAC;AAEtK,4FAA4F;AAC5F,MAAM,UAAU,mBAAmB,CAAC,SAAmB,EAAU;IAChE,IAAI,CAAC,SAAS,CAAC,MAAM;QAAE,OAAO,gBAAgB,CAAC;IAC/C,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChE,OAAO,GAAG,gBAAgB;;;EAGzB,OAAO;0NACiN,CAAC;AAAA,CAC1N","sourcesContent":["/**\n * plan/constants.ts — tool identity, command names, and prompt copy.\n *\n * Name/label/command live here so `index.ts` only assembles the extension,\n * matching the todo/question constants.ts pattern. Prompt copy is the\n * model-facing contract; keep it stable.\n */\n\nimport type { SelectOption } from \"../../core/extensions/types.ts\";\n\nexport const EXIT_PLAN_TOOL_NAME = \"exit_plan\";\nexport const EXIT_PLAN_TOOL_LABEL = \"Exit Plan\";\nexport const PLAN_COMMAND_NAME = \"plan\";\nexport const PLAN_FLAG_NAME = \"plan\";\nexport const PLAN_ENTRY_TYPE = \"plan-mode\";\nexport const PLAN_STATUS_KEY = \"plan-mode\";\n\n/**\n * customType of the post-compaction kickoff message. Sent via sendMessage so\n * the LLM receives the full plan while the TUI renders a collapsed card.\n */\nexport const PLAN_KICKOFF_MESSAGE_TYPE = \"plan-kickoff\";\n\n/**\n * Tools blocked while planning: edit/write grant write access directly.\n * bash stays available and is constrained to read-only inspection via the\n * plan-mode system prompt (same contract as the explorer subagent), and\n * subagent stays available but is limited to the built-in explorer profile\n * by the tool_call guard. Other extension tools (question, todo, deepwiki,\n * ...) stay available.\n */\nexport const PLAN_BLOCKED_TOOLS: ReadonlySet<string> = new Set([\"edit\", \"write\"]);\n\n/**\n * Exploration tools activated on entry. Mirrors the explorer subagent's\n * EXPLORER_TOOLS (kept as a separate constant so plan does not depend on the\n * subagent extension): the standalone search tools plus bash for read-only\n * inspection. grep/find/ls are registered but not active in the default\n * session tool set, so plan mode must activate them explicitly.\n */\nexport const PLAN_EXPLORE_TOOLS: readonly string[] = [\"read\", \"grep\", \"find\", \"ls\", \"bash\"];\n\n/** Only subagent profile allowed while planning (read-only exploration). */\nexport const PLAN_ALLOWED_SUBAGENT = \"explorer\";\n\n/** Name of the subagent extension tool, for the plan-mode tool_call guard. */\nexport const PLAN_SUBAGENT_TOOL_NAME = \"subagent\";\n\n/** Max characters of plan markdown echoed into the post-compaction kickoff message. */\nexport const PLAN_EMBED_MAX_CHARS = 24_000;\n\nexport const MENU_EXECUTE = \"Start executing\";\nexport const MENU_COMPACT_EXECUTE = \"Compact context, then execute\";\nexport const MENU_KEEP_PLANNING = \"Keep planning\";\n\n/**\n * Approval choices. The label is the decision, the description is the\n * trade-off, so the three options can be told apart without reading to the\n * end of a sentence. select() resolves to the label.\n */\nexport const EXIT_PLAN_MENU_OPTIONS: readonly SelectOption[] = [\n\t{ label: MENU_EXECUTE, description: \"keep full context\" },\n\t{ label: MENU_COMPACT_EXECUTE, description: \"best for long tasks\" },\n\t{ label: MENU_KEEP_PLANNING, description: \"refine before running\" },\n];\n\n/** Esc maps to \"keep planning\", so the dismiss hint must not read as \"discard\". */\nexport const EXIT_PLAN_CANCEL_HINT = \"keep planning\";\n\n/**\n * /plan panel (shown when the command runs while planning): exit is the first\n * option, saved plans follow. Esc keeps planning with no side effects.\n */\nexport const PLAN_PANEL_TITLE = \"Plan mode\";\nexport const PLAN_PANEL_EXIT = \"Exit plan mode\";\nexport const PLAN_PANEL_EXIT_DESCRIPTION = \"restore full tool access\";\nexport const PLAN_PANEL_CANCEL_HINT = \"keep planning\";\nexport const PLAN_PANEL_MAX_FILES = 20;\n\nexport const EXIT_PLAN_TOOL_DESCRIPTION =\n\t\"Submit the finished plan and ask the user to approve leaving plan mode. Present the complete plan as normal response text first, then call this tool with a short title and the same plan markdown; on approval the plan is saved to disk. The user chooses between executing with full context, compacting the context before executing, or continuing to plan. Only available while plan mode is active.\";\n\nexport const EXIT_PLAN_PROMPT_SNIPPET = \"Submit the finished plan for user approval and leave plan mode\";\n\nexport const EXIT_PLAN_PROMPT_GUIDELINES = [\n\t\"Call `exit_plan` only after presenting the complete plan as response text; make it the only tool call in that step and stop after it returns.\",\n\t\"`exit_plan` results are authoritative for plan-mode state: follow them even when the plan-mode system prompt block is still present later in the run.\",\n];\n\nconst PLAN_MODE_PROMPT = `[PLAN MODE]\nYou are in plan mode: a read-only phase for exploring the codebase and agreeing on a plan with the user before any changes are made.\n\nRestrictions:\n- edit and write are unavailable; do not attempt changes or workarounds.\n- bash is for read-only inspection only: git log/diff/blame/show/status, ls, wc, head, tail, cat, and similar. Never run anything that modifies state: no file creation or deletion, no redirect (>, >>) or heredoc writes, no temp files, no git commands that write (add, commit, checkout, restore, stash, clean), no installs, no network access.\n- subagent is limited to the read-only explorer profile: always pass agent: \"${PLAN_ALLOWED_SUBAGENT}\"; other profiles are blocked while planning.\n- Explore with read, grep, find, ls, read-only bash, and explorer subagents.\n\nWorking style:\n- Answer questions from the code, not from the user: explore before asking.\n- When product intent, scope, or risk tolerance is unclear, interview the user with the question tool. Focus on one decision per exchange (batch only tightly coupled decisions) and always include your recommendation and the trade-offs.\n- Skip the interview for small, clear tasks. Pick sensible defaults for low-risk details and state them in the plan.\n\nDelivering the plan:\n- When the plan is ready, present it in full as normal response text (goal, steps, verification criteria) so the user can read it, then call exit_plan with a short title and the same markdown as the plan parameter.\n- The exit_plan tool result is authoritative for mode state: this block can outlive plan mode within a run, so if the result says plan mode has ended, it has ended.`;\n\n/** Build the plan-mode system prompt block, listing plans already saved for this branch. */\nexport function buildPlanModePrompt(planFiles: string[]): string {\n\tif (!planFiles.length) return PLAN_MODE_PROMPT;\n\tconst listing = planFiles.map((path) => `- ${path}`).join(\"\\n\");\n\treturn `${PLAN_MODE_PROMPT}\n\nPlans already saved for this session (read them with the read tool):\n${listing}\nWhen revising a saved plan, read the latest one first, account for work already completed, and produce a revision that states what changed and why; set the revises parameter to the file name of the plan being revised.`;\n}\n"]}
@@ -1,30 +0,0 @@
1
- /**
2
- * plan — Claude-Code-style plan mode: read-only exploration and interview,
3
- * then a user-approved exit that saves the plan and optionally compacts.
4
- *
5
- * Shape:
6
- * - Entry (/plan or --plan) snapshots the active tool set and swaps to the
7
- * exploration set (read/grep/find/ls/bash + exit_plan; edit/write removed,
8
- * bash prompt-constrained to read-only, subagent guarded to the explorer
9
- * profile); a tool_call guard covers requests already in flight before the
10
- * tool-set change lands.
11
- * - The plan text travels as an exit_plan parameter, so the model needs no
12
- * write access to produce the plan file.
13
- * - "Compact, then execute" keeps plan mode active until compaction completes
14
- * (tools are restored in onComplete) and terminates the run via the tool
15
- * result, so there is no window where the model holds full context plus
16
- * write tools. The kickoff message embeds the plan itself — continuation
17
- * never depends on the compaction summary preserving a path.
18
- * - State is conversation-backed via custom entries and branch replay (same
19
- * pattern as todo): /reload, /tree, resume, and fork all restore.
20
- */
21
- import type { ExtensionAPI } from "../../core/extensions/types.ts";
22
- /**
23
- * First subagent profile in the call that is not allowed in plan mode, or
24
- * undefined when every profile is the read-only explorer. An omitted or null
25
- * agent resolves to the default "general" profile, so it is disallowed too.
26
- * Args arrive off the wire, so every field is read defensively.
27
- */
28
- export declare function findDisallowedSubagentProfile(input: unknown): string | undefined;
29
- export default function plan(pi: ExtensionAPI): void;
30
- //# sourceMappingURL=index.d.ts.map