@jixo/cli 0.11.0 → 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.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -5
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +18 -12
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/tasks/AiTaskTui.d.ts +22 -0
- package/dist/commands/tasks/AiTaskTui.d.ts.map +1 -0
- package/dist/commands/tasks/AiTaskTui.js +52 -0
- package/dist/commands/tasks/AiTaskTui.js.map +1 -0
- package/dist/commands/tasks/ai-tasl-tui.d.ts +22 -0
- package/dist/commands/tasks/ai-tasl-tui.d.ts.map +1 -0
- package/dist/commands/tasks/ai-tasl-tui.js +53 -0
- package/dist/commands/tasks/ai-tasl-tui.js.map +1 -0
- package/dist/commands/tasks/ai-tools.d.ts +2 -1
- package/dist/commands/tasks/ai-tools.d.ts.map +1 -1
- package/dist/commands/tasks/ai-tools.js +15 -11
- package/dist/commands/tasks/ai-tools.js.map +1 -1
- package/dist/commands/tasks/model-providers.d.ts +5 -1
- package/dist/commands/tasks/model-providers.d.ts.map +1 -1
- package/dist/commands/tasks/model-providers.js +31 -0
- package/dist/commands/tasks/model-providers.js.map +1 -1
- package/dist/commands/tasks/run-ai-task.d.ts.map +1 -1
- package/dist/commands/tasks/run-ai-task.js +104 -125
- package/dist/commands/tasks/run-ai-task.js.map +1 -1
- package/dist/commands/tasks/run.d.ts.map +1 -1
- package/dist/commands/tasks/run.js +8 -7
- package/dist/commands/tasks/run.js.map +1 -1
- package/dist/config.d.ts +14 -14
- package/dist/helper/handle-ai-error.js +1 -1
- package/dist/helper/handle-ai-error.js.map +1 -1
- package/dist/helper/logger.d.ts +3 -0
- package/dist/helper/logger.d.ts.map +1 -0
- package/dist/helper/logger.js +26 -0
- package/dist/helper/logger.js.map +1 -0
- package/dist/helper/resolve-ai-tasks.d.ts +7 -6
- package/dist/helper/resolve-ai-tasks.d.ts.map +1 -1
- package/dist/helper/resolve-ai-tasks.js +22 -19
- package/dist/helper/resolve-ai-tasks.js.map +1 -1
- package/dist/prompts.json +2 -14
- package/package.json +6 -2
@@ -1,115 +1,59 @@
|
|
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 {
|
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
9
|
import { handleError } from "../../helper/handle-ai-error.js";
|
10
|
+
import { createDebug } from "../../helper/logger.js";
|
10
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 {
|
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");
|
63
|
-
});
|
64
|
-
};
|
65
16
|
export const runAiTask = async (ai_task, loopTimes, allFiles, changedFilesSet) => {
|
17
|
+
const tool_spinner = spinner({
|
18
|
+
prefixText: "🧰",
|
19
|
+
text: "Preparing AI tools...",
|
20
|
+
});
|
21
|
+
tool_spinner.start();
|
66
22
|
const availableTools = {
|
67
23
|
...(await tools.fileSystem(ai_task.cwd)),
|
68
|
-
// ...(await tools.memory(path.join(ai_task.cwd, `.jixo/${ai_task.name}.memory.json`))),
|
69
24
|
...(await tools.pnpm()),
|
70
25
|
...(await tools.jixo(ai_task)),
|
71
26
|
...(await tools.git(ai_task.cwd)),
|
72
27
|
};
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
const
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
+
}
|
82
38
|
};
|
83
|
-
|
84
|
-
|
85
|
-
|
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())}`)}`);
|
86
43
|
};
|
87
|
-
const ti = setInterval(
|
88
|
-
|
44
|
+
const ti = setInterval(updateTuiState, 1000);
|
45
|
+
updateTuiState();
|
89
46
|
try {
|
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);
|
47
|
+
await _runAiTask(ai_task, availableTools, allFiles, changedFilesSet, tui, __writeJsonLineLog);
|
105
48
|
}
|
106
49
|
finally {
|
107
50
|
// Fallback spinner stop if loop exits unexpectedly
|
108
51
|
clearInterval(ti);
|
109
|
-
|
52
|
+
tui.stop();
|
53
|
+
json_line_log_file_handle.close();
|
110
54
|
}
|
111
55
|
};
|
112
|
-
const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet,
|
56
|
+
const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, tui, __writeJsonLineLog) => {
|
113
57
|
const model = getModel(ai_task.model);
|
114
58
|
const initialMessages = [];
|
115
59
|
const maxTurns = 40; // Safeguard against infinite loops
|
@@ -165,16 +109,19 @@ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, lo
|
|
165
109
|
});
|
166
110
|
}
|
167
111
|
const currentMessages = [...initialMessages];
|
112
|
+
__writeJsonLineLog(...currentMessages);
|
168
113
|
loop: for (let turn = 0; turn < maxTurns; turn++) {
|
169
114
|
if (turn === 0) {
|
170
|
-
|
115
|
+
tui.setStatus("turns", `Connecting To ${model.provider}...`);
|
171
116
|
}
|
172
117
|
else {
|
173
|
-
|
174
|
-
|
118
|
+
tui.setStatus("turns", `Processing step ${turn + 1}/${maxTurns}...`);
|
119
|
+
const userTurnMessage = {
|
175
120
|
role: "user",
|
176
121
|
content: `Turns: ${turn}/${maxTurns}`,
|
177
|
-
}
|
122
|
+
};
|
123
|
+
currentMessages.push(userTurnMessage);
|
124
|
+
__writeJsonLineLog(userTurnMessage);
|
178
125
|
}
|
179
126
|
const result = await streamText({
|
180
127
|
model: model,
|
@@ -196,13 +143,14 @@ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, lo
|
|
196
143
|
ERROR: "ERROR",
|
197
144
|
};
|
198
145
|
for await (const part of result.fullStream) {
|
146
|
+
__writeJsonLineLog(part);
|
199
147
|
if (firstStreamPart) {
|
200
148
|
firstStreamPart = false;
|
201
|
-
|
149
|
+
tui.text = ""; // Clear initial connecting/processing message
|
202
150
|
}
|
203
151
|
const LOOP_SIGNAL = await match(part)
|
204
152
|
.with({ type: "text" }, (textPart) => {
|
205
|
-
|
153
|
+
tui.prefixText = "🤖 ";
|
206
154
|
let assistantTextPart = assistantMessageContent.findLast((part) => part.type === "text");
|
207
155
|
if (assistantTextPart == null) {
|
208
156
|
assistantTextPart = { type: "text", text: "" };
|
@@ -210,13 +158,13 @@ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, lo
|
|
210
158
|
}
|
211
159
|
assistantTextPart.text += textPart.text;
|
212
160
|
if (fullText === "")
|
213
|
-
|
161
|
+
tui.text = "";
|
214
162
|
fullText += textPart.text;
|
215
|
-
|
163
|
+
tui.text = "\n" + fullText.split("\n").slice(-10).join("\n");
|
216
164
|
})
|
217
165
|
.with({ type: "tool-call" }, (callPart) => {
|
218
|
-
|
219
|
-
|
166
|
+
tui.prefixText = "🛠️ ";
|
167
|
+
tui.text = "Requesting tool: " + blue(callPart.toolName);
|
220
168
|
log("\nQAQ tool-call: %y", callPart);
|
221
169
|
requestedToolCalls.push(callPart);
|
222
170
|
// Update assistant message to include tool calls
|
@@ -228,40 +176,42 @@ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, lo
|
|
228
176
|
});
|
229
177
|
})
|
230
178
|
.with({ type: "error" }, async (errorPart) => {
|
231
|
-
|
232
|
-
|
233
|
-
const
|
234
|
-
|
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
|
+
}
|
235
185
|
})
|
236
186
|
.with({ type: "reasoning" }, (reasoningPart) => {
|
237
|
-
|
187
|
+
tui.prefixText = "🤔 ";
|
238
188
|
if (fullReasoningText === "")
|
239
|
-
|
189
|
+
tui.text = "";
|
240
190
|
fullReasoningText += reasoningPart.text;
|
241
|
-
|
191
|
+
tui.text = "\n" + gray(fullReasoningText.split("\n").slice(-3).join("\n"));
|
242
192
|
})
|
243
193
|
// Add other console logs for debugging if needed, but keep them minimal for production
|
244
194
|
.with({ type: "file" }, (p) => {
|
245
|
-
|
246
|
-
|
195
|
+
tui.prefixText = "📃 ";
|
196
|
+
tui.text = p.file.mediaType;
|
247
197
|
log("\nQAQ file: %y", p.file);
|
248
198
|
})
|
249
199
|
.with({ type: "source" }, (p) => {
|
250
|
-
|
200
|
+
tui.prefixText = "🔗 ";
|
251
201
|
if (p.sourceType === "url") {
|
252
202
|
if (p.title) {
|
253
|
-
|
203
|
+
tui.text = `[${p.title}](${p.url})`;
|
254
204
|
}
|
255
205
|
else {
|
256
|
-
|
206
|
+
tui.text = p.url;
|
257
207
|
}
|
258
208
|
}
|
259
209
|
else {
|
260
210
|
if (p.filename) {
|
261
|
-
|
211
|
+
tui.text = `[${p.title}](${p.filename})`;
|
262
212
|
}
|
263
213
|
else {
|
264
|
-
|
214
|
+
tui.text = p.title;
|
265
215
|
}
|
266
216
|
}
|
267
217
|
log("\nQAQ source: %y", p);
|
@@ -271,22 +221,50 @@ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, lo
|
|
271
221
|
.with({ type: "tool-call-delta" }, (p) => log("\nQAQ tool-call-delta: %y", p))
|
272
222
|
.with({ type: "reasoning-part-finish" }, (p) => log("\nQAQ reasoning-part-finish: %y", p))
|
273
223
|
.with({ type: "start-step" }, (p) => log("\nQAQ start-step: %y", p))
|
274
|
-
.with({ type: "finish-step" }, (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
|
+
})
|
275
252
|
.with({ type: "start" }, (p) => log("\nQAQ start: %y", p))
|
276
253
|
.with({ type: "finish" }, async (finishPart) => {
|
277
254
|
log("\nQAQ finish: %y", finishPart);
|
278
|
-
// Add the assistant's message from this
|
255
|
+
// Add the assistant's message from this step to the history
|
279
256
|
currentMessages.push(_currentAssistantMessage);
|
257
|
+
__writeJsonLineLog(_currentAssistantMessage);
|
280
258
|
if (finishPart.finishReason === "stop" || finishPart.finishReason === "length") {
|
281
|
-
|
282
|
-
|
259
|
+
tui.prefixText = tui.endInfo.prefixText = "✅ ";
|
260
|
+
tui.text = tui.endInfo.text = green(`${cyan(`[${ai_task.jobName}]`)} Completed`);
|
283
261
|
// Task finished without tool calls or after tool calls that didn't lead to more calls.
|
284
262
|
return LOOP_SIGNALS.RETURN; // Exit the outer loop and function
|
285
263
|
}
|
286
264
|
if (finishPart.finishReason === "tool-calls") {
|
287
265
|
if (requestedToolCalls.length === 0) {
|
288
|
-
|
289
|
-
|
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.`);
|
290
268
|
return LOOP_SIGNALS.RETURN; // Exit, something is off
|
291
269
|
}
|
292
270
|
const toolResultMessages = [];
|
@@ -308,7 +286,7 @@ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, lo
|
|
308
286
|
});
|
309
287
|
continue;
|
310
288
|
}
|
311
|
-
|
289
|
+
tui.text = `Executing tool: ${toolCall.toolName}...`;
|
312
290
|
const executionResult = await func_catch(() => toolToExecute.execute(toolCall.args, {
|
313
291
|
toolCallId: toolCall.toolCallId,
|
314
292
|
messages: currentMessages,
|
@@ -326,19 +304,20 @@ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, lo
|
|
326
304
|
],
|
327
305
|
});
|
328
306
|
if (executionResult.success) {
|
329
|
-
|
307
|
+
tui.text = `Tool ${toolCall.toolName} executed.`;
|
330
308
|
}
|
331
309
|
else {
|
332
|
-
|
310
|
+
tui.text = `Error executing tool ${toolCall.toolName}.`;
|
333
311
|
}
|
334
312
|
}
|
335
313
|
currentMessages.push(...toolResultMessages);
|
336
|
-
|
314
|
+
__writeJsonLineLog(...toolResultMessages);
|
315
|
+
// Loop continues for the next step
|
337
316
|
}
|
338
317
|
else {
|
339
318
|
// Other finish reasons, potentially an error or unexpected state
|
340
|
-
|
341
|
-
|
319
|
+
tui.prefixText = tui.endInfo.prefixText = "🛑 ";
|
320
|
+
tui.text = tui.endInfo.text = red(`${cyan(`[${ai_task.jobName}]`)} task finished with unhandled reason: ${finishPart.finishReason}`);
|
342
321
|
return LOOP_SIGNALS.ERROR;
|
343
322
|
}
|
344
323
|
})
|
@@ -355,8 +334,8 @@ const _runAiTask = async (ai_task, availableTools, allFiles, changedFilesSet, lo
|
|
355
334
|
}
|
356
335
|
// If the stream finishes without a 'finish' part (e.g. error thrown inside), this loop might exit. Ensure spinner stops.
|
357
336
|
if (turn === maxTurns - 1) {
|
358
|
-
|
359
|
-
|
337
|
+
tui.prefixText = tui.endInfo.prefixText = "🚧 ";
|
338
|
+
tui.text = tui.endInfo.text = yellow(`${cyan(`[${ai_task.jobName}]`)} Max interaction turns reached.`);
|
360
339
|
break;
|
361
340
|
}
|
362
341
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"run-ai-task.js","sourceRoot":"","sources":["../../../src/commands/tasks/run-ai-task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAe,MAAM,iBAAiB,CAAC;AAC7G,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AACxC,OAAO,EAAC,UAAU,EAAE,UAAU,EAAiF,MAAM,IAAI,CAAC;AAC1H,OAAO,WAAW,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAC,KAAK,EAAE,CAAC,EAAC,MAAM,YAAY,CAAC;AACpC,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AACrC,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,EAAC,mBAAmB,EAAE,cAAc,IAAI,iBAAiB,EAAC,MAAM,gCAAgC,CAAC;AAExG,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AACpC,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AAE/C,WAAW,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE;IAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;QACjC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC1B,IAAI,SAAS,GAAG,CAAC,CAAC;YAClB,IAAI,CAAC,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACnB,SAAS,GAAG,EAAE,CAAC;YACjB,CAAC;YACD,IAAI,CAAC,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACnB,SAAS,GAAG,EAAE,CAAC;YACjB,CAAC;YACD,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;gBAClB,OAAO,WAAW,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5F,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7B,OAAO,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AACF,MAAM,GAAG,GAAG,WAAW,CAAC,kBAAkB,CAAC,CAAC;AAE5C,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAE,EAAE;IAClC,OAAO,KAAK,CAAC,KAAK,CAAC;SAChB,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAC5E,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACxE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SAC7H,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;SAC3E,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;SACnE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;SACnE,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;YAClC,OAAO,SAAS,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;YAChC,OAAO,SAAS,CAAC,MAAM,CAAC,8BAA8B,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;YAChC,OAAO,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACrC,CAAC;QACD,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC;YACnC,OAAO,SAAS,CAAC,SAAS,CAAC,0BAA0B,CAAC,CAAC;QACzD,CAAC;QACD,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC7B,OAAO,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACtC,CAAC;QACD,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC;YACnC,OAAO,SAAS,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,SAAS,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AACF,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,OAAe,EAAE,SAAiB,EAAE,QAAqB,EAAE,eAA4C,EAAE,EAAE;IACzI,MAAM,cAAc,GAAY;QAC9B,GAAG,CAAC,MAAM,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACxC,wFAAwF;QACxF,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACvB,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,GAAG,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;KAClC,CAAC;IAEF,MAAM,OAAO,GAAG,OAAO,CAAC,yBAAyB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAE1E,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,KAAK,EAAE,CAAC;IAChB,MAAM,OAAO,GAAG;QACd,UAAU,EAAE,EAAE;QACd,IAAI,EAAE,EAAE;QACR,IAAI,UAAU;YACZ,OAAO,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC,EAAE,CAAC;QACvG,CAAC;KACF,CAAC;IACF,IAAI,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACpC,MAAM,gBAAgB,GAAG,GAAG,EAAE;QAC5B,OAAO,CAAC,UAAU,GAAG,GAAG,KAAK,CAAC,IAAI,SAAS,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,KAAK,UAAU,EAAE,CAAC;IACzI,CAAC,CAAC;IACF,MAAM,EAAE,GAAG,WAAW,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAC/C,gBAAgB,EAAE,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,UAAU,CACd,OAAO,EACP,cAAc,EACd,QAAQ,EACR,eAAe,EACf;YACE,IAAI,IAAI;gBACN,OAAO,OAAO,CAAC,IAAI,CAAC;YACtB,CAAC;YACD,IAAI,IAAI,CAAC,CAAC;gBACR,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;YACnB,CAAC;YACD,IAAI,UAAU;gBACZ,OAAO,UAAU,CAAC;YACpB,CAAC;YACD,IAAI,UAAU,CAAC,CAAC;gBACd,UAAU,GAAG,CAAC,CAAC;gBACf,gBAAgB,EAAE,CAAC;YACrB,CAAC;SACF,EACD,OAAO,CACR,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,mDAAmD;QACnD,aAAa,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAClC,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,KAAK,EACtB,OAAe,EACf,cAAuB,EACvB,QAAqB,EACrB,eAA4C,EAC5C,OAA6C,EAC7C,OAIC,EACD,EAAE;IACF,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAEtC,MAAM,eAAe,GAAmB,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,mCAAmC;IAExD,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAU,EAAE,CAAC;QAC/C,MAAM,YAAY,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAEzC,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,CAAC,EAAE;aAC1C,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;YAC7C,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC7B,IAAI,GAAG,GAAQ,OAAO,CAAC;gBACvB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;oBACtB,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;oBAC1B,IAAI,CAAC,GAAG,EAAE,CAAC;wBACT,MAAM;oBACR,CAAC;gBACH,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;iBAAM,CAAC;gBACN,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACnC,CAAC;QACH,CAAC,CAAC;aACD,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;YACxC,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,QAAQ,GACZ,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC;gBAChC,KAAK,CAAC,MAAM,CAAC;qBACV,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC;qBAC1C,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACzB,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC;aACD,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;YACtC,OAAO,IAAI,CAAC,SAAS,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAC7C,CAAC,CAAC;aACD,UAAU,CACT,cAAc,EACd,IAAI,CAAC,SAAS,CAAC;YACb,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;gBACb,KAAK,EAAE,QAAQ,CAAC,MAAM;gBACtB,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;aAC1C;SACF,CAAC,CACH;aACA,UAAU,CAAC,cAAc,EAAE,GAAG,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC;aAC/C,UAAU,CACT,kBAAkB,EAClB,IAAI,CAAC,SAAS,CACZ,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,MAAM,CACpC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,EAAE;YAC5B,IAAI,CAAC,GAAG,CAAC,GAAG;gBACV,KAAK,EAAE,YAAY,CAAC,MAAM;gBAC1B,KAAK,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;aAC/C,CAAC;YACF,OAAO,IAAI,CAAC;QACd,CAAC,EACD,EAAsD,CACvD,CACF,CACF,CAAC;QACJ,GAAG,CAAC,UAAU,IAAI,GAAG,EAAE,aAAa,CAAC,CAAC;QACtC,eAAe,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,aAAa;SACvB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,eAAe,GAAmB,CAAC,GAAG,eAAe,CAAC,CAAC;IAE7D,IAAI,EAAE,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC;QACjD,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,GAAG,iBAAiB,KAAK,CAAC,QAAQ,KAAK,CAAC;QACtD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,GAAG,mBAAmB,IAAI,GAAG,CAAC,KAAK,CAAC;YAChD,eAAe,CAAC,IAAI,CAAC;gBACnB,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,UAAU,IAAI,IAAI,QAAQ,EAAE;aACtC,CAAC,CAAC;QACL,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC9B,KAAK,EAAE,KAAK;YACZ,QAAQ,EAAE,eAAe;YACzB,KAAK,EAAE,cAAc;YACrB,UAAU,EAAE,MAAM,EAAE,uCAAuC;YAC3D,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;SAClB,CAAC,CAAC;QAEH,IAAI,iBAAiB,GAAG,EAAE,CAAC;QAC3B,IAAI,QAAQ,GAAG,EAAE,CAAC;QAClB,IAAI,eAAe,GAAG,IAAI,CAAC;QAC3B,MAAM,kBAAkB,GAAmB,EAAE,CAAC,CAAC,sDAAsD;QAErG,MAAM,uBAAuB,GAAiD,EAAE,CAAC;QACjF,MAAM,wBAAwB,GAA0B,EAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,uBAAuB,EAAC,CAAC;QAE9G,MAAM,YAAY,GAAG;YACnB,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,OAAO;YACd,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,OAAO;SACN,CAAC;QACX,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YAC3C,IAAI,eAAe,EAAE,CAAC;gBACpB,eAAe,GAAG,KAAK,CAAC;gBACxB,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,8CAA8C;YACnE,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC;iBAClC,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,EAAE,CAAC,QAAQ,EAAE,EAAE;gBACjC,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;gBAC3B,IAAI,iBAAiB,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;gBACzF,IAAI,iBAAiB,IAAI,IAAI,EAAE,CAAC;oBAC9B,iBAAiB,GAAG,EAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAC,CAAC;oBAC7C,uBAAuB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBAClD,CAAC;gBACD,iBAAiB,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC;gBACxC,IAAI,QAAQ,KAAK,EAAE;oBAAE,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC;gBACvC,QAAQ,IAAI,QAAQ,CAAC,IAAI,CAAC;gBAC1B,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnE,CAAC,CAAC;iBACD,IAAI,CAAC,EAAC,IAAI,EAAE,WAAW,EAAC,EAAE,CAAC,QAAQ,EAAE,EAAE;gBACtC,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC;gBAC5B,OAAO,CAAC,IAAI,GAAG,mBAAmB,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAC7D,GAAG,CAAC,qBAAqB,EAAE,QAAQ,CAAC,CAAC;gBACrC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAClC,iDAAiD;gBACjD,uBAAuB,CAAC,IAAI,CAAC;oBAC3B,IAAI,EAAE,WAAW;oBACjB,UAAU,EAAE,QAAQ,CAAC,UAAU;oBAC/B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oBAC3B,IAAI,EAAE,QAAQ,CAAC,IAAI;iBACpB,CAAC,CAAC;YACL,CAAC,CAAC;iBACD,IAAI,CAAC,EAAC,IAAI,EAAE,OAAO,EAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;gBACzC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;gBAC/C,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;gBACxD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;gBAE7D,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,2BAA2B;YACxD,CAAC,CAAC;iBACD,IAAI,CAAC,EAAC,IAAI,EAAE,WAAW,EAAC,EAAE,CAAC,aAAa,EAAE,EAAE;gBAC3C,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;gBAC3B,IAAI,iBAAiB,KAAK,EAAE;oBAAE,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC;gBAChD,iBAAiB,IAAI,aAAa,CAAC,IAAI,CAAC;gBACxC,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACjF,CAAC,CAAC;gBACF,uFAAuF;iBACtF,IAAI,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE;gBAC1B,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;gBAC3B,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;gBAEhC,GAAG,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC,CAAC;iBACD,IAAI,CAAC,EAAC,IAAI,EAAE,QAAQ,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE;gBAC5B,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;gBAC3B,IAAI,CAAC,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;oBAC3B,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;wBACZ,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC;oBAC1C,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC;oBACvB,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;wBACf,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC;oBAC/C,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC;oBACzB,CAAC;gBACH,CAAC;gBAED,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC;YAC7B,CAAC,CAAC;iBACD,IAAI,CAAC,EAAC,IAAI,EAAE,aAAa,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC;iBACnE,IAAI,CAAC,EAAC,IAAI,EAAE,2BAA2B,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,qCAAqC,EAAE,CAAC,CAAC,CAAC;iBAC/F,IAAI,CAAC,EAAC,IAAI,EAAE,iBAAiB,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,2BAA2B,EAAE,CAAC,CAAC,CAAC;iBAC3E,IAAI,CAAC,EAAC,IAAI,EAAE,uBAAuB,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,iCAAiC,EAAE,CAAC,CAAC,CAAC;iBACvF,IAAI,CAAC,EAAC,IAAI,EAAE,YAAY,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;iBACjE,IAAI,CAAC,EAAC,IAAI,EAAE,aAAa,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC,CAAC,CAAC;iBACnE,IAAI,CAAC,EAAC,IAAI,EAAE,OAAO,EAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC;iBACvD,IAAI,CAAC,EAAC,IAAI,EAAE,QAAQ,EAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;gBAC3C,GAAG,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC;gBACpC,4DAA4D;gBAC5D,eAAe,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;gBAE/C,IAAI,UAAU,CAAC,YAAY,KAAK,MAAM,IAAI,UAAU,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;oBAC/E,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;oBAC/C,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;oBAC9E,uFAAuF;oBACvF,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,mCAAmC;gBACjE,CAAC;gBAED,IAAI,UAAU,CAAC,YAAY,KAAK,YAAY,EAAE,CAAC;oBAC7C,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBACpC,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;wBAChD,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,0DAA0D,CAAC,CAAC;wBAC7H,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC,yBAAyB;oBACvD,CAAC;oBAED,MAAM,kBAAkB,GAAmB,EAAE,CAAC;oBAC9C,KAAK,MAAM,QAAQ,IAAI,kBAAkB,EAAE,CAAC;wBAC1C,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;wBACxD,IAAI,CAAC,aAAa,IAAI,OAAO,aAAa,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;4BAClE,OAAO,CAAC,KAAK,CAAC,QAAQ,QAAQ,CAAC,QAAQ,+BAA+B,CAAC,CAAC;4BACxE,kBAAkB,CAAC,IAAI,CAAC;gCACtB,IAAI,EAAE,MAAM;gCACZ,OAAO,EAAE;oCACP;wCACE,IAAI,EAAE,aAAa;wCACnB,UAAU,EAAE,QAAQ,CAAC,UAAU;wCAC/B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;wCAC3B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAC,KAAK,EAAE,QAAQ,QAAQ,CAAC,QAAQ,+BAA+B,EAAC,CAAC;wCACzF,OAAO,EAAE,IAAI;qCACd;iCACF;6BACF,CAAC,CAAC;4BACH,SAAS;wBACX,CAAC;wBACD,OAAO,CAAC,IAAI,GAAG,mBAAmB,QAAQ,CAAC,QAAQ,KAAK,CAAC;wBACzD,MAAM,eAAe,GAAG,MAAM,UAAU,CAAC,GAAG,EAAE,CAC5C,aAAa,CAAC,OAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;4BACpC,UAAU,EAAE,QAAQ,CAAC,UAAU;4BAC/B,QAAQ,EAAE,eAAe;yBAC1B,CAAC,CACH,EAAE,CAAC;wBACJ,kBAAkB,CAAC,IAAI,CAAC;4BACtB,IAAI,EAAE,MAAM;4BACZ,OAAO,EAAE;gCACP;oCACE,IAAI,EAAE,aAAa;oCACnB,UAAU,EAAE,QAAQ,CAAC,UAAU;oCAC/B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oCAC3B,OAAO,EAAE,CAAC,eAAe,CAAC,OAAO;oCACjC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC;iCACjG;6BACF;yBACF,CAAC,CAAC;wBACH,IAAI,eAAe,CAAC,OAAO,EAAE,CAAC;4BAC5B,OAAO,CAAC,IAAI,GAAG,QAAQ,QAAQ,CAAC,QAAQ,YAAY,CAAC;wBACvD,CAAC;6BAAM,CAAC;4BACN,OAAO,CAAC,IAAI,GAAG,wBAAwB,QAAQ,CAAC,QAAQ,GAAG,CAAC;wBAC9D,CAAC;oBACH,CAAC;oBACD,eAAe,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,CAAC;oBAC5C,mCAAmC;gBACrC,CAAC;qBAAM,CAAC;oBACN,iEAAiE;oBACjE,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;oBAChD,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,yCAAyC,UAAU,CAAC,YAAY,EAAE,CAAC,CAAC;oBAClI,OAAO,YAAY,CAAC,KAAK,CAAC;gBAC5B,CAAC;YACH,CAAC,CAAC;iBACD,SAAS,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,2CAA2C;YAEnE,IAAI,WAAW,KAAK,YAAY,CAAC,KAAK,EAAE,CAAC;gBACvC,MAAM,WAAW,CAAC;YACpB,CAAC;YACD,IAAI,WAAW,KAAK,YAAY,CAAC,MAAM,EAAE,CAAC;gBACxC,MAAM,IAAI,CAAC;YACb,CAAC;iBAAM,IAAI,WAAW,KAAK,YAAY,CAAC,KAAK,EAAE,CAAC;gBAC9C,MAAM;YACR,CAAC;QACH,CAAC;QACD,yHAAyH;QACzH,IAAI,IAAI,KAAK,QAAQ,GAAG,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC;YAChD,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,iCAAiC,CAAC,CAAC;YACpG,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC,CAAC","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
|
+
{"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,
|
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"}
|
@@ -16,14 +16,14 @@ export const run = async (_cwd, options) => {
|
|
16
16
|
if (fs.existsSync(cwdIgnoreFilepath)) {
|
17
17
|
ignore.push(...fs.readFileSync(cwdIgnoreFilepath, "utf-8").split("\n"));
|
18
18
|
}
|
19
|
-
const
|
19
|
+
const exitedJobs = new Set();
|
20
20
|
let { force = false } = options;
|
21
21
|
const { loopTimes: MAX_LOOP_TIMES = Infinity } = options;
|
22
22
|
let currentTimes = 1;
|
23
23
|
let retryTimes = 0;
|
24
24
|
const MAX_RETRY_TIMES = 3;
|
25
25
|
while (currentTimes <= MAX_LOOP_TIMES) {
|
26
|
-
const ai_tasks = resolveAiTasks(cwd, config.tasks);
|
26
|
+
const ai_tasks = resolveAiTasks(cwd, config.tasks, currentTimes - 1);
|
27
27
|
const allFiles = [...walkFiles(cwd, { ignore })];
|
28
28
|
let allDone = true;
|
29
29
|
try {
|
@@ -34,14 +34,14 @@ export const run = async (_cwd, options) => {
|
|
34
34
|
continue;
|
35
35
|
}
|
36
36
|
}
|
37
|
-
if (
|
37
|
+
if (exitedJobs.has(ai_task.jobName)) {
|
38
38
|
continue;
|
39
39
|
}
|
40
40
|
const { dirs: task_dirs } = ai_task;
|
41
41
|
if (!task_dirs.some((dir) => dirMatcher.isMatch(dir))) {
|
42
42
|
continue;
|
43
43
|
}
|
44
|
-
if (!nameMatcher.isMatch(ai_task.
|
44
|
+
if (!nameMatcher.isMatch(ai_task.jobName)) {
|
45
45
|
continue;
|
46
46
|
}
|
47
47
|
const isCwdTask = cwd === task_dirs[0] && task_dirs.length === 1;
|
@@ -61,12 +61,13 @@ export const run = async (_cwd, options) => {
|
|
61
61
|
/// 只要有一个任务执行了,那么allDone就要标记成false,进入下一次循环来判断
|
62
62
|
allDone = false;
|
63
63
|
await runAiTask(ai_task, currentTimes, task_allFiles, task_changedFiles);
|
64
|
-
if (ai_task.
|
65
|
-
|
64
|
+
if (ai_task.exitCode != null) {
|
65
|
+
exitedJobs.add(ai_task.jobName);
|
66
66
|
}
|
67
67
|
}
|
68
68
|
}
|
69
|
-
catch {
|
69
|
+
catch (e) {
|
70
|
+
console.error(e);
|
70
71
|
// 遇到异常,那么重试
|
71
72
|
if (retryTimes < MAX_RETRY_TIMES) {
|
72
73
|
retryTimes += 1;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/tasks/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,yBAAyB,EAAE,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC3G,OAAO,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AACzC,OAAO,EAAC,cAAc,EAAC,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAC,SAAS,EAAC,MAAM,kBAAkB,CAAC;AAE3C,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EACtB,IAAY,EACZ,OAKC,EACD,EAAE;IACF,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IAErC,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAC,CAAC;IAC5G,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAC,CAAC;IACzG,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,IAAI,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/tasks/run.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,yBAAyB,EAAE,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC3G,OAAO,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAC,WAAW,EAAC,MAAM,cAAc,CAAC;AACzC,OAAO,EAAC,cAAc,EAAC,MAAM,kCAAkC,CAAC;AAChE,OAAO,EAAC,SAAS,EAAC,MAAM,kBAAkB,CAAC;AAE3C,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,EACtB,IAAY,EACZ,OAKC,EACD,EAAE;IACF,MAAM,GAAG,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;IAErC,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAC,CAAC;IAC5G,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,EAAC,CAAC;IACzG,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,IAAI,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;IAErC,IAAI,EAAC,KAAK,GAAG,KAAK,EAAC,GAAG,OAAO,CAAC;IAC9B,MAAM,EAAC,SAAS,EAAE,cAAc,GAAG,QAAQ,EAAC,GAAG,OAAO,CAAC;IACvD,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,eAAe,GAAG,CAAC,CAAC;IAC1B,OAAO,YAAY,IAAI,cAAc,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,CAAC,CAAC,CAAC;QAErE,MAAM,QAAQ,GAAG,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,EAAC,MAAM,EAAC,CAAC,CAAC,CAAC;QAC/C,IAAI,OAAO,GAAG,IAAI,CAAC;QAEnB,IAAI,CAAC;YACH,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;gBAC/B,kCAAkC;gBAClC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,EAAE,CAAC;wBACjC,SAAS;oBACX,CAAC;gBACH,CAAC;gBACD,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBACpC,SAAS;gBACX,CAAC;gBAED,MAAM,EAAC,IAAI,EAAE,SAAS,EAAC,GAAG,OAAO,CAAC;gBAClC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBACtD,SAAS;gBACX,CAAC;gBACD,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBAC1C,SAAS;gBACX,CAAC;gBACD,MAAM,SAAS,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC;gBAEjE,MAAM,YAAY,GAAG,CAAC,MAAM,yBAAyB,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC;gBAEnG,MAAM,iBAAiB,GAAG,SAAS;oBACjC,CAAC,CAAC,EAAC,CAAC,GAAG,CAAC,EAAE,YAAY,EAAC;oBACvB,CAAC,CAAC,SAAS,CAAC,MAAM,CACd,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE;wBACjB,IAAI,CAAC,QAAQ,CAAC,GAAG,iBAAiB,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE;4BACxD,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,GAAG,GAAG,CAAC,EAAE,CAAC;gCAC1C,OAAO,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,EAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAC,CAAC,CAAC;4BACtE,CAAC;wBACH,CAAC,CAAC,CAAC;wBACH,OAAO,IAAI,CAAC;oBACd,CAAC,EACD,EAAiC,CAClC,CAAC;gBAEN,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,EAAC,MAAM,EAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAEpH,WAAW,CAAC,GAAG,CAAC,CAAC;gBAEjB,6CAA6C;gBAC7C,OAAO,GAAG,KAAK,CAAC;gBAChB,MAAM,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,CAAC,CAAC;gBAEzE,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;oBAC7B,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACjB,YAAY;YACZ,IAAI,UAAU,GAAG,eAAe,EAAE,CAAC;gBACjC,UAAU,IAAI,CAAC,CAAC;gBAChB,SAAS;YACX,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;QACH,CAAC;QACD,sBAAsB;QACtB,KAAK,GAAG,KAAK,CAAC;QACd,YAAY,IAAI,CAAC,CAAC;QAClB,oBAAoB;QACpB,UAAU,GAAG,CAAC,CAAC;QAEf,oBAAoB;QACpB,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC,CAAC","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 exitedJobs = 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, currentTimes - 1);\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 (exitedJobs.has(ai_task.jobName)) {\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.jobName)) {\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.exitCode != null) {\n exitedJobs.add(ai_task.jobName);\n }\n }\n } catch (e) {\n console.error(e);\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"]}
|