@nick848/sf-cli 1.0.11 → 1.0.13
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/CHANGELOG.md +61 -0
- package/dist/cli/index.js +415 -56
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +388 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +388 -50
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -250,18 +250,67 @@ async function executeWorkflow(ctx) {
|
|
|
250
250
|
lines.push("");
|
|
251
251
|
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 7/8: \u5F00\u53D1\u5B9E\u73B0 \u2501\u2501\u2501"));
|
|
252
252
|
lines.push("");
|
|
253
|
-
lines.push(chalk9__default.default.yellow(" \u{
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
253
|
+
lines.push(chalk9__default.default.yellow(" \u{1F680} \u6B63\u5728\u8C03\u7528 AI \u751F\u6210\u4EE3\u7801..."));
|
|
254
|
+
try {
|
|
255
|
+
const developResult = await executeDevelopment(ctx, activeSession);
|
|
256
|
+
if (developResult.success) {
|
|
257
|
+
lines.push(chalk9__default.default.green(" \u2713 \u4EE3\u7801\u751F\u6210\u5B8C\u6210"));
|
|
258
|
+
for (const file of developResult.files) {
|
|
259
|
+
lines.push(chalk9__default.default.gray(` - ${file}`));
|
|
260
|
+
}
|
|
261
|
+
activeSession.implFiles = developResult.files;
|
|
262
|
+
activeSession.phase = "review";
|
|
263
|
+
} else {
|
|
264
|
+
lines.push(chalk9__default.default.red(` \u2717 \u4EE3\u7801\u751F\u6210\u5931\u8D25: ${developResult.error}`));
|
|
265
|
+
lines.push(chalk9__default.default.gray(" \u8BF7\u624B\u52A8\u5B9E\u73B0\u4EE3\u7801\u540E\u8F93\u5165 continue \u7EE7\u7EED"));
|
|
266
|
+
return { output: lines.join("\n") };
|
|
267
|
+
}
|
|
268
|
+
} catch (error) {
|
|
269
|
+
lines.push(chalk9__default.default.red(` \u2717 \u5F00\u53D1\u9636\u6BB5\u51FA\u9519: ${error.message}`));
|
|
270
|
+
lines.push(chalk9__default.default.gray(" \u8BF7\u624B\u52A8\u5B9E\u73B0\u4EE3\u7801\u540E\u8F93\u5165 continue \u7EE7\u7EED"));
|
|
271
|
+
return { output: lines.join("\n") };
|
|
272
|
+
}
|
|
257
273
|
}
|
|
258
274
|
if (activeSession.phase === "review") {
|
|
259
275
|
lines.push("");
|
|
260
276
|
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 8/8: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
|
|
261
277
|
lines.push("");
|
|
262
|
-
lines.push(chalk9__default.default.yellow(" \u{1F50D} \u4EE3\u7801\u5BA1\u6838
|
|
263
|
-
|
|
264
|
-
|
|
278
|
+
lines.push(chalk9__default.default.yellow(" \u{1F50D} \u6B63\u5728\u8FDB\u884C\u4EE3\u7801\u5BA1\u6838..."));
|
|
279
|
+
try {
|
|
280
|
+
const reviewResult = await executeReview(ctx, activeSession);
|
|
281
|
+
if (reviewResult.passed) {
|
|
282
|
+
lines.push(chalk9__default.default.green(" \u2713 \u4EE3\u7801\u5BA1\u6838\u901A\u8FC7"));
|
|
283
|
+
if (reviewResult.suggestions.length > 0) {
|
|
284
|
+
lines.push(chalk9__default.default.gray(" \u5EFA\u8BAE:"));
|
|
285
|
+
for (const s of reviewResult.suggestions.slice(0, 3)) {
|
|
286
|
+
lines.push(chalk9__default.default.gray(` - ${s}`));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
await archiveWorkflow(ctx.options.workingDirectory);
|
|
290
|
+
const summary = activeSession.refinedRequirement;
|
|
291
|
+
activeSession = null;
|
|
292
|
+
lines.push("");
|
|
293
|
+
lines.push(chalk9__default.default.green.bold("\u{1F389} \u5DE5\u4F5C\u6D41\u5DF2\u5B8C\u6210\uFF01"));
|
|
294
|
+
lines.push(chalk9__default.default.gray(`\u9700\u6C42: ${summary.slice(0, 60)}${summary.length > 60 ? "..." : ""}`));
|
|
295
|
+
lines.push("");
|
|
296
|
+
lines.push(chalk9__default.default.cyan("\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41"));
|
|
297
|
+
return { output: lines.join("\n") };
|
|
298
|
+
} else {
|
|
299
|
+
lines.push(chalk9__default.default.red(" \u2717 \u4EE3\u7801\u5BA1\u6838\u672A\u901A\u8FC7"));
|
|
300
|
+
lines.push(chalk9__default.default.gray(" \u95EE\u9898:"));
|
|
301
|
+
for (const issue of reviewResult.issues.slice(0, 5)) {
|
|
302
|
+
lines.push(chalk9__default.default.red(` - ${issue}`));
|
|
303
|
+
}
|
|
304
|
+
lines.push("");
|
|
305
|
+
lines.push(chalk9__default.default.yellow(" \u8BF7\u4FEE\u590D\u95EE\u9898\u540E\u8F93\u5165 y \u91CD\u65B0\u5BA1\u6838"));
|
|
306
|
+
lines.push(chalk9__default.default.gray(" \u6216\u8F93\u5165 n \u56DE\u9000\u5230\u89C4\u683C\u9636\u6BB5"));
|
|
307
|
+
return { output: lines.join("\n") };
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
lines.push(chalk9__default.default.red(` \u2717 \u5BA1\u6838\u9636\u6BB5\u51FA\u9519: ${error.message}`));
|
|
311
|
+
lines.push(chalk9__default.default.gray(" \u8F93\u5165 pass \u5F3A\u5236\u901A\u8FC7\uFF0C\u6216 fix \u4FEE\u590D\u95EE\u9898"));
|
|
312
|
+
return { output: lines.join("\n") };
|
|
313
|
+
}
|
|
265
314
|
}
|
|
266
315
|
return { output: lines.join("\n") };
|
|
267
316
|
} catch (error) {
|
|
@@ -344,19 +393,25 @@ async function handleWorkflowInput(input, ctx) {
|
|
|
344
393
|
}
|
|
345
394
|
}
|
|
346
395
|
if (activeSession.phase === "review") {
|
|
347
|
-
if (trimmed === "
|
|
396
|
+
if (trimmed === "pass" || trimmed === "\u901A\u8FC7" || trimmed === "\u5F3A\u5236\u901A\u8FC7") {
|
|
348
397
|
await archiveWorkflow(ctx.options.workingDirectory);
|
|
349
398
|
const summary = activeSession.refinedRequirement;
|
|
350
399
|
activeSession = null;
|
|
351
400
|
return {
|
|
352
401
|
output: chalk9__default.default.green("\u2713 \u5DE5\u4F5C\u6D41\u5DF2\u5B8C\u6210") + chalk9__default.default.gray(`
|
|
353
|
-
\u9700\u6C42: ${summary.slice(0, 60)}
|
|
402
|
+
\u9700\u6C42: ${summary.slice(0, 60)}${summary.length > 60 ? "..." : ""}`) + chalk9__default.default.cyan("\n\n\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41")
|
|
354
403
|
};
|
|
355
404
|
}
|
|
356
|
-
if (trimmed === "
|
|
405
|
+
if (trimmed === "y" || trimmed === "yes" || trimmed === "\u91CD\u65B0\u5BA1\u6838" || trimmed === "retry") {
|
|
406
|
+
return executeWorkflow(ctx);
|
|
407
|
+
}
|
|
408
|
+
if (trimmed === "n" || trimmed === "no" || trimmed === "\u56DE\u9000" || trimmed === "rollback") {
|
|
357
409
|
activeSession.phase = "spec";
|
|
410
|
+
return executeWorkflow(ctx);
|
|
411
|
+
}
|
|
412
|
+
if (trimmed === "fix" || trimmed === "\u4FEE\u590D") {
|
|
358
413
|
return {
|
|
359
|
-
output: chalk9__default.default.yellow("\
|
|
414
|
+
output: chalk9__default.default.yellow("\u{1F4DD} \u8BF7\u624B\u52A8\u4FEE\u590D\u4EE3\u7801\u95EE\u9898") + chalk9__default.default.gray("\n\u4FEE\u590D\u5B8C\u6210\u540E\u8F93\u5165 y \u91CD\u65B0\u5BA1\u6838") + chalk9__default.default.gray("\n\u6216\u8F93\u5165 n \u56DE\u9000\u5230\u89C4\u683C\u9636\u6BB5")
|
|
360
415
|
};
|
|
361
416
|
}
|
|
362
417
|
}
|
|
@@ -478,6 +533,207 @@ function getCategoryLabel(category) {
|
|
|
478
533
|
};
|
|
479
534
|
return labels[category] || category;
|
|
480
535
|
}
|
|
536
|
+
async function executeDevelopment(ctx, session) {
|
|
537
|
+
const workingDir = ctx.options.workingDirectory;
|
|
538
|
+
const files = [];
|
|
539
|
+
try {
|
|
540
|
+
const systemPrompt = buildDevelopmentPrompt(session);
|
|
541
|
+
const messages = [
|
|
542
|
+
{
|
|
543
|
+
role: "system",
|
|
544
|
+
content: `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u524D\u7AEF\u5F00\u53D1\u5DE5\u7A0B\u5E08\u3002\u8BF7\u6839\u636E\u9700\u6C42\u89C4\u683C\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002
|
|
545
|
+
|
|
546
|
+
\u8981\u6C42\uFF1A
|
|
547
|
+
1. \u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801
|
|
548
|
+
2. \u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u4EE3\u7801\u98CE\u683C\u548C\u89C4\u8303
|
|
549
|
+
3. \u4F7F\u7528\u9879\u76EE\u6307\u5B9A\u7684\u6280\u672F\u6808
|
|
550
|
+
4. \u4EE3\u7801\u8981\u6709\u9002\u5F53\u7684\u6CE8\u91CA
|
|
551
|
+
5. \u8FD4\u56DE\u683C\u5F0F\uFF1A\u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u4EE3\u7801 \`\`\` \u5305\u88F9
|
|
552
|
+
|
|
553
|
+
\u9879\u76EE\u4FE1\u606F\uFF1A
|
|
554
|
+
- \u540D\u79F0: ${session.context?.name}
|
|
555
|
+
- \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
|
|
556
|
+
- \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
|
|
557
|
+
|
|
558
|
+
${session.context?.devStandards ? `\u5F00\u53D1\u89C4\u8303\uFF1A
|
|
559
|
+
${session.context.devStandards.slice(0, 2e3)}` : ""}`
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
role: "user",
|
|
563
|
+
content: systemPrompt
|
|
564
|
+
}
|
|
565
|
+
];
|
|
566
|
+
const response = await ctx.modelService.sendMessage(messages, {
|
|
567
|
+
temperature: 0.3,
|
|
568
|
+
maxTokens: 8e3,
|
|
569
|
+
agent: "frontend-dev"
|
|
570
|
+
});
|
|
571
|
+
const codeBlocks = parseCodeBlocks(response.content);
|
|
572
|
+
for (const block of codeBlocks) {
|
|
573
|
+
const filePath = path4__namespace.join(workingDir, block.filename);
|
|
574
|
+
const dir = path4__namespace.dirname(filePath);
|
|
575
|
+
await fs4__namespace.mkdir(dir, { recursive: true });
|
|
576
|
+
await fs4__namespace.writeFile(filePath, block.code, "utf-8");
|
|
577
|
+
files.push(block.filename);
|
|
578
|
+
}
|
|
579
|
+
if (files.length === 0) {
|
|
580
|
+
const implDir = path4__namespace.join(workingDir, "src", "features");
|
|
581
|
+
await fs4__namespace.mkdir(implDir, { recursive: true });
|
|
582
|
+
const featureName = session.specItems[0]?.title || "feature";
|
|
583
|
+
const fileName = `${featureName.replace(/[^a-zA-Z0-9]/g, "_")}.ts`;
|
|
584
|
+
const filePath = path4__namespace.join(implDir, fileName);
|
|
585
|
+
const stubCode = `/**
|
|
586
|
+
* ${session.requirement}
|
|
587
|
+
*
|
|
588
|
+
* TODO: \u6B64\u6587\u4EF6\u7531 AI \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u6839\u636E\u9700\u6C42\u5B8C\u5584\u5B9E\u73B0
|
|
589
|
+
*/
|
|
590
|
+
|
|
591
|
+
export function ${featureName.replace(/[^a-zA-Z0-9]/g, "")}() {
|
|
592
|
+
// TODO: \u5B9E\u73B0\u529F\u80FD
|
|
593
|
+
console.log('${featureName} - \u5F85\u5B9E\u73B0');
|
|
594
|
+
}
|
|
595
|
+
`;
|
|
596
|
+
await fs4__namespace.writeFile(filePath, stubCode, "utf-8");
|
|
597
|
+
files.push(`src/features/${fileName}`);
|
|
598
|
+
}
|
|
599
|
+
return { success: true, files };
|
|
600
|
+
} catch (error) {
|
|
601
|
+
return {
|
|
602
|
+
success: false,
|
|
603
|
+
files: [],
|
|
604
|
+
error: error.message
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
function buildDevelopmentPrompt(session) {
|
|
609
|
+
const lines = [];
|
|
610
|
+
lines.push("## \u9700\u6C42\u63CF\u8FF0");
|
|
611
|
+
lines.push(session.refinedRequirement);
|
|
612
|
+
lines.push("");
|
|
613
|
+
lines.push("## BDD \u573A\u666F");
|
|
614
|
+
for (const scenario of session.bddScenarios) {
|
|
615
|
+
lines.push(`### ${scenario.feature}`);
|
|
616
|
+
for (const s of scenario.scenarios) {
|
|
617
|
+
lines.push(`- ${s.name}`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
lines.push("");
|
|
621
|
+
lines.push("## \u4EFB\u52A1\u5217\u8868");
|
|
622
|
+
for (const item of session.specItems) {
|
|
623
|
+
lines.push(`- [${item.id}] ${item.title}: ${item.description}`);
|
|
624
|
+
}
|
|
625
|
+
lines.push("");
|
|
626
|
+
lines.push("\u8BF7\u6839\u636E\u4EE5\u4E0A\u9700\u6C42\u89C4\u683C\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002");
|
|
627
|
+
return lines.join("\n");
|
|
628
|
+
}
|
|
629
|
+
function parseCodeBlocks(content) {
|
|
630
|
+
const blocks = [];
|
|
631
|
+
const regex = /```(\S+)\n([\s\S]*?)```/g;
|
|
632
|
+
let match;
|
|
633
|
+
while ((match = regex.exec(content)) !== null) {
|
|
634
|
+
const filename = match[1];
|
|
635
|
+
const code = match[2].trim();
|
|
636
|
+
if (["text", "json", "markdown", "md"].includes(filename.toLowerCase())) {
|
|
637
|
+
continue;
|
|
638
|
+
}
|
|
639
|
+
blocks.push({ filename, code });
|
|
640
|
+
}
|
|
641
|
+
return blocks;
|
|
642
|
+
}
|
|
643
|
+
async function executeReview(ctx, session) {
|
|
644
|
+
const workingDir = ctx.options.workingDirectory;
|
|
645
|
+
const issues = [];
|
|
646
|
+
const suggestions = [];
|
|
647
|
+
try {
|
|
648
|
+
const codeContents = [];
|
|
649
|
+
for (const file of session.implFiles) {
|
|
650
|
+
try {
|
|
651
|
+
const content = await fs4__namespace.readFile(path4__namespace.join(workingDir, file), "utf-8");
|
|
652
|
+
codeContents.push(`// ${file}
|
|
653
|
+
${content}`);
|
|
654
|
+
} catch {
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
const testContents = [];
|
|
658
|
+
for (const file of session.testFiles) {
|
|
659
|
+
try {
|
|
660
|
+
const content = await fs4__namespace.readFile(path4__namespace.join(workingDir, file), "utf-8");
|
|
661
|
+
testContents.push(`// ${file}
|
|
662
|
+
${content}`);
|
|
663
|
+
} catch {
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
const messages = [
|
|
667
|
+
{
|
|
668
|
+
role: "system",
|
|
669
|
+
content: `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u4EE3\u7801\u5BA1\u6838\u4E13\u5BB6\u3002\u8BF7\u5BA1\u6838\u4EE5\u4E0B\u4EE3\u7801\u5B9E\u73B0\u662F\u5426\u7B26\u5408\u9700\u6C42\u89C4\u683C\u3002
|
|
670
|
+
|
|
671
|
+
\u5BA1\u6838\u6807\u51C6\uFF1A
|
|
672
|
+
1. \u4EE3\u7801\u662F\u5426\u6B63\u786E\u5B9E\u73B0\u4E86\u9700\u6C42\u89C4\u683C\u4E2D\u7684\u529F\u80FD
|
|
673
|
+
2. \u4EE3\u7801\u8D28\u91CF\uFF08\u53EF\u8BFB\u6027\u3001\u53EF\u7EF4\u62A4\u6027\uFF09
|
|
674
|
+
3. \u6F5C\u5728\u7684 bug \u548C\u8FB9\u754C\u60C5\u51B5\u5904\u7406
|
|
675
|
+
4. \u4EE3\u7801\u98CE\u683C\u662F\u5426\u7B26\u5408\u9879\u76EE\u89C4\u8303
|
|
676
|
+
5. \u6D4B\u8BD5\u8986\u76D6\u662F\u5426\u5145\u5206
|
|
677
|
+
|
|
678
|
+
\u8FD4\u56DE\u683C\u5F0F\uFF1A
|
|
679
|
+
- \u5982\u679C\u901A\u8FC7\u5BA1\u6838\uFF0C\u8FD4\u56DE "\u5BA1\u6838\u901A\u8FC7" \u5E76\u5217\u51FA\u6539\u8FDB\u5EFA\u8BAE
|
|
680
|
+
- \u5982\u679C\u4E0D\u901A\u8FC7\uFF0C\u5217\u51FA\u5177\u4F53\u95EE\u9898
|
|
681
|
+
|
|
682
|
+
\u9879\u76EE\u4FE1\u606F\uFF1A
|
|
683
|
+
- \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
|
|
684
|
+
- \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
|
|
685
|
+
|
|
686
|
+
${session.context?.devStandards ? `\u5F00\u53D1\u89C4\u8303\uFF1A
|
|
687
|
+
${session.context.devStandards.slice(0, 1e3)}` : ""}`
|
|
688
|
+
},
|
|
689
|
+
{
|
|
690
|
+
role: "user",
|
|
691
|
+
content: `## \u9700\u6C42\u89C4\u683C
|
|
692
|
+
${session.refinedRequirement}
|
|
693
|
+
|
|
694
|
+
## \u4EFB\u52A1\u5217\u8868
|
|
695
|
+
${session.specItems.map((item) => `- [${item.id}] ${item.title}`).join("\n")}
|
|
696
|
+
|
|
697
|
+
## \u5B9E\u73B0\u4EE3\u7801
|
|
698
|
+
${codeContents.join("\n\n") || "\uFF08\u65E0\u4EE3\u7801\u6587\u4EF6\uFF09"}
|
|
699
|
+
|
|
700
|
+
## \u6D4B\u8BD5\u4EE3\u7801
|
|
701
|
+
${testContents.join("\n\n") || "\uFF08\u65E0\u6D4B\u8BD5\u6587\u4EF6\uFF09"}
|
|
702
|
+
|
|
703
|
+
\u8BF7\u5BA1\u6838\u4EE5\u4E0A\u4EE3\u7801\u5B9E\u73B0\u3002`
|
|
704
|
+
}
|
|
705
|
+
];
|
|
706
|
+
const response = await ctx.modelService.sendMessage(messages, {
|
|
707
|
+
temperature: 0.2,
|
|
708
|
+
maxTokens: 2e3,
|
|
709
|
+
agent: "code-reviewer"
|
|
710
|
+
});
|
|
711
|
+
const result = response.content;
|
|
712
|
+
const passed = result.includes("\u5BA1\u6838\u901A\u8FC7") || result.includes("\u901A\u8FC7") || !result.includes("\u4E0D\u901A\u8FC7");
|
|
713
|
+
const issueMatches = result.match(/问题[::]\s*([\s\S]*?)(?=建议|$)/i);
|
|
714
|
+
if (issueMatches) {
|
|
715
|
+
const issueList = issueMatches[1].split(/[\n-]/).filter((s) => s.trim());
|
|
716
|
+
issues.push(...issueList.map((s) => s.trim()).filter((s) => s));
|
|
717
|
+
}
|
|
718
|
+
const suggestionMatches = result.match(/建议[::]\s*([\s\S]*?)$/i);
|
|
719
|
+
if (suggestionMatches) {
|
|
720
|
+
const suggestionList = suggestionMatches[1].split(/[\n-]/).filter((s) => s.trim());
|
|
721
|
+
suggestions.push(...suggestionList.map((s) => s.trim()).filter((s) => s));
|
|
722
|
+
}
|
|
723
|
+
if (issues.length === 0 && !passed) {
|
|
724
|
+
const lines = result.split("\n").filter((l) => l.includes("\u95EE\u9898") || l.includes("\u9519\u8BEF") || l.includes("\u7F3A\u9677"));
|
|
725
|
+
issues.push(...lines.map((l) => l.replace(/^[-*]\s*/, "").trim()).filter((l) => l));
|
|
726
|
+
}
|
|
727
|
+
if (suggestions.length === 0) {
|
|
728
|
+
const lines = result.split("\n").filter((l) => l.includes("\u5EFA\u8BAE") || l.includes("\u6539\u8FDB") || l.includes("\u4F18\u5316"));
|
|
729
|
+
suggestions.push(...lines.map((l) => l.replace(/^[-*]\s*/, "").trim()).filter((l) => l));
|
|
730
|
+
}
|
|
731
|
+
return { passed, issues, suggestions };
|
|
732
|
+
} catch (error) {
|
|
733
|
+
suggestions.push(`\u5BA1\u6838\u8FC7\u7A0B\u51FA\u9519: ${error.message}`);
|
|
734
|
+
return { passed: true, issues, suggestions };
|
|
735
|
+
}
|
|
736
|
+
}
|
|
481
737
|
async function readProjectContext(workingDir) {
|
|
482
738
|
const context = {
|
|
483
739
|
name: path4__namespace.basename(workingDir),
|
|
@@ -8629,7 +8885,7 @@ async function executeShell(command, ctx) {
|
|
|
8629
8885
|
init_cjs_shims();
|
|
8630
8886
|
init_new();
|
|
8631
8887
|
async function handleNaturalLanguage(input, ctx) {
|
|
8632
|
-
input.trim()
|
|
8888
|
+
const trimmedInput = input.trim();
|
|
8633
8889
|
const session = getActiveSession();
|
|
8634
8890
|
if (session) {
|
|
8635
8891
|
const result = await handleWorkflowInput(input, ctx);
|
|
@@ -8640,81 +8896,163 @@ async function handleNaturalLanguage(input, ctx) {
|
|
|
8640
8896
|
};
|
|
8641
8897
|
}
|
|
8642
8898
|
}
|
|
8643
|
-
ctx.
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8899
|
+
const apiKey = ctx.configManager.get("apiKey");
|
|
8900
|
+
if (!apiKey) {
|
|
8901
|
+
return {
|
|
8902
|
+
output: chalk9__default.default.yellow("\u26A0\uFE0F \u672A\u914D\u7F6E API Key\uFF0C\u65E0\u6CD5\u4F7F\u7528 AI \u529F\u80FD") + chalk9__default.default.gray("\n\n\u8BF7\u5148\u6267\u884C /model \u914D\u7F6E\u6A21\u578B") + chalk9__default.default.gray("\n\u652F\u6301: GLM-5, GPT-4o, Claude"),
|
|
8903
|
+
contextUsed: 0
|
|
8904
|
+
};
|
|
8905
|
+
}
|
|
8906
|
+
try {
|
|
8907
|
+
const response = await ctx.modelService.sendMessage(
|
|
8908
|
+
[
|
|
8909
|
+
{
|
|
8910
|
+
role: "system",
|
|
8911
|
+
content: buildSystemPrompt(ctx)
|
|
8912
|
+
},
|
|
8913
|
+
{
|
|
8914
|
+
role: "user",
|
|
8915
|
+
content: trimmedInput
|
|
8916
|
+
}
|
|
8917
|
+
],
|
|
8918
|
+
{
|
|
8919
|
+
temperature: 0.7,
|
|
8920
|
+
maxTokens: 2e3
|
|
8921
|
+
}
|
|
8922
|
+
);
|
|
8923
|
+
ctx.contextManager.addMessage({
|
|
8924
|
+
role: "user",
|
|
8925
|
+
content: trimmedInput
|
|
8926
|
+
});
|
|
8927
|
+
ctx.contextManager.addMessage({
|
|
8928
|
+
role: "assistant",
|
|
8929
|
+
content: response.content
|
|
8930
|
+
});
|
|
8931
|
+
return {
|
|
8932
|
+
output: response.content,
|
|
8933
|
+
contextUsed: response.usage?.totalTokens || 0
|
|
8934
|
+
};
|
|
8935
|
+
} catch (error) {
|
|
8936
|
+
const errorMessage = error.message;
|
|
8937
|
+
if (errorMessage.includes("\u672A\u914D\u7F6E") || errorMessage.includes("\u672A\u521D\u59CB\u5316")) {
|
|
8938
|
+
return {
|
|
8939
|
+
output: chalk9__default.default.yellow("\u26A0\uFE0F \u6A21\u578B\u672A\u6B63\u786E\u914D\u7F6E") + chalk9__default.default.gray("\n\n\u8BF7\u6267\u884C /model \u91CD\u65B0\u914D\u7F6E"),
|
|
8940
|
+
contextUsed: 0
|
|
8941
|
+
};
|
|
8942
|
+
}
|
|
8943
|
+
if (errorMessage.includes("timeout") || errorMessage.includes("\u8D85\u65F6")) {
|
|
8944
|
+
return {
|
|
8945
|
+
output: chalk9__default.default.red("\u2717 \u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"),
|
|
8946
|
+
contextUsed: 0
|
|
8947
|
+
};
|
|
8948
|
+
}
|
|
8949
|
+
return {
|
|
8950
|
+
output: chalk9__default.default.red(`\u2717 \u5904\u7406\u5931\u8D25: ${errorMessage}`),
|
|
8951
|
+
contextUsed: 0
|
|
8952
|
+
};
|
|
8953
|
+
}
|
|
8954
|
+
}
|
|
8955
|
+
function buildSystemPrompt(ctx) {
|
|
8956
|
+
const parts = [
|
|
8957
|
+
"\u4F60\u662F sf-cli \u7684 AI \u52A9\u624B\uFF0C\u4E00\u4E2A\u4E13\u4E1A\u7684\u8F6F\u4EF6\u5F00\u53D1\u52A9\u624B\u3002",
|
|
8958
|
+
"",
|
|
8959
|
+
"\u4F60\u53EF\u4EE5\u5E2E\u52A9\u7528\u6237\uFF1A",
|
|
8960
|
+
"1. \u7406\u89E3\u548C\u5206\u6790\u9700\u6C42",
|
|
8961
|
+
"2. \u63D0\u4F9B\u4EE3\u7801\u5EFA\u8BAE\u548C\u5B9E\u73B0\u65B9\u6848",
|
|
8962
|
+
"3. \u56DE\u7B54\u6280\u672F\u95EE\u9898",
|
|
8963
|
+
"4. \u8F85\u52A9\u8FDB\u884C\u4EE3\u7801\u5BA1\u67E5",
|
|
8964
|
+
"",
|
|
8965
|
+
"\u5F53\u524D\u9879\u76EE\u4FE1\u606F\uFF1A",
|
|
8966
|
+
`- \u5DE5\u4F5C\u76EE\u5F55: ${ctx.options.workingDirectory}`,
|
|
8967
|
+
`- \u6A21\u578B: ${ctx.modelService.getCurrentModel() || "\u672A\u6307\u5B9A"}`
|
|
8968
|
+
];
|
|
8969
|
+
return parts.join("\n");
|
|
8652
8970
|
}
|
|
8653
8971
|
|
|
8654
8972
|
// src/cli/executor.ts
|
|
8655
8973
|
init_new();
|
|
8656
|
-
var
|
|
8974
|
+
var ALWAYS_ALLOWED = [
|
|
8657
8975
|
"help",
|
|
8658
8976
|
"h",
|
|
8659
8977
|
"?",
|
|
8660
|
-
"init",
|
|
8661
|
-
"i",
|
|
8662
8978
|
"model",
|
|
8663
8979
|
"m",
|
|
8664
|
-
"new",
|
|
8665
|
-
"n",
|
|
8666
8980
|
"exit",
|
|
8667
8981
|
"e",
|
|
8668
8982
|
"q",
|
|
8669
8983
|
"quit",
|
|
8670
8984
|
"clear",
|
|
8671
8985
|
"c",
|
|
8672
|
-
"update",
|
|
8673
|
-
"u",
|
|
8674
8986
|
"version",
|
|
8675
8987
|
"v"
|
|
8676
8988
|
];
|
|
8989
|
+
var REQUIRES_API_KEY = [
|
|
8990
|
+
"new",
|
|
8991
|
+
"n",
|
|
8992
|
+
"init",
|
|
8993
|
+
"i",
|
|
8994
|
+
"update",
|
|
8995
|
+
"u"
|
|
8996
|
+
];
|
|
8677
8997
|
var CommandExecutor = class {
|
|
8678
8998
|
async execute(parseResult, ctx) {
|
|
8679
8999
|
if (!parseResult.success || !parseResult.command) {
|
|
8680
9000
|
return { output: chalk9__default.default.red(`\u9519\u8BEF: ${parseResult.error}`) };
|
|
8681
9001
|
}
|
|
8682
9002
|
const { command } = parseResult;
|
|
9003
|
+
const hasApiKey = !!ctx.configManager.get("apiKey");
|
|
8683
9004
|
const hasActiveWorkflow = getActiveSession() !== null;
|
|
8684
|
-
if (
|
|
8685
|
-
|
|
8686
|
-
|
|
8687
|
-
|
|
9005
|
+
if (command.type === "slash" /* SLASH */) {
|
|
9006
|
+
const cmd = command.command?.toLowerCase() || "";
|
|
9007
|
+
if (ALWAYS_ALLOWED.includes(cmd)) {
|
|
9008
|
+
return this.executeSlashCommand(command, ctx);
|
|
9009
|
+
}
|
|
9010
|
+
if (REQUIRES_API_KEY.includes(cmd)) {
|
|
9011
|
+
if (!hasApiKey) {
|
|
8688
9012
|
return {
|
|
8689
|
-
output: chalk9__default.default.yellow("\
|
|
9013
|
+
output: chalk9__default.default.yellow("\u26A0\uFE0F \u8BF7\u5148\u914D\u7F6E API Key") + chalk9__default.default.gray("\n\n\u6267\u884C /model \u9009\u62E9\u6A21\u578B\u5E76\u914D\u7F6E API Key")
|
|
8690
9014
|
};
|
|
8691
9015
|
}
|
|
8692
|
-
|
|
9016
|
+
return this.executeSlashCommand(command, ctx);
|
|
9017
|
+
}
|
|
9018
|
+
if (!hasActiveWorkflow) {
|
|
9019
|
+
return {
|
|
9020
|
+
output: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
|
|
9021
|
+
};
|
|
9022
|
+
}
|
|
9023
|
+
return this.executeSlashCommand(command, ctx);
|
|
9024
|
+
}
|
|
9025
|
+
if (command.type === "dollar" /* DOLLAR */) {
|
|
9026
|
+
if (!hasActiveWorkflow) {
|
|
8693
9027
|
return {
|
|
8694
9028
|
output: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u8C03\u7528 Agent") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
|
|
8695
9029
|
};
|
|
8696
|
-
}
|
|
9030
|
+
}
|
|
9031
|
+
if (!hasApiKey) {
|
|
9032
|
+
return {
|
|
9033
|
+
output: chalk9__default.default.yellow("\u26A0\uFE0F \u8BF7\u5148\u914D\u7F6E API Key") + chalk9__default.default.gray("\n\n\u6267\u884C /model \u914D\u7F6E\u6A21\u578B")
|
|
9034
|
+
};
|
|
9035
|
+
}
|
|
9036
|
+
return this.executeAgent(command, ctx);
|
|
9037
|
+
}
|
|
9038
|
+
if (command.type === "shell" /* SHELL */) {
|
|
9039
|
+
if (!hasActiveWorkflow) {
|
|
8697
9040
|
return {
|
|
8698
9041
|
output: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u6267\u884C Shell \u547D\u4EE4") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
|
|
8699
9042
|
};
|
|
8700
9043
|
}
|
|
9044
|
+
return this.executeShell(command, ctx);
|
|
8701
9045
|
}
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
return this.executeShell(command, ctx);
|
|
8711
|
-
case "natural" /* NATURAL */:
|
|
8712
|
-
return this.executeNaturalLanguage(command, ctx);
|
|
8713
|
-
case "yolo" /* YOLO */:
|
|
8714
|
-
return this.executeYolo(ctx);
|
|
8715
|
-
default:
|
|
8716
|
-
return { output: chalk9__default.default.red("\u672A\u77E5\u7684\u547D\u4EE4\u7C7B\u578B") };
|
|
9046
|
+
if (command.type === "at" /* AT */) {
|
|
9047
|
+
return this.executeFileReference(command, ctx);
|
|
9048
|
+
}
|
|
9049
|
+
if (command.type === "natural" /* NATURAL */) {
|
|
9050
|
+
return this.executeNaturalLanguage(command, ctx);
|
|
9051
|
+
}
|
|
9052
|
+
if (command.type === "yolo" /* YOLO */) {
|
|
9053
|
+
return this.executeYolo(ctx);
|
|
8717
9054
|
}
|
|
9055
|
+
return { output: chalk9__default.default.red("\u672A\u77E5\u7684\u547D\u4EE4\u7C7B\u578B") };
|
|
8718
9056
|
}
|
|
8719
9057
|
async executeSlashCommand(command, ctx) {
|
|
8720
9058
|
const result = await runSlashCommand(
|