@jixo/cli 0.10.1 → 0.12.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 (54) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +6 -5
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/init.d.ts.map +1 -1
  5. package/dist/commands/init.js +18 -12
  6. package/dist/commands/init.js.map +1 -1
  7. package/dist/commands/prompts/list.js +2 -2
  8. package/dist/commands/prompts/list.js.map +1 -1
  9. package/dist/commands/tasks/AiTaskTui.d.ts +22 -0
  10. package/dist/commands/tasks/AiTaskTui.d.ts.map +1 -0
  11. package/dist/commands/tasks/AiTaskTui.js +52 -0
  12. package/dist/commands/tasks/AiTaskTui.js.map +1 -0
  13. package/dist/commands/tasks/ai-tasl-tui.d.ts +22 -0
  14. package/dist/commands/tasks/ai-tasl-tui.d.ts.map +1 -0
  15. package/dist/commands/tasks/ai-tasl-tui.js +53 -0
  16. package/dist/commands/tasks/ai-tasl-tui.js.map +1 -0
  17. package/dist/commands/tasks/ai-tools.d.ts +281 -8
  18. package/dist/commands/tasks/ai-tools.d.ts.map +1 -1
  19. package/dist/commands/tasks/ai-tools.js +55 -16
  20. package/dist/commands/tasks/ai-tools.js.map +1 -1
  21. package/dist/commands/tasks/model-providers.d.ts +5 -1
  22. package/dist/commands/tasks/model-providers.d.ts.map +1 -1
  23. package/dist/commands/tasks/model-providers.js +31 -0
  24. package/dist/commands/tasks/model-providers.js.map +1 -1
  25. package/dist/commands/tasks/run-ai-task.d.ts +1 -1
  26. package/dist/commands/tasks/run-ai-task.d.ts.map +1 -1
  27. package/dist/commands/tasks/run-ai-task.js +141 -115
  28. package/dist/commands/tasks/run-ai-task.js.map +1 -1
  29. package/dist/commands/tasks/run.d.ts.map +1 -1
  30. package/dist/commands/tasks/run.js +24 -14
  31. package/dist/commands/tasks/run.js.map +1 -1
  32. package/dist/config.d.ts +14 -14
  33. package/dist/helper/ai-retry-error.d.ts +1 -1
  34. package/dist/helper/ai-retry-error.d.ts.map +1 -1
  35. package/dist/helper/ai-retry-error.js +63 -30
  36. package/dist/helper/ai-retry-error.js.map +1 -1
  37. package/dist/helper/handle-ai-error.d.ts +5 -0
  38. package/dist/helper/handle-ai-error.d.ts.map +1 -0
  39. package/dist/helper/handle-ai-error.js +122 -0
  40. package/dist/helper/handle-ai-error.js.map +1 -0
  41. package/dist/helper/logger.d.ts +3 -0
  42. package/dist/helper/logger.d.ts.map +1 -0
  43. package/dist/helper/logger.js +26 -0
  44. package/dist/helper/logger.js.map +1 -0
  45. package/dist/helper/prompts-loader.d.ts +9 -3
  46. package/dist/helper/prompts-loader.d.ts.map +1 -1
  47. package/dist/helper/prompts-loader.js +16 -16
  48. package/dist/helper/prompts-loader.js.map +1 -1
  49. package/dist/helper/resolve-ai-tasks.d.ts +24 -10
  50. package/dist/helper/resolve-ai-tasks.d.ts.map +1 -1
  51. package/dist/helper/resolve-ai-tasks.js +68 -26
  52. package/dist/helper/resolve-ai-tasks.js.map +1 -1
  53. package/dist/prompts.json +2 -2
  54. package/package.json +8 -3
@@ -1,101 +1,81 @@
1
1
  import { blue, cyan, FileEntry, gray, green, red, spinner, YAML, yellow } from "@gaubee/nodekit";
2
2
  import { func_catch } from "@gaubee/util";
3
- import { AISDKError, streamText } from "ai";
4
- import createDebug from "debug";
3
+ import { streamText } from "ai";
5
4
  import ms from "ms";
5
+ import { open } from "node:fs/promises";
6
6
  import os from "node:os";
7
+ import path from "node:path";
7
8
  import { match, P } from "ts-pattern";
8
- import { safeEnv } from "../../env.js";
9
- import { handleRetryError } from "../../helper/ai-retry-error.js";
10
- import { getPromptConfigs } from "../../helper/prompts-loader.js";
9
+ import { handleError } from "../../helper/handle-ai-error.js";
10
+ import { createDebug } from "../../helper/logger.js";
11
+ import { getAllPromptConfigs, getAllSkillMap as getAllSkillNavMap } from "../../helper/prompts-loader.js";
12
+ import { AiTaskTui } from "./ai-tasl-tui.js";
11
13
  import { tools } from "./ai-tools.js";
12
- import { providers } from "./model-providers.js";
13
- createDebug.formatters.y = (v) => {
14
- return JSON.stringify(v, (_k, v) => {
15
- if (typeof v === "string") {
16
- let slice_len = 0;
17
- if (v.length > 200) {
18
- slice_len = 50;
19
- }
20
- if (v.length > 100) {
21
- slice_len = 30;
22
- }
23
- if (slice_len > 0) {
24
- return `<string:${v.length}>${v.slice(0, slice_len)}${gray("...")}${v.slice(-slice_len)}`;
25
- }
26
- return v;
27
- }
28
- if (AISDKError.isInstance(v)) {
29
- return red(v.message);
30
- }
31
- return v;
32
- });
33
- };
14
+ import { getModel } from "./model-providers.js";
34
15
  const log = createDebug("jixo:run-ai-task");
