@x-code-cli/core 0.1.11 → 0.2.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 (111) hide show
  1. package/dist/agent/api-errors.d.ts.map +1 -1
  2. package/dist/agent/api-errors.js +18 -0
  3. package/dist/agent/api-errors.js.map +1 -1
  4. package/dist/agent/diff.d.ts +35 -0
  5. package/dist/agent/diff.d.ts.map +1 -0
  6. package/dist/agent/diff.js +83 -0
  7. package/dist/agent/diff.js.map +1 -0
  8. package/dist/agent/loop-state.d.ts +45 -3
  9. package/dist/agent/loop-state.d.ts.map +1 -1
  10. package/dist/agent/loop-state.js +24 -3
  11. package/dist/agent/loop-state.js.map +1 -1
  12. package/dist/agent/loop.d.ts +10 -6
  13. package/dist/agent/loop.d.ts.map +1 -1
  14. package/dist/agent/loop.js +212 -30
  15. package/dist/agent/loop.js.map +1 -1
  16. package/dist/agent/plan-storage.d.ts +55 -0
  17. package/dist/agent/plan-storage.d.ts.map +1 -0
  18. package/dist/agent/plan-storage.js +156 -0
  19. package/dist/agent/plan-storage.js.map +1 -0
  20. package/dist/agent/session-store.d.ts +114 -0
  21. package/dist/agent/session-store.d.ts.map +1 -0
  22. package/dist/agent/session-store.js +415 -0
  23. package/dist/agent/session-store.js.map +1 -0
  24. package/dist/agent/sub-agents/built-in.d.ts +3 -0
  25. package/dist/agent/sub-agents/built-in.d.ts.map +1 -0
  26. package/dist/agent/sub-agents/built-in.js +98 -0
  27. package/dist/agent/sub-agents/built-in.js.map +1 -0
  28. package/dist/agent/sub-agents/index.d.ts +7 -0
  29. package/dist/agent/sub-agents/index.d.ts.map +1 -0
  30. package/dist/agent/sub-agents/index.js +5 -0
  31. package/dist/agent/sub-agents/index.js.map +1 -0
  32. package/dist/agent/sub-agents/loader.d.ts +5 -0
  33. package/dist/agent/sub-agents/loader.d.ts.map +1 -0
  34. package/dist/agent/sub-agents/loader.js +117 -0
  35. package/dist/agent/sub-agents/loader.js.map +1 -0
  36. package/dist/agent/sub-agents/registry.d.ts +14 -0
  37. package/dist/agent/sub-agents/registry.d.ts.map +1 -0
  38. package/dist/agent/sub-agents/registry.js +37 -0
  39. package/dist/agent/sub-agents/registry.js.map +1 -0
  40. package/dist/agent/sub-agents/runner.d.ts +26 -0
  41. package/dist/agent/sub-agents/runner.d.ts.map +1 -0
  42. package/dist/agent/sub-agents/runner.js +287 -0
  43. package/dist/agent/sub-agents/runner.js.map +1 -0
  44. package/dist/agent/sub-agents/types.d.ts +63 -0
  45. package/dist/agent/sub-agents/types.d.ts.map +1 -0
  46. package/dist/agent/sub-agents/types.js +2 -0
  47. package/dist/agent/sub-agents/types.js.map +1 -0
  48. package/dist/agent/system-prompt.d.ts +15 -0
  49. package/dist/agent/system-prompt.d.ts.map +1 -1
  50. package/dist/agent/system-prompt.js +161 -0
  51. package/dist/agent/system-prompt.js.map +1 -1
  52. package/dist/agent/tool-execution.d.ts +4 -3
  53. package/dist/agent/tool-execution.d.ts.map +1 -1
  54. package/dist/agent/tool-execution.js +316 -14
  55. package/dist/agent/tool-execution.js.map +1 -1
  56. package/dist/agent/tool-result-sanitize.d.ts +12 -0
  57. package/dist/agent/tool-result-sanitize.d.ts.map +1 -1
  58. package/dist/agent/tool-result-sanitize.js +70 -0
  59. package/dist/agent/tool-result-sanitize.js.map +1 -1
  60. package/dist/config/index.d.ts +6 -0
  61. package/dist/config/index.d.ts.map +1 -1
  62. package/dist/config/index.js.map +1 -1
  63. package/dist/index.d.ts +11 -5
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +10 -3
  66. package/dist/index.js.map +1 -1
  67. package/dist/knowledge/session.d.ts +4 -7
  68. package/dist/knowledge/session.d.ts.map +1 -1
  69. package/dist/knowledge/session.js +20 -55
  70. package/dist/knowledge/session.js.map +1 -1
  71. package/dist/permissions/index.d.ts +18 -3
  72. package/dist/permissions/index.d.ts.map +1 -1
  73. package/dist/permissions/index.js +20 -2
  74. package/dist/permissions/index.js.map +1 -1
  75. package/dist/tools/ask-user.d.ts.map +1 -1
  76. package/dist/tools/ask-user.js +8 -6
  77. package/dist/tools/ask-user.js.map +1 -1
  78. package/dist/tools/enter-plan-mode.d.ts +25 -0
  79. package/dist/tools/enter-plan-mode.d.ts.map +1 -0
  80. package/dist/tools/enter-plan-mode.js +120 -0
  81. package/dist/tools/enter-plan-mode.js.map +1 -0
  82. package/dist/tools/exit-plan-mode.d.ts +13 -0
  83. package/dist/tools/exit-plan-mode.d.ts.map +1 -0
  84. package/dist/tools/exit-plan-mode.js +22 -0
  85. package/dist/tools/exit-plan-mode.js.map +1 -0
  86. package/dist/tools/grep.d.ts +1 -1
  87. package/dist/tools/index.d.ts +20 -4
  88. package/dist/tools/index.d.ts.map +1 -1
  89. package/dist/tools/index.js +7 -1
  90. package/dist/tools/index.js.map +1 -1
  91. package/dist/tools/save-knowledge.d.ts +2 -2
  92. package/dist/tools/shell-provider.d.ts +4 -0
  93. package/dist/tools/shell-provider.d.ts.map +1 -1
  94. package/dist/tools/shell-provider.js +2 -0
  95. package/dist/tools/shell-provider.js.map +1 -1
  96. package/dist/tools/task.d.ts +14 -0
  97. package/dist/tools/task.d.ts.map +1 -0
  98. package/dist/tools/task.js +95 -0
  99. package/dist/tools/task.js.map +1 -0
  100. package/dist/tools/todo-write.d.ts +21 -0
  101. package/dist/tools/todo-write.d.ts.map +1 -0
  102. package/dist/tools/todo-write.js +117 -0
  103. package/dist/tools/todo-write.js.map +1 -0
  104. package/dist/types/index.d.ts +103 -0
  105. package/dist/types/index.d.ts.map +1 -1
  106. package/dist/types/index.js.map +1 -1
  107. package/package.json +1 -1
  108. package/dist/knowledge/session-usage.d.ts +0 -24
  109. package/dist/knowledge/session-usage.d.ts.map +0 -1
  110. package/dist/knowledge/session-usage.js +0 -86
  111. package/dist/knowledge/session-usage.js.map +0 -1
