@gavin-hu/my-pi-agent 0.20.0 → 0.22.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 (298) hide show
  1. package/README.md +46 -30
  2. package/README.zh-CN.md +40 -25
  3. package/assets/screens/board.png +0 -0
  4. package/assets/screens/chrome.png +0 -0
  5. package/assets/screens/file-browse.png +0 -0
  6. package/assets/screens/plan-review.png +0 -0
  7. package/assets/screens/plan.png +0 -0
  8. package/docs/extensions/README.md +22 -23
  9. package/docs/extensions/board.md +397 -168
  10. package/docs/extensions/bytefly.md +234 -197
  11. package/docs/extensions/check.md +15 -17
  12. package/docs/extensions/context.md +35 -15
  13. package/docs/extensions/file-browse.md +57 -63
  14. package/docs/extensions/file-open.md +9 -11
  15. package/docs/extensions/file-read.md +12 -14
  16. package/docs/extensions/goal.md +15 -17
  17. package/docs/extensions/job.md +54 -42
  18. package/docs/extensions/memory.md +17 -19
  19. package/docs/extensions/plan.md +197 -140
  20. package/docs/extensions/question.md +16 -18
  21. package/docs/extensions/rewind.md +17 -19
  22. package/docs/extensions/serve.md +145 -0
  23. package/docs/extensions/session-bus.md +38 -16
  24. package/docs/extensions/subagent.md +23 -25
  25. package/docs/extensions/team.md +83 -44
  26. package/docs/extensions/todo.md +18 -18
  27. package/docs/extensions/watch.md +31 -31
  28. package/docs/extensions/web-access.md +2 -4
  29. package/docs/extensions/wechat.md +34 -35
  30. package/docs/extensions/worktree.md +56 -50
  31. package/extensions/board/commands.ts +79 -25
  32. package/extensions/board/format.ts +43 -24
  33. package/extensions/board/index.ts +17 -4
  34. package/extensions/board/input.ts +4 -9
  35. package/extensions/board/join.ts +5 -20
  36. package/extensions/board/lazy-page.ts +40 -0
  37. package/extensions/board/page.ts +65 -93
  38. package/extensions/board/result.ts +30 -39
  39. package/extensions/board/rows.ts +62 -25
  40. package/extensions/board/schema.ts +49 -11
  41. package/extensions/board/snapshot.ts +8 -6
  42. package/extensions/board/tone.ts +22 -0
  43. package/extensions/board/tools.ts +154 -55
  44. package/extensions/board/transport/router.ts +3 -5
  45. package/extensions/board/transport/server.ts +59 -28
  46. package/extensions/board/types.ts +36 -42
  47. package/extensions/board/view/card.ts +229 -0
  48. package/extensions/board/view/client.ts +35 -16
  49. package/extensions/board/view/dialog.ts +169 -6
  50. package/extensions/board/view/empty.ts +47 -0
  51. package/extensions/board/view/keys.ts +13 -2
  52. package/extensions/board/view/live.ts +90 -28
  53. package/extensions/board/view/names.ts +13 -4
  54. package/extensions/board/view/page.ts +38 -13
  55. package/extensions/board/view/render.ts +219 -277
  56. package/extensions/board/view/styles.ts +130 -32
  57. package/extensions/board/view/team.ts +297 -76
  58. package/extensions/bytefly/block/fallback.ts +1 -1
  59. package/extensions/bytefly/doctor/runtime.ts +5 -2
  60. package/extensions/bytefly/footer/collect/label.ts +60 -0
  61. package/extensions/bytefly/footer/collect/snapshot.ts +8 -1
  62. package/extensions/bytefly/footer/config.ts +7 -8
  63. package/extensions/bytefly/footer/register.ts +33 -4
  64. package/extensions/bytefly/footer/render/footer.ts +18 -4
  65. package/extensions/bytefly/footer/render/key.ts +46 -0
  66. package/extensions/bytefly/footer/render/layout.ts +13 -3
  67. package/extensions/bytefly/footer/render/lines.ts +10 -7
  68. package/extensions/bytefly/footer/render/segments.ts +41 -38
  69. package/extensions/bytefly/footer/render/status.ts +0 -11
  70. package/extensions/bytefly/footer/types.ts +7 -0
  71. package/extensions/bytefly/header/component.ts +4 -20
  72. package/extensions/bytefly/header/config.ts +1 -1
  73. package/extensions/bytefly/index.ts +32 -6
  74. package/extensions/bytefly/mode/editor.ts +115 -0
  75. package/extensions/bytefly/panel/commands.ts +210 -120
  76. package/extensions/bytefly/panel/format.ts +4 -4
  77. package/extensions/bytefly/panel/settings.ts +73 -6
  78. package/extensions/bytefly/panel/tui/keys.ts +2 -6
  79. package/extensions/bytefly/update/cache.ts +1 -1
  80. package/extensions/bytefly/update/register.ts +4 -4
  81. package/extensions/bytefly/working/config.ts +5 -7
  82. package/extensions/bytefly/working/format.ts +10 -13
  83. package/extensions/bytefly/working/register.ts +22 -27
  84. package/extensions/check/commands.ts +3 -2
  85. package/extensions/check/render.ts +10 -1
  86. package/extensions/check/{tui.ts → view/check-screens.ts} +14 -19
  87. package/extensions/context/commands.ts +2 -2
  88. package/extensions/context/{tui.ts → view/context-report.ts} +51 -19
  89. package/extensions/file-browse/config/config.ts +4 -19
  90. package/extensions/file-browse/index.ts +89 -79
  91. package/extensions/file-browse/live/live.ts +1 -1
  92. package/extensions/file-browse/transport/router.ts +12 -4
  93. package/extensions/file-browse/transport/server.ts +61 -28
  94. package/extensions/file-browse/view/chrome.ts +4 -4
  95. package/extensions/file-browse/view/client.ts +3 -1
  96. package/extensions/file-browse/view/html.ts +73 -40
  97. package/extensions/file-browse/view/live-client.ts +2 -2
  98. package/extensions/file-browse/view/markdown.ts +13 -14
  99. package/extensions/file-browse/view/palette.ts +2 -2
  100. package/extensions/file-browse/view/raw-html.ts +9 -9
  101. package/extensions/file-browse/view/tree.ts +1 -1
  102. package/extensions/file-browse/view/urls.ts +20 -6
  103. package/extensions/file-read/render.ts +4 -4
  104. package/extensions/goal/plan-route.ts +2 -2
  105. package/extensions/goal/tui.ts +12 -2
  106. package/extensions/job/child.ts +527 -0
  107. package/extensions/job/clock.ts +142 -0
  108. package/extensions/job/commands.ts +4 -2
  109. package/extensions/job/config.ts +8 -1
  110. package/extensions/job/format.ts +22 -1
  111. package/extensions/job/log-writer.ts +13 -2
  112. package/extensions/job/registry.ts +63 -7
  113. package/extensions/job/render.ts +34 -0
  114. package/extensions/job/runtime.ts +296 -655
  115. package/extensions/job/session.ts +132 -19
  116. package/extensions/job/store.ts +7 -7
  117. package/extensions/job/tools.ts +21 -9
  118. package/extensions/job/types.ts +47 -0
  119. package/extensions/job/{tui.ts → view/jobs-screen.ts} +19 -99
  120. package/extensions/job/waiters.ts +44 -1
  121. package/extensions/memory/commands.ts +4 -2
  122. package/extensions/memory/{tui.ts → view/memory-picker.ts} +12 -12
  123. package/extensions/plan/commands.ts +12 -9
  124. package/extensions/plan/feedback.ts +62 -16
  125. package/extensions/plan/format.ts +8 -2
  126. package/extensions/plan/git-bash.ts +115 -16
  127. package/extensions/plan/index.ts +58 -51
  128. package/extensions/plan/plan-index.ts +4 -2
  129. package/extensions/plan/plan-text.ts +114 -0
  130. package/extensions/plan/plans.ts +5 -54
  131. package/extensions/plan/policy.ts +8 -10
  132. package/extensions/plan/review-lazy.ts +85 -0
  133. package/extensions/plan/review.ts +2 -2
  134. package/extensions/plan/runtime.ts +61 -41
  135. package/extensions/plan/sections.ts +1 -1
  136. package/extensions/plan/steps.ts +3 -3
  137. package/extensions/plan/todos.ts +1 -1
  138. package/extensions/plan/tools/cancel.ts +27 -62
  139. package/extensions/plan/tools/enter.ts +55 -81
  140. package/extensions/plan/tools/exit.ts +221 -238
  141. package/extensions/plan/tools/refusal.ts +18 -0
  142. package/extensions/plan/tools/steps.ts +75 -92
  143. package/extensions/plan/tools/write.ts +77 -120
  144. package/extensions/plan/tools.ts +188 -30
  145. package/extensions/plan/tui.ts +5 -5
  146. package/extensions/plan/types.ts +48 -5
  147. package/extensions/plan/web-blocks.ts +76 -5
  148. package/extensions/plan/web-chrome.ts +4 -0
  149. package/extensions/plan/web-client.ts +102 -2
  150. package/extensions/plan/web-collab.ts +4 -4
  151. package/extensions/plan/web-comments.ts +39 -8
  152. package/extensions/plan/web-composer.ts +14 -3
  153. package/extensions/plan/web-keys.ts +149 -25
  154. package/extensions/plan/web-lazy.ts +53 -0
  155. package/extensions/plan/web-markdown.ts +10 -68
  156. package/extensions/plan/web-outline.ts +22 -2
  157. package/extensions/plan/web-page.ts +56 -86
  158. package/extensions/plan/web-payload.ts +188 -0
  159. package/extensions/plan/web-plan.ts +23 -13
  160. package/extensions/plan/web-router.ts +18 -9
  161. package/extensions/plan/web-settle.ts +14 -7
  162. package/extensions/plan/web-share-session.ts +24 -55
  163. package/extensions/plan/web-share.ts +19 -37
  164. package/extensions/plan/web-write.ts +112 -0
  165. package/extensions/plan/web.ts +67 -131
  166. package/extensions/question/tools.ts +6 -2
  167. package/extensions/question/{tui.ts → view/question-screen.ts} +11 -11
  168. package/extensions/rewind/commands/commands.ts +6 -3
  169. package/extensions/rewind/state/runtime.ts +1 -1
  170. package/extensions/rewind/{view/status.ts → status.ts} +4 -4
  171. package/extensions/rewind/view/review-tui.ts +4 -4
  172. package/extensions/serve/config.ts +39 -0
  173. package/extensions/serve/index.ts +85 -0
  174. package/extensions/serve/registry.ts +260 -0
  175. package/extensions/session-bus/commands.ts +11 -6
  176. package/extensions/session-bus/join-request.ts +17 -9
  177. package/extensions/session-bus/mail-watch.ts +26 -17
  178. package/extensions/session-bus/protocol.ts +15 -3
  179. package/extensions/session-bus/resolve.ts +5 -7
  180. package/extensions/session-bus/result.ts +1 -27
  181. package/extensions/session-bus/runtime.ts +40 -12
  182. package/extensions/session-bus/store.ts +101 -19
  183. package/extensions/session-bus/tools.ts +5 -4
  184. package/extensions/session-bus/types.ts +19 -0
  185. package/extensions/session-bus/{tui.ts → view/session-list.ts} +16 -16
  186. package/extensions/subagent/agents.ts +1 -1
  187. package/extensions/subagent/commands.ts +4 -2
  188. package/extensions/subagent/format.ts +15 -15
  189. package/extensions/subagent/index.ts +1 -1
  190. package/extensions/subagent/render.ts +3 -3
  191. package/extensions/subagent/{background-tui.ts → view/agents-board.ts} +11 -11
  192. package/extensions/team/commands.ts +24 -5
  193. package/extensions/team/dispatch.ts +18 -4
  194. package/extensions/team/format.ts +17 -2
  195. package/extensions/team/index.ts +9 -8
  196. package/extensions/team/schema.ts +6 -5
  197. package/extensions/team/tools.ts +107 -45
  198. package/extensions/team/types.ts +3 -2
  199. package/extensions/todo/commands.ts +4 -2
  200. package/extensions/todo/format.ts +11 -0
  201. package/extensions/todo/render.ts +57 -0
  202. package/extensions/todo/runtime.ts +1 -1
  203. package/extensions/todo/tools.ts +1 -1
  204. package/extensions/todo/{tui.ts → view/todo-screen.ts} +18 -90
  205. package/extensions/todo/widget.ts +47 -0
  206. package/extensions/watch/commands.ts +4 -2
  207. package/extensions/watch/format.ts +36 -7
  208. package/extensions/watch/render.ts +57 -0
  209. package/extensions/watch/runtime.ts +27 -22
  210. package/extensions/watch/tools.ts +4 -4
  211. package/extensions/watch/{tui.ts → view/watch-screen.ts} +18 -80
  212. package/extensions/web-access/fetch/tool.ts +12 -4
  213. package/extensions/wechat/commands/commands.ts +18 -14
  214. package/extensions/wechat/index.ts +72 -37
  215. package/extensions/wechat/state/credentials.ts +1 -1
  216. package/extensions/wechat/state/state.ts +1 -1
  217. package/extensions/wechat/text/status.ts +112 -0
  218. package/extensions/wechat/types.ts +2 -2
  219. package/extensions/wechat/view/status-screen.ts +4 -103
  220. package/extensions/worktree/commands.ts +11 -9
  221. package/extensions/worktree/enter.ts +2 -2
  222. package/extensions/worktree/exit.ts +2 -2
  223. package/extensions/worktree/index.ts +5 -5
  224. package/extensions/worktree/screen.ts +3 -3
  225. package/extensions/worktree/status.ts +2 -2
  226. package/extensions/worktree/tools.ts +113 -116
  227. package/lib/README.md +28 -13
  228. package/lib/board/actions.ts +111 -0
  229. package/lib/board/artifact.ts +149 -0
  230. package/lib/board/card.ts +163 -52
  231. package/lib/board/config.ts +58 -0
  232. package/lib/board/contract.ts +113 -0
  233. package/lib/board/join.ts +38 -0
  234. package/lib/board/lanes.ts +182 -0
  235. package/lib/board/lead.ts +130 -0
  236. package/lib/board/limits.ts +78 -0
  237. package/lib/board/links.ts +31 -10
  238. package/lib/board/page-pointer.ts +30 -5
  239. package/lib/board/read.ts +83 -0
  240. package/lib/board/reason.ts +102 -0
  241. package/lib/board/round-text.ts +68 -6
  242. package/lib/board/round.ts +31 -15
  243. package/lib/board/rules.ts +151 -307
  244. package/lib/board/seat.ts +35 -0
  245. package/lib/board/session.ts +199 -51
  246. package/lib/board/skipped.ts +22 -0
  247. package/lib/board/steps.ts +487 -0
  248. package/lib/board/store.ts +119 -36
  249. package/lib/board/tone.ts +92 -0
  250. package/lib/board/view.ts +81 -63
  251. package/lib/bus-request.ts +83 -0
  252. package/{extensions/watch → lib}/child.ts +40 -21
  253. package/lib/env.ts +65 -7
  254. package/lib/format.ts +13 -0
  255. package/lib/http/index.ts +17 -11
  256. package/lib/http/mount.ts +142 -0
  257. package/lib/http/port.ts +30 -0
  258. package/lib/http/serve.ts +170 -46
  259. package/lib/http/server.ts +3 -3
  260. package/lib/lazy.ts +45 -0
  261. package/lib/plan-entry.ts +46 -21
  262. package/lib/plans/paths.ts +82 -0
  263. package/lib/policy.ts +9 -6
  264. package/lib/report.ts +3 -2
  265. package/lib/requirements.ts +10 -10
  266. package/lib/session-label.ts +129 -7
  267. package/lib/session-roster.ts +43 -1
  268. package/lib/session-tool.ts +39 -22
  269. package/lib/stray-fields.ts +7 -2
  270. package/lib/tool-names.ts +5 -10
  271. package/lib/tui/README.md +29 -11
  272. package/lib/tui/chrome.ts +16 -15
  273. package/lib/tui/cursor.ts +18 -3
  274. package/lib/tui/glyphs.ts +11 -11
  275. package/lib/tui/render-cache.ts +29 -0
  276. package/lib/tui/tokens.ts +33 -2
  277. package/lib/tui/tool.ts +33 -4
  278. package/lib/web/README.md +21 -0
  279. package/lib/web/client-runtime.ts +27 -1
  280. package/lib/web/components.ts +5 -1
  281. package/lib/web/index.ts +1 -0
  282. package/lib/web/markdown.ts +83 -0
  283. package/lib/web/markup.ts +20 -2
  284. package/lib/web/runtime.ts +9 -10
  285. package/package.json +8 -2
  286. package/skills/init/SKILL.md +5 -5
  287. package/skills/next/SKILL.md +3 -5
  288. package/extensions/board/config.ts +0 -36
  289. package/extensions/board/seat.ts +0 -28
  290. package/lib/tui/index.ts +0 -34
  291. package/skills/project-docs/SKILL.md +0 -133
  292. package/skills/project-docs/references/audit.md +0 -131
  293. package/skills/project-docs/references/changelog.md +0 -105
  294. package/skills/project-docs/references/discovery.md +0 -127
  295. package/skills/project-docs/references/readme.md +0 -80
  296. package/skills/project-docs/references/release.md +0 -84
  297. package/skills/project-docs/references/roadmap.md +0 -93
  298. package/skills/project-docs/scripts/state.ts +0 -316
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The `cancel_plan_mode` tool registration.
2
+ * The `cancel` action of the `plan` tool.
3
3
  *