35
- const getModel = (model) => {
36
- return match(model)
37
- .with(P.string.startsWith("deepseek-"), (model) => providers.deepseek(model))
38
- .with(P.string.startsWith("gemini-"), (model) => providers.google(model))
39
- .with(P.string.startsWith("o3-"), P.string.startsWith("o1-"), P.string.startsWith("gpt-"), (model) => providers.openai(model))
40
- .with(P.string.startsWith("claude-"), (model) => providers.anthropic(model))
41
- .with(P.string.startsWith("grok-"), (model) => providers.xai(model))
42
- .with(P.string.includes("/"), (model) => providers.deepinfra(model))
43
- .otherwise(() => {
44
- if (safeEnv.JIXO_DEEPSEEK_API_KEY) {
45
- return providers.deepseek("deepseek-reasoner");
46
- }
47
- if (safeEnv.JIXO_GOOGLE_API_KEY) {
48
- return providers.google("gemini-2.5-pro-preview-05-06");
49
- }
50
- if (safeEnv.JIXO_OPENAI_API_KEY) {
51
- return providers.openai("o3-mini");
52
- }
53
- if (safeEnv.JIXO_ANTHROPIC_API_KEY) {
54
- return providers.anthropic("claude-4-sonnet-20250514");
55
- }
56
- if (safeEnv.JIXO_XAI_API_KEY) {
57
- return providers.xai("grok-3-beta");
58
- }
59
- if (safeEnv.JIXO_DEEPINFRA_API_KEY) {
60
- return providers.deepinfra("meta-llama/Meta-Llama-3.1-405B-Instruct");
61
- }
62
- return providers.deepseek("deepseek-reasoner");
16
+ export const runAiTask = async (ai_task, loopTimes, allFiles, changedFilesSet) => {
17
+ const tool_spinner = spinner({
18
+ prefixText: "🧰",
19
+ text: "Preparing AI tools...",
63
20
  });
64
- };
65
- export const runAiTask = async (ai_task, allFiles, changedFilesSet) => {
66
- const loading = spinner(`Initializing AI task: ${cyan(ai_task.name)}...`);
67
- loading.prefixText = "⏳ ";
68
- loading.start();
69
- const endInfo = {
70
- prefixText: "",
71
- text: "",
72
- suffixText: `⏱️ ${gray(ms(new Date().getTime() - new Date(ai_task.startTime).getTime(), { long: true }))}`,
21
+ tool_spinner.start();
22
+ const availableTools = {
23
+ ...(await tools.fileSystem(ai_task.cwd)),
24
+ ...(await tools.pnpm()),
25
+ ...(await tools.jixo(ai_task)),
26
+ ...(await tools.git(ai_task.cwd)),
73
27
  };
28
+ tool_spinner.clear();
29
+ tool_spinner.stop();
30
+ const json_line_log_file_handle = await open(path.join(ai_task.cwd, ".jixo", `${ai_task.runner}.log.jsonl`), "a");
31
+ const __writeJsonLineLog = (...lineDatas) => {
32
+ for (const lineData of lineDatas) {
33
+ try {
34
+ json_line_log_file_handle.appendFile(JSON.stringify(lineData) + "\n");
35
+ }
36
+ catch { }
37
+ }
38
+ };
39
+ const tui = new AiTaskTui(ai_task, spinner({ text: `Initializing AI task: ${cyan(ai_task.jobName)}...`, prefixText: "⏳ " }));
40
+ tui.spinner.start();
41
+ const updateTuiState = () => {
42
+ tui.setStatus("loop and time", `${green(`[${loopTimes}]`)} ${cyan(`+${ms(Date.now() - new Date(ai_task.startTime).getTime())}`)}`);
43
+ };
44
+ const ti = setInterval(updateTuiState, 1000);
45
+ updateTuiState();
74
46
  try {
75
- await _runAiTask(ai_task, allFiles, changedFilesSet, loading, endInfo);
47
+ await _runAiTask(ai_task, availableTools, allFiles, changedFilesSet, tui, __writeJsonLineLog);
76
48
  }
77
49
  finally {
78
50
  // Fallback spinner stop if loop exits unexpectedly
79
- loading.stopAndPersist(endInfo);
51
+ clearInterval(ti);
52
+ tui.stop();
53
+ json_line_log_file_handle.close();
80
54
  }
81
55
  };
82
- const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo) => {
56
+ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, tui, __writeJsonLineLog) => {
83
57
  const model = getModel(ai_task.model);
84
- const availableTools = {
85
- ...(await tools.fileSystem(ai_task.cwd)),
86
- // ...(await tools.memory(path.join(ai_task.cwd, `.jixo/${ai_task.name}.memory.json`))),
87
- ...(await tools.sequentialThinking()),
88
- ...(await tools.jixoSkill().tools),
89
- // ...(await tools.git(ai_task.cwd)),
90
- };
91
58
  const initialMessages = [];
92
59
  const maxTurns = 40; // Safeguard against infinite loops
93
- const promptConfigs = getPromptConfigs();
60
+ const promptConfigs = getAllPromptConfigs();
94
61
  for (const role of ["system", "user"]) {
95
62
  const promptConfig = promptConfigs[role];
96
63
  const promptContent = promptConfig.content //
97
- .replace(/\{\{task.(\w+)\}\}/g, (_, key) => {
98
- return Reflect.get(ai_task, key);
64
+ .replace(/\{\{task.([\.\w]+)\}\}/g, (_, key) => {
65
+ if (key.includes(".")) {
66
+ const paths = key.split(".");
67
+ let res = ai_task;
68
+ for (const p of paths) {
69
+ res = Reflect.get(res, p);
70
+ if (!res) {
71
+ break;
72
+ }
73
+ }
74
+ return res;
75
+ }
76
+ else {
77
+ return Reflect.get(ai_task, key);
78
+ }
99
79
  })
100
80
  .replace(/\{\{env.(\w+)\}\}/g, (_, key) => {
101
81
  const envKey = key.toUpperCase();
@@ -106,7 +86,7 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
106
86
  return envValue;
107
87
  })
108
88
  .replaceAll("{{allSkills}}", (_, key) => {
109
- return YAML.stringify(tools.jixoSkill().allSkillNavList);
89
+ return YAML.stringify(getAllSkillNavMap());
110
90
  })
111
91
  .replaceAll("{{allFiles}}", YAML.stringify({
112
92
  [ai_task.cwd]: {
@@ -129,22 +109,26 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
129
109
  });
130
110
  }
131
111
  const currentMessages = [...initialMessages];
112
+ __writeJsonLineLog(...currentMessages);
132
113
  loop: for (let turn = 0; turn < maxTurns; turn++) {
133
114
  if (turn === 0) {
134
- loading.text = `Connecting To ${model.provider}...`;
115
+ tui.setStatus("turns", `Connecting To ${model.provider}...`);
135
116
  }
136
117
  else {
137
- loading.text = `Processing turn ${turn + 1}...`;
138
- currentMessages.push({
118
+ tui.setStatus("turns", `Processing step ${turn + 1}/${maxTurns}...`);
119
+ const userTurnMessage = {
139
120
  role: "user",
140
121
  content: `Turns: ${turn}/${maxTurns}`,
141
- });
122
+ };
123
+ currentMessages.push(userTurnMessage);
124
+ __writeJsonLineLog(userTurnMessage);
142
125
  }
143
126
  const result = await streamText({
144
127
  model: model,
145
128
  messages: currentMessages,
146
129
  tools: availableTools,
147
130
  toolChoice: "auto", // Changed to auto for more flexibility
131
+ onError: () => { },
148
132
  });
149
133
  let fullReasoningText = "";
150
134
  let fullText = "";
@@ -159,13 +143,14 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
159
143
  ERROR: "ERROR",
160
144
  };
161
145
  for await (const part of result.fullStream) {
146
+ __writeJsonLineLog(part);
162
147
  if (firstStreamPart) {
163
148
  firstStreamPart = false;
164
- loading.text = ""; // Clear initial connecting/processing message
149
+ tui.text = ""; // Clear initial connecting/processing message
165
150
  }
166
151
  const LOOP_SIGNAL = await match(part)
167
152
  .with({ type: "text" }, (textPart) => {
168
- loading.prefixText = "🤖 ";
153
+ tui.prefixText = "🤖 ";
169
154
  let assistantTextPart = assistantMessageContent.findLast((part) => part.type === "text");
170
155
  if (assistantTextPart == null) {
171
156
  assistantTextPart = { type: "text", text: "" };
@@ -173,13 +158,13 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
173
158
  }
174
159
  assistantTextPart.text += textPart.text;
175
160
  if (fullText === "")
176
- fullText = "\n"; // For consistent display
161
+ tui.text = "";
177
162
  fullText += textPart.text;
178
- loading.text = fullText.split("\n").slice(-10).join("\n");
163
+ tui.text = "\n" + fullText.split("\n").slice(-10).join("\n");
179
164
  })
180
165
  .with({ type: "tool-call" }, (callPart) => {
181
- loading.prefixText = "🛠️ ";
182
- loading.text = "Requesting tool: " + blue(callPart.toolName);
166
+ tui.prefixText = "🛠️ ";
167
+ tui.text = "Requesting tool: " + blue(callPart.toolName);
183
168
  log("\nQAQ tool-call: %y", callPart);
184
169
  requestedToolCalls.push(callPart);
185
170
  // Update assistant message to include tool calls
@@ -191,31 +176,43 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
191
176
  });
192
177
  })
193
178
  .with({ type: "error" }, async (errorPart) => {
194
- loading.prefixText = endInfo.prefixText = "❌ ";
195
- loading.text = endInfo.text = red(`${errorPart.error}`);
196
- await handleRetryError(errorPart.error, loading);
197
- return LOOP_SIGNALS.BREAK; // Stop processing on error
179
+ tui.prefixText = tui.endInfo.prefixText = "❌ ";
180
+ tui.text = tui.endInfo.text = red(`${errorPart.error}`);
181
+ const handled = await handleError(errorPart.error, tui);
182
+ if (!handled) {
183
+ return LOOP_SIGNALS.BREAK; // Stop processing on error
184
+ }
198
185
  })
199
186
  .with({ type: "reasoning" }, (reasoningPart) => {
200
- loading.prefixText = "🤔 ";
187
+ tui.prefixText = "🤔 ";
201
188
  if (fullReasoningText === "")
202
- loading.text = "";
189
+ tui.text = "";
203
190
  fullReasoningText += reasoningPart.text;
204
- loading.text = gray(fullReasoningText.split("\n").slice(-3).join("\n"));
191
+ tui.text = "\n" + gray(fullReasoningText.split("\n").slice(-3).join("\n"));
205
192
  })
206
193
  // Add other console logs for debugging if needed, but keep them minimal for production
207
194
  .with({ type: "file" }, (p) => {
208
- loading.prefixText = "📃 ";
209
- loading.text = p.file.mediaType;
195
+ tui.prefixText = "📃 ";
196
+ tui.text = p.file.mediaType;
210
197
  log("\nQAQ file: %y", p.file);
211
198
  })
212
199
  .with({ type: "source" }, (p) => {
213
- loading.prefixText = "🔗 ";
214
- if (p.title) {
215
- loading.text = `[${p.title}](${p.url})`;
200
+ tui.prefixText = "🔗 ";
201
+ if (p.sourceType === "url") {
202
+ if (p.title) {
203
+ tui.text = `[${p.title}](${p.url})`;
204
+ }
205
+ else {
206
+ tui.text = p.url;
207
+ }
216
208
  }
217
209
  else {
218
- loading.text = p.url;
210
+ if (p.filename) {
211
+ tui.text = `[${p.title}](${p.filename})`;
212
+ }
213
+ else {
214
+ tui.text = p.title;
215
+ }
219
216
  }
220
217
  log("\nQAQ source: %y", p);
221
218
  })
@@ -224,22 +221,50 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
224
221
  .with({ type: "tool-call-delta" }, (p) => log("\nQAQ tool-call-delta: %y", p))
225
222
  .with({ type: "reasoning-part-finish" }, (p) => log("\nQAQ reasoning-part-finish: %y", p))
226
223
  .with({ type: "start-step" }, (p) => log("\nQAQ start-step: %y", p))
227
- .with({ type: "finish-step" }, (p) => log("\nQAQ finish-step: %y", p))
224
+ .with({ type: "finish-step" }, (p) => {
225
+ log("\nQAQ finish-step: %y", p);
226
+ /**
227
+ * This event marks the end of an intermediate step, not the entire turn.
228
+ * We handle potential issues here, but the main logic for continuing or
229
+ * stopping the loop is in the final 'finish' event handler.
230
+ */
231
+ return match(p)
232
+ .with({ finishReason: P.union("content-filter", "error") }, (part) => {
233
+ // A step finishing due to an error or content filter is a serious issue.
234
+ // Update the TUI to reflect this problem immediately.
235
+ const reasonText = part.finishReason === "content-filter" ? "Content filter violation" : "Model error";
236
+ tui.prefixText = tui.endInfo.prefixText = "⚠️ ";
237
+ tui.text = tui.endInfo.text = red(`Step failed due to ${reasonText}. Will be retry.`);
238
+ log(red(`Step finished with critical reason: ${part.finishReason}`));
239
+ return LOOP_SIGNALS.RETURN;
240
+ })
241
+ .with({ finishReason: P.union("other", "unknown") }, (part) => {
242
+ // Log unusual finish reasons for debugging purposes.
243
+ log(yellow(`Step finished with an unusual reason: ${part.finishReason}`));
244
+ })
245
+ .otherwise(() => {
246
+ // This covers 'stop', 'length', and 'tool-calls'. These are normal
247
+ // reasons for a step to finish. The final 'finish' event will
248
+ // determine the overall outcome of the turn. No special action is needed here.
249
+ log(`Step finished with normal reason: ${p.finishReason}. Awaiting end of turn.`);
250
+ });
251
+ })
228
252
  .with({ type: "start" }, (p) => log("\nQAQ start: %y", p))
229
253
  .with({ type: "finish" }, async (finishPart) => {
230
254
  log("\nQAQ finish: %y", finishPart);
231
- // Add the assistant's message from this turn to the history
255
+ // Add the assistant's message from this step to the history
232
256
  currentMessages.push(_currentAssistantMessage);
257
+ __writeJsonLineLog(_currentAssistantMessage);
233
258
  if (finishPart.finishReason === "stop" || finishPart.finishReason === "length") {
234
- loading.prefixText = endInfo.prefixText = "✅ ";
235
- loading.text = endInfo.text = green(`${cyan(`[${ai_task.name}]`)} Completed`);
259
+ tui.prefixText = tui.endInfo.prefixText = "✅ ";
260
+ tui.text = tui.endInfo.text = green(`${cyan(`[${ai_task.jobName}]`)} Completed`);
236
261
  // Task finished without tool calls or after tool calls that didn't lead to more calls.
237
262
  return LOOP_SIGNALS.RETURN; // Exit the outer loop and function
238
263
  }
239
264
  if (finishPart.finishReason === "tool-calls") {
240
265
  if (requestedToolCalls.length === 0) {
241
- loading.prefixText = endInfo.prefixText = "🚧 ";
242
- loading.text = endInfo.text = yellow(`${cyan(`[${ai_task.name}]`)} finished with 'tool-calls' but no tools were requested.`);
266
+ tui.prefixText = tui.endInfo.prefixText = "🚧 ";
267
+ tui.text = tui.endInfo.text = yellow(`${cyan(`[${ai_task.jobName}]`)} finished with 'tool-calls' but no tools were requested.`);
243
268
  return LOOP_SIGNALS.RETURN; // Exit, something is off
244
269
  }
245
270
  const toolResultMessages = [];
@@ -261,7 +286,7 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
261
286
  });
262
287
  continue;
263
288
  }
264
- loading.text = `Executing tool: ${toolCall.toolName}...`;
289
+ tui.text = `Executing tool: ${toolCall.toolName}...`;
265
290
  const executionResult = await func_catch(() => toolToExecute.execute(toolCall.args, {
266
291
  toolCallId: toolCall.toolCallId,
267
292
  messages: currentMessages,
@@ -279,19 +304,20 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
279
304
  ],
280
305
  });
281
306
  if (executionResult.success) {
282
- loading.text = `Tool ${toolCall.toolName} executed.`;
307
+ tui.text = `Tool ${toolCall.toolName} executed.`;
283
308
  }
284
309
  else {
285
- loading.text = `Error executing tool ${toolCall.toolName}.`;
310
+ tui.text = `Error executing tool ${toolCall.toolName}.`;
286
311
  }
287
312
  }
288
313
  currentMessages.push(...toolResultMessages);
289
- // Loop continues for the next turn
314
+ __writeJsonLineLog(...toolResultMessages);
315
+ // Loop continues for the next step
290
316
  }
291
317
  else {
292
318
  // Other finish reasons, potentially an error or unexpected state
293
- loading.prefixText = endInfo.prefixText = "🛑 ";
294
- loading.text = endInfo.text = red(`${cyan(`[${ai_task.name}]`)} task finished with unhandled reason: ${finishPart.finishReason}`);
319
+ tui.prefixText = tui.endInfo.prefixText = "🛑 ";
320
+ tui.text = tui.endInfo.text = red(`${cyan(`[${ai_task.jobName}]`)} task finished with unhandled reason: ${finishPart.finishReason}`);
295
321
  return LOOP_SIGNALS.ERROR;
296
322
  }
297
323
  })
@@ -308,8 +334,8 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
308
334
  }
309
335
  // If the stream finishes without a 'finish' part (e.g. error thrown inside), this loop might exit. Ensure spinner stops.
310
336
  if (turn === maxTurns - 1) {
311
- loading.prefixText = endInfo.prefixText = "🚧 ";
312
- loading.text = endInfo.text = yellow(`${cyan(`[${ai_task.name}]`)} Max interaction turns reached.`);
337
+ tui.prefixText = tui.endInfo.prefixText = "🚧 ";
338
+ tui.text = tui.endInfo.text = yellow(`${cyan(`[${ai_task.jobName}]`)} Max interaction turns reached.`);
313
339
  break;
314
340
  }
315
341
  }
@@ -1 +1 @@
1
- {"version":3,"file":"run-ai-task.js","sourceRoot":"","sources":["../../../src/commands/tasks/run-ai-task.ts"],"names":[],"mappings":"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","sourcesContent":["import {blue, cyan, FileEntry, gray, green, red, spinner, YAML, yellow, type Spinner} from \"@gaubee/nodekit\";\nimport {func_catch} from \"@gaubee/util\";\nimport {AISDKError, streamText, type AssistantModelMessage, type ModelMessage, type ToolCallPart, type ToolSet} from \"ai\";\nimport createDebug from \"debug\";\nimport ms from \"ms\";\nimport os from \"node:os\";\nimport {match, P} from \"ts-pattern\";\nimport {safeEnv} from \"../../env.js\";\nimport {handleRetryError} from \"../../helper/ai-retry-error.js\";\nimport {getPromptConfigs} from \"../../helper/prompts-loader.js\";\nimport type {AiTask} from \"../../helper/resolve-ai-tasks.js\";\nimport {tools} from \"./ai-tools.js\";\nimport {providers} from \"./model-providers.js\";\n\ncreateDebug.formatters.y = (v) => {\n return JSON.stringify(v, (_k, v) => {\n if (typeof v === \"string\") {\n let slice_len = 0;\n if (v.length > 200) {\n slice_len = 50;\n }\n if (v.length > 100) {\n slice_len = 30;\n }\n if (slice_len > 0) {\n return `<string:${v.length}>${v.slice(0, slice_len)}${gray(\"...\")}${v.slice(-slice_len)}`;\n }\n return v;\n }\n if (AISDKError.isInstance(v)) {\n return red(v.message);\n }\n return v;\n });\n};\nconst log = createDebug(\"jixo:run-ai-task\");\n\nconst getModel = (model?: string) => {\n return match(model)\n .with(P.string.startsWith(\"deepseek-\"), (model) => providers.deepseek(model))\n .with(P.string.startsWith(\"gemini-\"), (model) => providers.google(model))\n .with(P.string.startsWith(\"o3-\"), P.string.startsWith(\"o1-\"), P.string.startsWith(\"gpt-\"), (model) => providers.openai(model))\n .with(P.string.startsWith(\"claude-\"), (model) => providers.anthropic(model))\n .with(P.string.startsWith(\"grok-\"), (model) => providers.xai(model))\n .with(P.string.includes(\"/\"), (model) => providers.deepinfra(model))\n .otherwise(() => {\n if (safeEnv.JIXO_DEEPSEEK_API_KEY) {\n return providers.deepseek(\"deepseek-reasoner\");\n }\n if (safeEnv.JIXO_GOOGLE_API_KEY) {\n return providers.google(\"gemini-2.5-pro-preview-05-06\");\n }\n if (safeEnv.JIXO_OPENAI_API_KEY) {\n return providers.openai(\"o3-mini\");\n }\n if (safeEnv.JIXO_ANTHROPIC_API_KEY) {\n return providers.anthropic(\"claude-4-sonnet-20250514\");\n }\n if (safeEnv.JIXO_XAI_API_KEY) {\n return providers.xai(\"grok-3-beta\");\n }\n if (safeEnv.JIXO_DEEPINFRA_API_KEY) {\n return providers.deepinfra(\"meta-llama/Meta-Llama-3.1-405B-Instruct\");\n }\n return providers.deepseek(\"deepseek-reasoner\");\n });\n};\nexport const runAiTask = async (ai_task: AiTask, allFiles: FileEntry[], changedFilesSet: Record<string, FileEntry[]>) => {\n const loading = spinner(`Initializing AI task: ${cyan(ai_task.name)}...`);\n loading.prefixText = \"⏳ \";\n loading.start();\n const endInfo = {\n prefixText: \"\",\n text: \"\",\n suffixText: `⏱️ ${gray(ms(new Date().getTime() - new Date(ai_task.startTime).getTime(), {long: true}))}`,\n };\n try {\n await _runAiTask(ai_task, allFiles, changedFilesSet, loading, endInfo);\n } finally {\n // Fallback spinner stop if loop exits unexpectedly\n loading.stopAndPersist(endInfo);\n }\n};\n\nconst _runAiTask = async (\n ai_task: AiTask,\n allFiles: FileEntry[],\n changedFilesSet: Record<string, FileEntry[]>,\n loading: Spinner,\n endInfo: {\n prefixText: string;\n text: string;\n suffixText: string;\n },\n) => {\n const model = getModel(ai_task.model);\n const availableTools: ToolSet = {\n ...(await tools.fileSystem(ai_task.cwd)),\n // ...(await tools.memory(path.join(ai_task.cwd, `.jixo/${ai_task.name}.memory.json`))),\n ...(await tools.sequentialThinking()),\n ...(await tools.jixoSkill().tools),\n // ...(await tools.git(ai_task.cwd)),\n };\n\n const initialMessages: ModelMessage[] = [];\n const maxTurns = 40; // Safeguard against infinite loops\n\n const promptConfigs = getPromptConfigs();\n for (const role of [\"system\", \"user\"] as const) {\n const promptConfig = promptConfigs[role];\n\n const promptContent = promptConfig.content //\n .replace(/\\{\\{task.(\\w+)\\}\\}/g, (_, key) => {\n return Reflect.get(ai_task, key);\n })\n .replace(/\\{\\{env.(\\w+)\\}\\}/g, (_, key) => {\n const envKey = key.toUpperCase();\n const envValue =\n Reflect.get(process.env, envKey) ??\n match(envKey)\n .with(\"USER\", () => os.userInfo().username)\n .otherwise(() => \"\");\n return envValue;\n })\n .replaceAll(\"{{allSkills}}\", (_, key) => {\n return YAML.stringify(tools.jixoSkill().allSkillNavList);\n })\n .replaceAll(\n \"{{allFiles}}\",\n YAML.stringify({\n [ai_task.cwd]: {\n count: allFiles.length,\n file: allFiles.map((e) => e.relativePath),\n },\n }),\n )\n .replaceAll(\"{{maxTurns}}\", () => `${maxTurns}`)\n .replaceAll(\n \"{{changedFiles}}\",\n YAML.stringify(\n Object.entries(changedFilesSet).reduce(\n (tree, [dir, changedFiles]) => {\n tree[dir] = {\n count: changedFiles.length,\n files: changedFiles.map((e) => e.relativePath),\n };\n return tree;\n },\n {} as Record<string, {count: number; files: string[]}>,\n ),\n ),\n );\n log(`PROMPT ${role}:`, promptContent);\n initialMessages.push({\n role: role,\n content: promptContent,\n });\n }\n\n const currentMessages: ModelMessage[] = [...initialMessages];\n\n loop: for (let turn = 0; turn < maxTurns; turn++) {\n if (turn === 0) {\n loading.text = `Connecting To ${model.provider}...`;\n } else {\n loading.text = `Processing turn ${turn + 1}...`;\n currentMessages.push({\n role: \"user\",\n content: `Turns: ${turn}/${maxTurns}`,\n });\n }\n const result = await streamText({\n model: model,\n messages: currentMessages,\n tools: availableTools,\n toolChoice: \"auto\", // Changed to auto for more flexibility\n });\n\n let fullReasoningText = \"\";\n let fullText = \"\";\n let firstStreamPart = true;\n const requestedToolCalls: ToolCallPart[] = []; // Using any for now, should be ToolCallPart from 'ai'\n\n const assistantMessageContent: AssistantModelMessage[\"content\"] & unknown[] = [];\n const _currentAssistantMessage: AssistantModelMessage = {role: \"assistant\", content: assistantMessageContent};\n\n const LOOP_SIGNALS = {\n RETURN: \"RETURN\",\n BREAK: \"BREAK\",\n CONTINUE: \"CONTINUE\",\n ERROR: \"ERROR\",\n } as const;\n for await (const part of result.fullStream) {\n if (firstStreamPart) {\n firstStreamPart = false;\n loading.text = \"\"; // Clear initial connecting/processing message\n }\n const LOOP_SIGNAL = await match(part)\n .with({type: \"text\"}, (textPart) => {\n loading.prefixText = \"🤖 \";\n let assistantTextPart = assistantMessageContent.findLast((part) => part.type === \"text\");\n if (assistantTextPart == null) {\n assistantTextPart = {type: \"text\", text: \"\"};\n assistantMessageContent.push(assistantTextPart);\n }\n assistantTextPart.text += textPart.text;\n if (fullText === \"\") fullText = \"\\n\"; // For consistent display\n fullText += textPart.text;\n loading.text = fullText.split(\"\\n\").slice(-10).join(\"\\n\");\n })\n .with({type: \"tool-call\"}, (callPart) => {\n loading.prefixText = \"🛠️ \";\n loading.text = \"Requesting tool: \" + blue(callPart.toolName);\n log(\"\\nQAQ tool-call: %y\", callPart);\n requestedToolCalls.push(callPart);\n // Update assistant message to include tool calls\n assistantMessageContent.push({\n type: \"tool-call\",\n toolCallId: callPart.toolCallId,\n toolName: callPart.toolName,\n args: callPart.args,\n });\n })\n .with({type: \"error\"}, async (errorPart) => {\n loading.prefixText = endInfo.prefixText = \"❌ \";\n loading.text = endInfo.text = red(`${errorPart.error}`);\n await handleRetryError(errorPart.error, loading);\n return LOOP_SIGNALS.BREAK; // Stop processing on error\n })\n .with({type: \"reasoning\"}, (reasoningPart) => {\n loading.prefixText = \"🤔 \";\n if (fullReasoningText === \"\") loading.text = \"\";\n fullReasoningText += reasoningPart.text;\n loading.text = gray(fullReasoningText.split(\"\\n\").slice(-3).join(\"\\n\"));\n })\n // Add other console logs for debugging if needed, but keep them minimal for production\n .with({type: \"file\"}, (p) => {\n loading.prefixText = \"📃 \";\n loading.text = p.file.mediaType;\n\n log(\"\\nQAQ file: %y\", p.file);\n })\n .with({type: \"source\"}, (p) => {\n loading.prefixText = \"🔗 \";\n if (p.title) {\n loading.text = `[${p.title}](${p.url})`;\n } else {\n loading.text = p.url;\n }\n\n log(\"\\nQAQ source: %y\", p);\n })\n .with({type: \"tool-result\"}, (p) => log(\"\\nQAQ tool-result: %y\", p))\n .with({type: \"tool-call-streaming-start\"}, (p) => log(\"\\nQAQ tool-call-streaming-start: %y\", p))\n .with({type: \"tool-call-delta\"}, (p) => log(\"\\nQAQ tool-call-delta: %y\", p))\n .with({type: \"reasoning-part-finish\"}, (p) => log(\"\\nQAQ reasoning-part-finish: %y\", p))\n .with({type: \"start-step\"}, (p) => log(\"\\nQAQ start-step: %y\", p))\n .with({type: \"finish-step\"}, (p) => log(\"\\nQAQ finish-step: %y\", p))\n .with({type: \"start\"}, (p) => log(\"\\nQAQ start: %y\", p))\n .with({type: \"finish\"}, async (finishPart) => {\n log(\"\\nQAQ finish: %y\", finishPart);\n // Add the assistant's message from this turn to the history\n currentMessages.push(_currentAssistantMessage);\n\n if (finishPart.finishReason === \"stop\" || finishPart.finishReason === \"length\") {\n loading.prefixText = endInfo.prefixText = \"✅ \";\n loading.text = endInfo.text = green(`${cyan(`[${ai_task.name}]`)} Completed`);\n // Task finished without tool calls or after tool calls that didn't lead to more calls.\n return LOOP_SIGNALS.RETURN; // Exit the outer loop and function\n }\n\n if (finishPart.finishReason === \"tool-calls\") {\n if (requestedToolCalls.length === 0) {\n loading.prefixText = endInfo.prefixText = \"🚧 \";\n loading.text = endInfo.text = yellow(`${cyan(`[${ai_task.name}]`)} finished with 'tool-calls' but no tools were requested.`);\n return LOOP_SIGNALS.RETURN; // Exit, something is off\n }\n\n const toolResultMessages: ModelMessage[] = [];\n for (const toolCall of requestedToolCalls) {\n const toolToExecute = availableTools[toolCall.toolName];\n if (!toolToExecute || typeof toolToExecute.execute !== \"function\") {\n console.error(`Tool ${toolCall.toolName} not found or not executable.`);\n toolResultMessages.push({\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n result: JSON.stringify({error: `Tool ${toolCall.toolName} not found or not executable.`}),\n isError: true,\n },\n ],\n });\n continue;\n }\n loading.text = `Executing tool: ${toolCall.toolName}...`;\n const executionResult = await func_catch(() =>\n toolToExecute.execute!(toolCall.args, {\n toolCallId: toolCall.toolCallId,\n messages: currentMessages,\n }),\n )();\n toolResultMessages.push({\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n isError: !executionResult.success,\n result: JSON.stringify(executionResult.success ? executionResult.result : executionResult.error),\n },\n ],\n });\n if (executionResult.success) {\n loading.text = `Tool ${toolCall.toolName} executed.`;\n } else {\n loading.text = `Error executing tool ${toolCall.toolName}.`;\n }\n }\n currentMessages.push(...toolResultMessages);\n // Loop continues for the next turn\n } else {\n // Other finish reasons, potentially an error or unexpected state\n loading.prefixText = endInfo.prefixText = \"🛑 \";\n loading.text = endInfo.text = red(`${cyan(`[${ai_task.name}]`)} task finished with unhandled reason: ${finishPart.finishReason}`);\n return LOOP_SIGNALS.ERROR;\n }\n })\n .otherwise(() => {}); // Handle any other part types if necessary\n\n if (LOOP_SIGNAL === LOOP_SIGNALS.ERROR) {\n throw LOOP_SIGNAL;\n }\n if (LOOP_SIGNAL === LOOP_SIGNALS.RETURN) {\n break loop;\n } else if (LOOP_SIGNAL === LOOP_SIGNALS.BREAK) {\n break;\n }\n }\n // If the stream finishes without a 'finish' part (e.g. error thrown inside), this loop might exit. Ensure spinner stops.\n if (turn === maxTurns - 1) {\n loading.prefixText = endInfo.prefixText = \"🚧 \";\n loading.text = endInfo.text = yellow(`${cyan(`[${ai_task.name}]`)} Max interaction turns reached.`);\n break;\n }\n }\n};\n"]}
1
+ {"version":3,"file":"run-ai-task.js","sourceRoot":"","sources":["../../../src/commands/tasks/run-ai-task.ts"],"names":[],"mappings":"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","sourcesContent":["import {blue, cyan, FileEntry, gray, green, red, spinner, YAML, yellow} from \"@gaubee/nodekit\";\nimport {func_catch} from \"@gaubee/util\";\nimport {streamText, type AssistantModelMessage, type ModelMessage, type ToolCallPart, type ToolSet} from \"ai\";\nimport ms from \"ms\";\nimport {open} from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport {match, P} from \"ts-pattern\";\nimport {handleError} from \"../../helper/handle-ai-error.js\";\nimport {createDebug} from \"../../helper/logger.js\";\nimport {getAllPromptConfigs, getAllSkillMap as getAllSkillNavMap} from \"../../helper/prompts-loader.js\";\nimport type {AiTask} from \"../../helper/resolve-ai-tasks.js\";\nimport {AiTaskTui} from \"./ai-tasl-tui.js\";\nimport {tools} from \"./ai-tools.js\";\nimport {getModel} from \"./model-providers.js\";\n\nconst log = createDebug(\"jixo:run-ai-task\");\n\nexport const runAiTask = async (ai_task: AiTask, loopTimes: number, allFiles: FileEntry[], changedFilesSet: Record<string, FileEntry[]>) => {\n const tool_spinner = spinner({\n prefixText: \"🧰\",\n text: \"Preparing AI tools...\",\n });\n tool_spinner.start();\n const availableTools: ToolSet = {\n ...(await tools.fileSystem(ai_task.cwd)),\n ...(await tools.pnpm()),\n ...(await tools.jixo(ai_task)),\n ...(await tools.git(ai_task.cwd)),\n };\n tool_spinner.clear();\n tool_spinner.stop();\n\n const json_line_log_file_handle = await open(path.join(ai_task.cwd, \".jixo\", `${ai_task.runner}.log.jsonl`), \"a\");\n const __writeJsonLineLog = (...lineDatas: any[]) => {\n for (const lineData of lineDatas) {\n try {\n json_line_log_file_handle.appendFile(JSON.stringify(lineData) + \"\\n\");\n } catch {}\n }\n };\n\n const tui = new AiTaskTui(ai_task, spinner({text: `Initializing AI task: ${cyan(ai_task.jobName)}...`, prefixText: \"⏳ \"}));\n tui.spinner.start();\n const updateTuiState = () => {\n tui.setStatus(\"loop and time\", `${green(`[${loopTimes}]`)} ${cyan(`+${ms(Date.now() - new Date(ai_task.startTime).getTime())}`)}`);\n };\n const ti = setInterval(updateTuiState, 1000);\n updateTuiState();\n try {\n await _runAiTask(ai_task, availableTools, allFiles, changedFilesSet, tui, __writeJsonLineLog);\n } finally {\n // Fallback spinner stop if loop exits unexpectedly\n clearInterval(ti);\n tui.stop();\n json_line_log_file_handle.close();\n }\n};\n\nconst _runAiTask = async (\n ai_task: AiTask,\n availableTools: ToolSet,\n allFiles: FileEntry[],\n changedFilesSet: Record<string, FileEntry[]>,\n tui: AiTaskTui,\n __writeJsonLineLog: (...lineDatas: any[]) => void,\n) => {\n const model = getModel(ai_task.model);\n\n const initialMessages: ModelMessage[] = [];\n const maxTurns = 40; // Safeguard against infinite loops\n\n const promptConfigs = getAllPromptConfigs();\n\n for (const role of [\"system\", \"user\"] as const) {\n const promptConfig = promptConfigs[role];\n\n const promptContent = promptConfig.content //\n .replace(/\\{\\{task.([\\.\\w]+)\\}\\}/g, (_, key) => {\n if (key.includes(\".\")) {\n const paths = key.split(\".\");\n let res: any = ai_task;\n for (const p of paths) {\n res = Reflect.get(res, p);\n if (!res) {\n break;\n }\n }\n return res;\n } else {\n return Reflect.get(ai_task, key);\n }\n })\n .replace(/\\{\\{env.(\\w+)\\}\\}/g, (_, key) => {\n const envKey = key.toUpperCase();\n const envValue =\n Reflect.get(process.env, envKey) ??\n match(envKey)\n .with(\"USER\", () => os.userInfo().username)\n .otherwise(() => \"\");\n return envValue;\n })\n .replaceAll(\"{{allSkills}}\", (_, key) => {\n return YAML.stringify(getAllSkillNavMap());\n })\n .replaceAll(\n \"{{allFiles}}\",\n YAML.stringify({\n [ai_task.cwd]: {\n count: allFiles.length,\n file: allFiles.map((e) => e.relativePath),\n },\n }),\n )\n .replaceAll(\"{{maxTurns}}\", () => `${maxTurns}`)\n .replaceAll(\n \"{{changedFiles}}\",\n YAML.stringify(\n Object.entries(changedFilesSet).reduce(\n (tree, [dir, changedFiles]) => {\n tree[dir] = {\n count: changedFiles.length,\n files: changedFiles.map((e) => e.relativePath),\n };\n return tree;\n },\n {} as Record<string, {count: number; files: string[]}>,\n ),\n ),\n );\n log(`PROMPT ${role}:`, promptContent);\n initialMessages.push({\n role: role,\n content: promptContent,\n });\n }\n\n const currentMessages: ModelMessage[] = [...initialMessages];\n\n __writeJsonLineLog(...currentMessages);\n\n loop: for (let turn = 0; turn < maxTurns; turn++) {\n if (turn === 0) {\n tui.setStatus(\"turns\", `Connecting To ${model.provider}...`);\n } else {\n tui.setStatus(\"turns\", `Processing step ${turn + 1}/${maxTurns}...`);\n const userTurnMessage: ModelMessage = {\n role: \"user\",\n content: `Turns: ${turn}/${maxTurns}`,\n };\n currentMessages.push(userTurnMessage);\n __writeJsonLineLog(userTurnMessage);\n }\n const result = await streamText({\n model: model,\n messages: currentMessages,\n tools: availableTools,\n toolChoice: \"auto\", // Changed to auto for more flexibility\n onError: () => {},\n });\n\n let fullReasoningText = \"\";\n let fullText = \"\";\n let firstStreamPart = true;\n const requestedToolCalls: ToolCallPart[] = []; // Using any for now, should be ToolCallPart from 'ai'\n\n const assistantMessageContent: AssistantModelMessage[\"content\"] & unknown[] = [];\n const _currentAssistantMessage: AssistantModelMessage = {role: \"assistant\", content: assistantMessageContent};\n\n const LOOP_SIGNALS = {\n RETURN: \"RETURN\",\n BREAK: \"BREAK\",\n CONTINUE: \"CONTINUE\",\n ERROR: \"ERROR\",\n } as const;\n for await (const part of result.fullStream) {\n __writeJsonLineLog(part);\n\n if (firstStreamPart) {\n firstStreamPart = false;\n tui.text = \"\"; // Clear initial connecting/processing message\n }\n\n const LOOP_SIGNAL = await match(part)\n .with({type: \"text\"}, (textPart) => {\n tui.prefixText = \"🤖 \";\n let assistantTextPart = assistantMessageContent.findLast((part) => part.type === \"text\");\n if (assistantTextPart == null) {\n assistantTextPart = {type: \"text\", text: \"\"};\n assistantMessageContent.push(assistantTextPart);\n }\n assistantTextPart.text += textPart.text;\n if (fullText === \"\") tui.text = \"\";\n fullText += textPart.text;\n tui.text = \"\\n\" + fullText.split(\"\\n\").slice(-10).join(\"\\n\");\n })\n .with({type: \"tool-call\"}, (callPart) => {\n tui.prefixText = \"🛠️ \";\n tui.text = \"Requesting tool: \" + blue(callPart.toolName);\n log(\"\\nQAQ tool-call: %y\", callPart);\n requestedToolCalls.push(callPart);\n // Update assistant message to include tool calls\n assistantMessageContent.push({\n type: \"tool-call\",\n toolCallId: callPart.toolCallId,\n toolName: callPart.toolName,\n args: callPart.args,\n });\n })\n .with({type: \"error\"}, async (errorPart) => {\n tui.prefixText = tui.endInfo.prefixText = \"❌ \";\n tui.text = tui.endInfo.text = red(`${errorPart.error}`);\n const handled = await handleError(errorPart.error, tui);\n if (!handled) {\n return LOOP_SIGNALS.BREAK; // Stop processing on error\n }\n })\n .with({type: \"reasoning\"}, (reasoningPart) => {\n tui.prefixText = \"🤔 \";\n if (fullReasoningText === \"\") tui.text = \"\";\n fullReasoningText += reasoningPart.text;\n tui.text = \"\\n\" + gray(fullReasoningText.split(\"\\n\").slice(-3).join(\"\\n\"));\n })\n // Add other console logs for debugging if needed, but keep them minimal for production\n .with({type: \"file\"}, (p) => {\n tui.prefixText = \"📃 \";\n tui.text = p.file.mediaType;\n\n log(\"\\nQAQ file: %y\", p.file);\n })\n .with({type: \"source\"}, (p) => {\n tui.prefixText = \"🔗 \";\n if (p.sourceType === \"url\") {\n if (p.title) {\n tui.text = `[${p.title}](${p.url})`;\n } else {\n tui.text = p.url;\n }\n } else {\n if (p.filename) {\n tui.text = `[${p.title}](${p.filename})`;\n } else {\n tui.text = p.title;\n }\n }\n\n log(\"\\nQAQ source: %y\", p);\n })\n .with({type: \"tool-result\"}, (p) => log(\"\\nQAQ tool-result: %y\", p))\n .with({type: \"tool-call-streaming-start\"}, (p) => log(\"\\nQAQ tool-call-streaming-start: %y\", p))\n .with({type: \"tool-call-delta\"}, (p) => log(\"\\nQAQ tool-call-delta: %y\", p))\n .with({type: \"reasoning-part-finish\"}, (p) => log(\"\\nQAQ reasoning-part-finish: %y\", p))\n .with({type: \"start-step\"}, (p) => log(\"\\nQAQ start-step: %y\", p))\n .with({type: \"finish-step\"}, (p) => {\n log(\"\\nQAQ finish-step: %y\", p);\n /**\n * This event marks the end of an intermediate step, not the entire turn.\n * We handle potential issues here, but the main logic for continuing or\n * stopping the loop is in the final 'finish' event handler.\n */\n return match(p)\n .with({finishReason: P.union(\"content-filter\", \"error\")}, (part) => {\n // A step finishing due to an error or content filter is a serious issue.\n // Update the TUI to reflect this problem immediately.\n const reasonText = part.finishReason === \"content-filter\" ? \"Content filter violation\" : \"Model error\";\n tui.prefixText = tui.endInfo.prefixText = \"⚠️ \";\n tui.text = tui.endInfo.text = red(`Step failed due to ${reasonText}. Will be retry.`);\n log(red(`Step finished with critical reason: ${part.finishReason}`));\n return LOOP_SIGNALS.RETURN;\n })\n .with({finishReason: P.union(\"other\", \"unknown\")}, (part) => {\n // Log unusual finish reasons for debugging purposes.\n log(yellow(`Step finished with an unusual reason: ${part.finishReason}`));\n })\n .otherwise(() => {\n // This covers 'stop', 'length', and 'tool-calls'. These are normal\n // reasons for a step to finish. The final 'finish' event will\n // determine the overall outcome of the turn. No special action is needed here.\n log(`Step finished with normal reason: ${p.finishReason}. Awaiting end of turn.`);\n });\n })\n .with({type: \"start\"}, (p) => log(\"\\nQAQ start: %y\", p))\n .with({type: \"finish\"}, async (finishPart) => {\n log(\"\\nQAQ finish: %y\", finishPart);\n // Add the assistant's message from this step to the history\n currentMessages.push(_currentAssistantMessage);\n __writeJsonLineLog(_currentAssistantMessage);\n\n if (finishPart.finishReason === \"stop\" || finishPart.finishReason === \"length\") {\n tui.prefixText = tui.endInfo.prefixText = \"✅ \";\n tui.text = tui.endInfo.text = green(`${cyan(`[${ai_task.jobName}]`)} Completed`);\n // Task finished without tool calls or after tool calls that didn't lead to more calls.\n return LOOP_SIGNALS.RETURN; // Exit the outer loop and function\n }\n\n if (finishPart.finishReason === \"tool-calls\") {\n if (requestedToolCalls.length === 0) {\n tui.prefixText = tui.endInfo.prefixText = \"🚧 \";\n tui.text = tui.endInfo.text = yellow(`${cyan(`[${ai_task.jobName}]`)} finished with 'tool-calls' but no tools were requested.`);\n return LOOP_SIGNALS.RETURN; // Exit, something is off\n }\n\n const toolResultMessages: ModelMessage[] = [];\n for (const toolCall of requestedToolCalls) {\n const toolToExecute = availableTools[toolCall.toolName];\n if (!toolToExecute || typeof toolToExecute.execute !== \"function\") {\n console.error(`Tool ${toolCall.toolName} not found or not executable.`);\n toolResultMessages.push({\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n result: JSON.stringify({error: `Tool ${toolCall.toolName} not found or not executable.`}),\n isError: true,\n },\n ],\n });\n continue;\n }\n tui.text = `Executing tool: ${toolCall.toolName}...`;\n const executionResult = await func_catch(() =>\n toolToExecute.execute!(toolCall.args, {\n toolCallId: toolCall.toolCallId,\n messages: currentMessages,\n }),\n )();\n toolResultMessages.push({\n role: \"tool\",\n content: [\n {\n type: \"tool-result\",\n toolCallId: toolCall.toolCallId,\n toolName: toolCall.toolName,\n isError: !executionResult.success,\n result: JSON.stringify(executionResult.success ? executionResult.result : executionResult.error),\n },\n ],\n });\n if (executionResult.success) {\n tui.text = `Tool ${toolCall.toolName} executed.`;\n } else {\n tui.text = `Error executing tool ${toolCall.toolName}.`;\n }\n }\n currentMessages.push(...toolResultMessages);\n __writeJsonLineLog(...toolResultMessages);\n // Loop continues for the next step\n } else {\n // Other finish reasons, potentially an error or unexpected state\n tui.prefixText = tui.endInfo.prefixText = \"🛑 \";\n tui.text = tui.endInfo.text = red(`${cyan(`[${ai_task.jobName}]`)} task finished with unhandled reason: ${finishPart.finishReason}`);\n return LOOP_SIGNALS.ERROR;\n }\n })\n .otherwise(() => {}); // Handle any other part types if necessary\n\n if (LOOP_SIGNAL === LOOP_SIGNALS.ERROR) {\n throw LOOP_SIGNAL;\n }\n if (LOOP_SIGNAL === LOOP_SIGNALS.RETURN) {\n break loop;\n } else if (LOOP_SIGNAL === LOOP_SIGNALS.BREAK) {\n break;\n }\n }\n // If the stream finishes without a 'finish' part (e.g. error thrown inside), this loop might exit. Ensure spinner stops.\n if (turn === maxTurns - 1) {\n tui.prefixText = tui.endInfo.prefixText = \"🚧 \";\n tui.text = tui.endInfo.text = yellow(`${cyan(`[${ai_task.jobName}]`)} Max interaction turns reached.`);\n break;\n }\n }\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/run.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,GAAG,GACd,MAAM,MAAM,EACZ,SAAS;IACP,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,kBAmFF,CAAC"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/tasks/run.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,GAAG,GACd,MAAM,MAAM,EACZ,SAAS;IACP,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,kBA+FF,CAAC"}
@@ -9,37 +9,43 @@ import { runAiTask } from "./run-ai-task.js";
9
9
  export const run = async (_cwd, options) => {
10
10
  const cwd = normalizeFilePath(_cwd);
11
11
  const config = await loadConfig(cwd);
12
+ const nameMatcher = options.nameFilter.length ? new Ignore(options.nameFilter, cwd) : { isMatch: () => true };
13
+ const dirMatcher = options.dirFilter.length ? new Ignore(options.dirFilter, cwd) : { isMatch: () => true };
14
+ const cwdIgnoreFilepath = path.join(cwd, ".gitignore");
15
+ const ignore = [".git"];
16
+ if (fs.existsSync(cwdIgnoreFilepath)) {
17
+ ignore.push(...fs.readFileSync(cwdIgnoreFilepath, "utf-8").split("\n"));
18
+ }
19
+ const exitedJobs = new Set();
12
20
  let { force = false } = options;
13
21
  const { loopTimes: MAX_LOOP_TIMES = Infinity } = options;
14
22
  let currentTimes = 1;
15
23
  let retryTimes = 0;
16
24
  const MAX_RETRY_TIMES = 3;
17
25
  while (currentTimes <= MAX_LOOP_TIMES) {
18
- const ai_tasks = resolveAiTasks(cwd, config.tasks);
19
- const nameMatcher = options.nameFilter.length ? new Ignore(options.nameFilter, cwd) : { isMatch: () => true };
20
- const dirMatcher = options.dirFilter.length ? new Ignore(options.dirFilter, cwd) : { isMatch: () => true };
21
- const cwdIgnoreFilepath = path.join(cwd, ".gitignore");
22
- const ignore = [".git"];
23
- if (fs.existsSync(cwdIgnoreFilepath)) {
24
- ignore.push(...fs.readFileSync(cwdIgnoreFilepath, "utf-8").split("\n"));
25
- }
26
+ const ai_tasks = resolveAiTasks(cwd, config.tasks, currentTimes - 1);
26
27
  const allFiles = [...walkFiles(cwd, { ignore })];
27
28
  let allDone = true;
28
29
  try {
29
30
  for (const ai_task of ai_tasks) {
30
- // 如果进度已经满了,那么跳过
31
- if (ai_task.preProgress >= 1 && !force) {
31
+ // 如果进度已经满了,并且没有任何依赖文件的变更,那么跳过这个任务
32
+ if (!force) {
33
+ if (ai_task.log.preProgress >= 1) {
34
+ continue;
35
+ }
36
+ }
37
+ if (exitedJobs.has(ai_task.jobName)) {
32
38
  continue;
33
39
  }
34
40
  const { dirs: task_dirs } = ai_task;
35
41
  if (!task_dirs.some((dir) => dirMatcher.isMatch(dir))) {
36
42
  continue;
37
43
  }
38
- if (!nameMatcher.isMatch(ai_task.name)) {
44
+ if (!nameMatcher.isMatch(ai_task.jobName)) {
39
45
  continue;
40
46
  }
41
47
  const isCwdTask = cwd === task_dirs[0] && task_dirs.length === 1;
42
- const changedFiles = (await findChangedFilesSinceTime(ai_task.preUpdateTime, cwd)) ?? allFiles;
48
+ const changedFiles = (await findChangedFilesSinceTime(ai_task.log.preUpdateTime, cwd)) ?? allFiles;
43
49
  const task_changedFiles = isCwdTask
44
50
  ? { [cwd]: changedFiles }
45
51
  : task_dirs.reduce((tree, task_dir) => {
@@ -54,10 +60,14 @@ export const run = async (_cwd, options) => {
54
60
  loadJixoEnv(cwd);
55
61
  /// 只要有一个任务执行了,那么allDone就要标记成false,进入下一次循环来判断
56
62
  allDone = false;
57
- await runAiTask(ai_task, task_allFiles, task_changedFiles);
63
+ await runAiTask(ai_task, currentTimes, task_allFiles, task_changedFiles);
64
+ if (ai_task.exitCode != null) {
65
+ exitedJobs.add(ai_task.jobName);
66
+ }
58
67
  }
59
68
  }
60
- catch {
69
+ catch (e) {
70
+ console.error(e);
61
71
  // 遇到异常,那么重试
62
72
  if (retryTimes < MAX_RETRY_TIMES) {
63
73
  retryTimes += 1;