@@ -0,0 +1,120 @@
1
+ // @x-code-cli/core — enterPlanMode tool (mode switch, no execute — handled in agent loop)
2
+ import { tool } from 'ai';
3
+ import { z } from 'zod';
4
+ /** The tool description below is the heart of plan-mode auto-trigger
5
+ * behavior — it's what the model reads in the tool list and uses to
6
+ * decide whether to recommend plan mode. Ported (with naming
7
+ * adjustments for our tool surface) from Claude Code's
8
+ * `EnterPlanModeTool/prompt.ts` external-user prompt
9
+ * (`/d/res/claude-code/src/tools/EnterPlanModeTool/prompt.ts:16-99`).
10
+ *
11
+ * WHY THIS IS LONG: a one-line description ("use for complex tasks")
12
+ * produces a model that almost never calls the tool — it has no
13
+ * concrete trigger pattern to match against the user's request. CC's
14
+ * prompt deliberately includes 7 numbered criteria, multiple worked
15
+ * examples per criterion, and an explicit "PREFER plan mode unless
16
+ * simple" anchor — that's what gets the model to actually recommend
17
+ * plan mode for refactors, new features, architectural decisions,
18
+ * etc. The token cost (~600 tokens in tool list each turn) is what
19
+ * buys the auto-trigger behavior; without it plan mode is dead UX.
20
+ *
21
+ * No `execute` field — the side-effect (asking the user to confirm,
22
+ * mutating LoopState.permissionMode, invalidating the system-prompt
23
+ * cache) is handled manually in `processToolCalls`. Same pattern as
24
+ * `askUser`. */
25
+ export const enterPlanMode = tool({
26
+ description: `Use this tool proactively when you're about to start a non-trivial implementation task. Getting user sign-off on your approach before writing code prevents wasted effort and ensures alignment. This tool transitions you into plan mode where you can explore the codebase and design an implementation approach for user approval.
27
+
28
+ ## When to Use This Tool
29
+
30
+ **Prefer using enterPlanMode** for implementation tasks unless they're simple. Use it when ANY of these conditions apply:
31
+
32
+ 1. **New Feature Implementation**: Adding meaningful new functionality
33
+ - Example: "Add a logout button" - where should it go? What should happen on click?
34
+ - Example: "Add form validation" - what rules? What error messages?
35
+
36
+ 2. **Multiple Valid Approaches**: The task can be solved in several different ways
37
+ - Example: "Add caching to the API" - could use Redis, in-memory, file-based, etc.
38
+ - Example: "Improve performance" - many optimization strategies possible
39
+
40
+ 3. **Code Modifications**: Changes that affect existing behavior or structure
41
+ - Example: "Update the login flow" - what exactly should change?
42
+ - Example: "Refactor this component" - what's the target architecture?
43
+
44
+ 4. **Architectural Decisions**: The task requires choosing between patterns or technologies
45
+ - Example: "Add real-time updates" - WebSockets vs SSE vs polling
46
+ - Example: "Implement state management" - Redux vs Context vs custom solution
47
+
48
+ 5. **Multi-File Changes**: The task will likely touch more than 2-3 files
49
+ - Example: "Refactor the authentication system"
50
+ - Example: "Add a new API endpoint with tests"
51
+
52
+ 6. **Unclear Requirements**: You need to explore before understanding the full scope
53
+ - Example: "Make the app faster" - need to profile and identify bottlenecks
54
+ - Example: "Fix the bug in checkout" - need to investigate root cause
55
+
56
+ 7. **User Preferences Matter**: The implementation could reasonably go multiple ways
57
+ - If you would use askUser to clarify the approach, use enterPlanMode instead
58
+ - Plan mode lets you explore first, then present options with context
59
+
60
+ ## When NOT to Use This Tool
61
+
62
+ Only skip enterPlanMode for simple tasks:
63
+ - Single-line or few-line fixes (typos, obvious bugs, small tweaks)
64
+ - Adding a single function with clear requirements
65
+ - Tasks where the user has given very specific, detailed instructions
66
+ - Pure research / "what does X do" questions — just answer them directly
67
+
68
+ ## What Happens in Plan Mode
69
+
70
+ In plan mode, you'll:
71
+ 1. Thoroughly explore the codebase using readFile, glob, grep, and listDir
72
+ 2. Understand existing patterns and architecture
73
+ 3. Design an implementation approach
74
+ 4. Use askUser to clarify approaches with the user when needed
75
+ 5. Write the plan incrementally to a session-scoped plan file
76
+ 6. Exit plan mode with exitPlanMode when ready to implement
77
+
78
+ ## Examples
79
+
80
+ ### GOOD - Use enterPlanMode:
81
+ User: "Add user authentication to the app"
82
+ - Requires architectural decisions (session vs JWT, where to store tokens, middleware structure)
83
+
84
+ User: "Optimize the database queries"
85
+ - Multiple approaches possible, need to profile first, significant impact
86
+
87
+ User: "Implement dark mode"
88
+ - Architectural decision on theme system, affects many components
89
+
90
+ User: "Add a delete button to the user profile"
91
+ - Seems simple but involves: where to place it, confirmation dialog, API call, error handling, state updates
92
+
93
+ User: "Update the error handling in the API"
94
+ - Affects multiple files, user should approve the approach
95
+
96
+ ### BAD - Don't use enterPlanMode:
97
+ User: "Fix the typo in the README"
98
+ - Straightforward, no planning needed
99
+
100
+ User: "Add a console.log to debug this function"
101
+ - Simple, obvious implementation
102
+
103
+ User: "What files handle routing?"
104
+ - Research / Q&A task, not implementation — just answer
105
+
106
+ ## Important Notes
107
+
108
+ - This tool REQUIRES user approval — they must consent to entering plan mode (an approval dialog appears).
109
+ - If unsure whether to use it, err on the side of planning — it's better to get alignment upfront than to redo work.
110
+ - Do not call enterPlanMode if you are already in plan mode (check the system prompt; if you see plan-mode instructions you are already in it).`,
111
+ inputSchema: z.object({
112
+ topic: z
113
+ .string()
114
+ .min(1)
115
+ .max(60)
116
+ .optional()
117
+ .describe('STRONGLY RECOMMENDED. A 3-5 word English filename slug summarizing the user\'s task. Lowercase, hyphen-separated, no spaces or special chars. The plan file is named `<topic>-<YYYYMMDD-HHMMSS>.md` so this makes the file identifiable in `ls .x-code/plans/`. Translate non-English requests into English keywords (e.g. user asks "重构这个项目" → topic: "refactor-x-code-cli"; user asks "加 OAuth 登录" → topic: "add-oauth-login"). Omit only when you genuinely cannot summarize — the file then falls back to timestamp-only naming.'),
118
+ }),
119
+ });
120
+ //# sourceMappingURL=enter-plan-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enter-plan-mode.js","sourceRoot":"","sources":["../../src/tools/enter-plan-mode.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;;;;;;;;;;;;;iBAoBiB;AACjB,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gJAoFiI;IAC9I,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,KAAK,EAAE,CAAC;aACL,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,EAAE,CAAC;aACP,QAAQ,EAAE;aACV,QAAQ,CACP,sgBAAsgB,CACvgB;KACJ,CAAC;CACH,CAAC,CAAA"}
@@ -0,0 +1,13 @@
1
+ /** Present the plan to the user for approval. The user sees a Yes/No
2
+ * dialog with the plan body inline; on Yes, the session leaves plan mode
3
+ * and the next turn can write code; on No, the session stays in plan
4
+ * mode and the model is told to revise.
5
+ *
6
+ * No `execute` field — the dispatch path in `processToolCalls` reads the
7
+ * plan file, calls `callbacks.onPlanApprovalRequest(planText)`, and
8
+ * feeds the verdict back as a synthetic tool result so the model knows
9
+ * whether to proceed or iterate. */
10
+ export declare const exitPlanMode: import("ai").Tool<{
11
+ plan?: string | undefined;
12
+ }, never>;
13
+ //# sourceMappingURL=exit-plan-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-plan-mode.d.ts","sourceRoot":"","sources":["../../src/tools/exit-plan-mode.ts"],"names":[],"mappings":"AAKA;;;;;;;;qCAQqC;AACrC,eAAO,MAAM,YAAY;;SAWvB,CAAA"}
@@ -0,0 +1,22 @@
1
+ // @x-code-cli/core — exitPlanMode tool (user-approval gate, no execute — handled in agent loop)
2
+ import { tool } from 'ai';
3
+ import { z } from 'zod';
4
+ /** Present the plan to the user for approval. The user sees a Yes/No
5
+ * dialog with the plan body inline; on Yes, the session leaves plan mode
6
+ * and the next turn can write code; on No, the session stays in plan
7
+ * mode and the model is told to revise.
8
+ *
9
+ * No `execute` field — the dispatch path in `processToolCalls` reads the
10
+ * plan file, calls `callbacks.onPlanApprovalRequest(planText)`, and
11
+ * feeds the verdict back as a synthetic tool result so the model knows
12
+ * whether to proceed or iterate. */
13
+ export const exitPlanMode = tool({
14
+ description: 'Use this tool when you are in plan mode and have finished writing your plan to the plan file and are ready for user approval. This tool reads the plan from the file you wrote during planning — pass an optional `plan` parameter only if you want to override what is in the file. The user sees the plan content in an approval dialog and chooses Yes/No. The model cannot leave plan mode without user approval; if rejected, revise the plan file (using edit) and call this again. Do NOT use this for research / Q&A — only when the user has asked you to implement something and you have a complete plan written to the plan file. Do NOT use askUser to ask "is this plan okay?" — exitPlanMode is the only correct way to request plan approval.',
15
+ inputSchema: z.object({
16
+ plan: z
17
+ .string()
18
+ .optional()
19
+ .describe('Optional override for the plan body. By default the plan body comes from the plan file you wrote during planning — only pass this argument if you want to use different content (rare).'),
20
+ }),
21
+ });
22
+ //# sourceMappingURL=exit-plan-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-plan-mode.js","sourceRoot":"","sources":["../../src/tools/exit-plan-mode.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;qCAQqC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;IAC/B,WAAW,EACT,+tBAA+tB;IACjuB,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,yLAAyL,CAC1L;KACJ,CAAC;CACH,CAAC,CAAA"}
@@ -1,7 +1,7 @@
1
1
  export declare const grep: import("ai").Tool<{
2
2
  pattern: string;
3
- path?: string | undefined;
4
3
  glob?: string | undefined;
4
+ path?: string | undefined;
5
5
  maxResults?: number | undefined;
6
6
  }, string>;
