@jixo/cli 0.10.0 → 0.11.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 +2 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/prompts/list.js +2 -2
  5. package/dist/commands/prompts/list.js.map +1 -1
  6. package/dist/commands/tasks/ai-tools.d.ts +280 -8
  7. package/dist/commands/tasks/ai-tools.d.ts.map +1 -1
  8. package/dist/commands/tasks/ai-tools.js +49 -14
  9. package/dist/commands/tasks/ai-tools.js.map +1 -1
  10. package/dist/commands/tasks/run-ai-task.d.ts +1 -1
  11. package/dist/commands/tasks/run-ai-task.d.ts.map +1 -1
  12. package/dist/commands/tasks/run-ai-task.js +71 -24
  13. package/dist/commands/tasks/run-ai-task.js.map +1 -1
  14. package/dist/commands/tasks/run.d.ts.map +1 -1
  15. package/dist/commands/tasks/run.js +20 -11
  16. package/dist/commands/tasks/run.js.map +1 -1
  17. package/dist/helper/ai-retry-error.d.ts +1 -1
  18. package/dist/helper/ai-retry-error.d.ts.map +1 -1
  19. package/dist/helper/ai-retry-error.js +63 -30
  20. package/dist/helper/ai-retry-error.js.map +1 -1
  21. package/dist/helper/handle-ai-error.d.ts +5 -0
  22. package/dist/helper/handle-ai-error.d.ts.map +1 -0
  23. package/dist/helper/handle-ai-error.js +122 -0
  24. package/dist/helper/handle-ai-error.js.map +1 -0
  25. package/dist/helper/prompts-loader.d.ts +9 -3
  26. package/dist/helper/prompts-loader.d.ts.map +1 -1
  27. package/dist/helper/prompts-loader.js +16 -16
  28. package/dist/helper/prompts-loader.js.map +1 -1
  29. package/dist/helper/resolve-ai-tasks.d.ts +21 -8
  30. package/dist/helper/resolve-ai-tasks.d.ts.map +1 -1
  31. package/dist/helper/resolve-ai-tasks.js +58 -19
  32. package/dist/helper/resolve-ai-tasks.js.map +1 -1
  33. package/dist/prompts.json +14 -2
  34. package/package.json +4 -3
  35. package/dist/commands/run.d.ts +0 -5
  36. package/dist/commands/run.d.ts.map +0 -1
  37. package/dist/commands/run.js +0 -36
  38. package/dist/commands/run.js.map +0 -1
  39. package/dist/commands/tasks/run-ai.d.ts +0 -278
  40. package/dist/commands/tasks/run-ai.d.ts.map +0 -1
  41. package/dist/commands/tasks/run-ai.js +0 -179
  42. package/dist/commands/tasks/run-ai.js.map +0 -1
  43. package/dist/commands/upgrade.d.ts +0 -4
  44. package/dist/commands/upgrade.d.ts.map +0 -1
  45. package/dist/commands/upgrade.js +0 -17
  46. package/dist/commands/upgrade.js.map +0 -1
  47. package/dist/helper/prompts.d.ts +0 -3
  48. package/dist/helper/prompts.d.ts.map +0 -1
  49. package/dist/helper/prompts.js +0 -28
  50. package/dist/helper/prompts.js.map +0 -1
  51. package/dist/helper/run-ai.d.ts +0 -12
  52. package/dist/helper/run-ai.d.ts.map +0 -1
  53. package/dist/helper/run-ai.js +0 -179
  54. package/dist/helper/run-ai.js.map +0 -1
@@ -6,8 +6,8 @@ import ms from "ms";
6
6
  import os from "node:os";
7
7
  import { match, P } from "ts-pattern";
8
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 { getAllPromptConfigs, getAllSkillMap as getAllSkillNavMap } from "../../helper/prompts-loader.js";
11
11
  import { tools } from "./ai-tools.js";
12
12
  import { providers } from "./model-providers.js";
13
13
  createDebug.formatters.y = (v) => {
@@ -62,40 +62,76 @@ const getModel = (model) => {
62
62
  return providers.deepseek("deepseek-reasoner");
63
63
  });
64
64
  };
