@x-code-cli/core 0.1.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 (125) hide show
  1. package/dist/agent/loop.d.ts +19 -0
  2. package/dist/agent/loop.d.ts.map +1 -0
  3. package/dist/agent/loop.js +443 -0
  4. package/dist/agent/loop.js.map +1 -0
  5. package/dist/agent/messages.d.ts +8 -0
  6. package/dist/agent/messages.d.ts.map +1 -0
  7. package/dist/agent/messages.js +51 -0
  8. package/dist/agent/messages.js.map +1 -0
  9. package/dist/agent/plan-mode.d.ts +11 -0
  10. package/dist/agent/plan-mode.d.ts.map +1 -0
  11. package/dist/agent/plan-mode.js +37 -0
  12. package/dist/agent/plan-mode.js.map +1 -0
  13. package/dist/agent/pricing.d.ts +9 -0
  14. package/dist/agent/pricing.d.ts.map +1 -0
  15. package/dist/agent/pricing.js +47 -0
  16. package/dist/agent/pricing.js.map +1 -0
  17. package/dist/agent/system-prompt.d.ts +9 -0
  18. package/dist/agent/system-prompt.d.ts.map +1 -0
  19. package/dist/agent/system-prompt.js +93 -0
  20. package/dist/agent/system-prompt.js.map +1 -0
  21. package/dist/config/index.d.ts +28 -0
  22. package/dist/config/index.d.ts.map +1 -0
  23. package/dist/config/index.js +88 -0
  24. package/dist/config/index.js.map +1 -0
  25. package/dist/index.d.ts +20 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +24 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/knowledge/auto-memory.d.ts +36 -0
  30. package/dist/knowledge/auto-memory.d.ts.map +1 -0
  31. package/dist/knowledge/auto-memory.js +151 -0
  32. package/dist/knowledge/auto-memory.js.map +1 -0
  33. package/dist/knowledge/hooks.d.ts +3 -0
  34. package/dist/knowledge/hooks.d.ts.map +1 -0
  35. package/dist/knowledge/hooks.js +59 -0
  36. package/dist/knowledge/hooks.js.map +1 -0
  37. package/dist/knowledge/init.d.ts +8 -0
  38. package/dist/knowledge/init.d.ts.map +1 -0
  39. package/dist/knowledge/init.js +98 -0
  40. package/dist/knowledge/init.js.map +1 -0
  41. package/dist/knowledge/loader.d.ts +14 -0
  42. package/dist/knowledge/loader.d.ts.map +1 -0
  43. package/dist/knowledge/loader.js +130 -0
  44. package/dist/knowledge/loader.js.map +1 -0
  45. package/dist/knowledge/session.d.ts +11 -0
  46. package/dist/knowledge/session.d.ts.map +1 -0
  47. package/dist/knowledge/session.js +108 -0
  48. package/dist/knowledge/session.js.map +1 -0
  49. package/dist/permissions/index.d.ts +14 -0
  50. package/dist/permissions/index.d.ts.map +1 -0
  51. package/dist/permissions/index.js +46 -0
  52. package/dist/permissions/index.js.map +1 -0
  53. package/dist/providers/registry.d.ts +2 -0
  54. package/dist/providers/registry.d.ts.map +1 -0
  55. package/dist/providers/registry.js +46 -0
  56. package/dist/providers/registry.js.map +1 -0
  57. package/dist/tools/ask-user.d.ts +8 -0
  58. package/dist/tools/ask-user.d.ts.map +1 -0
  59. package/dist/tools/ask-user.js +19 -0
  60. package/dist/tools/ask-user.js.map +1 -0
  61. package/dist/tools/edit.d.ts +7 -0
  62. package/dist/tools/edit.d.ts.map +1 -0
  63. package/dist/tools/edit.js +14 -0
  64. package/dist/tools/edit.js.map +1 -0
  65. package/dist/tools/enter-plan-mode.d.ts +2 -0
  66. package/dist/tools/enter-plan-mode.d.ts.map +1 -0
  67. package/dist/tools/enter-plan-mode.js +11 -0
  68. package/dist/tools/enter-plan-mode.js.map +1 -0
  69. package/dist/tools/exit-plan-mode.d.ts +2 -0
  70. package/dist/tools/exit-plan-mode.d.ts.map +1 -0
  71. package/dist/tools/exit-plan-mode.js +9 -0
  72. package/dist/tools/exit-plan-mode.js.map +1 -0
  73. package/dist/tools/glob.d.ts +5 -0
  74. package/dist/tools/glob.d.ts.map +1 -0
  75. package/dist/tools/glob.js +28 -0
  76. package/dist/tools/glob.js.map +1 -0
  77. package/dist/tools/grep.d.ts +7 -0
  78. package/dist/tools/grep.d.ts.map +1 -0
  79. package/dist/tools/grep.js +54 -0
  80. package/dist/tools/grep.js.map +1 -0
  81. package/dist/tools/index.d.ts +77 -0
  82. package/dist/tools/index.d.ts.map +1 -0
  83. package/dist/tools/index.js +41 -0
  84. package/dist/tools/index.js.map +1 -0
  85. package/dist/tools/list-dir.d.ts +4 -0
  86. package/dist/tools/list-dir.d.ts.map +1 -0
  87. package/dist/tools/list-dir.js +25 -0
  88. package/dist/tools/list-dir.js.map +1 -0
  89. package/dist/tools/read-file.d.ts +6 -0
  90. package/dist/tools/read-file.d.ts.map +1 -0
  91. package/dist/tools/read-file.js +28 -0
  92. package/dist/tools/read-file.js.map +1 -0
  93. package/dist/tools/save-knowledge.d.ts +8 -0
  94. package/dist/tools/save-knowledge.d.ts.map +1 -0
  95. package/dist/tools/save-knowledge.js +36 -0
  96. package/dist/tools/save-knowledge.js.map +1 -0
  97. package/dist/tools/shell-utils.d.ts +14 -0
  98. package/dist/tools/shell-utils.d.ts.map +1 -0
  99. package/dist/tools/shell-utils.js +111 -0
  100. package/dist/tools/shell-utils.js.map +1 -0
  101. package/dist/tools/shell.d.ts +5 -0
  102. package/dist/tools/shell.d.ts.map +1 -0
  103. package/dist/tools/shell.js +12 -0
  104. package/dist/tools/shell.js.map +1 -0
  105. package/dist/tools/web-fetch.d.ts +5 -0
  106. package/dist/tools/web-fetch.d.ts.map +1 -0
  107. package/dist/tools/web-fetch.js +59 -0
  108. package/dist/tools/web-fetch.js.map +1 -0
  109. package/dist/tools/web-search.d.ts +5 -0
  110. package/dist/tools/web-search.d.ts.map +1 -0
  111. package/dist/tools/web-search.js +27 -0
  112. package/dist/tools/web-search.js.map +1 -0
  113. package/dist/tools/write-file.d.ts +5 -0
  114. package/dist/tools/write-file.d.ts.map +1 -0
  115. package/dist/tools/write-file.js +12 -0
  116. package/dist/tools/write-file.js.map +1 -0
  117. package/dist/types/index.d.ts +108 -0
  118. package/dist/types/index.d.ts.map +1 -0
  119. package/dist/types/index.js +36 -0
  120. package/dist/types/index.js.map +1 -0
  121. package/dist/utils.d.ts +9 -0
  122. package/dist/utils.d.ts.map +1 -0
  123. package/dist/utils.js +34 -0
  124. package/dist/utils.js.map +1 -0
  125. package/package.json +42 -0