7
7
  //# sourceMappingURL=grep.d.ts.map
@@ -1,11 +1,14 @@
1
1
  import { askUser } from './ask-user.js';
2
2
  import { edit } from './edit.js';
3
+ import { enterPlanMode } from './enter-plan-mode.js';
4
+ import { exitPlanMode } from './exit-plan-mode.js';
3
5
  import { glob } from './glob.js';
4
6
  import { grep } from './grep.js';
5
7
  import { listDir } from './list-dir.js';
6
8
  import { readFile } from './read-file.js';
7
9
  import { saveKnowledge } from './save-knowledge.js';
8
10
  import { shell } from './shell.js';
11
+ import { todoWrite } from './todo-write.js';
9
12
  import { webFetch } from './web-fetch.js';
10
13
  import { webSearch } from './web-search.js';
11
14
  import { writeFile } from './write-file.js';
@@ -63,8 +66,8 @@ export declare const toolRegistry: {
63
66
  }, string>;
64
67
  grep: import("ai").Tool<{
65
68
  pattern: string;
66
- path?: string | undefined;
67
69
  glob?: string | undefined;
70
+ path?: string | undefined;
68
71
  maxResults?: number | undefined;
69
72
  }, string>;
70
73
  listDir: import("ai").Tool<{
@@ -86,14 +89,27 @@ export declare const toolRegistry: {
86
89
  question: string;
87
90
  }, never>;
88
91
  saveKnowledge: import("ai").Tool<{
89
- category: "user" | "feedback" | "project" | "reference";
92
+ category: "project" | "user" | "feedback" | "reference";
90
93
  action: "add" | "delete";
91
94
  key: string;
92
95
  fact: string;
93
- scope: "project" | "global";
96
+ scope: "global" | "project";
94
97
  }, string>;
98
+ enterPlanMode: import("ai").Tool<{
99
+ topic?: string | undefined;
100
+ }, never>;
101
+ exitPlanMode: import("ai").Tool<{
102
+ plan?: string | undefined;
103
+ }, never>;
104
+ todoWrite: import("ai").Tool<{
105
+ todos: {
106
+ content?: string | undefined;
107
+ status?: "pending" | "in_progress" | "completed" | undefined;
108
+ activeForm?: string | undefined;
109
+ }[];
110
+ }, never>;
95
111
  };