4
4
  * This is the escape hatch that does not need a plan file or a review dialog:
5
5
  * when the user asks to leave planning, the model can restore write access
@@ -7,73 +7,38 @@
7
7
  * still review the saved artifact.
8
8
  */
9
9
 
10
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
11
- import { Type } from "typebox";
12
- import { reuseText, toolDetails } from "../../../lib/tui/chrome.ts";
10
+ import type { AgentToolResult, ExtensionToolContext, Theme } from "@earendil-works/pi-coding-agent";
13
11
  import { paint } from "../../../lib/tui/tokens.ts";
14
- import { callLine, detailsOrLine } from "../../../lib/tui/tool.ts";
15
- import { failedResult } from "../../../lib/tool-result.ts";
16
- import { CANCEL_TOOL, type PlanRuntime } from "../runtime.ts";
17
- import type { CancelPlanModeDetails } from "../types.ts";
12
+ import { callLine, type ToolCallText } from "../../../lib/tui/tool.ts";
13
+ import { planRefusal } from "./refusal.ts";
14
+ import { PLAN_TOOL, type PlanRuntime } from "../runtime.ts";
15
+ import type { CancelPlanModeDetails, PlanDetails } from "../types.ts";
18
16
 
19
17
  const CANCELLED_TEXT =
20
18
  "Plan mode is off and write access is restored. The plan was not approved; no todo items or goal were recorded. " +
