@nick848/sf-cli 1.0.20 → 1.0.22
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/index.js +389 -122
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +387 -120
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +387 -120
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -104,7 +104,10 @@ async function executeWorkflow(ctx) {
|
|
|
104
104
|
if (activeSession.phase === "context") {
|
|
105
105
|
lines.push(chalk9.cyan("\u2501\u2501\u2501 \u9636\u6BB5 1/9: \u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6 \u2501\u2501\u2501"));
|
|
106
106
|
lines.push("");
|
|
107
|
+
const loader = new LoadingIndicator2("\u8BFB\u53D6\u9879\u76EE\u914D\u7F6E");
|
|
108
|
+
loader.start();
|
|
107
109
|
activeSession.context = await readProjectContext(ctx.options.workingDirectory);
|
|
110
|
+
loader.stop();
|
|
108
111
|
lines.push(chalk9.gray(` \u9879\u76EE: ${activeSession.context.name}`));
|
|
109
112
|
lines.push(chalk9.gray(` \u7C7B\u578B: ${activeSession.context.type}`));
|
|
110
113
|
lines.push(chalk9.gray(` \u6846\u67B6: ${activeSession.context.framework || "\u672A\u8BC6\u522B"}`));
|
|
@@ -194,7 +197,7 @@ ${resource.analysis}`;
|
|
|
194
197
|
lines.push("");
|
|
195
198
|
lines.push(chalk9.cyan("\u2501\u2501\u2501 \u9636\u6BB5 5/9: BDD \u573A\u666F\u62C6\u89E3 \u2501\u2501\u2501"));
|
|
196
199
|
lines.push("");
|
|
197
|
-
const loader = new
|
|
200
|
+
const loader = new LoadingIndicator2("AI \u6B63\u5728\u751F\u6210 BDD \u573A\u666F");
|
|
198
201
|
loader.start();
|
|
199
202
|
try {
|
|
200
203
|
activeSession.bddScenarios = await generateBDDScenariosWithAI(
|
|
@@ -229,7 +232,7 @@ ${resource.analysis}`;
|
|
|
229
232
|
lines.push("");
|
|
230
233
|
lines.push(chalk9.cyan("\u2501\u2501\u2501 \u9636\u6BB5 6/9: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
|
|
231
234
|
lines.push("");
|
|
232
|
-
const loader = new
|
|
235
|
+
const loader = new LoadingIndicator2("AI \u6B63\u5728\u62C6\u5206\u89C4\u683C");
|
|
233
236
|
loader.start();
|
|
234
237
|
try {
|
|
235
238
|
activeSession.specItems = await generateSpecItemsWithAI(
|
|
@@ -398,31 +401,85 @@ async function handleWorkflowInput(input, ctx) {
|
|
|
398
401
|
activeSession.phase = "analysis";
|
|
399
402
|
return executeWorkflow(ctx);
|
|
400
403
|
}
|
|
401
|
-
if (activeSession.phase === "spec") {
|
|
404
|
+
if (activeSession.phase === "spec" || activeSession.specFeedbackState === "waiting_confirm") {
|
|
402
405
|
if (trimmed === "y" || trimmed === "yes" || trimmed === "\u786E\u8BA4") {
|
|
406
|
+
activeSession.specFeedbackState = void 0;
|
|
403
407
|
activeSession.phase = "tdd";
|
|
404
408
|
return executeWorkflow(ctx);
|
|
405
409
|
}
|
|
406
|
-
if (trimmed === "n" || trimmed === "no" || trimmed === "\u91CD\u65B0") {
|
|
407
|
-
activeSession.
|
|
408
|
-
|
|
409
|
-
activeSession.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
410
|
+
if (trimmed === "n" || trimmed === "no" || trimmed === "\u4E0D\u6EE1\u610F" || trimmed === "\u91CD\u65B0") {
|
|
411
|
+
activeSession.specFeedbackState = "collecting_feedback";
|
|
412
|
+
if (!activeSession.specFeedbacks) {
|
|
413
|
+
activeSession.specFeedbacks = [];
|
|
414
|
+
}
|
|
415
|
+
return {
|
|
416
|
+
output: chalk9.yellow("\n\u{1F4DD} \u8BF7\u8F93\u5165\u60A8\u5BF9\u89C4\u683C\u4E0D\u6EE1\u610F\u7684\u5730\u65B9:") + chalk9.gray("\n - \u9057\u6F0F\u7684\u529F\u80FD\u70B9") + chalk9.gray("\n - \u4E0D\u5408\u7406\u7684\u62C6\u5206") + chalk9.gray("\n - \u9700\u8981\u8865\u5145\u7684\u7EC6\u8282") + chalk9.gray("\n - \u5176\u4ED6\u6539\u8FDB\u5EFA\u8BAE") + chalk9.cyan('\n\n\u8F93\u5165\u5B8C\u6210\u540E\uFF0C\u8F93\u5165\u7A7A\u884C\u6216 "done" \u7ED3\u675F\u8F93\u5165')
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (activeSession.specFeedbackState === "collecting_feedback") {
|
|
421
|
+
if (trimmed === "" || trimmed === "done" || trimmed === "\u5B8C\u6210") {
|
|
422
|
+
if (!activeSession.specFeedbacks || activeSession.specFeedbacks.length === 0) {
|
|
423
|
+
return {
|
|
424
|
+
output: chalk9.yellow('\u26A0\uFE0F \u8BF7\u81F3\u5C11\u8F93\u5165\u4E00\u6761\u53CD\u9988\u610F\u89C1\uFF0C\u6216\u8F93\u5165 "cancel" \u53D6\u6D88')
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
activeSession.specFeedbackState = "feedback_received";
|
|
428
|
+
const loader = new LoadingIndicator2("AI \u6B63\u5728\u6839\u636E\u53CD\u9988\u91CD\u65B0\u751F\u6210\u89C4\u683C");
|
|
429
|
+
loader.start();
|
|
430
|
+
try {
|
|
431
|
+
activeSession.specItems = await generateSpecItemsWithFeedback(
|
|
432
|
+
activeSession.refinedRequirement,
|
|
433
|
+
activeSession.context,
|
|
434
|
+
activeSession.bddScenarios,
|
|
435
|
+
activeSession.clarificationQuestions,
|
|
436
|
+
activeSession.referenceResources,
|
|
437
|
+
activeSession.specFeedbacks,
|
|
438
|
+
ctx
|
|
439
|
+
);
|
|
440
|
+
loader.stop(chalk9.green(" \u2713 \u89C4\u683C\u5DF2\u6839\u636E\u53CD\u9988\u91CD\u65B0\u751F\u6210"));
|
|
441
|
+
} catch (error) {
|
|
442
|
+
loader.stop(chalk9.yellow(" \u26A0 \u4F7F\u7528\u57FA\u7840\u65B9\u6CD5\u91CD\u65B0\u751F\u6210"));
|
|
443
|
+
activeSession.specItems = generateSpecItems(
|
|
444
|
+
activeSession.refinedRequirement,
|
|
445
|
+
activeSession.context,
|
|
446
|
+
activeSession.bddScenarios,
|
|
447
|
+
activeSession.clarificationQuestions,
|
|
448
|
+
activeSession.referenceResources
|
|
449
|
+
);
|
|
450
|
+
}
|
|
420
451
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
452
|
+
activeSession.specFeedbackState = "waiting_confirm";
|
|
453
|
+
const lines = [];
|
|
454
|
+
lines.push(chalk9.cyan("\n\u2501\u2501\u2501 \u66F4\u65B0\u540E\u7684\u4EFB\u52A1\u6982\u89C8 \u2501\u2501\u2501"));
|
|
455
|
+
for (const item of activeSession.specItems.slice(0, 8)) {
|
|
456
|
+
const icon = item.priority === "high" ? "\u{1F534}" : item.priority === "medium" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
457
|
+
lines.push(chalk9.gray(` ${icon} [${item.id}] ${item.title}`));
|
|
458
|
+
}
|
|
459
|
+
if (activeSession.specItems.length > 8) {
|
|
460
|
+
lines.push(chalk9.gray(` ... \u5171 ${activeSession.specItems.length} \u4E2A\u4EFB\u52A1`));
|
|
461
|
+
}
|
|
421
462
|
return {
|
|
422
|
-
output:
|
|
423
|
-
|
|
463
|
+
output: lines.join("\n") + chalk9.green(`
|
|
464
|
+
|
|
465
|
+
\u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u66F4\u65B0`) + chalk9.gray(`
|
|
466
|
+
\u8DEF\u5F84: ${specPath}`) + chalk9.yellow("\n\n\u8BF7\u786E\u8BA4:") + chalk9.green("\n y - \u786E\u8BA4\u89C4\u683C") + chalk9.red("\n n - \u4ECD\u6709\u95EE\u9898\uFF0C\u7EE7\u7EED\u53CD\u9988")
|
|
424
467
|
};
|
|
425
468
|
}
|
|
469
|
+
if (trimmed === "cancel" || trimmed === "\u53D6\u6D88") {
|
|
470
|
+
activeSession.specFeedbackState = "waiting_confirm";
|
|
471
|
+
activeSession.specFeedbacks = [];
|
|
472
|
+
return {
|
|
473
|
+
output: chalk9.gray("\u5DF2\u53D6\u6D88\u53CD\u9988\uFF0C\u8FD4\u56DE\u89C4\u683C\u786E\u8BA4") + chalk9.yellow("\n\n\u8BF7\u786E\u8BA4:") + chalk9.green("\n y - \u786E\u8BA4\u89C4\u683C") + chalk9.red("\n n - \u4E0D\u6EE1\u610F\uFF0C\u91CD\u65B0\u751F\u6210")
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
if (!activeSession.specFeedbacks) {
|
|
477
|
+
activeSession.specFeedbacks = [];
|
|
478
|
+
}
|
|
479
|
+
activeSession.specFeedbacks.push(trimmed);
|
|
480
|
+
return {
|
|
481
|
+
output: chalk9.gray(`\u5DF2\u8BB0\u5F55\u53CD\u9988 #${activeSession.specFeedbacks.length}: `) + chalk9.white(trimmed.slice(0, 50)) + chalk9.gray('\n\u7EE7\u7EED\u8F93\u5165\uFF0C\u6216\u8F93\u5165 "done" \u5B8C\u6210\u53CD\u9988')
|
|
482
|
+
};
|
|
426
483
|
}
|
|
427
484
|
if (activeSession.phase === "develop") {
|
|
428
485
|
if (trimmed === "continue" || trimmed === "\u7EE7\u7EED" || trimmed === "done" || trimmed === "\u5B8C\u6210") {
|
|
@@ -574,107 +631,115 @@ function getCategoryLabel(category) {
|
|
|
574
631
|
async function executeDevelopment(ctx, session) {
|
|
575
632
|
const workingDir = ctx.options.workingDirectory;
|
|
576
633
|
const files = [];
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
const
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
634
|
+
console.log("");
|
|
635
|
+
for (let i = 0; i < session.specItems.length; i++) {
|
|
636
|
+
const item = session.specItems[i];
|
|
637
|
+
const prefix = `[${i + 1}/${session.specItems.length}]`;
|
|
638
|
+
if (item.title.includes("\u6D4B\u8BD5") || item.title.includes("test")) {
|
|
639
|
+
continue;
|
|
640
|
+
}
|
|
641
|
+
const loader = new LoadingIndicator2(`${prefix} \u751F\u6210: ${item.title.slice(0, 20)}...`);
|
|
642
|
+
loader.start();
|
|
643
|
+
try {
|
|
644
|
+
const taskPrompt = buildTaskPrompt(session, item, i);
|
|
645
|
+
const messages = [
|
|
646
|
+
{
|
|
647
|
+
role: "system",
|
|
648
|
+
content: `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u524D\u7AEF\u5F00\u53D1\u5DE5\u7A0B\u5E08\u3002\u8BF7\u6839\u636E\u4EFB\u52A1\u63CF\u8FF0\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002
|
|
585
649
|
|
|
586
650
|
\u26A0\uFE0F \u91CD\u8981\u89C4\u5219\uFF1A
|
|
587
|
-
1. \
|
|
588
|
-
2. \
|
|
589
|
-
3. \
|
|
590
|
-
|
|
591
|
-
\u4EE3\u7801\u8981\u6C42\uFF1A
|
|
592
|
-
1. \u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801
|
|
593
|
-
2. \u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u4EE3\u7801\u98CE\u683C\u548C\u89C4\u8303
|
|
594
|
-
3. \u4F7F\u7528\u9879\u76EE\u6307\u5B9A\u7684\u6280\u672F\u6808
|
|
595
|
-
4. \u4EE3\u7801\u8981\u6709\u9002\u5F53\u7684\u6CE8\u91CA
|
|
596
|
-
5. \u8FD4\u56DE\u683C\u5F0F\uFF1A\u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u4EE3\u7801 \`\`\` \u5305\u88F9
|
|
651
|
+
1. \u53EA\u751F\u6210\u5F53\u524D\u4EFB\u52A1\u76F8\u5173\u7684\u4EE3\u7801\uFF0C\u4E0D\u8981\u751F\u6210\u5176\u4ED6\u4EFB\u52A1\u7684\u4EE3\u7801
|
|
652
|
+
2. \u6280\u672F\u5B9E\u73B0\u5FC5\u987B\u4E25\u683C\u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u5F00\u53D1\u89C4\u8303
|
|
653
|
+
3. \u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801
|
|
654
|
+
4. \u8FD4\u56DE\u683C\u5F0F\uFF1A\u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u4EE3\u7801 \`\`\` \u5305\u88F9
|
|
597
655
|
|
|
598
656
|
\u9879\u76EE\u4FE1\u606F\uFF1A
|
|
599
657
|
- \u540D\u79F0: ${session.context?.name}
|
|
600
658
|
- \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
|
|
601
659
|
- \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
|
|
602
660
|
|
|
603
|
-
${session.context?.devStandards ? `\u3010\
|
|
604
|
-
${session.context.devStandards.slice(0,
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
661
|
+
${session.context?.devStandards ? `\u3010\u5F00\u53D1\u89C4\u8303\u3011
|
|
662
|
+
${session.context.devStandards.slice(0, 2e3)}` : ""}`
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
role: "user",
|
|
666
|
+
content: taskPrompt
|
|
667
|
+
}
|
|
668
|
+
];
|
|
669
|
+
const response = await ctx.modelService.sendMessage(messages, {
|
|
670
|
+
temperature: 0.3,
|
|
671
|
+
maxTokens: 4e3,
|
|
672
|
+
// 单个任务减少 token
|
|
673
|
+
agent: "frontend-dev",
|
|
674
|
+
timeout: 3e5
|
|
675
|
+
// 5分钟超时,确保复杂代码有足够时间
|
|
676
|
+
});
|
|
677
|
+
const codeBlocks = parseCodeBlocks(response.content);
|
|
678
|
+
if (codeBlocks.length > 0) {
|
|
679
|
+
for (const block of codeBlocks) {
|
|
680
|
+
const filePath = path5.join(workingDir, block.filename);
|
|
681
|
+
const dir = path5.dirname(filePath);
|
|
682
|
+
await fs4.mkdir(dir, { recursive: true });
|
|
683
|
+
await fs4.writeFile(filePath, block.code, "utf-8");
|
|
684
|
+
files.push(block.filename);
|
|
685
|
+
}
|
|
686
|
+
loader.stop(chalk9.green(`${prefix} \u2713 ${item.title.slice(0, 25)} (${codeBlocks.length} \u4E2A\u6587\u4EF6)`));
|
|
687
|
+
} else {
|
|
688
|
+
const implDir = path5.join(workingDir, "src");
|
|
689
|
+
await fs4.mkdir(implDir, { recursive: true });
|
|
690
|
+
const fileName = `${item.title.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, "_")}.ts`;
|
|
691
|
+
const filePath = path5.join(implDir, fileName);
|
|
692
|
+
await fs4.writeFile(filePath, `// TODO: ${item.title}
|
|
693
|
+
// ${item.description}
|
|
694
|
+
`, "utf-8");
|
|
695
|
+
files.push(`src/${fileName}`);
|
|
696
|
+
loader.stop(chalk9.yellow(`${prefix} \u26A0 \u751F\u6210\u57FA\u7840\u6A21\u677F: ${item.title.slice(0, 20)}`));
|
|
697
|
+
}
|
|
698
|
+
if (i < session.specItems.length - 1) {
|
|
699
|
+
await new Promise((resolve4) => setTimeout(resolve4, 500));
|
|
609
700
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
const response = await ctx.modelService.sendMessage(messages, {
|
|
613
|
-
temperature: 0.3,
|
|
614
|
-
maxTokens: 8e3,
|
|
615
|
-
agent: "frontend-dev",
|
|
616
|
-
timeout: 18e4
|
|
617
|
-
// 3 分钟超时
|
|
618
|
-
});
|
|
619
|
-
loader.update("\u6B63\u5728\u89E3\u6790\u4EE3\u7801");
|
|
620
|
-
const codeBlocks = parseCodeBlocks(response.content);
|
|
621
|
-
for (const block of codeBlocks) {
|
|
622
|
-
const filePath = path5.join(workingDir, block.filename);
|
|
623
|
-
const dir = path5.dirname(filePath);
|
|
624
|
-
await fs4.mkdir(dir, { recursive: true });
|
|
625
|
-
await fs4.writeFile(filePath, block.code, "utf-8");
|
|
626
|
-
files.push(block.filename);
|
|
627
|
-
}
|
|
628
|
-
if (files.length === 0) {
|
|
629
|
-
const implDir = path5.join(workingDir, "src", "features");
|
|
630
|
-
await fs4.mkdir(implDir, { recursive: true });
|
|
631
|
-
const featureName = session.specItems[0]?.title || "feature";
|
|
632
|
-
const fileName = `${featureName.replace(/[^a-zA-Z0-9]/g, "_")}.ts`;
|
|
633
|
-
const filePath = path5.join(implDir, fileName);
|
|
634
|
-
const stubCode = `/**
|
|
635
|
-
* ${session.requirement}
|
|
636
|
-
*
|
|
637
|
-
* TODO: \u6B64\u6587\u4EF6\u7531 AI \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u6839\u636E\u9700\u6C42\u5B8C\u5584\u5B9E\u73B0
|
|
638
|
-
*/
|
|
639
|
-
|
|
640
|
-
export function ${featureName.replace(/[^a-zA-Z0-9]/g, "")}() {
|
|
641
|
-
// TODO: \u5B9E\u73B0\u529F\u80FD
|
|
642
|
-
console.log('${featureName} - \u5F85\u5B9E\u73B0');
|
|
643
|
-
}
|
|
644
|
-
`;
|
|
645
|
-
await fs4.writeFile(filePath, stubCode, "utf-8");
|
|
646
|
-
files.push(`src/features/${fileName}`);
|
|
701
|
+
} catch (error) {
|
|
702
|
+
loader.stop(chalk9.red(`${prefix} \u2717 \u5931\u8D25: ${error.message.slice(0, 40)}`));
|
|
647
703
|
}
|
|
648
|
-
|
|
704
|
+
}
|
|
705
|
+
if (files.length > 0) {
|
|
649
706
|
return { success: true, files };
|
|
650
|
-
}
|
|
651
|
-
loader.stop();
|
|
707
|
+
} else {
|
|
652
708
|
return {
|
|
653
709
|
success: false,
|
|
654
710
|
files: [],
|
|
655
|
-
error:
|
|
711
|
+
error: "\u6240\u6709\u4EFB\u52A1\u4EE3\u7801\u751F\u6210\u5931\u8D25"
|
|
656
712
|
};
|
|
657
713
|
}
|
|
658
714
|
}
|
|
659
|
-
function
|
|
715
|
+
function buildTaskPrompt(session, item, index) {
|
|
660
716
|
const lines = [];
|
|
661
|
-
lines.push(
|
|
662
|
-
lines.push(
|
|
663
|
-
lines.push(
|
|
664
|
-
lines.push(
|
|
665
|
-
|
|
666
|
-
lines.push(
|
|
667
|
-
for (const
|
|
668
|
-
lines.push(`- ${
|
|
717
|
+
lines.push(`## \u5F53\u524D\u4EFB\u52A1 (#${index + 1})`);
|
|
718
|
+
lines.push(`**\u6807\u9898**: ${item.title}`);
|
|
719
|
+
lines.push(`**\u63CF\u8FF0**: ${item.description}`);
|
|
720
|
+
lines.push(`**\u4F18\u5148\u7EA7**: ${item.priority}`);
|
|
721
|
+
if (item.tests && item.tests.length > 0) {
|
|
722
|
+
lines.push(`**\u9A8C\u6536\u6807\u51C6**:`);
|
|
723
|
+
for (const t of item.tests) {
|
|
724
|
+
lines.push(`- ${t}`);
|
|
669
725
|
}
|
|
670
726
|
}
|
|
671
727
|
lines.push("");
|
|
672
|
-
lines.push(
|
|
673
|
-
|
|
674
|
-
|
|
728
|
+
lines.push(`## \u6574\u4F53\u9700\u6C42\u80CC\u666F`);
|
|
729
|
+
lines.push(session.requirement);
|
|
730
|
+
const relatedScenario = session.bddScenarios.find(
|
|
731
|
+
(s) => item.title.includes(s.feature) || s.feature.includes(item.title)
|
|
732
|
+
);
|
|
733
|
+
if (relatedScenario) {
|
|
734
|
+
lines.push("");
|
|
735
|
+
lines.push(`## \u76F8\u5173 BDD \u573A\u666F`);
|
|
736
|
+
lines.push(`Feature: ${relatedScenario.feature}`);
|
|
737
|
+
for (const s of relatedScenario.scenarios.slice(0, 2)) {
|
|
738
|
+
lines.push(`- ${s.name}`);
|
|
739
|
+
}
|
|
675
740
|
}
|
|
676
741
|
lines.push("");
|
|
677
|
-
lines.push("\u8BF7\
|
|
742
|
+
lines.push("\u8BF7\u751F\u6210\u5B9E\u73B0\u6B64\u4EFB\u52A1\u7684\u4EE3\u7801\u3002\u53EA\u751F\u6210\u5F53\u524D\u4EFB\u52A1\u9700\u8981\u7684\u6587\u4EF6\u3002");
|
|
678
743
|
return lines.join("\n");
|
|
679
744
|
}
|
|
680
745
|
function parseCodeBlocks(content) {
|
|
@@ -695,6 +760,8 @@ async function executeReview(ctx, session) {
|
|
|
695
760
|
const workingDir = ctx.options.workingDirectory;
|
|
696
761
|
const issues = [];
|
|
697
762
|
const suggestions = [];
|
|
763
|
+
const loader = new LoadingIndicator2("AI \u6B63\u5728\u5BA1\u6838\u4EE3\u7801");
|
|
764
|
+
loader.start();
|
|
698
765
|
try {
|
|
699
766
|
const codeContents = [];
|
|
700
767
|
for (const file of session.implFiles) {
|
|
@@ -757,7 +824,9 @@ ${testContents.join("\n\n") || "\uFF08\u65E0\u6D4B\u8BD5\u6587\u4EF6\uFF09"}
|
|
|
757
824
|
const response = await ctx.modelService.sendMessage(messages, {
|
|
758
825
|
temperature: 0.2,
|
|
759
826
|
maxTokens: 2e3,
|
|
760
|
-
agent: "code-reviewer"
|
|
827
|
+
agent: "code-reviewer",
|
|
828
|
+
timeout: 18e4
|
|
829
|
+
// 3分钟超时
|
|
761
830
|
});
|
|
762
831
|
const result = response.content;
|
|
763
832
|
const passed = result.includes("\u5BA1\u6838\u901A\u8FC7") || result.includes("\u901A\u8FC7") || !result.includes("\u4E0D\u901A\u8FC7");
|
|
@@ -779,8 +848,10 @@ ${testContents.join("\n\n") || "\uFF08\u65E0\u6D4B\u8BD5\u6587\u4EF6\uFF09"}
|
|
|
779
848
|
const lines = result.split("\n").filter((l) => l.includes("\u5EFA\u8BAE") || l.includes("\u6539\u8FDB") || l.includes("\u4F18\u5316"));
|
|
780
849
|
suggestions.push(...lines.map((l) => l.replace(/^[-*]\s*/, "").trim()).filter((l) => l));
|
|
781
850
|
}
|
|
851
|
+
loader.stop(passed ? chalk9.green(" \u2713 \u5BA1\u6838\u901A\u8FC7") : chalk9.yellow(" \u26A0 \u53D1\u73B0\u95EE\u9898"));
|
|
782
852
|
return { passed, issues, suggestions };
|
|
783
853
|
} catch (error) {
|
|
854
|
+
loader.stop(chalk9.red(" \u2717 \u5BA1\u6838\u51FA\u9519"));
|
|
784
855
|
suggestions.push(`\u5BA1\u6838\u8FC7\u7A0B\u51FA\u9519: ${error.message}`);
|
|
785
856
|
return { passed: true, issues, suggestions };
|
|
786
857
|
}
|
|
@@ -986,7 +1057,8 @@ ${r.analysis}`).join("\n\n") : "\u65E0"}
|
|
|
986
1057
|
], {
|
|
987
1058
|
temperature: 0.3,
|
|
988
1059
|
maxTokens: 4e3,
|
|
989
|
-
timeout:
|
|
1060
|
+
timeout: 3e5
|
|
1061
|
+
// 5分钟超时
|
|
990
1062
|
});
|
|
991
1063
|
try {
|
|
992
1064
|
const jsonMatch = response.content.match(/```json\s*([\s\S]*?)```/);
|
|
@@ -1194,7 +1266,7 @@ ${questions.filter((q) => q.answered).map((q) => `- ${q.question}: ${q.answer}`)
|
|
|
1194
1266
|
- \u96C6\u6210\u6D4B\u8BD5
|
|
1195
1267
|
|
|
1196
1268
|
\u8BF7\u76F4\u63A5\u8F93\u51FA JSON \u6570\u7EC4\u3002`;
|
|
1197
|
-
const loader = new
|
|
1269
|
+
const loader = new LoadingIndicator2("AI \u6B63\u5728\u62C6\u5206\u89C4\u683C");
|
|
1198
1270
|
loader.start();
|
|
1199
1271
|
try {
|
|
1200
1272
|
const response = await ctx.modelService.sendMessage([
|
|
@@ -1202,25 +1274,131 @@ ${questions.filter((q) => q.answered).map((q) => `- ${q.question}: ${q.answer}`)
|
|
|
1202
1274
|
], {
|
|
1203
1275
|
temperature: 0.3,
|
|
1204
1276
|
maxTokens: 4e3,
|
|
1205
|
-
timeout:
|
|
1277
|
+
timeout: 3e5
|
|
1278
|
+
// 5分钟超时
|
|
1206
1279
|
});
|
|
1207
1280
|
const jsonMatch = response.content.match(/```json\s*([\s\S]*?)```/);
|
|
1208
1281
|
if (jsonMatch) {
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1282
|
+
try {
|
|
1283
|
+
const parsed = JSON.parse(jsonMatch[1].trim());
|
|
1284
|
+
loader.stop(chalk9.green(` \u2713 \u5DF2\u62C6\u5206 ${parsed.length} \u4E2A\u4EFB\u52A1`));
|
|
1285
|
+
return parsed.map((item, index) => ({
|
|
1286
|
+
id: item.id || `T${String(index + 1).padStart(3, "0")}`,
|
|
1287
|
+
title: item.title,
|
|
1288
|
+
description: item.description,
|
|
1289
|
+
priority: item.priority || "medium",
|
|
1290
|
+
files: [],
|
|
1291
|
+
tests: item.acceptanceCriteria || []
|
|
1292
|
+
}));
|
|
1293
|
+
} catch (parseError) {
|
|
1294
|
+
loader.stop(chalk9.yellow(` \u26A0 JSON \u89E3\u6790\u5931\u8D25: ${parseError.message.slice(0, 50)}`));
|
|
1295
|
+
return generateSpecItems(requirement, context, bddScenarios, questions, references);
|
|
1296
|
+
}
|
|
1219
1297
|
}
|
|
1220
|
-
|
|
1298
|
+
try {
|
|
1299
|
+
const parsed = JSON.parse(response.content);
|
|
1300
|
+
if (Array.isArray(parsed)) {
|
|
1301
|
+
loader.stop(chalk9.green(` \u2713 \u5DF2\u62C6\u5206 ${parsed.length} \u4E2A\u4EFB\u52A1`));
|
|
1302
|
+
return parsed.map((item, index) => ({
|
|
1303
|
+
id: item.id || `T${String(index + 1).padStart(3, "0")}`,
|
|
1304
|
+
title: item.title,
|
|
1305
|
+
description: item.description,
|
|
1306
|
+
priority: item.priority || "medium",
|
|
1307
|
+
files: [],
|
|
1308
|
+
tests: item.acceptanceCriteria || []
|
|
1309
|
+
}));
|
|
1310
|
+
}
|
|
1311
|
+
} catch {
|
|
1312
|
+
}
|
|
1313
|
+
loader.stop(chalk9.yellow(" \u26A0 \u672A\u80FD\u89E3\u6790 AI \u54CD\u5E94\uFF0C\u4F7F\u7528\u57FA\u7840\u62C6\u5206"));
|
|
1221
1314
|
return generateSpecItems(requirement, context, bddScenarios, questions, references);
|
|
1222
1315
|
} catch (error) {
|
|
1223
|
-
|
|
1316
|
+
const errMsg = error.message.slice(0, 80);
|
|
1317
|
+
loader.stop(chalk9.yellow(` \u26A0 AI \u8C03\u7528\u5931\u8D25: ${errMsg}`));
|
|
1318
|
+
return generateSpecItems(requirement, context, bddScenarios, questions, references);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
async function generateSpecItemsWithFeedback(requirement, context, bddScenarios, questions, references, feedbacks, ctx) {
|
|
1322
|
+
const prompt2 = `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u9879\u76EE\u7ECF\u7406\u548C\u6280\u672F\u67B6\u6784\u5E08\u3002\u8BF7\u6839\u636E\u7528\u6237\u53CD\u9988\uFF0C\u91CD\u65B0\u62C6\u5206\u9700\u6C42\u4EFB\u52A1\u3002
|
|
1323
|
+
|
|
1324
|
+
## \u9700\u6C42\u63CF\u8FF0
|
|
1325
|
+
${requirement}
|
|
1326
|
+
|
|
1327
|
+
## \u9879\u76EE\u4E0A\u4E0B\u6587
|
|
1328
|
+
- \u6280\u672F\u6808: ${context.techStack?.join(", ") || "TypeScript"}
|
|
1329
|
+
- \u6846\u67B6: ${context.framework || "\u672A\u6307\u5B9A"}
|
|
1330
|
+
${context.devStandards ? `
|
|
1331
|
+
## \u5F00\u53D1\u89C4\u8303\uFF08\u5FC5\u987B\u9075\u5FAA\uFF09
|
|
1332
|
+
${context.devStandards.slice(0, 2e3)}
|
|
1333
|
+
` : ""}
|
|
1334
|
+
|
|
1335
|
+
## \u4E4B\u524D\u7684 BDD \u573A\u666F
|
|
1336
|
+
${bddScenarios.map((s) => `- Feature: ${s.feature}`).join("\n")}
|
|
1337
|
+
|
|
1338
|
+
## \u7528\u6237\u53CD\u9988\uFF08\u5FC5\u987B\u89E3\u51B3\u8FD9\u4E9B\u95EE\u9898\uFF09
|
|
1339
|
+
${feedbacks.map((f, i) => `${i + 1}. ${f}`).join("\n")}
|
|
1340
|
+
|
|
1341
|
+
## \u8981\u6C42
|
|
1342
|
+
1. **\u5FC5\u987B\u89E3\u51B3\u7528\u6237\u53CD\u9988\u4E2D\u7684\u6240\u6709\u95EE\u9898**
|
|
1343
|
+
2. \u5982\u679C\u7528\u6237\u6307\u51FA\u9057\u6F0F\u7684\u529F\u80FD\u70B9\uFF0C\u8BF7\u8865\u5145\u76F8\u5173\u4EFB\u52A1
|
|
1344
|
+
3. \u5982\u679C\u7528\u6237\u6307\u51FA\u62C6\u5206\u4E0D\u5408\u7406\uFF0C\u8BF7\u91CD\u65B0\u8C03\u6574\u7C92\u5EA6
|
|
1345
|
+
4. \u5982\u679C\u7528\u6237\u9700\u8981\u66F4\u591A\u7EC6\u8282\uFF0C\u8BF7\u62C6\u5206\u5F97\u66F4\u7EC6\u81F4
|
|
1346
|
+
5. \u6BCF\u4E2A\u4EFB\u52A1\u5E94\u8BE5\u5355\u4E00\u804C\u8D23\u30012-4\u5C0F\u65F6\u53EF\u5B8C\u6210
|
|
1347
|
+
|
|
1348
|
+
## \u8F93\u51FA\u683C\u5F0F (JSON)
|
|
1349
|
+
\`\`\`json
|
|
1350
|
+
[
|
|
1351
|
+
{
|
|
1352
|
+
"id": "T001",
|
|
1353
|
+
"title": "\u4EFB\u52A1\u6807\u9898\uFF08\u7B80\u77ED\u660E\u786E\uFF09",
|
|
1354
|
+
"description": "\u8BE6\u7EC6\u63CF\u8FF0",
|
|
1355
|
+
"priority": "high",
|
|
1356
|
+
"acceptanceCriteria": ["\u9A8C\u6536\u6807\u51C61", "\u9A8C\u6536\u6807\u51C62"]
|
|
1357
|
+
}
|
|
1358
|
+
]
|
|
1359
|
+
\`\`\`
|
|
1360
|
+
|
|
1361
|
+
\u8BF7\u76F4\u63A5\u8F93\u51FA JSON \u6570\u7EC4\uFF0C\u786E\u4FDD\u89E3\u51B3\u4E86\u7528\u6237\u7684\u6240\u6709\u53CD\u9988\u3002`;
|
|
1362
|
+
try {
|
|
1363
|
+
const response = await ctx.modelService.sendMessage([
|
|
1364
|
+
{ role: "user", content: prompt2 }
|
|
1365
|
+
], {
|
|
1366
|
+
temperature: 0.3,
|
|
1367
|
+
maxTokens: 4e3,
|
|
1368
|
+
timeout: 3e5
|
|
1369
|
+
// 5分钟超时
|
|
1370
|
+
});
|
|
1371
|
+
const jsonMatch = response.content.match(/```json\s*([\s\S]*?)```/);
|
|
1372
|
+
if (jsonMatch) {
|
|
1373
|
+
try {
|
|
1374
|
+
const parsed = JSON.parse(jsonMatch[1].trim());
|
|
1375
|
+
return parsed.map((item, index) => ({
|
|
1376
|
+
id: item.id || `T${String(index + 1).padStart(3, "0")}`,
|
|
1377
|
+
title: item.title,
|
|
1378
|
+
description: item.description,
|
|
1379
|
+
priority: item.priority || "medium",
|
|
1380
|
+
files: [],
|
|
1381
|
+
tests: item.acceptanceCriteria || []
|
|
1382
|
+
}));
|
|
1383
|
+
} catch {
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
try {
|
|
1387
|
+
const parsed = JSON.parse(response.content);
|
|
1388
|
+
if (Array.isArray(parsed)) {
|
|
1389
|
+
return parsed.map((item, index) => ({
|
|
1390
|
+
id: item.id || `T${String(index + 1).padStart(3, "0")}`,
|
|
1391
|
+
title: item.title,
|
|
1392
|
+
description: item.description,
|
|
1393
|
+
priority: item.priority || "medium",
|
|
1394
|
+
files: [],
|
|
1395
|
+
tests: item.acceptanceCriteria || []
|
|
1396
|
+
}));
|
|
1397
|
+
}
|
|
1398
|
+
} catch {
|
|
1399
|
+
}
|
|
1400
|
+
return generateSpecItems(requirement, context, bddScenarios, questions, references);
|
|
1401
|
+
} catch {
|
|
1224
1402
|
return generateSpecItems(requirement, context, bddScenarios, questions, references);
|
|
1225
1403
|
}
|
|
1226
1404
|
}
|
|
@@ -1290,6 +1468,16 @@ function formatSpecFile(session) {
|
|
|
1290
1468
|
lines.push("");
|
|
1291
1469
|
}
|
|
1292
1470
|
}
|
|
1471
|
+
if (session.specFeedbacks && session.specFeedbacks.length > 0) {
|
|
1472
|
+
lines.push("## \u89C4\u683C\u8FED\u4EE3\u53CD\u9988");
|
|
1473
|
+
lines.push("");
|
|
1474
|
+
for (let i = 0; i < session.specFeedbacks.length; i++) {
|
|
1475
|
+
lines.push(`${i + 1}. ${session.specFeedbacks[i]}`);
|
|
1476
|
+
}
|
|
1477
|
+
lines.push("");
|
|
1478
|
+
lines.push("---");
|
|
1479
|
+
lines.push("");
|
|
1480
|
+
}
|
|
1293
1481
|
lines.push("## \u4EFB\u52A1\u5217\u8868");
|
|
1294
1482
|
lines.push("");
|
|
1295
1483
|
for (const item of session.specItems) {
|
|
@@ -1310,7 +1498,7 @@ async function generateTests(workingDir, session, ctx) {
|
|
|
1310
1498
|
for (const scenario of session.bddScenarios) {
|
|
1311
1499
|
const testName = scenario.feature.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, "_");
|
|
1312
1500
|
const testPath = path5.join(testDir, `${testName}.test.ts`);
|
|
1313
|
-
const loader = new
|
|
1501
|
+
const loader = new LoadingIndicator2(`\u751F\u6210\u6D4B\u8BD5: ${scenario.feature.slice(0, 20)}...`);
|
|
1314
1502
|
loader.start();
|
|
1315
1503
|
try {
|
|
1316
1504
|
const content = await generateTestFileWithAI(scenario, session, ctx);
|
|
@@ -1365,7 +1553,9 @@ ${scenario.scenarios.map((s) => `
|
|
|
1365
1553
|
{ role: "user", content: prompt2 }
|
|
1366
1554
|
], {
|
|
1367
1555
|
temperature: 0.3,
|
|
1368
|
-
maxTokens: 4e3
|
|
1556
|
+
maxTokens: 4e3,
|
|
1557
|
+
timeout: 18e4
|
|
1558
|
+
// 3分钟超时
|
|
1369
1559
|
});
|
|
1370
1560
|
const codeMatch = response.content.match(/```(?:typescript|ts|javascript|js)?\n([\s\S]*?)```/);
|
|
1371
1561
|
if (codeMatch) {
|
|
@@ -1464,7 +1654,10 @@ async function fetchAndAnalyzeReference(url, ctx, projectContext) {
|
|
|
1464
1654
|
const type = detectResourceType(url);
|
|
1465
1655
|
let content = "";
|
|
1466
1656
|
let analysis = "";
|
|
1657
|
+
const loader = new LoadingIndicator2(`\u83B7\u53D6 ${url.slice(0, 40)}...`);
|
|
1658
|
+
loader.start();
|
|
1467
1659
|
try {
|
|
1660
|
+
loader.update("\u6B63\u5728\u83B7\u53D6\u7F51\u9875\u5185\u5BB9");
|
|
1468
1661
|
const response = await fetch(url, {
|
|
1469
1662
|
headers: {
|
|
1470
1663
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
|
@@ -1475,11 +1668,14 @@ async function fetchAndAnalyzeReference(url, ctx, projectContext) {
|
|
|
1475
1668
|
}
|
|
1476
1669
|
content = await response.text();
|
|
1477
1670
|
if (ctx.modelService.getCurrentModel()) {
|
|
1671
|
+
loader.update("\u6B63\u5728\u5206\u6790\u5185\u5BB9");
|
|
1478
1672
|
analysis = await analyzeReferenceContent(url, content, type, ctx, projectContext);
|
|
1479
1673
|
} else {
|
|
1480
1674
|
analysis = extractBasicInfo(content, type);
|
|
1481
1675
|
}
|
|
1676
|
+
loader.stop();
|
|
1482
1677
|
} catch (error) {
|
|
1678
|
+
loader.stop();
|
|
1483
1679
|
throw new Error(`\u65E0\u6CD5\u83B7\u53D6\u53C2\u8003\u8D44\u6E90: ${error.message}`);
|
|
1484
1680
|
}
|
|
1485
1681
|
return { url, type, content: content.slice(0, 1e4), analysis };
|
|
@@ -1548,14 +1744,16 @@ ${content.slice(0, 8e3)}
|
|
|
1548
1744
|
\u6CE8\u610F\uFF1A\u8BF7\u4EE5 Markdown \u683C\u5F0F\u8F93\u51FA\uFF0C\u91CD\u70B9\u7A81\u51FA**\u4E1A\u52A1\u903B\u8F91**\u548C**\u529F\u80FD\u7279\u6027**\u3002
|
|
1549
1745
|
\u6280\u672F\u5B9E\u73B0\u65B9\u6848\u7531\u9879\u76EE\u89C4\u8303\u51B3\u5B9A\uFF0C\u6B64\u5904\u4E0D\u6D89\u53CA\u3002
|
|
1550
1746
|
`;
|
|
1551
|
-
const loader = new
|
|
1747
|
+
const loader = new LoadingIndicator2("AI \u6B63\u5728\u5206\u6790\u53C2\u8003\u8D44\u6E90");
|
|
1552
1748
|
loader.start();
|
|
1553
1749
|
try {
|
|
1554
1750
|
const response = await ctx.modelService.sendMessage([
|
|
1555
1751
|
{ role: "user", content: prompt2 }
|
|
1556
1752
|
], {
|
|
1557
1753
|
temperature: 0.3,
|
|
1558
|
-
maxTokens: 4e3
|
|
1754
|
+
maxTokens: 4e3,
|
|
1755
|
+
timeout: 18e4
|
|
1756
|
+
// 3分钟超时
|
|
1559
1757
|
});
|
|
1560
1758
|
loader.stop(chalk9.green(" \u2713 \u5206\u6790\u5B8C\u6210"));
|
|
1561
1759
|
return response.content;
|
|
@@ -1602,11 +1800,11 @@ function getActiveSession() {
|
|
|
1602
1800
|
function clearActiveSession() {
|
|
1603
1801
|
activeSession = null;
|
|
1604
1802
|
}
|
|
1605
|
-
var
|
|
1803
|
+
var LoadingIndicator2, MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, CLARITY_THRESHOLD, activeSession, new_default;
|
|
1606
1804
|
var init_new = __esm({
|
|
1607
1805
|
"src/commands/new.ts"() {
|
|
1608
1806
|
init_esm_shims();
|
|
1609
|
-
|
|
1807
|
+
LoadingIndicator2 = class {
|
|
1610
1808
|
frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1611
1809
|
frameIndex = 0;
|
|
1612
1810
|
interval = null;
|
|
@@ -1971,9 +2169,10 @@ var BaseAdapter = class {
|
|
|
1971
2169
|
}
|
|
1972
2170
|
/**
|
|
1973
2171
|
* 获取超时时间
|
|
2172
|
+
* 默认 5 分钟,对于复杂的代码生成任务足够
|
|
1974
2173
|
*/
|
|
1975
2174
|
getTimeout() {
|
|
1976
|
-
return this.config?.timeout ||
|
|
2175
|
+
return this.config?.timeout || 3e5;
|
|
1977
2176
|
}
|
|
1978
2177
|
/**
|
|
1979
2178
|
* 获取重试次数
|
|
@@ -8163,6 +8362,36 @@ ${chalk9.yellow("\u793A\u4F8B:")}
|
|
|
8163
8362
|
|
|
8164
8363
|
// src/commands/model.ts
|
|
8165
8364
|
init_esm_shims();
|
|
8365
|
+
var LoadingIndicator = class {
|
|
8366
|
+
frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
8367
|
+
frameIndex = 0;
|
|
8368
|
+
interval = null;
|
|
8369
|
+
message;
|
|
8370
|
+
constructor(message) {
|
|
8371
|
+
this.message = message;
|
|
8372
|
+
}
|
|
8373
|
+
start() {
|
|
8374
|
+
process.stdout.write("\x1B[?25l");
|
|
8375
|
+
this.interval = setInterval(() => {
|
|
8376
|
+
const frame = this.frames[this.frameIndex];
|
|
8377
|
+
process.stdout.write(`\r${chalk9.cyan(frame)} ${this.message}...`);
|
|
8378
|
+
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
8379
|
+
}, 80);
|
|
8380
|
+
}
|
|
8381
|
+
stop(finalMessage) {
|
|
8382
|
+
if (this.interval) {
|
|
8383
|
+
clearInterval(this.interval);
|
|
8384
|
+
this.interval = null;
|
|
8385
|
+
}
|
|
8386
|
+
process.stdout.write("\x1B[?25h");
|
|
8387
|
+
if (finalMessage) {
|
|
8388
|
+
process.stdout.write(`\r${finalMessage}
|
|
8389
|
+
`);
|
|
8390
|
+
} else {
|
|
8391
|
+
process.stdout.write("\r" + " ".repeat(60) + "\r");
|
|
8392
|
+
}
|
|
8393
|
+
}
|
|
8394
|
+
};
|
|
8166
8395
|
async function handleModel(args, ctx) {
|
|
8167
8396
|
const subCommand = args[0];
|
|
8168
8397
|
const configManager = ctx.configManager;
|
|
@@ -8262,9 +8491,12 @@ async function verifyCurrentModel(configManager, modelService) {
|
|
|
8262
8491
|
output: chalk9.red(`\u2717 \u672A\u77E5\u6A21\u578B: ${currentModel}`)
|
|
8263
8492
|
};
|
|
8264
8493
|
}
|
|
8494
|
+
const loader = new LoadingIndicator(`\u9A8C\u8BC1 ${modelInfo.name} API Key`);
|
|
8495
|
+
loader.start();
|
|
8265
8496
|
try {
|
|
8266
8497
|
const adapter = createAdapter(modelInfo.provider);
|
|
8267
8498
|
const isValid = await adapter.validateApiKey(apiKey);
|
|
8499
|
+
loader.stop();
|
|
8268
8500
|
if (isValid) {
|
|
8269
8501
|
return {
|
|
8270
8502
|
output: chalk9.green(`\u2713 API Key \u9A8C\u8BC1\u6210\u529F
|
|
@@ -8276,6 +8508,7 @@ async function verifyCurrentModel(configManager, modelService) {
|
|
|
8276
8508
|
};
|
|
8277
8509
|
}
|
|
8278
8510
|
} catch (error) {
|
|
8511
|
+
loader.stop();
|
|
8279
8512
|
return {
|
|
8280
8513
|
output: chalk9.red(`\u2717 \u9A8C\u8BC1\u5931\u8D25: ${error.message}`)
|
|
8281
8514
|
};
|
|
@@ -9487,6 +9720,36 @@ async function executeShell(command, ctx) {
|
|
|
9487
9720
|
// src/commands/natural.ts
|
|
9488
9721
|
init_esm_shims();
|
|
9489
9722
|
init_new();
|
|
9723
|
+
var LoadingIndicator3 = class {
|
|
9724
|
+
frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
9725
|
+
frameIndex = 0;
|
|
9726
|
+
interval = null;
|
|
9727
|
+
message;
|
|
9728
|
+
constructor(message) {
|
|
9729
|
+
this.message = message;
|
|
9730
|
+
}
|
|
9731
|
+
start() {
|
|
9732
|
+
process.stdout.write("\x1B[?25l");
|
|
9733
|
+
this.interval = setInterval(() => {
|
|
9734
|
+
const frame = this.frames[this.frameIndex];
|
|
9735
|
+
process.stdout.write(`\r${chalk9.cyan(frame)} ${this.message}...`);
|
|
9736
|
+
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
9737
|
+
}, 80);
|
|
9738
|
+
}
|
|
9739
|
+
stop(finalMessage) {
|
|
9740
|
+
if (this.interval) {
|
|
9741
|
+
clearInterval(this.interval);
|
|
9742
|
+
this.interval = null;
|
|
9743
|
+
}
|
|
9744
|
+
process.stdout.write("\x1B[?25h");
|
|
9745
|
+
if (finalMessage) {
|
|
9746
|
+
process.stdout.write(`\r${finalMessage}
|
|
9747
|
+
`);
|
|
9748
|
+
} else {
|
|
9749
|
+
process.stdout.write("\r" + " ".repeat(60) + "\r");
|
|
9750
|
+
}
|
|
9751
|
+
}
|
|
9752
|
+
};
|
|
9490
9753
|
async function handleNaturalLanguage(input, ctx) {
|
|
9491
9754
|
const trimmedInput = input.trim();
|
|
9492
9755
|
const session = getActiveSession();
|
|
@@ -9506,6 +9769,8 @@ async function handleNaturalLanguage(input, ctx) {
|
|
|
9506
9769
|
contextUsed: 0
|
|
9507
9770
|
};
|
|
9508
9771
|
}
|
|
9772
|
+
const loader = new LoadingIndicator3("AI \u601D\u8003\u4E2D");
|
|
9773
|
+
loader.start();
|
|
9509
9774
|
try {
|
|
9510
9775
|
const response = await ctx.modelService.sendMessage(
|
|
9511
9776
|
[
|
|
@@ -9523,6 +9788,7 @@ async function handleNaturalLanguage(input, ctx) {
|
|
|
9523
9788
|
maxTokens: 2e3
|
|
9524
9789
|
}
|
|
9525
9790
|
);
|
|
9791
|
+
loader.stop();
|
|
9526
9792
|
ctx.contextManager.addMessage({
|
|
9527
9793
|
role: "user",
|
|
9528
9794
|
content: trimmedInput
|
|
@@ -9536,6 +9802,7 @@ async function handleNaturalLanguage(input, ctx) {
|
|
|
9536
9802
|
contextUsed: response.usage?.totalTokens || 0
|
|
9537
9803
|
};
|
|
9538
9804
|
} catch (error) {
|
|
9805
|
+
loader.stop();
|
|
9539
9806
|
const errorMessage = error.message;
|
|
9540
9807
|
if (errorMessage.includes("\u672A\u914D\u7F6E") || errorMessage.includes("\u672A\u521D\u59CB\u5316")) {
|
|
9541
9808
|
return {
|