96
- export { readFile, writeFile, edit, shell, glob, grep, listDir, webSearch, webFetch, askUser, saveKnowledge, };
112
+ export { readFile, writeFile, edit, shell, glob, grep, listDir, webSearch, webFetch, askUser, saveKnowledge, enterPlanMode, exitPlanMode, todoWrite, };
97
113
  export { MAX_TOOL_RESULT_LINES, MAX_TOOL_RESULT_BYTES, MAX_AGGREGATE_TOOL_RESULT_BYTES, truncateToolResult, } from './truncate.js';
98
114
  export type { TruncateOptions } from './truncate.js';
99
115
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYxB,CAAA;AAED,OAAO,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,SAAS,EACT,QAAQ,EACR,OAAO,EACP,aAAa,GACd,CAAA;AAED,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,+BAA+B,EAC/B,kBAAkB,GACnB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAexB,CAAA;AAED,OAAO,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,SAAS,EACT,QAAQ,EACR,OAAO,EACP,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,GACV,CAAA;AAED,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,+BAA+B,EAC/B,kBAAkB,GACnB,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA"}
@@ -1,12 +1,15 @@
1
1
  // @x-code-cli/core — Tool registry (unified export)
2
2
  import { askUser } from './ask-user.js';
3
3
  import { edit } from './edit.js';
4
+ import { enterPlanMode } from './enter-plan-mode.js';
5
+ import { exitPlanMode } from './exit-plan-mode.js';
4
6
  import { glob } from './glob.js';
5
7
  import { grep } from './grep.js';
6
8
  import { listDir } from './list-dir.js';
7
9
  import { readFile } from './read-file.js';
8
10
  import { saveKnowledge } from './save-knowledge.js';
9
11
  import { shell } from './shell.js';
12
+ import { todoWrite } from './todo-write.js';
10
13
  import { webFetch } from './web-fetch.js';
11
14
  import { webSearch } from './web-search.js';
12
15
  import { writeFile } from './write-file.js';
@@ -22,7 +25,10 @@ export const toolRegistry = {
22
25
  webFetch,
23
26
  askUser,
24
27
  saveKnowledge,
28
+ enterPlanMode,
29
+ exitPlanMode,
30
+ todoWrite,
25
31
  };
26
- export { readFile, writeFile, edit, shell, glob, grep, listDir, webSearch, webFetch, askUser, saveKnowledge, };
32
+ export { readFile, writeFile, edit, shell, glob, grep, listDir, webSearch, webFetch, askUser, saveKnowledge, enterPlanMode, exitPlanMode, todoWrite, };
27
33
  export { MAX_TOOL_RESULT_LINES, MAX_TOOL_RESULT_BYTES, MAX_AGGREGATE_TOOL_RESULT_BYTES, truncateToolResult, } from './truncate.js';