21
19
  "Any saved plan file remains for a later review.";
22
20
 
23
- export function registerCancelTool(pi: ExtensionAPI, runtime: PlanRuntime): void {
24
- pi.registerTool({
25
- name: CANCEL_TOOL,
26
- label: "Cancel plan mode",
27
- description:
28
- "Leave plan mode without approving a plan. Restores write access; no todo items or goal are recorded. " +
29
- "Use when the user asks to exit, cancel, or abandon planning.",
30
- promptSnippet: "Leave plan mode without approving the plan.",
31
- promptGuidelines: [
32
- "Call cancel_plan_mode when the user asks to leave or abandon planning without approving a plan.",
33
- ],
34
- parameters: Type.Object({}),
35
- defaultActive: false,
36
- executionMode: "sequential",
37
- // The mode change touches no files; like enter_plan_mode, it needs no
38
- // destructive annotation.
39
- annotations: { readOnlyHint: true, openWorldHint: false },
40
-
41
- async execute(_toolCallId, _params, _signal, _onUpdate, ctx) {
42
- if (!runtime.isEnabled()) {
43
- return failedResult("Not in plan mode; there is nothing to cancel.", {
44
- cancelled: false,
45
- } satisfies CancelPlanModeDetails);
46
- }
47
- runtime.disable(ctx);
48
- ctx.ui.notify("Plan mode off — full access restored. The plan was not approved.", "info");
49
- return {
50
- content: [{ type: "text", text: CANCELLED_TEXT }],
51
- details: { cancelled: true } satisfies CancelPlanModeDetails,
52
- };
53
- },
21
+ export async function executeCancel(
22
+ runtime: PlanRuntime,
23
+ ctx: ExtensionToolContext,
24
+ ): Promise<AgentToolResult<PlanDetails>> {
25
+ if (!runtime.isEnabled()) {
26
+ return planRefusal("cancel", "Not in plan mode; there is nothing to cancel.");
27
+ }
28
+ runtime.disable(ctx);
29
+ ctx.ui.notify("Plan mode off — full access restored. The plan was not approved.", "info");
30
+ return {
31
+ content: [{ type: "text", text: CANCELLED_TEXT }],
32
+ details: { action: "cancel", cancelled: true } satisfies CancelPlanModeDetails,
33
+ };
34
+ }
54
35
 
55
- renderCall(_args, theme, context) {
56
- return callLine(theme, context?.lastComponent, CANCEL_TOOL, "left plan mode");
57
- },
36
+ export function callCancel(theme: Theme, last: unknown): ToolCallText {
37
+ return callLine(theme, last, PLAN_TOOL, "cancel");
38
+ }
58
39
 
59
- renderResult(result, options, theme, context) {
60
- const text = reuseText(context?.lastComponent);
61
- const outcome = detailsOrLine(
62
- theme,
63
- result,
64
- options.expanded,
65
- toolDetails<CancelPlanModeDetails>(result.details),
66
- );
67
- if ("line" in outcome) {
68
- text.setText(outcome.line);
69
- return text;
70
- }
71
- text.setText(
72
- outcome.details.cancelled
73
- ? paint(theme, "warn", "Plan mode off — plan not approved")
74
- : paint(theme, "meta", "Not in plan mode"),
75
- );
76
- return text;
77
- },
78
- });
40
+ export function textCancel(details: CancelPlanModeDetails, theme: Theme): string {
41
+ return details.cancelled
42
+ ? paint(theme, "warn", "Plan mode off — plan not approved")
43
+ : paint(theme, "meta", "Not in plan mode");
79
44
  }
@@ -1,98 +1,72 @@
1
1
  /**
2
- * The `enter_plan_mode` tool registration.
2
+ * The `enter` action of the `plan` tool.
3
3
  *
4
4
  * It asks for confirmation, then turns the runtime's enabled flag on; the tool
5
5
  * gating and persistence belong to `runtime.ts`.
6
6
  */
7
7
 
8
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
9
- import { Type } from "typebox";
10
- import { reuseText, toolDetails } from "../../../lib/tui/chrome.ts";
11
- import { GLYPHS } from "../../../lib/tui/glyphs.ts";
12
- import { paint } from "../../../lib/tui/tokens.ts";
13
- import { callLine, detailsOrLine } from "../../../lib/tui/tool.ts";
14
- import { failedResult } from "../../../lib/tool-result.ts";
8
+ import type { AgentToolResult, ExtensionToolContext, Theme } from "@earendil-works/pi-coding-agent";
15
9
  import { isRemoteTurn, remoteLanguage } from "../../../lib/interaction.ts";
16
10
  import { PLAN_CONSENT, PLAN_CONSENT_SHORT, PLAN_CONSENT_SHORT_ZH, READ_ONLY_SUMMARY } from "../../../lib/plan-entry.ts";
17
- import { ENTER_TOOL, type PlanRuntime } from "../runtime.ts";
11
+ import { failedResult } from "../../../lib/tool-result.ts";
12
+ import { GLYPHS } from "../../../lib/tui/glyphs.ts";
13
+ import { paint } from "../../../lib/tui/tokens.ts";
14
+ import { callLine, type ToolCallText } from "../../../lib/tui/tool.ts";
15
+ import { PLAN_TOOL, type PlanRuntime } from "../runtime.ts";
18
16
  import type { EnterPlanModeDetails } from "../types.ts";
19
17
 
20
18
  const ENTERED_TEXT =
21
- "You are now in plan mode. Explore read-only, then save the full plan with write_plan (a short title and the markdown) " +
22
- "and call exit_plan_mode with the returned path so the user can read the file and choose. " +
19
+ "You are now in plan mode. Explore read-only, then save the full plan with `plan` action `write` (a short title and the " +
20
+ "markdown) and call `plan` action `exit` with the returned plan_path so the user can read the file and choose. " +
23
21
  `While planning, ${READ_ONLY_SUMMARY}.`;
24
22
 
25
- export function registerEnterTool(pi: ExtensionAPI, runtime: PlanRuntime): void {
26
- pi.registerTool({
27
- name: ENTER_TOOL,
28
- label: "Enter plan mode",
29
- description:
30
- "Enter read-only plan mode: investigate and design, then save the plan with write_plan and present it with " +
31
- "exit_plan_mode. Entering switches the session's active tool set to read-only and requires the user to confirm.",
32
- promptSnippet: "Ask the user to enter read-only plan mode.",
33
- promptGuidelines: [
34
- "Call enter_plan_mode before a non-trivial implementation task; skip it for small, obvious changes.",
35
- ],
36
- parameters: Type.Object({}),
37
- executionMode: "sequential",
38
- // readOnlyHint stays true: entering plan mode changes only the session's
39
- // tool set, never files or system state, so it needs no approval.
40
- annotations: { readOnlyHint: true, openWorldHint: false },
41
-
42
- async execute(_toolCallId, _params, _signal, _onUpdate, ctx) {
43
- if (runtime.isEnabled()) {
44
- return {
45
- content: [{ type: "text", text: "Already in plan mode." }],
46
- details: { entered: true, already: true } satisfies EnterPlanModeDetails,
47
- };
48
- }
49
- if (!ctx.hasUI) {
50
- return failedResult(
51
- "No interactive UI is available to confirm entering plan mode. Ask the user whether they want a plan.",
52
- { entered: false, unavailable: true } satisfies EnterPlanModeDetails,
53
- );
54
- }
23
+ export async function executeEnter(
24
+ runtime: PlanRuntime,
25
+ ctx: ExtensionToolContext,
26
+ ): Promise<AgentToolResult<EnterPlanModeDetails>> {
27
+ if (runtime.isEnabled()) {
28
+ return {
29
+ content: [{ type: "text", text: "Already in plan mode." }],
30
+ details: { action: "enter", entered: true, already: true } satisfies EnterPlanModeDetails,
31
+ };
32
+ }
33
+ if (!ctx.hasUI) {
34
+ return failedResult(
35
+ "No interactive UI is available to confirm entering plan mode. Ask the user whether they want a plan.",
36
+ { action: "enter", entered: false, unavailable: true } satisfies EnterPlanModeDetails,
37
+ );
38
+ }
55
39
 
56
- const consent = isRemoteTurn(ctx)
57
- ? remoteLanguage(ctx) === "zh"
58
- ? PLAN_CONSENT_SHORT_ZH
59
- : PLAN_CONSENT_SHORT
60
- : PLAN_CONSENT;
61
- const approved = await ctx.ui.confirm("Enter plan mode?", consent);
62
- if (!approved) {
63
- return {
64
- content: [{ type: "text", text: "Stayed in normal mode. Proceed, or ask the user how to continue." }],
65
- details: { entered: false } satisfies EnterPlanModeDetails,
66
- };
67
- }
68
- runtime.enable(ctx);
69
- if (isRemoteTurn(ctx)) {
70
- // The peer UI has no footer chip; say the mode and its exit in the chat.
71
- ctx.ui.notify("Plan mode on — write access is off. Say “exit plan mode” to leave without approving.", "info");
72
- }
73
- return {
74
- content: [{ type: "text", text: ENTERED_TEXT }],
75
- details: { entered: true } satisfies EnterPlanModeDetails,
76
- };
77
- },
40
+ const consent = isRemoteTurn(ctx)
41
+ ? remoteLanguage(ctx) === "zh"
42
+ ? PLAN_CONSENT_SHORT_ZH
43
+ : PLAN_CONSENT_SHORT
44
+ : PLAN_CONSENT;
45
+ const approved = await ctx.ui.confirm("Enter plan mode?", consent);
46
+ if (!approved) {
47
+ return {
48
+ content: [{ type: "text", text: "Stayed in normal mode. Proceed, or ask the user how to continue." }],
49
+ details: { action: "enter", entered: false } satisfies EnterPlanModeDetails,
50
+ };
51
+ }
52
+ runtime.enable(ctx);
53
+ if (isRemoteTurn(ctx)) {
54
+ // The peer UI has no footer chip; say the mode and its exit in the chat.
55
+ ctx.ui.notify("Plan mode on — write access is off. Say “exit plan mode” to leave without approving.", "info");
56
+ }
57
+ return {
58
+ content: [{ type: "text", text: ENTERED_TEXT }],
59
+ details: { action: "enter", entered: true } satisfies EnterPlanModeDetails,
60
+ };
61
+ }
78
62
 
79
- renderCall(_args, theme, context) {
80
- return callLine(theme, context?.lastComponent, ENTER_TOOL, "requested plan mode");
81
- },
63
+ export function callEnter(theme: Theme, last: unknown): ToolCallText {
64
+ return callLine(theme, last, PLAN_TOOL, "enter");
65
+ }
82
66
 
83
- renderResult(result, options, theme, context) {
84
- const text = reuseText(context?.lastComponent);
85
- const outcome = detailsOrLine(theme, result, options.expanded, toolDetails<EnterPlanModeDetails>(result.details));
86
- if ("line" in outcome) {
87
- text.setText(outcome.line);
88
- return text;
89
- }
90
- const details = outcome.details;
91
- if (details.unavailable) text.setText(paint(theme, "warn", "No UI to confirm plan mode"));
92
- else if (details.already) text.setText(paint(theme, "meta", "Already in plan mode"));
93
- else if (details.entered) text.setText(paint(theme, "ok", `${GLYPHS.check} Plan mode enabled`));
94
- else text.setText(paint(theme, "meta", "Stayed in normal mode"));
95
- return text;
96
- },
97
- });
67
+ export function textEnter(details: EnterPlanModeDetails, theme: Theme): string {
68
+ if (details.unavailable) return paint(theme, "warn", "No UI to confirm plan mode");
69
+ if (details.already) return paint(theme, "meta", "Already in plan mode");
70
+ if (details.entered) return paint(theme, "ok", `${GLYPHS.check} Plan mode enabled`);
71
+ return paint(theme, "meta", "Stayed in normal mode");
98
72
  }