@@ -0,0 +1,19 @@
1
+ import type { LanguageModel, ModelMessage } from 'ai';
2
+ import type { AgentCallbacks, AgentOptions, TokenUsage } from '../types/index.js';
3
+ export interface LoopState {
4
+ messages: ModelMessage[];
5
+ tokenUsage: TokenUsage;
6
+ planMode: boolean;
7
+ planId: string | null;
8
+ sessionId: string;
9
+ startedAt: string;
10
+ filesModified: Set<string>;
11
+ turnCount: number;
12
+ }
13
+ /** Compress old messages into a summary */
14
+ export declare function compressMessages(messages: ModelMessage[], model: LanguageModel): Promise<ModelMessage[]>;
15
+ /** Main agent loop */
16
+ export declare function agentLoop(userMessage: string, model: LanguageModel, options: AgentOptions, callbacks: AgentCallbacks, existingState?: LoopState): Promise<LoopState>;
17
+ /** Save session on exit */
18
+ export declare function saveSession(state: LoopState, model: LanguageModel): Promise<void>;
19
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AAYrD,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAuHjF,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC1B,SAAS,EAAE,MAAM,CAAA;CAClB;AAqDD,2CAA2C;AAC3C,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAc9G;AAsJD,sBAAsB;AACtB,wBAAsB,SAAS,CAC7B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,cAAc,EACzB,aAAa,CAAC,EAAE,SAAS,GACxB,OAAO,CAAC,SAAS,CAAC,CA2JpB;AAED,2BAA2B;AAC3B,wBAAsB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CASvF"}
@@ -0,0 +1,443 @@
1
+ // @x-code/core — Agent Loop (core logic: streaming, tool calls, permission, context compression)
2
+ import { execa } from 'execa';
3
+ import fs from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { generateText, streamText } from 'ai';
6
+ import { buildKnowledgeContext, loadRuleFiles } from '../knowledge/loader.js';
7
+ import { formatSessionForPrompt, generateSessionSummary, loadLatestSession, saveSessionSummary, } from '../knowledge/session.js';
8
+ import { checkPermission } from '../permissions/index.js';
9
+ import { toolRegistry, truncateToolResult } from '../tools/index.js';
10
+ import { getShellConfig } from '../tools/shell-utils.js';
11
+ import { estimateTokens, toolResultMessage } from './messages.js';
12
+ import { ensurePlansDir, generatePlanId, getPlanPath } from './plan-mode.js';
13
+ import { estimateCost } from './pricing.js';
14
+ import { buildSystemPrompt } from './system-prompt.js';
15
+ const KEEP_RECENT = 6;
16
+ const DEFAULT_TOKEN_BUDGET_RATIO = 0.8;
17
+ /** Count occurrences of a substring without creating intermediate arrays */
18
+ function countOccurrences(content, search) {
19
+ let count = 0;
20
+ let pos = 0;
21
+ while ((pos = content.indexOf(search, pos)) !== -1) {
22
+ count++;
23
+ pos += search.length;
24
+ }
25
+ return count;
26
+ }
27
+ /**
28
+ * Ensure all assistant messages have a reasoning content part.
29
+ *
30
+ * DeepSeek Reasoner requires the `reasoning_content` field on every assistant
31
+ * message during tool-call chains. The upstream `@ai-sdk/deepseek` converter
32
+ * sets `reasoning_content: undefined` when no reasoning part exists, and
33
+ * `JSON.stringify` strips `undefined` values — causing the DeepSeek API to
34
+ * reject the request with a 400 "Missing reasoning_content" error.
35
+ *
36
+ * This helper injects an empty `{ type: 'reasoning', text: '' }` part into any
37
+ * assistant message that lacks one, so the converter always produces
38
+ * `"reasoning_content": ""` in the JSON body.
39
+ */
40
+ function ensureReasoningContentParts(messages, modelId) {
41
+ if (!modelId.includes('deepseek-reasoner'))
42
+ return;
43
+ for (const msg of messages) {
44
+ if (msg.role !== 'assistant')
45
+ continue;
46
+ const content = msg.content;
47
+ if (!Array.isArray(content))
48
+ continue;
49
+ const hasReasoning = content.some((p) => p.type === 'reasoning');
50
+ if (!hasReasoning) {
51
+ // Prepend an empty reasoning part so the converter produces `reasoning_content: ""`
52
+ ;
53
+ content.unshift({ type: 'reasoning', text: '' });
54
+ }
55
+ }
56
+ }
57
+ /** Context window sizes per model (tokens). Falls back to provider default, then 128k. */
58
+ const MODEL_CONTEXT_WINDOWS = {
59
+ // Anthropic
60
+ 'anthropic:claude-opus-4-6': 200000,
61
+ 'anthropic:claude-sonnet-4-5': 200000,
62
+ 'anthropic:claude-haiku-4-5': 200000,
63
+ // OpenAI
64
+ 'openai:gpt-4.1': 1047576,
65
+ 'openai:gpt-4.1-mini': 1047576,
66
+ 'openai:gpt-4.1-nano': 1047576,
67
+ 'openai:o3': 200000,
68
+ 'openai:o4-mini': 200000,
69
+ // Google
70
+ 'google:gemini-2.5-pro': 1000000,
71
+ 'google:gemini-2.5-flash': 1000000,
72
+ // DeepSeek
73
+ 'deepseek:deepseek-chat': 64000,
74
+ 'deepseek:deepseek-reasoner': 64000,
75
+ // Alibaba
76
+ 'alibaba:qwen-max': 128000,
77
+ 'alibaba:qwen-plus': 128000,
78
+ // xAI
79
+ 'xai:grok-3': 131072,
80
+ 'xai:grok-3-mini': 131072,
81
+ // Zhipu
82
+ 'zhipu:glm-4-plus': 128000,
83
+ // Moonshot
84
+ 'moonshotai:kimi-k2.5': 131072,
85
+ };
86
+ /** Provider-level fallback context windows */
87
+ const PROVIDER_CONTEXT_WINDOWS = {
88
+ anthropic: 200000,
89
+ openai: 128000,
90
+ google: 1000000,
91
+ deepseek: 64000,
92
+ alibaba: 128000,
93
+ xai: 128000,
94
+ zhipu: 128000,
95
+ moonshotai: 128000,
96
+ };
97
+ function getTokenBudget(modelId) {
98
+ const contextWindow = MODEL_CONTEXT_WINDOWS[modelId] ?? PROVIDER_CONTEXT_WINDOWS[modelId.split(':')[0]] ?? 128000;
99
+ return Math.floor(contextWindow * DEFAULT_TOKEN_BUDGET_RATIO);
100
+ }
101
+ /** Execute a write tool (writeFile / edit) */
102
+ async function executeWriteTool(toolName, input) {
103
+ if (toolName === 'writeFile') {
104
+ const filePath = input.filePath;
105
+ const content = input.content;
106
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
107
+ await fs.writeFile(filePath, content, 'utf-8');
108
+ return `File written: ${filePath} (${content.length} characters)`;
109
+ }
110
+ if (toolName === 'edit') {
111
+ const filePath = input.filePath;
112
+ const oldString = input.oldString;
113
+ const newString = input.newString;
114
+ const replaceAll = input.replaceAll ?? false;
115
+ const content = await fs.readFile(filePath, 'utf-8');
116
+ if (!replaceAll) {
117
+ const count = countOccurrences(content, oldString);
118
+ if (count === 0)
119
+ return `Error: old_string not found in ${filePath}`;
120
+ if (count > 1)
121
+ return `Error: old_string is not unique in ${filePath} (found ${count} occurrences). Provide more context or set replaceAll: true.`;
122
+ }
123
+ const newContent = replaceAll ? content.replaceAll(oldString, newString) : content.replace(oldString, newString);
124
+ await fs.writeFile(filePath, newContent, 'utf-8');
125
+ return `File edited: ${filePath}`;
126
+ }
127
+ return 'Error: unknown write tool';
128
+ }
129
+ /** Execute a shell command with streaming */
130
+ async function executeShell(command, timeout, callbacks) {
131
+ const { executable, args } = getShellConfig();
132
+ const proc = execa(executable, [...args, command], {
133
+ timeout,
134
+ reject: false,
135
+ });
136
+ proc.stdout?.on('data', (chunk) => {
137
+ callbacks.onShellOutput(chunk.toString());
138
+ });
139
+ proc.stderr?.on('data', (chunk) => {
140
+ callbacks.onShellOutput(chunk.toString());
141
+ });
142
+ const result = await proc;
143
+ return `exit code: ${result.exitCode}\n${result.stdout}\n${result.stderr}`.trim();
144
+ }
145
+ /** Compress old messages into a summary */
146
+ export async function compressMessages(messages, model) {
147
+ const recent = messages.slice(-KEEP_RECENT);
148
+ const old = messages.slice(0, -KEEP_RECENT);
149
+ if (old.length === 0)
150
+ return messages;
151
+ const { text: summary } = await generateText({
152
+ model,
153
+ system: 'Summarize the following conversation concisely, preserving key decisions, file changes, and context needed to continue.',
154
+ messages: old,
155
+ });
156
+ return [{ role: 'user', content: `[Previous conversation summary]\n${summary}` }, ...recent];
157
+ }
158
+ /** Classify API error and return a user-friendly recovery message */
159
+ function classifyApiError(err) {
160
+ const msg = err instanceof Error ? err.message : String(err);
161
+ const statusMatch = msg.match(/(\d{3})/);
162
+ const status = statusMatch ? Number(statusMatch[1]) : 0;
163
+ if (msg.includes('Missing `reasoning_content`') || msg.includes('reasoning_content')) {
164
+ return {
165
+ message: 'DeepSeek Reasoner requires reasoning_content in assistant messages during tool-call chains. This is usually an SDK compatibility issue — please report it.',
166
+ retryable: false,
167
+ };
168
+ }
169
+ if (msg.includes('API key is missing') || msg.includes('API_KEY')) {
170
+ // Extract provider name from message like "DeepSeek API key API key is missing..."
171
+ const providerMatch = msg.match(/^(\w+)\s+API key/i);
172
+ const provider = providerMatch ? providerMatch[1] : 'Provider';
173
+ return {
174
+ message: `${provider} API key is not set. Please set the corresponding environment variable (e.g. ${provider.toUpperCase()}_API_KEY).`,
175
+ retryable: false,
176
+ };
177
+ }
178
+ if (status === 401 || msg.includes('Unauthorized') || msg.includes('Invalid API Key')) {
179
+ return {
180
+ message: 'API authentication failed (401). Please check your API key with /model or reconfigure with `xc init`.',
181
+ retryable: false,
182
+ };
183
+ }
184
+ if (status === 403 || msg.includes('Forbidden')) {
185
+ return {
186
+ message: 'API access forbidden (403). Your API key may not have permission for this model.',
187
+ retryable: false,
188
+ };
189
+ }
190
+ if (status === 503 || msg.includes('Service Unavailable') || msg.includes('overloaded')) {
191
+ return {
192
+ message: 'Model service unavailable (503). Try switching to a different model with /model.',
193
+ retryable: false,
194
+ };
195
+ }
196
+ if (status === 429 || msg.includes('rate limit') || msg.includes('Rate limit')) {
197
+ return {
198
+ message: 'Rate limited (429). Waiting for retry... (AI SDK handles exponential backoff automatically with maxRetries: 3)',
199
+ retryable: true, // AI SDK maxRetries handles this
200
+ };
201
+ }
202
+ if (msg.includes('timeout') || msg.includes('ETIMEDOUT') || msg.includes('ECONNRESET')) {
203
+ return {
204
+ message: `Network error: ${msg}. Retrying...`,
205
+ retryable: true,
206
+ };
207
+ }
208
+ return { message: msg, retryable: false };
209
+ }
210
+ /** Helper to push a tool result to state and notify the UI */
211
+ function pushToolResult(state, callbacks, toolCallId, toolName, output) {
212
+ state.messages.push(toolResultMessage(toolCallId, toolName, output));
213
+ callbacks.onToolResult(toolCallId, output);
214
+ }
215
+ /** Handle all tool calls from a single model turn */
216
+ async function handleToolCalls(toolCalls, state, options, callbacks) {
217
+ for (const tc of toolCalls) {
218
+ const { toolName, input, toolCallId } = tc;
219
+ let output;
220
+ // ── Plan mode tools ──
221
+ if (toolName === 'enterPlanMode') {
222
+ state.planMode = true;
223
+ state.planId = generatePlanId();
224
+ await ensurePlansDir();
225
+ output = `Plan mode activated. Plan ID: ${state.planId}. Use only read-only tools. Save plan to ${getPlanPath(state.planId)}`;
226
+ pushToolResult(state, callbacks, toolCallId, toolName, output);
227
+ continue;
228
+ }
229
+ if (toolName === 'exitPlanMode') {
230
+ state.planMode = false;
231
+ if (state.planId) {
232
+ const planPath = getPlanPath(state.planId);
233
+ try {
234
+ const planContent = await fs.readFile(planPath, 'utf-8');
235
+ output = `Plan ready for review:\n\n${planContent}`;
236
+ }
237
+ catch {
238
+ output = 'Plan mode exited. No plan file found.';
239
+ }
240
+ }
241
+ else {
242
+ output = 'Plan mode exited.';
243
+ }
244
+ pushToolResult(state, callbacks, toolCallId, toolName, output);
245
+ continue;
246
+ }
247
+ // ── askUser tool ──
248
+ if (toolName === 'askUser') {
249
+ const question = input.question;
250
+ const optionsList = input.options;
251
+ const answer = await callbacks.onAskUser(question, optionsList);
252
+ output = `User answered: ${answer}`;
253
+ pushToolResult(state, callbacks, toolCallId, toolName, output);
254
+ continue;
255
+ }
256
+ // ── Permission check for write tools and shell ──
257
+ if (toolName === 'writeFile' || toolName === 'edit' || toolName === 'shell') {
258
+ const approved = await checkPermission({ toolName, input }, options.trustMode, callbacks.onAskPermission);
259
+ if (!approved) {
260
+ pushToolResult(state, callbacks, toolCallId, toolName, 'Permission denied by user.');
261
+ continue;
262
+ }
263
+ }
264
+ // ── Execute tool ──
265
+ try {
266
+ if (toolName === 'writeFile' || toolName === 'edit') {
267
+ output = await executeWriteTool(toolName, input);
268
+ const filePath = input.filePath;
269
+ state.filesModified.add(filePath);
270
+ }
271
+ else if (toolName === 'shell') {
272
+ const timeout = input.timeout ?? 30000;
273
+ output = await executeShell(input.command, timeout, callbacks);
274
+ }
275
+ else {
276
+ // Tools with execute (readFile, glob, grep, etc.) are auto-executed by AI SDK
277
+ continue;
278
+ }
279
+ }
280
+ catch (err) {
281
+ output = `Error: ${err instanceof Error ? err.message : String(err)}`;
282
+ }
283
+ output = truncateToolResult(output);
284
+ pushToolResult(state, callbacks, toolCallId, toolName, output);
285
+ }
286
+ }
287
+ /** Main agent loop */
288
+ export async function agentLoop(userMessage, model, options, callbacks, existingState) {
289
+ const state = existingState ?? {
290
+ messages: [],
291
+ tokenUsage: { inputTokens: 0, outputTokens: 0, totalTokens: 0, estimatedCost: 0, costCurrency: 'USD' },
292
+ planMode: false,
293
+ planId: null,
294
+ sessionId: Date.now().toString(36),
295
+ startedAt: new Date().toISOString(),
296
+ filesModified: new Set(),
297
+ turnCount: 0,
298
+ };
299
+ state.messages.push({ role: 'user', content: userMessage });
300
+ // Load rules once — shared between @rule-name resolution and buildKnowledgeContext
301
+ const rules = await loadRuleFiles();
302
+ // Check for @rule-name references in user message
303
+ const ruleRefs = userMessage.match(/@([\w-]+)/g);
304
+ let extraRuleContext = '';
305
+ if (ruleRefs) {
306
+ for (const ref of ruleRefs) {
307
+ const ruleName = ref.slice(1); // remove @
308
+ const rule = rules.find((r) => r.filename === ruleName);
309
+ if (rule) {
310
+ extraRuleContext += `\n\n### Rule: ${rule.filename}\n${rule.content}`;
311
+ }
312
+ }
313
+ }
314
+ const sessionSummary = await loadLatestSession();
315
+ const sessionContext = sessionSummary ? formatSessionForPrompt(sessionSummary) : undefined;
316
+ const knowledgeContext = await buildKnowledgeContext({ sessionContext, rules });
317
+ const fullKnowledgeContext = knowledgeContext + extraRuleContext;
318
+ const tokenBudget = getTokenBudget(options.modelId);
319
+ while (state.turnCount < options.maxTurns) {
320
+ state.turnCount++;
321
+ // Context compression check — also saves session summary before compressing
322
+ if (estimateTokens(state.messages) > tokenBudget) {
323
+ try {
324
+ const summary = await generateSessionSummary(state.messages, model, state.sessionId, state.startedAt, [
325
+ ...state.filesModified,
326
+ ]);
327
+ await saveSessionSummary(summary);
328
+ }
329
+ catch {
330
+ // Don't block compression on session save failure
331
+ }
332
+ state.messages = await compressMessages(state.messages, model);
333
+ callbacks.onContextCompressed('Context compressed to fit token budget.');
334
+ }
335
+ const systemPrompt = buildSystemPrompt({
336
+ knowledgeContext: fullKnowledgeContext,
337
+ planMode: state.planMode,
338
+ modelId: options.modelId,
339
+ });
340
+ let result;
341
+ try {
342
+ result = streamText({
343
+ model,
344
+ system: systemPrompt,
345
+ messages: state.messages,
346
+ tools: toolRegistry,
347
+ maxRetries: 3,
348
+ abortSignal: options.abortSignal,
349
+ });
350
+ }
351
+ catch (err) {
352
+ const classified = classifyApiError(err);
353
+ callbacks.onError(new Error(classified.message));
354
+ break;
355
+ }
356
+ // Stream chunks to UI
357
+ try {
358
+ for await (const chunk of result.fullStream) {
359
+ if (chunk.type === 'text-delta') {
360
+ callbacks.onTextDelta(chunk.text ?? '');
361
+ }
362
+ if (chunk.type === 'tool-call') {
363
+ callbacks.onToolCall(chunk.toolName ?? '', (chunk.input ?? {}));
364
+ }
365
+ // Truncate auto-executed tool results (readFile, glob, grep, etc.)
366
+ if (chunk.type === 'tool-result') {
367
+ const raw = typeof chunk.output === 'string' ? chunk.output : JSON.stringify(chunk.output ?? '');
368
+ const truncated = truncateToolResult(raw);
369
+ if (truncated !== raw) {
370
+ // Result was truncated — the original is already in messages via AI SDK,
371
+ // but we notify via callback so the UI can show it
372
+ callbacks.onToolResult(chunk.toolCallId ?? '', truncated);
373
+ }
374
+ }
375
+ }
376
+ }
377
+ catch (err) {
378
+ const classified = classifyApiError(err);
379
+ callbacks.onError(new Error(classified.message));
380
+ if (!classified.retryable)
381
+ break;
382
+ // For retryable errors, AI SDK maxRetries already handles retry;
383
+ // if we still get here, the retries were exhausted — break
384
+ break;
385
+ }
386
+ // Collect response + usage (may fail if stream errored)
387
+ let finishReason;
388
+ try {
389
+ const response = await result.response;
390
+ state.messages.push(...response.messages);
391
+ // Workaround: DeepSeek Reasoner requires `reasoning_content` on every
392
+ // assistant message in tool-call chains. Ensure it's always present.
393
+ ensureReasoningContentParts(state.messages, options.modelId);
394
+ const usage = await result.usage;
395
+ if (usage) {
396
+ state.tokenUsage.inputTokens += usage.inputTokens ?? 0;
397
+ state.tokenUsage.outputTokens += usage.outputTokens ?? 0;
398
+ state.tokenUsage.totalTokens = state.tokenUsage.inputTokens + state.tokenUsage.outputTokens;
399
+ const costEstimate = estimateCost(options.modelId, state.tokenUsage.inputTokens, state.tokenUsage.outputTokens);
400
+ state.tokenUsage.estimatedCost = costEstimate.cost;
401
+ state.tokenUsage.costCurrency = costEstimate.currency;
402
+ callbacks.onUsageUpdate(state.tokenUsage);
403
+ }
404
+ finishReason = await result.finishReason;
405
+ }
406
+ catch (err) {
407
+ const classified = classifyApiError(err);
408
+ callbacks.onError(new Error(classified.message));
409
+ break;
410
+ }
411
+ if (finishReason === 'tool-calls') {
412
+ let toolCalls;
413
+ try {
414
+ toolCalls = await result.toolCalls;
415
+ }
416
+ catch (err) {
417
+ const classified = classifyApiError(err);
418
+ callbacks.onError(new Error(classified.message));
419
+ break;
420
+ }
421
+ await handleToolCalls(toolCalls, state, options, callbacks);
422
+ continue;
423
+ }
424
+ break;
425
+ }
426
+ if (state.turnCount >= options.maxTurns) {
427
+ callbacks.onError(new Error(`Reached maximum turns (${options.maxTurns}). Stopping agent loop.`));
428
+ }
429
+ return state;
430
+ }
431
+ /** Save session on exit */
432
+ export async function saveSession(state, model) {
433
+ try {
434
+ const summary = await generateSessionSummary(state.messages, model, state.sessionId, state.startedAt, [
435
+ ...state.filesModified,
436
+ ]);
437
+ await saveSessionSummary(summary);
438
+ }
439
+ catch {
440
+ // Don't crash on session save failure
441
+ }
442
+ }
443
+ //# sourceMappingURL=loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.js","sourceRoot":"","sources":["../../src/agent/loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ModelMessage } from 'ai';
2
+ /** Create a user message */
3
+ export declare function userMessage(content: string): ModelMessage;
4
+ /** Create a tool result message */
5
+ export declare function toolResultMessage(toolCallId: string, toolName: string, result: string): ModelMessage;
6
+ /** Estimate token count from text (rough: chars / 4) */
7
+ export declare function estimateTokens(messages: ModelMessage[]): number;
8
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/agent/messages.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AAEtC,4BAA4B;AAC5B,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAEzD;AAED,mCAAmC;AACnC,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAYpG;AAED,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAyB/D"}
@@ -0,0 +1,51 @@
1
+ /** Create a user message */
2
+ export function userMessage(content) {
3
+ return { role: 'user', content };
4
+ }
5
+ /** Create a tool result message */
6
+ export function toolResultMessage(toolCallId, toolName, result) {
7
+ return {
8
+ role: 'tool',
9
+ content: [
10
+ {
11
+ type: 'tool-result',
12
+ toolCallId,
13
+ toolName,
14
+ output: { type: 'text', value: result },
15
+ },
16
+ ],
17
+ };
18
+ }
19
+ /** Estimate token count from text (rough: chars / 4) */
20
+ export function estimateTokens(messages) {
21
+ let chars = 0;
22
+ for (const msg of messages) {
23
+ if (typeof msg.content === 'string') {
24
+ chars += msg.content.length;
25
+ }
26
+ else if (Array.isArray(msg.content)) {
27
+ for (const part of msg.content) {
28
+ if ('text' in part && typeof part.text === 'string') {
29
+ chars += part.text.length;
30
+ }
31
+ else if ('result' in part && typeof part.result === 'string') {
32
+ chars += part.result.length;
33
+ }
34
+ else if ('output' in part) {
35
+ // Handle tool-result messages created by toolResultMessage()
36
+ const output = part.output;
37
+ if (typeof output === 'string') {
38
+ chars += output.length;
39
+ }
40
+ else if (output && typeof output === 'object' && 'value' in output) {
41
+ const value = output.value;
42
+ if (typeof value === 'string')
43
+ chars += value.length;
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ return Math.ceil(chars / 4);
50
+ }
51
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/agent/messages.ts"],"names":[],"mappings":"AAGA,4BAA4B;AAC5B,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;AAClC,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,iBAAiB,CAAC,UAAkB,EAAE,QAAgB,EAAE,MAAc;IACpF,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,aAAa;gBACnB,UAAU;gBACV,QAAQ;gBACR,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;aACxC;SACF;KACF,CAAA;AACH,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,cAAc,CAAC,QAAwB;IACrD,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACpC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAA;QAC7B,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC/B,IAAI,MAAM,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACpD,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAA;gBAC3B,CAAC;qBAAM,IAAI,QAAQ,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;oBAC/D,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA;gBAC7B,CAAC;qBAAM,IAAI,QAAQ,IAAI,IAAI,EAAE,CAAC;oBAC5B,6DAA6D;oBAC7D,MAAM,MAAM,GAAI,IAA4B,CAAC,MAAM,CAAA;oBACnD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;wBAC/B,KAAK,IAAI,MAAM,CAAC,MAAM,CAAA;oBACxB,CAAC;yBAAM,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;wBACrE,MAAM,KAAK,GAAI,MAA6B,CAAC,KAAK,CAAA;wBAClD,IAAI,OAAO,KAAK,KAAK,QAAQ;4BAAE,KAAK,IAAI,KAAK,CAAC,MAAM,CAAA;oBACtD,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;AAC7B,CAAC"}
@@ -0,0 +1,11 @@
1
+ /** Generate a plan ID based on timestamp */
2
+ export declare function generatePlanId(): string;
3
+ /** Get the plan file path */
4
+ export declare function getPlanPath(planId: string): string;
5
+ /** Ensure plans directory exists */
6
+ export declare function ensurePlansDir(): Promise<void>;
7
+ /** Read a plan file */
8
+ export declare function readPlan(planId: string): Promise<string | null>;
9
+ /** List all plan files */
10
+ export declare function listPlans(): Promise<string[]>;
11
+ //# sourceMappingURL=plan-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-mode.d.ts","sourceRoot":"","sources":["../../src/agent/plan-mode.ts"],"names":[],"mappings":"AAMA,4CAA4C;AAC5C,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,6BAA6B;AAC7B,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,oCAAoC;AACpC,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAEpD;AAED,uBAAuB;AACvB,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMrE;AAED,0BAA0B;AAC1B,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAQnD"}
@@ -0,0 +1,37 @@
1
+ // @x-code/core — Plan Mode logic
2
+ import fs from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ const PLANS_DIR = '.x-code/plans';
5
+ /** Generate a plan ID based on timestamp */
6
+ export function generatePlanId() {
7
+ return new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
8
+ }
9
+ /** Get the plan file path */
10
+ export function getPlanPath(planId) {
11
+ return path.join(process.cwd(), PLANS_DIR, `${planId}.md`);
12
+ }
13
+ /** Ensure plans directory exists */
14
+ export async function ensurePlansDir() {
15
+ await fs.mkdir(path.join(process.cwd(), PLANS_DIR), { recursive: true });
16
+ }
17
+ /** Read a plan file */
18
+ export async function readPlan(planId) {
19
+ try {
20
+ return await fs.readFile(getPlanPath(planId), 'utf-8');
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ /** List all plan files */
27
+ export async function listPlans() {
28
+ try {
29
+ const dir = path.join(process.cwd(), PLANS_DIR);
30
+ const files = await fs.readdir(dir);
31
+ return files.filter((f) => f.endsWith('.md')).map((f) => f.replace('.md', ''));
32
+ }
33
+ catch {
34
+ return [];
35
+ }
36
+ }
37
+ //# sourceMappingURL=plan-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan-mode.js","sourceRoot":"","sources":["../../src/agent/plan-mode.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjC,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,MAAM,SAAS,GAAG,eAAe,CAAA;AAEjC,4CAA4C;AAC5C,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AACpE,CAAC;AAED,6BAA6B;AAC7B,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,GAAG,MAAM,KAAK,CAAC,CAAA;AAC5D,CAAC;AAED,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;AAC1E,CAAC;AAED,uBAAuB;AACvB,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAc;IAC3C,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAA;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,0BAA0B;AAC1B,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAA;QAC/C,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACnC,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAA;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface CostEstimate {
2
+ cost: number;
3
+ currency: 'USD' | 'CNY';
4
+ }
5
+ /** Estimate cost from model ID and token counts. Returns cost and currency. */
6
+ export declare function estimateCost(modelId: string, inputTokens: number, outputTokens: number): CostEstimate;
7
+ /** Format cost string with currency symbol */
8
+ export declare function formatCost(estimate: CostEstimate): string;
9
+ //# sourceMappingURL=pricing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/agent/pricing.ts"],"names":[],"mappings":"AA2CA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,KAAK,GAAG,KAAK,CAAA;CACxB;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,YAAY,CAKrG;AAED,8CAA8C;AAC9C,wBAAgB,UAAU,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAIzD"}