28
34
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,QAAQ;IACR,SAAS;IACT,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,OAAO;IACP,SAAS;IACT,QAAQ;IACR,OAAO;IACP,aAAa;CACd,CAAA;AAED,OAAO,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,SAAS,EACT,QAAQ,EACR,OAAO,EACP,aAAa,GACd,CAAA;AAED,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,+BAA+B,EAC/B,kBAAkB,GACnB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,QAAQ;IACR,SAAS;IACT,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,OAAO;IACP,SAAS;IACT,QAAQ;IACR,OAAO;IACP,aAAa;IACb,aAAa;IACb,YAAY;IACZ,SAAS;CACV,CAAA;AAED,OAAO,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,SAAS,EACT,QAAQ,EACR,OAAO,EACP,aAAa,EACb,aAAa,EACb,YAAY,EACZ,SAAS,GACV,CAAA;AAED,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,+BAA+B,EAC/B,kBAAkB,GACnB,MAAM,eAAe,CAAA"}
@@ -1,8 +1,8 @@
1
1
  export declare const saveKnowledge: import("ai").Tool<{
2
- category: "user" | "feedback" | "project" | "reference";
2
+ category: "project" | "user" | "feedback" | "reference";
3
3
  action: "add" | "delete";
4
4
  key: string;
5
5
  fact: string;
6
- scope: "project" | "global";
6
+ scope: "global" | "project";
7
7
  }, string>;
8
8
  //# sourceMappingURL=save-knowledge.d.ts.map
@@ -4,6 +4,10 @@ export interface ShellSpawnOptions {
4
4
  timeout: number;
5
5
  env?: NodeJS.ProcessEnv;
6
6
  cwd?: string;
7
+ /** When this signal aborts, execa kills the child process tree. Used to
8
+ * honor user Esc / Ctrl+C cancellation mid-command without waiting for
9
+ * the timeout. */
10
+ signal?: AbortSignal;
7
11
  }
8
12
  export interface ShellProvider {
9
13
  type: ShellType;
@@ -1 +1 @@
1
- {"version":3,"file":"shell-provider.d.ts","sourceRoot":"","sources":["../../src/tools/shell-provider.ts"],"names":[],"mappings":"AAMA,OAAO,EAAS,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;AAGjD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,YAAY,CAAA;AAErD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAA;IACf,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAAA;CAC/D;AA6DD,wBAAgB,gBAAgB,IAAI,aAAa,CAYhD"}
1
+ {"version":3,"file":"shell-provider.d.ts","sourceRoot":"","sources":["../../src/tools/shell-provider.ts"],"names":[],"mappings":"AAMA,OAAO,EAAS,KAAK,aAAa,EAAE,MAAM,OAAO,CAAA;AAGjD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,YAAY,CAAA;AAErD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;uBAEmB;IACnB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,SAAS,CAAA;IACf,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAAA;CAC/D;AA+DD,wBAAgB,gBAAgB,IAAI,aAAa,CAYhD"}
@@ -14,6 +14,7 @@ function createPosixProvider(executable, type) {
14
14
  timeout: opts.timeout,
15
15
  cwd: opts.cwd,
16
16
  reject: false,
17
+ cancelSignal: opts.signal,
17
18
  env: { ...(opts.env ?? process.env), PYTHONIOENCODING: 'utf-8' },
18
19
  });
19
20
  },
@@ -53,6 +54,7 @@ function createPowerShellProvider(executable) {
53
54
  timeout: opts.timeout,
54
55
  cwd: opts.cwd,
55
56
  reject: false,
57
+ cancelSignal: opts.signal,
56
58
  env: { ...(opts.env ?? process.env), PYTHONIOENCODING: 'utf-8' },
57
59
  });
58
60
  },