65
- export const runAiTask = async (ai_task, allFiles, changedFilesSet) => {
65
+ export const runAiTask = async (ai_task, loopTimes, allFiles, changedFilesSet) => {
66
+ const availableTools = {
67
+ ...(await tools.fileSystem(ai_task.cwd)),
68
+ // ...(await tools.memory(path.join(ai_task.cwd, `.jixo/${ai_task.name}.memory.json`))),
69
+ ...(await tools.pnpm()),
70
+ ...(await tools.jixo(ai_task)),
71
+ ...(await tools.git(ai_task.cwd)),
72
+ };
66
73
  const loading = spinner(`Initializing AI task: ${cyan(ai_task.name)}...`);
67
74
  loading.prefixText = "⏳ ";
68
75
  loading.start();
69
76
  const endInfo = {
70
77
  prefixText: "",
71
78
  text: "",
72
- suffixText: `⏱️ ${gray(ms(new Date().getTime() - new Date(ai_task.startTime).getTime(), { long: true }))}`,
79
+ get suffixText() {
80
+ return `⏱️ ${gray(ms(new Date().getTime() - new Date(ai_task.startTime).getTime(), { long: true }))}`;
81
+ },
82
+ };
83
+ let prefixText = loading.prefixText;
84
+ const updatePrefixText = () => {
85
+ loading.prefixText = `${green(`[${loopTimes}]`)} ${cyan(`+${ms(Date.now() - new Date(ai_task.startTime).getTime())}`)}\n${prefixText}`;
73
86
  };
87
+ const ti = setInterval(updatePrefixText, 1000);
88
+ updatePrefixText();
74
89
  try {
75
- await _runAiTask(ai_task, allFiles, changedFilesSet, loading, endInfo);
90
+ await _runAiTask(ai_task, availableTools, allFiles, changedFilesSet, {
91
+ get text() {
92
+ return loading.text;
93
+ },
94
+ set text(v) {
95
+ loading.text = v;
96
+ },
97
+ get prefixText() {
98
+ return prefixText;
99
+ },
100
+ set prefixText(v) {
101
+ prefixText = v;
102
+ updatePrefixText();
103
+ },
104
+ }, endInfo);
76
105
  }
77
106
  finally {
78
107
  // Fallback spinner stop if loop exits unexpectedly
108
+ clearInterval(ti);
79
109
  loading.stopAndPersist(endInfo);
80
110
  }
81
111
  };
82
- const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo) => {
112
+ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, loading, endInfo) => {
83
113
  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
114
  const initialMessages = [];
92
115
  const maxTurns = 40; // Safeguard against infinite loops
93
- const promptConfigs = getPromptConfigs();
116
+ const promptConfigs = getAllPromptConfigs();
94
117
  for (const role of ["system", "user"]) {
95
118
  const promptConfig = promptConfigs[role];
96
119
  const promptContent = promptConfig.content //
97
- .replace(/\{\{task.(\w+)\}\}/g, (_, key) => {
98
- return Reflect.get(ai_task, key);
120
+ .replace(/\{\{task.([\.\w]+)\}\}/g, (_, key) => {
121
+ if (key.includes(".")) {
122
+ const paths = key.split(".");
123
+ let res = ai_task;
124
+ for (const p of paths) {
125
+ res = Reflect.get(res, p);
126
+ if (!res) {
127
+ break;
128
+ }
129
+ }
130
+ return res;
131
+ }
132
+ else {
133
+ return Reflect.get(ai_task, key);
134
+ }
99
135
  })
100
136
  .replace(/\{\{env.(\w+)\}\}/g, (_, key) => {
101
137
  const envKey = key.toUpperCase();
@@ -106,7 +142,7 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
106
142
  return envValue;
107
143
  })
108
144
  .replaceAll("{{allSkills}}", (_, key) => {
109
- return YAML.stringify(tools.jixoSkill().allSkillNavList);
145
+ return YAML.stringify(getAllSkillNavMap());
110
146
  })
111
147
  .replaceAll("{{allFiles}}", YAML.stringify({
112
148
  [ai_task.cwd]: {
@@ -145,6 +181,7 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
145
181
  messages: currentMessages,
146
182
  tools: availableTools,
147
183
  toolChoice: "auto", // Changed to auto for more flexibility
184
+ onError: () => { },
148
185
  });
149
186
  let fullReasoningText = "";
150
187
  let fullText = "";
@@ -173,9 +210,9 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
173
210
  }
174
211
  assistantTextPart.text += textPart.text;
175
212
  if (fullText === "")
176
- fullText = "\n"; // For consistent display
213
+ loading.text = "";
177
214
  fullText += textPart.text;
178
- loading.text = fullText.split("\n").slice(-10).join("\n");
215
+ loading.text = "\n" + fullText.split("\n").slice(-10).join("\n");
179
216
  })
180
217
  .with({ type: "tool-call" }, (callPart) => {
181
218
  loading.prefixText = "🛠️ ";
@@ -193,7 +230,7 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
193
230
  .with({ type: "error" }, async (errorPart) => {
194
231
  loading.prefixText = endInfo.prefixText = "❌ ";
195
232
  loading.text = endInfo.text = red(`${errorPart.error}`);
196
- await handleRetryError(errorPart.error, loading);
233
+ const _handled = await handleError(errorPart.error, loading);
197
234
  return LOOP_SIGNALS.BREAK; // Stop processing on error
198
235
  })
199
236
  .with({ type: "reasoning" }, (reasoningPart) => {
@@ -201,7 +238,7 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
201
238
  if (fullReasoningText === "")
202
239
  loading.text = "";
203
240
  fullReasoningText += reasoningPart.text;
204
- loading.text = gray(fullReasoningText.split("\n").slice(-3).join("\n"));
241
+ loading.text = "\n" + gray(fullReasoningText.split("\n").slice(-3).join("\n"));
205
242
  })
206
243
  // Add other console logs for debugging if needed, but keep them minimal for production
207
244
  .with({ type: "file" }, (p) => {
@@ -211,11 +248,21 @@ const _runAiTask = async (ai_task, allFiles, changedFilesSet, loading, endInfo)
211
248
  })
212
249
  .with({ type: "source" }, (p) => {
213
250
  loading.prefixText = "🔗 ";
214
- if (p.title) {
215
- loading.text = `[${p.title}](${p.url})`;
251
+ if (p.sourceType === "url") {
252
+ if (p.title) {
253
+ loading.text = `[${p.title}](${p.url})`;
254
+ }
255
+ else {
256
+ loading.text = p.url;
257
+ }
216
258
  }
217
259
  else {
218
- loading.text = p.url;
260
+ if (p.filename) {
261
+ loading.text = `[${p.title}](${p.filename})`;
262
+ }
263
+ else {
264
+ loading.text = p.title;
265
+ }
219
266
  }
220
267
  log("\nQAQ source: %y", p);
221
268
  })
@@ -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, 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 {handleError} from \"../../helper/handle-ai-error.js\";\nimport {getAllPromptConfigs, getAllSkillMap as getAllSkillNavMap} 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, loopTimes: number, allFiles: FileEntry[], changedFilesSet: Record<string, FileEntry[]>) => {\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.pnpm()),\n ...(await tools.jixo(ai_task)),\n ...(await tools.git(ai_task.cwd)),\n };\n\n const loading = spinner(`Initializing AI task: ${cyan(ai_task.name)}...`);\n\n loading.prefixText = \"⏳ \";\n loading.start();\n const endInfo = {\n prefixText: \"\",\n text: \"\",\n get suffixText() {\n return `⏱️ ${gray(ms(new Date().getTime() - new Date(ai_task.startTime).getTime(), {long: true}))}`;\n },\n };\n let prefixText = loading.prefixText;\n const updatePrefixText = () => {\n loading.prefixText = `${green(`[${loopTimes}]`)} ${cyan(`+${ms(Date.now() - new Date(ai_task.startTime).getTime())}`)}\\n${prefixText}`;\n };\n const ti = setInterval(updatePrefixText, 1000);\n updatePrefixText();\n try {\n await _runAiTask(\n ai_task,\n availableTools,\n allFiles,\n changedFilesSet,\n {\n get text() {\n return loading.text;\n },\n set text(v) {\n loading.text = v;\n },\n get prefixText() {\n return prefixText;\n },\n set prefixText(v) {\n prefixText = v;\n updatePrefixText();\n },\n },\n endInfo,\n );\n } finally {\n // Fallback spinner stop if loop exits unexpectedly\n clearInterval(ti);\n loading.stopAndPersist(endInfo);\n }\n};\n\nconst _runAiTask = async (\n ai_task: AiTask,\n availableTools: ToolSet,\n allFiles: FileEntry[],\n changedFilesSet: Record<string, FileEntry[]>,\n loading: Pick<Spinner, \"prefixText\" | \"text\">,\n endInfo: {\n prefixText: string;\n text: string;\n readonly suffixText: string;\n },\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 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 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 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 if (firstStreamPart) {\n firstStreamPart = false;\n loading.text = \"\"; // Clear initial connecting/processing message\n }\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 === \"\") loading.text = \"\";\n fullText += textPart.text;\n loading.text = \"\\n\" + 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 const _handled = await handleError(errorPart.error, loading);\n\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 = \"\\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 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.sourceType === \"url\") {\n if (p.title) {\n loading.text = `[${p.title}](${p.url})`;\n } else {\n loading.text = p.url;\n }\n } else {\n if (p.filename) {\n loading.text = `[${p.title}](${p.filename})`;\n } else {\n loading.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) => 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 +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,kBA8FF,CAAC"}
@@ -9,6 +9,14 @@ 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 exitedTasks = new Set();
12
20
  let { force = false } = options;
13
21
  const { loopTimes: MAX_LOOP_TIMES = Infinity } = options;
14
22
  let currentTimes = 1;
@@ -16,19 +24,17 @@ export const run = async (_cwd, options) => {
16
24
  const MAX_RETRY_TIMES = 3;
17
25
  while (currentTimes <= MAX_LOOP_TIMES) {
18
26
  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
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 (exitedTasks.has(ai_task.name)) {
32
38
  continue;
33
39
  }
34
40
  const { dirs: task_dirs } = ai_task;
@@ -39,7 +45,7 @@ export const run = async (_cwd, options) => {
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,7 +60,10 @@ 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.exited) {
65
+ exitedTasks.add(ai_task.name);
66
+ }
58
67
  }
59
68
  }
60
69
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/tasks/run.ts"],"names":[],"mappings":"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","sourcesContent":["import {FileEntry, findChangedFilesSinceTime, Ignore, normalizeFilePath, walkFiles} from \"@gaubee/nodekit\";\nimport {iter_map_not_null} from \"@gaubee/util\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {loadConfig} from \"../../config.js\";\nimport {loadJixoEnv} from \"../../env.js\";\nimport {resolveAiTasks} from \"../../helper/resolve-ai-tasks.js\";\nimport {runAiTask} from \"./run-ai-task.js\";\n\nexport const run = async (\n _cwd: string,\n options: {\n nameFilter: string[];\n dirFilter: string[];\n force?: boolean;\n loopTimes?: number;\n },\n) => {\n const cwd = normalizeFilePath(_cwd);\n const config = await loadConfig(cwd);\n\n let {force = false} = options;\n const {loopTimes: MAX_LOOP_TIMES = Infinity} = options;\n let currentTimes = 1;\n let retryTimes = 0;\n const MAX_RETRY_TIMES = 3;\n\n while (currentTimes <= MAX_LOOP_TIMES) {\n const ai_tasks = resolveAiTasks(cwd, config.tasks);\n const nameMatcher = options.nameFilter.length ? new Ignore(options.nameFilter, cwd) : {isMatch: () => true};\n const dirMatcher = options.dirFilter.length ? new Ignore(options.dirFilter, cwd) : {isMatch: () => true};\n const cwdIgnoreFilepath = path.join(cwd, \".gitignore\");\n const ignore = [\".git\"];\n if (fs.existsSync(cwdIgnoreFilepath)) {\n ignore.push(...fs.readFileSync(cwdIgnoreFilepath, \"utf-8\").split(\"\\n\"));\n }\n\n const allFiles = [...walkFiles(cwd, {ignore})];\n let allDone = true;\n\n try {\n for (const ai_task of ai_tasks) {\n // 如果进度已经满了,那么跳过\n if (ai_task.preProgress >= 1 && !force) {\n continue;\n }\n const {dirs: task_dirs} = ai_task;\n if (!task_dirs.some((dir) => dirMatcher.isMatch(dir))) {\n continue;\n }\n if (!nameMatcher.isMatch(ai_task.name)) {\n continue;\n }\n const isCwdTask = cwd === task_dirs[0] && task_dirs.length === 1;\n\n const changedFiles = (await findChangedFilesSinceTime(ai_task.preUpdateTime, cwd)) ?? allFiles;\n\n const task_changedFiles = isCwdTask\n ? {[cwd]: changedFiles}\n : task_dirs.reduce(\n (tree, task_dir) => {\n tree[task_dir] = iter_map_not_null(changedFiles, (file) => {\n if (file.path.startsWith(task_dirs + \"/\")) {\n return new FileEntry(file.path, {cwd: task_dir, state: file.stats});\n }\n });\n return tree;\n },\n {} as Record<string, FileEntry[]>,\n );\n\n const task_allFiles = isCwdTask ? allFiles : task_dirs.map((task_dir) => [...walkFiles(task_dir, {ignore})]).flat();\n\n loadJixoEnv(cwd);\n\n /// 只要有一个任务执行了,那么allDone就要标记成false,进入下一次循环来判断\n allDone = false;\n await runAiTask(ai_task, task_allFiles, task_changedFiles);\n }\n } catch {\n // 遇到异常,那么重试\n if (retryTimes < MAX_RETRY_TIMES) {\n retryTimes += 1;\n continue;\n } else {\n break;\n }\n }\n // force 只能生效一次,避免无限循环\n force = false;\n currentTimes += 1;\n /// 成功一次后,retry计数就重制\n retryTimes = 0;\n\n /// 如果没有任务执行了,那么退出循环\n if (allDone) {\n break;\n }\n }\n};\n"]}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/tasks/run.ts"],"names":[],"mappings":"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","sourcesContent":["import {FileEntry, findChangedFilesSinceTime, Ignore, normalizeFilePath, walkFiles} from \"@gaubee/nodekit\";\nimport {iter_map_not_null} from \"@gaubee/util\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport {loadConfig} from \"../../config.js\";\nimport {loadJixoEnv} from \"../../env.js\";\nimport {resolveAiTasks} from \"../../helper/resolve-ai-tasks.js\";\nimport {runAiTask} from \"./run-ai-task.js\";\n\nexport const run = async (\n _cwd: string,\n options: {\n nameFilter: string[];\n dirFilter: string[];\n force?: boolean;\n loopTimes?: number;\n },\n) => {\n const cwd = normalizeFilePath(_cwd);\n const config = await loadConfig(cwd);\n\n const nameMatcher = options.nameFilter.length ? new Ignore(options.nameFilter, cwd) : {isMatch: () => true};\n const dirMatcher = options.dirFilter.length ? new Ignore(options.dirFilter, cwd) : {isMatch: () => true};\n const cwdIgnoreFilepath = path.join(cwd, \".gitignore\");\n const ignore = [\".git\"];\n if (fs.existsSync(cwdIgnoreFilepath)) {\n ignore.push(...fs.readFileSync(cwdIgnoreFilepath, \"utf-8\").split(\"\\n\"));\n }\n const exitedTasks = new Set<string>();\n\n let {force = false} = options;\n const {loopTimes: MAX_LOOP_TIMES = Infinity} = options;\n let currentTimes = 1;\n let retryTimes = 0;\n const MAX_RETRY_TIMES = 3;\n while (currentTimes <= MAX_LOOP_TIMES) {\n const ai_tasks = resolveAiTasks(cwd, config.tasks);\n\n const allFiles = [...walkFiles(cwd, {ignore})];\n let allDone = true;\n\n try {\n for (const ai_task of ai_tasks) {\n // 如果进度已经满了,并且没有任何依赖文件的变更,那么跳过这个任务\n if (!force) {\n if (ai_task.log.preProgress >= 1) {\n continue;\n }\n }\n if (exitedTasks.has(ai_task.name)) {\n continue;\n }\n\n const {dirs: task_dirs} = ai_task;\n if (!task_dirs.some((dir) => dirMatcher.isMatch(dir))) {\n continue;\n }\n if (!nameMatcher.isMatch(ai_task.name)) {\n continue;\n }\n const isCwdTask = cwd === task_dirs[0] && task_dirs.length === 1;\n\n const changedFiles = (await findChangedFilesSinceTime(ai_task.log.preUpdateTime, cwd)) ?? allFiles;\n\n const task_changedFiles = isCwdTask\n ? {[cwd]: changedFiles}\n : task_dirs.reduce(\n (tree, task_dir) => {\n tree[task_dir] = iter_map_not_null(changedFiles, (file) => {\n if (file.path.startsWith(task_dirs + \"/\")) {\n return new FileEntry(file.path, {cwd: task_dir, state: file.stats});\n }\n });\n return tree;\n },\n {} as Record<string, FileEntry[]>,\n );\n\n const task_allFiles = isCwdTask ? allFiles : task_dirs.map((task_dir) => [...walkFiles(task_dir, {ignore})]).flat();\n\n loadJixoEnv(cwd);\n\n /// 只要有一个任务执行了,那么allDone就要标记成false,进入下一次循环来判断\n allDone = false;\n await runAiTask(ai_task, currentTimes, task_allFiles, task_changedFiles);\n\n if (ai_task.exited) {\n exitedTasks.add(ai_task.name);\n }\n }\n } catch {\n // 遇到异常,那么重试\n if (retryTimes < MAX_RETRY_TIMES) {\n retryTimes += 1;\n continue;\n } else {\n break;\n }\n }\n // force 只能生效一次,避免无限循环\n force = false;\n currentTimes += 1;\n /// 成功一次后,retry计数就重制\n retryTimes = 0;\n\n /// 如果没有任务执行了,那么退出循环\n if (allDone) {\n break;\n }\n }\n};\n"]}
@@ -1,3 +1,3 @@
1
1
  import { type Spinner } from "@gaubee/nodekit";
2
- export declare const handleRetryError: (error: unknown, loading: Spinner) => Promise<void>;
2
+ export declare const handleRetryError: (error: unknown, loading: Pick<Spinner, "prefixText" | "text">) => Promise<void>;
3
3
  //# sourceMappingURL=ai-retry-error.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-retry-error.d.ts","sourceRoot":"","sources":["../../src/helper/ai-retry-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,OAAO,EAAC,MAAM,iBAAiB,CAAC;AAK3D,eAAO,MAAM,gBAAgB,GAAU,OAAO,OAAO,EAAE,SAAS,OAAO,kBA6CtE,CAAC"}
1
+ {"version":3,"file":"ai-retry-error.d.ts","sourceRoot":"","sources":["../../src/helper/ai-retry-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,OAAO,EAAC,MAAM,iBAAiB,CAAC;AAMhE,eAAO,MAAM,gBAAgB,GAAU,OAAO,OAAO,EAAE,SAAS,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAAC,kBA0CnG,CAAC"}
@@ -1,7 +1,8 @@
1
- import { gray, yellow } from "@gaubee/nodekit";
2
- import { delay, str_trim_indent } from "@gaubee/util";
1
+ import { gray, red, yellow } from "@gaubee/nodekit";
2
+ import { delay } from "@gaubee/util";
3
3
  import { APICallError, RetryError } from "ai";
4
4
  import ms from "ms";
5
+ import { match } from "ts-pattern";
5
6
  import z from "zod";
6
7
  export const handleRetryError = async (error, loading) => {
7
8
  if (!RetryError.isInstance(error)) {
@@ -11,42 +12,52 @@ export const handleRetryError = async (error, loading) => {
11
12
  if (!APICallError.isInstance(inner_error)) {
12
13
  continue;
13
14
  }
14
- if (!inner_error.isRetryable) {
15
- continue;
16
- }
17
15
  try {
18
- const response = errorSchema.parse(JSON.parse(inner_error.responseBody ?? "{}"));
19
- const retryDetail = response.error.details.find((d) => "retryDelay" in d);
20
- if (retryDetail) {
21
- const retryDelay = ms(retryDetail.retryDelay);
22
- if (typeof retryDelay === "number") {
23
- const { prefixText, text } = loading;
24
- let remainingDelay = retryDelay;
25
- const tickInterval = 1000;
26
- const tick = () => {
27
- loading.prefixText = "⏲️ ";
28
- loading.text = str_trim_indent(`
29
- ${yellow(inner_error.message)}
30
- ${" " + gray("─".repeat(Math.max(4, process.stdout.columns - 2)))}
31
- Retrying in ${ms(remainingDelay)}...`);
32
- remainingDelay -= tickInterval;
33
- };
34
- tick();
35
- const ti = setInterval(tick, tickInterval);
36
- await delay(retryDelay);
37
- clearInterval(ti);
38
- // 回滚
39
- loading.prefixText = prefixText;
40
- loading.text = text;
16
+ if (!inner_error.isRetryable) {
17
+ const safeData = geminiErrorSchema.safeParse(inner_error.data);
18
+ if (!safeData.success) {
19
+ throw safeData.error;
20
+ }
21
+ const retryDetail = safeData.data.error.details.find((d) => "retryDelay" in d);
22
+ if (retryDetail) {
23
+ const retryDelay = ms(retryDetail.retryDelay);
24
+ if (typeof retryDelay === "number") {
25
+ await waitRetryDelay(loading, retryDelay, yellow(inner_error.message));
26
+ }
27
+ }
28
+ }
29
+ else {
30
+ const safeData = commonErrorSchema.safeParse(inner_error.data);
31
+ if (!safeData.success) {
32
+ throw safeData.error;
41
33
  }
34
+ console.log("QAQ response.error", safeData);
35
+ await match(safeData.data.error)
36
+ /// 余额不足
37
+ .with({ message: "Insufficient Balance" }, async () => {
38
+ /// 30s重试
39
+ await waitRetryDelay(loading, 1000 * 30, red("Insufficient Balance") + "\n" + red(inner_error.url));
40
+ })
41
+ .otherwise(() => {
42
+ throw inner_error;
43
+ });
42
44
  }
43
45
  }
44
46
  catch {
45
- console.error("\nQAQ unknown error", error);
47
+ console.error("\nQAQ unknown error", inner_error);
46
48
  }
47
49
  }
48
50
  };
49
- const errorSchema = z.object({
51
+ // const handleError
52
+ const commonErrorSchema = z.object({
53
+ error: z.object({
54
+ message: z.string(),
55
+ type: z.string(),
56
+ param: z.any(),
57
+ code: z.string(),
58
+ }),
59
+ });
60
+ const geminiErrorSchema = z.object({
50
61
  error: z.object({
51
62
  code: z.number(),
52
63
  message: z.string(),
@@ -72,4 +83,26 @@ const errorSchema = z.object({
72
83
  ])),
73
84
  }),
74
85
  });
86
+ const waitRetryDelay = async (loading, retryDelay, message) => {
87
+ const { prefixText, text } = loading;
88
+ let remainingDelay = retryDelay;
89
+ const tickInterval = 1000;
90
+ const tick = () => {
91
+ loading.prefixText = "⏲️ ";
92
+ loading.text = [
93
+ //
94
+ message,
95
+ " " + gray("─".repeat(Math.max(4, process.stdout.columns - 2))),
96
+ `Retrying in ${ms(remainingDelay)}...`,
97
+ ].join("\n");
98
+ remainingDelay -= tickInterval;
99
+ };
100
+ tick();
101
+ const ti = setInterval(tick, tickInterval);
102
+ await delay(retryDelay);
103
+ clearInterval(ti);
104
+ // 回滚
105
+ loading.prefixText = prefixText;
106
+ loading.text = text;
107
+ };
75
108
  //# sourceMappingURL=ai-retry-error.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-retry-error.js","sourceRoot":"","sources":["../../src/helper/ai-retry-error.ts"],"names":[],"mappings":"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","sourcesContent":["import {gray, yellow, type Spinner} from \"@gaubee/nodekit\";\r\nimport {delay, str_trim_indent} from \"@gaubee/util\";\r\nimport {APICallError, RetryError} from \"ai\";\r\nimport ms from \"ms\";\r\nimport z from \"zod\";\r\nexport const handleRetryError = async (error: unknown, loading: Spinner) => {\r\n if (!RetryError.isInstance(error)) {\r\n return;\r\n }\r\n for (const inner_error of error.errors) {\r\n if (!APICallError.isInstance(inner_error)) {\r\n continue;\r\n }\r\n if (!inner_error.isRetryable) {\r\n continue;\r\n }\r\n\r\n try {\r\n const response = errorSchema.parse(JSON.parse(inner_error.responseBody ?? \"{}\"));\r\n const retryDetail = response.error.details.find((d) => \"retryDelay\" in d);\r\n if (retryDetail) {\r\n const retryDelay = ms(retryDetail.retryDelay as ms.StringValue);\r\n\r\n if (typeof retryDelay === \"number\") {\r\n const {prefixText, text} = loading;\r\n let remainingDelay = retryDelay;\r\n const tickInterval = 1000;\r\n const tick = () => {\r\n loading.prefixText = \"⏲️ \";\r\n loading.text = str_trim_indent(`\r\n ${yellow(inner_error.message)}\r\n ${\" \" + gray(\"─\".repeat(Math.max(4, process.stdout.columns - 2)))}\r\n Retrying in ${ms(remainingDelay)}...`);\r\n remainingDelay -= tickInterval;\r\n };\r\n tick();\r\n\r\n const ti = setInterval(tick, tickInterval);\r\n await delay(retryDelay);\r\n clearInterval(ti);\r\n\r\n // 回滚\r\n loading.prefixText = prefixText;\r\n loading.text = text;\r\n }\r\n }\r\n } catch {\r\n console.error(\"\\nQAQ unknown error\", error);\r\n }\r\n }\r\n};\r\n\r\nconst errorSchema = z.object({\r\n error: z.object({\r\n code: z.number(),\r\n message: z.string(),\r\n status: z.string(),\r\n details: z.array(\r\n z.union([\r\n z.object({\r\n \"@type\": z.string(),\r\n violations: z.array(\r\n z.object({\r\n quotaMetric: z.string(),\r\n quotaId: z.string(),\r\n quotaDimensions: z.object({\r\n location: z.string(),\r\n model: z.string(),\r\n }),\r\n quotaValue: z.string(),\r\n }),\r\n ),\r\n }),\r\n z.object({\r\n \"@type\": z.string(),\r\n links: z.array(z.object({description: z.string(), url: z.string()})),\r\n }),\r\n z.object({\"@type\": z.string(), retryDelay: z.string()}),\r\n ]),\r\n ),\r\n }),\r\n});\r\n"]}
1
+ {"version":3,"file":"ai-retry-error.js","sourceRoot":"","sources":["../../src/helper/ai-retry-error.ts"],"names":[],"mappings":"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","sourcesContent":["import {gray, red, yellow, type Spinner} from \"@gaubee/nodekit\";\r\nimport {delay} from \"@gaubee/util\";\r\nimport {APICallError, RetryError} from \"ai\";\r\nimport ms from \"ms\";\r\nimport {match} from \"ts-pattern\";\r\nimport z from \"zod\";\r\nexport const handleRetryError = async (error: unknown, loading: Pick<Spinner, \"prefixText\" | \"text\">) => {\r\n if (!RetryError.isInstance(error)) {\r\n return;\r\n }\r\n for (const inner_error of error.errors) {\r\n if (!APICallError.isInstance(inner_error)) {\r\n continue;\r\n }\r\n try {\r\n if (!inner_error.isRetryable) {\r\n const safeData = geminiErrorSchema.safeParse(inner_error.data);\r\n if (!safeData.success) {\r\n throw safeData.error;\r\n }\r\n const retryDetail = safeData.data.error.details.find((d) => \"retryDelay\" in d);\r\n if (retryDetail) {\r\n const retryDelay = ms(retryDetail.retryDelay as ms.StringValue);\r\n\r\n if (typeof retryDelay === \"number\") {\r\n await waitRetryDelay(loading, retryDelay, yellow(inner_error.message));\r\n }\r\n }\r\n } else {\r\n const safeData = commonErrorSchema.safeParse(inner_error.data);\r\n if (!safeData.success) {\r\n throw safeData.error;\r\n }\r\n console.log(\"QAQ response.error\", safeData);\r\n await match(safeData.data.error)\r\n /// 余额不足\r\n .with({message: \"Insufficient Balance\"}, async () => {\r\n /// 30s重试\r\n await waitRetryDelay(loading, 1000 * 30, red(\"Insufficient Balance\") + \"\\n\" + red(inner_error.url));\r\n })\r\n .otherwise(() => {\r\n throw inner_error;\r\n });\r\n }\r\n } catch {\r\n console.error(\"\\nQAQ unknown error\", inner_error);\r\n }\r\n }\r\n};\r\n\r\n// const handleError\r\n\r\n\r\nconst commonErrorSchema = z.object({\r\n error: z.object({\r\n message: z.string(),\r\n type: z.string(),\r\n param: z.any(),\r\n code: z.string(),\r\n }),\r\n});\r\n\r\nconst geminiErrorSchema = z.object({\r\n error: z.object({\r\n code: z.number(),\r\n message: z.string(),\r\n status: z.string(),\r\n details: z.array(\r\n z.union([\r\n z.object({\r\n \"@type\": z.string(),\r\n violations: z.array(\r\n z.object({\r\n quotaMetric: z.string(),\r\n quotaId: z.string(),\r\n quotaDimensions: z.object({\r\n location: z.string(),\r\n model: z.string(),\r\n }),\r\n quotaValue: z.string(),\r\n }),\r\n ),\r\n }),\r\n z.object({\r\n \"@type\": z.string(),\r\n links: z.array(z.object({description: z.string(), url: z.string()})),\r\n }),\r\n z.object({\"@type\": z.string(), retryDelay: z.string()}),\r\n ]),\r\n ),\r\n }),\r\n});\r\n\r\nconst waitRetryDelay = async (loading: Pick<Spinner, \"prefixText\" | \"text\">, retryDelay: number, message: string) => {\r\n const {prefixText, text} = loading;\r\n let remainingDelay = retryDelay;\r\n const tickInterval = 1000;\r\n const tick = () => {\r\n loading.prefixText = \"⏲️ \";\r\n loading.text = [\r\n //\r\n message,\r\n \" \" + gray(\"─\".repeat(Math.max(4, process.stdout.columns - 2))),\r\n `Retrying in ${ms(remainingDelay)}...`,\r\n ].join(\"\\n\");\r\n remainingDelay -= tickInterval;\r\n };\r\n tick();\r\n\r\n const ti = setInterval(tick, tickInterval);\r\n await delay(retryDelay);\r\n clearInterval(ti);\r\n\r\n // 回滚\r\n loading.prefixText = prefixText;\r\n loading.text = text;\r\n};\r\n"]}
@@ -0,0 +1,5 @@
1
+ import { type Spinner } from "@gaubee/nodekit";
2
+ type Loading = Pick<Spinner, "prefixText" | "text">;
3
+ export declare const handleError: (error: unknown, loading: Loading) => Promise<true | undefined>;
4
+ export {};
5
+ //# sourceMappingURL=handle-ai-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handle-ai-error.d.ts","sourceRoot":"","sources":["../../src/helper/handle-ai-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,OAAO,EAAC,MAAM,iBAAiB,CAAC;AAMhE,KAAK,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAAC,CAAC;AAEpD,eAAO,MAAM,WAAW,GAAU,OAAO,OAAO,EAAE,SAAS,OAAO,8BAOjE,CAAC"}