@@ -1 +1 @@
1
- {"version":3,"file":"shell-provider.js","sourceRoot":"","sources":["../../src/tools/shell-provider.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,EAAE;AACF,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAC9E,0CAA0C;AAC1C,OAAO,EAAE,KAAK,EAAsB,MAAM,OAAO,CAAA;AACjD,OAAO,EAAE,MAAM,SAAS,CAAA;AAexB,SAAS,mBAAmB,CAAC,UAAkB,EAAE,IAAoB;IACnE,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,OAAO,EAAE,IAAI;YACjB,OAAO,KAAK,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;gBACxC,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,MAAM,EAAE,KAAK;gBACb,GAAG,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,gBAAgB,EAAE,OAAO,EAAE;aACjE,CAAC,CAAA;QACJ,CAAC;KACF,CAAA;AACH,CAAC;AAED,+EAA+E;AAC/E,4EAA4E;AAC5E,8EAA8E;AAC9E,yBAAyB;AACzB,SAAS,uBAAuB,CAAC,SAAiB;IAChD,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC7D,CAAC;AAED,SAAS,wBAAwB,CAAC,UAAkB;IAClD,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,KAAK,CAAC,OAAO,EAAE,IAAI;YACjB,6DAA6D;YAC7D,wEAAwE;YACxE,mEAAmE;YACnE,gDAAgD;YAChD,qEAAqE;YACrE,qEAAqE;YACrE,4BAA4B;YAC5B,oEAAoE;YACpE,qEAAqE;YACrE,uEAAuE;YACvE,qEAAqE;YACrE,iEAAiE;YACjE,MAAM,OAAO,GAAG;gBACd,0DAA0D;gBAC1D,0CAA0C;gBAC1C,OAAO;gBACP,qFAAqF;gBACrF,YAAY;aACb,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACZ,OAAO,KAAK,CACV,UAAU,EACV,CAAC,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,uBAAuB,CAAC,OAAO,CAAC,CAAC,EACtF;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,MAAM,EAAE,KAAK;gBACb,GAAG,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,gBAAgB,EAAE,OAAO,EAAE;aACjE,CACF,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,EAAE,CAAC,QAAQ,EAAE,KAAK,OAAO,EAAE,CAAC;QAC9B,wEAAwE;QACxE,6DAA6D;QAC7D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAA;QAC/B,IAAI,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,OAAO,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;QAC3E,CAAC;QACD,OAAO,wBAAwB,CAAC,gBAAgB,CAAC,CAAA;IACnD,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,WAAW,CAAA;IAClD,OAAO,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AACnF,CAAC"}
1
+ {"version":3,"file":"shell-provider.js","sourceRoot":"","sources":["../../src/tools/shell-provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { SubAgentRegistry } from '../agent/sub-agents/registry.js';
2
+ /** Build the task tool description dynamically from the registry.
3
+ * Called once per session when constructing the system prompt cache.
4
+ * The listing of available agents is embedded in the description so
5
+ * the model knows what subagent_type values are valid. */
6
+ export declare function buildTaskToolDescription(registry: SubAgentRegistry): string;
7
+ /** Create the task tool definition. Must be called with the registry
8
+ * so the description includes the available agent list. */
9
+ export declare function createTaskTool(registry: SubAgentRegistry): import("ai").Tool<{
10
+ description: string;
11
+ prompt: string;
12
+ subagent_type: string;
13
+ }, never>;
14
+ //# sourceMappingURL=task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.d.ts","sourceRoot":"","sources":["../../src/tools/task.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAEvE;;;2DAG2D;AAC3D,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAoE3E;AAED;4DAC4D;AAC5D,wBAAgB,cAAc,CAAC,QAAQ,EAAE,gBAAgB;;;;UAcxD"}
@@ -0,0 +1,95 @@
1
+ // @x-code-cli/core — task tool (sub-agent dispatch)
2
+ //
3
+ // The tool definition has no `execute` — dispatch is handled manually
4
+ // in tool-execution.ts's handleToolCall, which calls runSubAgent.
5
+ // This is intentional: the task tool needs access to LoopState,
6
+ // AgentOptions, and callbacks that aren't available in the tool's
7
+ // execute context.
8
+ import { tool } from 'ai';
9
+ import { z } from 'zod';
10
+ /** Build the task tool description dynamically from the registry.
11
+ * Called once per session when constructing the system prompt cache.
12
+ * The listing of available agents is embedded in the description so
13
+ * the model knows what subagent_type values are valid. */
14
+ export function buildTaskToolDescription(registry) {
15
+ const agents = registry.list();
16
+ const agentList = agents
17
+ .map((a) => ` - ${a.name}: ${a.description}`)
18
+ .join('\n');
19
+ return `Launch a sub-agent to handle a task in an isolated context. The sub-agent runs with its own message history and returns only its final conclusion — its intermediate tool calls never enter your context window, keeping the main conversation lean.
20
+
21
+ Available sub-agents:
22
+ ${agentList}
23
+
24
+ ## When to use
25
+
26
+ Use the task tool when intermediate tool output isn't worth keeping in your context:
27
+ - **Research / exploration**: open-ended questions about the codebase ("where is X defined", "find all callers of Y", "what test patterns does this project use")
28
+ - **Code review**: reviewing pending changes or specific files for bugs, security issues, style violations
29
+ - **Implementation planning**: designing an approach that requires reading many files before writing any
30
+ - **Multi-step investigation**: tasks that need 3+ tool calls whose raw output you don't need to see — only the conclusion matters
31
+
32
+ ## When NOT to use
33
+
34
+ Do NOT delegate when a direct tool call is faster or when you need the result in-context:
35
+ - If you want to read a specific file, use readFile directly
36
+ - If you are searching for a specific symbol like "class Foo", use grep directly
37
+ - If you are searching code within 1-3 known files, use readFile directly
38
+ - Simple single-step tasks (typo fix, add a comment, run one command)
39
+ - Tasks where your immediate next step depends on the raw output — do them locally to keep the critical path moving
40
+ - The user asked a simple question you can answer directly
41
+
42
+ ## Writing the prompt
43
+
44
+ Brief the sub-agent like a smart colleague who just walked into the room — it has zero prior context: hasn't seen this conversation, doesn't know what you've tried, doesn't understand why this task matters.
45
+ - Explain what you're trying to accomplish and why.
46
+ - Describe what you've already learned or ruled out.
47
+ - Give enough context about the surrounding problem that the agent can make judgment calls rather than just following a narrow instruction.
48
+ - Include concrete details: file paths, function names, line numbers, error messages.
49
+ - If you need a short response, say so ("report in under 200 words").
50
+ - For lookups: hand over the exact command. For investigations: hand over the question — prescribed steps become dead weight when the premise is wrong.
51
+
52
+ Terse command-style prompts produce shallow, generic work.
53
+
54
+ **Never delegate understanding.** Don't write "based on your findings, fix the bug" or "based on the research, implement it." Those phrases push synthesis onto the agent instead of doing it yourself. Write prompts that prove you understood: include file paths, line numbers, what specifically to change.
55
+
56
+ ## Concurrency safety
57
+
58
+ NEVER launch multiple sub-agents in one turn if they could modify the same files or resources. Only run multiple sub-agents in parallel when their tasks are genuinely independent (e.g., two read-only research questions about different parts of the codebase).
59
+
60
+ ## Example
61
+
62
+ <example>
63
+ user: "Can you check if there are any security issues in the auth module?"
64
+ assistant: I'll have the code reviewer check the auth module.
65
+ task({
66
+ description: "Review auth module security",
67
+ subagent_type: "code-reviewer",
68
+ prompt: "Review the authentication module for security issues. The main auth code lives in src/auth/. Focus on: JWT token handling in src/auth/jwt.ts, session management in src/auth/session.ts, and the login endpoint in src/routes/login.ts. Check for: token expiration handling, secret storage, injection vulnerabilities, and missing input validation. Report a numbered punch list with severity and file:line references."
69
+ })
70
+ </example>
71
+
72
+ <example>
73
+ user: "Fix the typo in README"
74
+ <commentary>Do NOT use task — this is a single-step edit. Just use the edit tool directly.</commentary>
75
+ </example>
76
+
77
+ <example>
78
+ user: "What does the glob tool do?"
79
+ <commentary>Do NOT use task — this is a direct Q&A question you can answer from your own knowledge.</commentary>
80
+ </example>`;
81
+ }
82
+ /** Create the task tool definition. Must be called with the registry
83
+ * so the description includes the available agent list. */
84
+ export function createTaskTool(registry) {
85
+ return tool({
86
+ description: buildTaskToolDescription(registry),
87
+ inputSchema: z.object({
88
+ description: z.string().describe('A short (3-5 words) description of the task'),
89
+ subagent_type: z.string().describe(`Which sub-agent to use. Available: ${registry.names().join(', ')}`),
90
+ prompt: z.string().describe('The complete task instruction sent to the sub-agent. Be specific — the sub-agent has no prior context.'),
91
+ }),
92
+ // No execute — handled manually in tool-execution.ts
93
+ });
94
+ }
95
+ //# sourceMappingURL=task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.js","sourceRoot":"","sources":["../../src/tools/task.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,EAAE;AACF,sEAAsE;AACtE,kEAAkE;AAClE,gEAAgE;AAChE,kEAAkE;AAClE,mBAAmB;AACnB,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AACzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB;;;2DAG2D;AAC3D,MAAM,UAAU,wBAAwB,CAAC,QAA0B;IACjE,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;IAC9B,MAAM,SAAS,GAAG,MAAM;SACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;SAC7C,IAAI,CAAC,IAAI,CAAC,CAAA;IAEb,OAAO;;;EAGP,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA0DA,CAAA;AACX,CAAC;AAED;4DAC4D;AAC5D,MAAM,UAAU,cAAc,CAAC,QAA0B;IACvD,OAAO,IAAI,CAAC;QACV,WAAW,EAAE,wBAAwB,CAAC,QAAQ,CAAC;QAC/C,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;YACpB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;YAC/E,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAChC,sCAAsC,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACpE;YACD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CACzB,wGAAwG,CACzG;SACF,CAAC;QACF,qDAAqD;KACtD,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ /** The model maintains a working checklist via this tool. Each call
2
+ * REPLACES the entire list (no merge / no delta) — the model is told
3
+ * to pass the full updated array every time, including unchanged items.
4
+ * When all items are completed, the agent loop auto-clears the list to
5
+ * free the live UI panel.
6
+ *
7
+ * Storage: in-memory on `LoopState.todos`, mirrored to React state via
8
+ * `callbacks.onTodosUpdate`. Never persisted to disk (matches Claude
9
+ * Code) — checklists are session-scoped working memory, not records.
10
+ *
11
+ * No `execute` field — the side-effect (mutating LoopState.todos and
12
+ * notifying the UI) is handled manually in `processToolCalls`. Same
13
+ * pattern as askUser / enterPlanMode. */
14
+ export declare const todoWrite: import("ai").Tool<{
15
+ todos: {
16
+ content?: string | undefined;
17
+ status?: "pending" | "in_progress" | "completed" | undefined;
18
+ activeForm?: string | undefined;
19
+ }[];
20
+ }, never>;
21
+ //# sourceMappingURL=todo-write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todo-write.d.ts","sourceRoot":"","sources":["../../src/tools/todo-write.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;0CAY0C;AAC1C,eAAO,MAAM,SAAS;;;;;;SAqGpB,CAAA"}
@@ -0,0 +1,117 @@
1
+ // @x-code-cli/core — todoWrite tool (model-managed checklist, no execute — handled in agent loop)
2
+ import { tool } from 'ai';
3
+ import { z } from 'zod';
4
+ /** The model maintains a working checklist via this tool. Each call
5
+ * REPLACES the entire list (no merge / no delta) — the model is told
6
+ * to pass the full updated array every time, including unchanged items.
7
+ * When all items are completed, the agent loop auto-clears the list to
8
+ * free the live UI panel.
9
+ *
10
+ * Storage: in-memory on `LoopState.todos`, mirrored to React state via
11
+ * `callbacks.onTodosUpdate`. Never persisted to disk (matches Claude
12
+ * Code) — checklists are session-scoped working memory, not records.
13
+ *
14
+ * No `execute` field — the side-effect (mutating LoopState.todos and
15
+ * notifying the UI) is handled manually in `processToolCalls`. Same
16
+ * pattern as askUser / enterPlanMode. */
17
+ export const todoWrite = tool({
18
+ description: `Use this tool to track multi-step tasks. The user sees a live checklist (☐ ◼ ✔) above the spinner — it makes long tasks feel structured and gives them visibility into your plan.
19
+
20
+ ## When to Use
21
+
22
+ - Multi-step tasks that involve 3+ logical steps
23
+ - Right after exitPlanMode is approved and you have an approved plan with several files / phases — translate the plan into todos before starting work
24
+ - The user gives multiple requests in one message ("do A, then B, then C")
25
+ - When you start a step (mark it \`in_progress\` BEFORE doing the work)
26
+ - When you finish a step (mark it \`completed\` IMMEDIATELY, not at the end)
27
+
28
+ ## When NOT to Use
29
+
30
+ - Single-file edits, typos, trivial fixes — todos add ceremony with no benefit
31
+ - Pure Q&A or research questions
32
+ - Tasks doable in 1-2 obvious steps
33
+ - Conversational replies that don't involve concrete work
34
+
35
+ ## Hard Rules
36
+
37
+ 1. **Status values**: \`pending\` | \`in_progress\` | \`completed\` (exactly these three).
38
+ 2. **Exactly ONE task in_progress at any time** — not zero, not two. The user reads the in_progress one as "what the agent is doing right now".
39
+ 3. **Mark complete IMMEDIATELY after finishing** — don't batch completions at the end of the run. The user wants live feedback.
40
+ 4. **Only mark complete when truly done** — if tests are failing, the implementation is partial, you hit an error, or you're going to follow up later: leave it as \`in_progress\` and add a NEW pending todo describing the unresolved part.
41
+ 5. **Provide both \`content\` and \`activeForm\`**:
42
+ - \`content\` is imperative: "Run tests", "Update auth handler"
43
+ - \`activeForm\` is present-continuous: "Running tests", "Updating auth handler"
44
+ - The activeForm is what shows in the live UI for the in_progress item.
45
+ 6. **Pass the FULL list every call** — todoWrite REPLACES the list, not merges. Include unchanged items.
46
+ 7. When you submit a list where every item is \`completed\`, the system auto-clears the checklist for you. No need to clear it manually.
47
+
48
+ ## Example
49
+
50
+ User: "Refactor the auth system to use JWT and update the login flow"
51
+
52
+ After exploration / planning, on the first implementation turn:
53
+ \`\`\`
54
+ todoWrite({
55
+ todos: [
56
+ { content: "Read existing auth implementation", activeForm: "Reading auth code", status: "in_progress" },
57
+ { content: "Add JWT signing/verification utility", activeForm: "Adding JWT utility", status: "pending" },
58
+ { content: "Update login handler", activeForm: "Updating login", status: "pending" },
59
+ { content: "Update protected routes middleware", activeForm: "Updating middleware", status: "pending" },
60
+ { content: "Add tests for new auth flow", activeForm: "Writing auth tests", status: "pending" }
61
+ ]
62
+ })
63
+ \`\`\`
64
+
65
+ After reading the code:
66
+ \`\`\`
67
+ todoWrite({
68
+ todos: [
69
+ { content: "Read existing auth implementation", activeForm: "Reading auth code", status: "completed" },
70
+ { content: "Add JWT signing/verification utility", activeForm: "Adding JWT utility", status: "in_progress" },
71
+ ...rest stay pending
72
+ ]
73
+ })
74
+ \`\`\`
75
+
76
+ After finishing all five (auto-cleared next call):
77
+ \`\`\`
78
+ todoWrite({ todos: [/* all five with status: "completed" */] })
79
+ \`\`\`
80
+
81
+ ## Bad usage
82
+
83
+ User: "fix this typo in README"
84
+ You: <do not call todoWrite — single edit, no value in a checklist>
85
+
86
+ User: "what does X do?"
87
+ You: <do not call todoWrite — pure Q&A, no work to track>`,
88
+ // SCHEMA LENIENCY (deliberate): all three per-todo fields are
89
+ // marked optional even though the tool description tells the model
90
+ // they are required. Reason: weaker provider models (DeepSeek-flash,
91
+ // GLM, Qwen, etc.) routinely drop one field per item — most often
92
+ // `status` on the last "current" entry, sometimes `content` when
93
+ // they think `activeForm` is enough. With strict requireds, Zod
94
+ // rejects the whole call → SDK emits tool-error → assistant
95
+ // tool_call with no result → next API turn fails with "tool must
96
+ // be a response to tool_calls". Validating loosely and synthesising
97
+ // sane defaults in the dispatch handler is dramatically more robust
98
+ // than playing whack-a-mole with model output. Strong models
99
+ // (Sonnet, Opus) still get the same rich description telling them
100
+ // to provide all three fields.
101
+ inputSchema: z.object({
102
+ todos: z
103
+ .array(z.object({
104
+ content: z.string().optional().describe('Imperative phrasing of the task ("Run tests").'),
105
+ activeForm: z
106
+ .string()
107
+ .optional()
108
+ .describe('Present-continuous phrasing ("Running tests"); shown in the live UI when this item is in_progress.'),
109
+ status: z
110
+ .enum(['pending', 'in_progress', 'completed'])
111
+ .optional()
112
+ .describe('Lifecycle state. Exactly one item should be in_progress at any time. Defaults to "pending" if omitted.'),
113
+ }))
114
+ .describe('The complete updated todo list. Every call REPLACES the existing list — include all items even if unchanged.'),
115
+ }),
116
+ });
117
+ //# sourceMappingURL=todo-write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"todo-write.js","sourceRoot":"","sources":["../../src/tools/todo-write.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;;;;;0CAY0C;AAC1C,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0DAqE2C;IACxD,8DAA8D;IAC9D,mEAAmE;IACnE,qEAAqE;IACrE,kEAAkE;IAClE,iEAAiE;IACjE,gEAAgE;IAChE,4DAA4D;IAC5D,iEAAiE;IACjE,oEAAoE;IACpE,oEAAoE;IACpE,6DAA6D;IAC7D,kEAAkE;IAClE,+BAA+B;IAC/B,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,KAAK,EAAE,CAAC;aACL,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;YACzF,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,oGAAoG,CAAC;YACjH,MAAM,EAAE,CAAC;iBACN,IAAI,CAAC,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;iBAC7C,QAAQ,EAAE;iBACV,QAAQ,CAAC,wGAAwG,CAAC;SACtH,CAAC,CACH;aACA,QAAQ,CAAC,8GAA8G,CAAC;KAC5H,CAAC;CACH,CAAC,CAAA"}