@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.mjs
CHANGED
|
@@ -225,18 +225,67 @@ async function executeWorkflow(ctx) {
|
|
|
225
225
|
lines.push("");
|
|
226
226
|
lines.push(chalk9.cyan("\u2501\u2501\u2501 \u9636\u6BB5 7/8: \u5F00\u53D1\u5B9E\u73B0 \u2501\u2501\u2501"));
|
|
227
227
|
lines.push("");
|
|
228
|
-
lines.push(chalk9.yellow(" \u{
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
lines.push(chalk9.yellow(" \u{1F680} \u6B63\u5728\u8C03\u7528 AI \u751F\u6210\u4EE3\u7801..."));
|
|
229
|
+
try {
|
|
230
|
+
const developResult = await executeDevelopment(ctx, activeSession);
|
|
231
|
+
if (developResult.success) {
|
|
232
|
+
lines.push(chalk9.green(" \u2713 \u4EE3\u7801\u751F\u6210\u5B8C\u6210"));
|
|
233
|
+
for (const file of developResult.files) {
|
|
234
|
+
lines.push(chalk9.gray(` - ${file}`));
|
|
235
|
+
}
|
|
236
|
+
activeSession.implFiles = developResult.files;
|
|
237
|
+
activeSession.phase = "review";
|
|
238
|
+
} else {
|
|
239
|
+
lines.push(chalk9.red(` \u2717 \u4EE3\u7801\u751F\u6210\u5931\u8D25: ${developResult.error}`));
|
|
240
|
+
lines.push(chalk9.gray(" \u8BF7\u624B\u52A8\u5B9E\u73B0\u4EE3\u7801\u540E\u8F93\u5165 continue \u7EE7\u7EED"));
|
|
241
|
+
return { output: lines.join("\n") };
|
|
242
|
+
}
|
|
243
|
+
} catch (error) {
|
|
244
|
+
lines.push(chalk9.red(` \u2717 \u5F00\u53D1\u9636\u6BB5\u51FA\u9519: ${error.message}`));
|
|
245
|
+
lines.push(chalk9.gray(" \u8BF7\u624B\u52A8\u5B9E\u73B0\u4EE3\u7801\u540E\u8F93\u5165 continue \u7EE7\u7EED"));
|
|
246
|
+
return { output: lines.join("\n") };
|
|
247
|
+
}
|
|
232
248
|
}
|
|
233
249
|
if (activeSession.phase === "review") {
|
|
234
250
|
lines.push("");
|
|
235
251
|
lines.push(chalk9.cyan("\u2501\u2501\u2501 \u9636\u6BB5 8/8: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
|
|
236
252
|
lines.push("");
|
|
237
|
-
lines.push(chalk9.yellow(" \u{1F50D} \u4EE3\u7801\u5BA1\u6838
|
|
238
|
-
|
|
239
|
-
|
|
253
|
+
lines.push(chalk9.yellow(" \u{1F50D} \u6B63\u5728\u8FDB\u884C\u4EE3\u7801\u5BA1\u6838..."));
|
|
254
|
+
try {
|
|
255
|
+
const reviewResult = await executeReview(ctx, activeSession);
|
|
256
|
+
if (reviewResult.passed) {
|
|
257
|
+
lines.push(chalk9.green(" \u2713 \u4EE3\u7801\u5BA1\u6838\u901A\u8FC7"));
|
|
258
|
+
if (reviewResult.suggestions.length > 0) {
|
|
259
|
+
lines.push(chalk9.gray(" \u5EFA\u8BAE:"));
|
|
260
|
+
for (const s of reviewResult.suggestions.slice(0, 3)) {
|
|
261
|
+
lines.push(chalk9.gray(` - ${s}`));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
await archiveWorkflow(ctx.options.workingDirectory);
|
|
265
|
+
const summary = activeSession.refinedRequirement;
|
|
266
|
+
activeSession = null;
|
|
267
|
+
lines.push("");
|
|
268
|
+
lines.push(chalk9.green.bold("\u{1F389} \u5DE5\u4F5C\u6D41\u5DF2\u5B8C\u6210\uFF01"));
|
|
269
|
+
lines.push(chalk9.gray(`\u9700\u6C42: ${summary.slice(0, 60)}${summary.length > 60 ? "..." : ""}`));
|
|
270
|
+
lines.push("");
|
|
271
|
+
lines.push(chalk9.cyan("\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41"));
|
|
272
|
+
return { output: lines.join("\n") };
|
|
273
|
+
} else {
|
|
274
|
+
lines.push(chalk9.red(" \u2717 \u4EE3\u7801\u5BA1\u6838\u672A\u901A\u8FC7"));
|
|
275
|
+
lines.push(chalk9.gray(" \u95EE\u9898:"));
|
|
276
|
+
for (const issue of reviewResult.issues.slice(0, 5)) {
|
|
277
|
+
lines.push(chalk9.red(` - ${issue}`));
|
|
278
|
+
}
|
|
279
|
+
lines.push("");
|
|
280
|
+
lines.push(chalk9.yellow(" \u8BF7\u4FEE\u590D\u95EE\u9898\u540E\u8F93\u5165 y \u91CD\u65B0\u5BA1\u6838"));
|
|
281
|
+
lines.push(chalk9.gray(" \u6216\u8F93\u5165 n \u56DE\u9000\u5230\u89C4\u683C\u9636\u6BB5"));
|
|
282
|
+
return { output: lines.join("\n") };
|
|
283
|
+
}
|
|
284
|
+
} catch (error) {
|
|
285
|
+
lines.push(chalk9.red(` \u2717 \u5BA1\u6838\u9636\u6BB5\u51FA\u9519: ${error.message}`));
|
|
286
|
+
lines.push(chalk9.gray(" \u8F93\u5165 pass \u5F3A\u5236\u901A\u8FC7\uFF0C\u6216 fix \u4FEE\u590D\u95EE\u9898"));
|
|
287
|
+
return { output: lines.join("\n") };
|
|
288
|
+
}
|
|
240
289
|
}
|
|
241
290
|
return { output: lines.join("\n") };
|
|
242
291
|
} catch (error) {
|
|
@@ -319,19 +368,25 @@ async function handleWorkflowInput(input, ctx) {
|
|
|
319
368
|
}
|
|
320
369
|
}
|
|
321
370
|
if (activeSession.phase === "review") {
|
|
322
|
-
if (trimmed === "
|
|
371
|
+
if (trimmed === "pass" || trimmed === "\u901A\u8FC7" || trimmed === "\u5F3A\u5236\u901A\u8FC7") {
|
|
323
372
|
await archiveWorkflow(ctx.options.workingDirectory);
|
|
324
373
|
const summary = activeSession.refinedRequirement;
|
|
325
374
|
activeSession = null;
|
|
326
375
|
return {
|
|
327
376
|
output: chalk9.green("\u2713 \u5DE5\u4F5C\u6D41\u5DF2\u5B8C\u6210") + chalk9.gray(`
|
|
328
|
-
\u9700\u6C42: ${summary.slice(0, 60)}
|
|
377
|
+
\u9700\u6C42: ${summary.slice(0, 60)}${summary.length > 60 ? "..." : ""}`) + chalk9.cyan("\n\n\u4F7F\u7528 /new <\u9700\u6C42> \u5F00\u59CB\u65B0\u7684\u5DE5\u4F5C\u6D41")
|
|
329
378
|
};
|
|
330
379
|
}
|
|
331
|
-
if (trimmed === "
|
|
380
|
+
if (trimmed === "y" || trimmed === "yes" || trimmed === "\u91CD\u65B0\u5BA1\u6838" || trimmed === "retry") {
|
|
381
|
+
return executeWorkflow(ctx);
|
|
382
|
+
}
|
|
383
|
+
if (trimmed === "n" || trimmed === "no" || trimmed === "\u56DE\u9000" || trimmed === "rollback") {
|
|
332
384
|
activeSession.phase = "spec";
|
|
385
|
+
return executeWorkflow(ctx);
|
|
386
|
+
}
|
|
387
|
+
if (trimmed === "fix" || trimmed === "\u4FEE\u590D") {
|
|
333
388
|
return {
|
|
334
|
-
output: chalk9.yellow("\
|
|
389
|
+
output: chalk9.yellow("\u{1F4DD} \u8BF7\u624B\u52A8\u4FEE\u590D\u4EE3\u7801\u95EE\u9898") + chalk9.gray("\n\u4FEE\u590D\u5B8C\u6210\u540E\u8F93\u5165 y \u91CD\u65B0\u5BA1\u6838") + chalk9.gray("\n\u6216\u8F93\u5165 n \u56DE\u9000\u5230\u89C4\u683C\u9636\u6BB5")
|
|
335
390
|
};
|
|
336
391
|
}
|
|
337
392
|
}
|
|
@@ -453,6 +508,207 @@ function getCategoryLabel(category) {
|
|
|
453
508
|
};
|
|
454
509
|
return labels[category] || category;
|
|
455
510
|
}
|
|
511
|
+
async function executeDevelopment(ctx, session) {
|
|
512
|
+
const workingDir = ctx.options.workingDirectory;
|
|
513
|
+
const files = [];
|
|
514
|
+
try {
|
|
515
|
+
const systemPrompt = buildDevelopmentPrompt(session);
|
|
516
|
+
const messages = [
|
|
517
|
+
{
|
|
518
|
+
role: "system",
|
|
519
|
+
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
|
|
520
|
+
|
|
521
|
+
\u8981\u6C42\uFF1A
|
|
522
|
+
1. \u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801
|
|
523
|
+
2. \u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u4EE3\u7801\u98CE\u683C\u548C\u89C4\u8303
|
|
524
|
+
3. \u4F7F\u7528\u9879\u76EE\u6307\u5B9A\u7684\u6280\u672F\u6808
|
|
525
|
+
4. \u4EE3\u7801\u8981\u6709\u9002\u5F53\u7684\u6CE8\u91CA
|
|
526
|
+
5. \u8FD4\u56DE\u683C\u5F0F\uFF1A\u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u4EE3\u7801 \`\`\` \u5305\u88F9
|
|
527
|
+
|
|
528
|
+
\u9879\u76EE\u4FE1\u606F\uFF1A
|
|
529
|
+
- \u540D\u79F0: ${session.context?.name}
|
|
530
|
+
- \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
|
|
531
|
+
- \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
|
|
532
|
+
|
|
533
|
+
${session.context?.devStandards ? `\u5F00\u53D1\u89C4\u8303\uFF1A
|
|
534
|
+
${session.context.devStandards.slice(0, 2e3)}` : ""}`
|
|
535
|
+
},
|
|
536
|
+
{
|
|
537
|
+
role: "user",
|
|
538
|
+
content: systemPrompt
|
|
539
|
+
}
|
|
540
|
+
];
|
|
541
|
+
const response = await ctx.modelService.sendMessage(messages, {
|
|
542
|
+
temperature: 0.3,
|
|
543
|
+
maxTokens: 8e3,
|
|
544
|
+
agent: "frontend-dev"
|
|
545
|
+
});
|
|
546
|
+
const codeBlocks = parseCodeBlocks(response.content);
|
|
547
|
+
for (const block of codeBlocks) {
|
|
548
|
+
const filePath = path5.join(workingDir, block.filename);
|
|
549
|
+
const dir = path5.dirname(filePath);
|
|
550
|
+
await fs4.mkdir(dir, { recursive: true });
|
|
551
|
+
await fs4.writeFile(filePath, block.code, "utf-8");
|
|
552
|
+
files.push(block.filename);
|
|
553
|
+
}
|
|
554
|
+
if (files.length === 0) {
|
|
555
|
+
const implDir = path5.join(workingDir, "src", "features");
|
|
556
|
+
await fs4.mkdir(implDir, { recursive: true });
|
|
557
|
+
const featureName = session.specItems[0]?.title || "feature";
|
|
558
|
+
const fileName = `${featureName.replace(/[^a-zA-Z0-9]/g, "_")}.ts`;
|
|
559
|
+
const filePath = path5.join(implDir, fileName);
|
|
560
|
+
const stubCode = `/**
|
|
561
|
+
* ${session.requirement}
|
|
562
|
+
*
|
|
563
|
+
* TODO: \u6B64\u6587\u4EF6\u7531 AI \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u6839\u636E\u9700\u6C42\u5B8C\u5584\u5B9E\u73B0
|
|
564
|
+
*/
|
|
565
|
+
|
|
566
|
+
export function ${featureName.replace(/[^a-zA-Z0-9]/g, "")}() {
|
|
567
|
+
// TODO: \u5B9E\u73B0\u529F\u80FD
|
|
568
|
+
console.log('${featureName} - \u5F85\u5B9E\u73B0');
|
|
569
|
+
}
|
|
570
|
+
`;
|
|
571
|
+
await fs4.writeFile(filePath, stubCode, "utf-8");
|
|
572
|
+
files.push(`src/features/${fileName}`);
|
|
573
|
+
}
|
|
574
|
+
return { success: true, files };
|
|
575
|
+
} catch (error) {
|
|
576
|
+
return {
|
|
577
|
+
success: false,
|
|
578
|
+
files: [],
|
|
579
|
+
error: error.message
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
function buildDevelopmentPrompt(session) {
|
|
584
|
+
const lines = [];
|
|
585
|
+
lines.push("## \u9700\u6C42\u63CF\u8FF0");
|
|
586
|
+
lines.push(session.refinedRequirement);
|
|
587
|
+
lines.push("");
|
|
588
|
+
lines.push("## BDD \u573A\u666F");
|
|
589
|
+
for (const scenario of session.bddScenarios) {
|
|
590
|
+
lines.push(`### ${scenario.feature}`);
|
|
591
|
+
for (const s of scenario.scenarios) {
|
|
592
|
+
lines.push(`- ${s.name}`);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
lines.push("");
|
|
596
|
+
lines.push("## \u4EFB\u52A1\u5217\u8868");
|
|
597
|
+
for (const item of session.specItems) {
|
|
598
|
+
lines.push(`- [${item.id}] ${item.title}: ${item.description}`);
|
|
599
|
+
}
|
|
600
|
+
lines.push("");
|
|
601
|
+
lines.push("\u8BF7\u6839\u636E\u4EE5\u4E0A\u9700\u6C42\u89C4\u683C\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002");
|
|
602
|
+
return lines.join("\n");
|
|
603
|
+
}
|
|
604
|
+
function parseCodeBlocks(content) {
|
|
605
|
+
const blocks = [];
|
|
606
|
+
const regex = /```(\S+)\n([\s\S]*?)```/g;
|
|
607
|
+
let match;
|
|
608
|
+
while ((match = regex.exec(content)) !== null) {
|
|
609
|
+
const filename = match[1];
|
|
610
|
+
const code = match[2].trim();
|
|
611
|
+
if (["text", "json", "markdown", "md"].includes(filename.toLowerCase())) {
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
blocks.push({ filename, code });
|
|
615
|
+
}
|
|
616
|
+
return blocks;
|
|
617
|
+
}
|
|
618
|
+
async function executeReview(ctx, session) {
|
|
619
|
+
const workingDir = ctx.options.workingDirectory;
|
|
620
|
+
const issues = [];
|
|
621
|
+
const suggestions = [];
|
|
622
|
+
try {
|
|
623
|
+
const codeContents = [];
|
|
624
|
+
for (const file of session.implFiles) {
|
|
625
|
+
try {
|
|
626
|
+
const content = await fs4.readFile(path5.join(workingDir, file), "utf-8");
|
|
627
|
+
codeContents.push(`// ${file}
|
|
628
|
+
${content}`);
|
|
629
|
+
} catch {
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
const testContents = [];
|
|
633
|
+
for (const file of session.testFiles) {
|
|
634
|
+
try {
|
|
635
|
+
const content = await fs4.readFile(path5.join(workingDir, file), "utf-8");
|
|
636
|
+
testContents.push(`// ${file}
|
|
637
|
+
${content}`);
|
|
638
|
+
} catch {
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
const messages = [
|
|
642
|
+
{
|
|
643
|
+
role: "system",
|
|
644
|
+
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
|
|
645
|
+
|
|
646
|
+
\u5BA1\u6838\u6807\u51C6\uFF1A
|
|
647
|
+
1. \u4EE3\u7801\u662F\u5426\u6B63\u786E\u5B9E\u73B0\u4E86\u9700\u6C42\u89C4\u683C\u4E2D\u7684\u529F\u80FD
|
|
648
|
+
2. \u4EE3\u7801\u8D28\u91CF\uFF08\u53EF\u8BFB\u6027\u3001\u53EF\u7EF4\u62A4\u6027\uFF09
|
|
649
|
+
3. \u6F5C\u5728\u7684 bug \u548C\u8FB9\u754C\u60C5\u51B5\u5904\u7406
|
|
650
|
+
4. \u4EE3\u7801\u98CE\u683C\u662F\u5426\u7B26\u5408\u9879\u76EE\u89C4\u8303
|
|
651
|
+
5. \u6D4B\u8BD5\u8986\u76D6\u662F\u5426\u5145\u5206
|
|
652
|
+
|
|
653
|
+
\u8FD4\u56DE\u683C\u5F0F\uFF1A
|
|
654
|
+
- \u5982\u679C\u901A\u8FC7\u5BA1\u6838\uFF0C\u8FD4\u56DE "\u5BA1\u6838\u901A\u8FC7" \u5E76\u5217\u51FA\u6539\u8FDB\u5EFA\u8BAE
|
|
655
|
+
- \u5982\u679C\u4E0D\u901A\u8FC7\uFF0C\u5217\u51FA\u5177\u4F53\u95EE\u9898
|
|
656
|
+
|
|
657
|
+
\u9879\u76EE\u4FE1\u606F\uFF1A
|
|
658
|
+
- \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
|
|
659
|
+
- \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
|
|
660
|
+
|
|
661
|
+
${session.context?.devStandards ? `\u5F00\u53D1\u89C4\u8303\uFF1A
|
|
662
|
+
${session.context.devStandards.slice(0, 1e3)}` : ""}`
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
role: "user",
|
|
666
|
+
content: `## \u9700\u6C42\u89C4\u683C
|
|
667
|
+
${session.refinedRequirement}
|
|
668
|
+
|
|
669
|
+
## \u4EFB\u52A1\u5217\u8868
|
|
670
|
+
${session.specItems.map((item) => `- [${item.id}] ${item.title}`).join("\n")}
|
|
671
|
+
|
|
672
|
+
## \u5B9E\u73B0\u4EE3\u7801
|
|
673
|
+
${codeContents.join("\n\n") || "\uFF08\u65E0\u4EE3\u7801\u6587\u4EF6\uFF09"}
|
|
674
|
+
|
|
675
|
+
## \u6D4B\u8BD5\u4EE3\u7801
|
|
676
|
+
${testContents.join("\n\n") || "\uFF08\u65E0\u6D4B\u8BD5\u6587\u4EF6\uFF09"}
|
|
677
|
+
|
|
678
|
+
\u8BF7\u5BA1\u6838\u4EE5\u4E0A\u4EE3\u7801\u5B9E\u73B0\u3002`
|
|
679
|
+
}
|
|
680
|
+
];
|
|
681
|
+
const response = await ctx.modelService.sendMessage(messages, {
|
|
682
|
+
temperature: 0.2,
|
|
683
|
+
maxTokens: 2e3,
|
|
684
|
+
agent: "code-reviewer"
|
|
685
|
+
});
|
|
686
|
+
const result = response.content;
|
|
687
|
+
const passed = result.includes("\u5BA1\u6838\u901A\u8FC7") || result.includes("\u901A\u8FC7") || !result.includes("\u4E0D\u901A\u8FC7");
|
|
688
|
+
const issueMatches = result.match(/问题[::]\s*([\s\S]*?)(?=建议|$)/i);
|
|
689
|
+
if (issueMatches) {
|
|
690
|
+
const issueList = issueMatches[1].split(/[\n-]/).filter((s) => s.trim());
|
|
691
|
+
issues.push(...issueList.map((s) => s.trim()).filter((s) => s));
|
|
692
|
+
}
|
|
693
|
+
const suggestionMatches = result.match(/建议[::]\s*([\s\S]*?)$/i);
|
|
694
|
+
if (suggestionMatches) {
|
|
695
|
+
const suggestionList = suggestionMatches[1].split(/[\n-]/).filter((s) => s.trim());
|
|
696
|
+
suggestions.push(...suggestionList.map((s) => s.trim()).filter((s) => s));
|
|
697
|
+
}
|
|
698
|
+
if (issues.length === 0 && !passed) {
|
|
699
|
+
const lines = result.split("\n").filter((l) => l.includes("\u95EE\u9898") || l.includes("\u9519\u8BEF") || l.includes("\u7F3A\u9677"));
|
|
700
|
+
issues.push(...lines.map((l) => l.replace(/^[-*]\s*/, "").trim()).filter((l) => l));
|
|
701
|
+
}
|
|
702
|
+
if (suggestions.length === 0) {
|
|
703
|
+
const lines = result.split("\n").filter((l) => l.includes("\u5EFA\u8BAE") || l.includes("\u6539\u8FDB") || l.includes("\u4F18\u5316"));
|
|
704
|
+
suggestions.push(...lines.map((l) => l.replace(/^[-*]\s*/, "").trim()).filter((l) => l));
|
|
705
|
+
}
|
|
706
|
+
return { passed, issues, suggestions };
|
|
707
|
+
} catch (error) {
|
|
708
|
+
suggestions.push(`\u5BA1\u6838\u8FC7\u7A0B\u51FA\u9519: ${error.message}`);
|
|
709
|
+
return { passed: true, issues, suggestions };
|
|
710
|
+
}
|
|
711
|
+
}
|
|
456
712
|
async function readProjectContext(workingDir) {
|
|
457
713
|
const context = {
|
|
458
714
|
name: path5.basename(workingDir),
|
|
@@ -8604,7 +8860,7 @@ async function executeShell(command, ctx) {
|
|
|
8604
8860
|
init_esm_shims();
|
|
8605
8861
|
init_new();
|
|
8606
8862
|
async function handleNaturalLanguage(input, ctx) {
|
|
8607
|
-
input.trim()
|
|
8863
|
+
const trimmedInput = input.trim();
|
|
8608
8864
|
const session = getActiveSession();
|
|
8609
8865
|
if (session) {
|
|
8610
8866
|
const result = await handleWorkflowInput(input, ctx);
|
|
@@ -8615,81 +8871,163 @@ async function handleNaturalLanguage(input, ctx) {
|
|
|
8615
8871
|
};
|
|
8616
8872
|
}
|
|
8617
8873
|
}
|
|
8618
|
-
ctx.
|
|
8619
|
-
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8874
|
+
const apiKey = ctx.configManager.get("apiKey");
|
|
8875
|
+
if (!apiKey) {
|
|
8876
|
+
return {
|
|
8877
|
+
output: chalk9.yellow("\u26A0\uFE0F \u672A\u914D\u7F6E API Key\uFF0C\u65E0\u6CD5\u4F7F\u7528 AI \u529F\u80FD") + chalk9.gray("\n\n\u8BF7\u5148\u6267\u884C /model \u914D\u7F6E\u6A21\u578B") + chalk9.gray("\n\u652F\u6301: GLM-5, GPT-4o, Claude"),
|
|
8878
|
+
contextUsed: 0
|
|
8879
|
+
};
|
|
8880
|
+
}
|
|
8881
|
+
try {
|
|
8882
|
+
const response = await ctx.modelService.sendMessage(
|
|
8883
|
+
[
|
|
8884
|
+
{
|
|
8885
|
+
role: "system",
|
|
8886
|
+
content: buildSystemPrompt(ctx)
|
|
8887
|
+
},
|
|
8888
|
+
{
|
|
8889
|
+
role: "user",
|
|
8890
|
+
content: trimmedInput
|
|
8891
|
+
}
|
|
8892
|
+
],
|
|
8893
|
+
{
|
|
8894
|
+
temperature: 0.7,
|
|
8895
|
+
maxTokens: 2e3
|
|
8896
|
+
}
|
|
8897
|
+
);
|
|
8898
|
+
ctx.contextManager.addMessage({
|
|
8899
|
+
role: "user",
|
|
8900
|
+
content: trimmedInput
|
|
8901
|
+
});
|
|
8902
|
+
ctx.contextManager.addMessage({
|
|
8903
|
+
role: "assistant",
|
|
8904
|
+
content: response.content
|
|
8905
|
+
});
|
|
8906
|
+
return {
|
|
8907
|
+
output: response.content,
|
|
8908
|
+
contextUsed: response.usage?.totalTokens || 0
|
|
8909
|
+
};
|
|
8910
|
+
} catch (error) {
|
|
8911
|
+
const errorMessage = error.message;
|
|
8912
|
+
if (errorMessage.includes("\u672A\u914D\u7F6E") || errorMessage.includes("\u672A\u521D\u59CB\u5316")) {
|
|
8913
|
+
return {
|
|
8914
|
+
output: chalk9.yellow("\u26A0\uFE0F \u6A21\u578B\u672A\u6B63\u786E\u914D\u7F6E") + chalk9.gray("\n\n\u8BF7\u6267\u884C /model \u91CD\u65B0\u914D\u7F6E"),
|
|
8915
|
+
contextUsed: 0
|
|
8916
|
+
};
|
|
8917
|
+
}
|
|
8918
|
+
if (errorMessage.includes("timeout") || errorMessage.includes("\u8D85\u65F6")) {
|
|
8919
|
+
return {
|
|
8920
|
+
output: chalk9.red("\u2717 \u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"),
|
|
8921
|
+
contextUsed: 0
|
|
8922
|
+
};
|
|
8923
|
+
}
|
|
8924
|
+
return {
|
|
8925
|
+
output: chalk9.red(`\u2717 \u5904\u7406\u5931\u8D25: ${errorMessage}`),
|
|
8926
|
+
contextUsed: 0
|
|
8927
|
+
};
|
|
8928
|
+
}
|
|
8929
|
+
}
|
|
8930
|
+
function buildSystemPrompt(ctx) {
|
|
8931
|
+
const parts = [
|
|
8932
|
+
"\u4F60\u662F sf-cli \u7684 AI \u52A9\u624B\uFF0C\u4E00\u4E2A\u4E13\u4E1A\u7684\u8F6F\u4EF6\u5F00\u53D1\u52A9\u624B\u3002",
|
|
8933
|
+
"",
|
|
8934
|
+
"\u4F60\u53EF\u4EE5\u5E2E\u52A9\u7528\u6237\uFF1A",
|
|
8935
|
+
"1. \u7406\u89E3\u548C\u5206\u6790\u9700\u6C42",
|
|
8936
|
+
"2. \u63D0\u4F9B\u4EE3\u7801\u5EFA\u8BAE\u548C\u5B9E\u73B0\u65B9\u6848",
|
|
8937
|
+
"3. \u56DE\u7B54\u6280\u672F\u95EE\u9898",
|
|
8938
|
+
"4. \u8F85\u52A9\u8FDB\u884C\u4EE3\u7801\u5BA1\u67E5",
|
|
8939
|
+
"",
|
|
8940
|
+
"\u5F53\u524D\u9879\u76EE\u4FE1\u606F\uFF1A",
|
|
8941
|
+
`- \u5DE5\u4F5C\u76EE\u5F55: ${ctx.options.workingDirectory}`,
|
|
8942
|
+
`- \u6A21\u578B: ${ctx.modelService.getCurrentModel() || "\u672A\u6307\u5B9A"}`
|
|
8943
|
+
];
|
|
8944
|
+
return parts.join("\n");
|
|
8627
8945
|
}
|
|
8628
8946
|
|
|
8629
8947
|
// src/cli/executor.ts
|
|
8630
8948
|
init_new();
|
|
8631
|
-
var
|
|
8949
|
+
var ALWAYS_ALLOWED = [
|
|
8632
8950
|
"help",
|
|
8633
8951
|
"h",
|
|
8634
8952
|
"?",
|
|
8635
|
-
"init",
|
|
8636
|
-
"i",
|
|
8637
8953
|
"model",
|
|
8638
8954
|
"m",
|
|
8639
|
-
"new",
|
|
8640
|
-
"n",
|
|
8641
8955
|
"exit",
|
|
8642
8956
|
"e",
|
|
8643
8957
|
"q",
|
|
8644
8958
|
"quit",
|
|
8645
8959
|
"clear",
|
|
8646
8960
|
"c",
|
|
8647
|
-
"update",
|
|
8648
|
-
"u",
|
|
8649
8961
|
"version",
|
|
8650
8962
|
"v"
|
|
8651
8963
|
];
|
|
8964
|
+
var REQUIRES_API_KEY = [
|
|
8965
|
+
"new",
|
|
8966
|
+
"n",
|
|
8967
|
+
"init",
|
|
8968
|
+
"i",
|
|
8969
|
+
"update",
|
|
8970
|
+
"u"
|
|
8971
|
+
];
|
|
8652
8972
|
var CommandExecutor = class {
|
|
8653
8973
|
async execute(parseResult, ctx) {
|
|
8654
8974
|
if (!parseResult.success || !parseResult.command) {
|
|
8655
8975
|
return { output: chalk9.red(`\u9519\u8BEF: ${parseResult.error}`) };
|
|
8656
8976
|
}
|
|
8657
8977
|
const { command } = parseResult;
|
|
8978
|
+
const hasApiKey = !!ctx.configManager.get("apiKey");
|
|
8658
8979
|
const hasActiveWorkflow = getActiveSession() !== null;
|
|
8659
|
-
if (
|
|
8660
|
-
|
|
8661
|
-
|
|
8662
|
-
|
|
8980
|
+
if (command.type === "slash" /* SLASH */) {
|
|
8981
|
+
const cmd = command.command?.toLowerCase() || "";
|
|
8982
|
+
if (ALWAYS_ALLOWED.includes(cmd)) {
|
|
8983
|
+
return this.executeSlashCommand(command, ctx);
|
|
8984
|
+
}
|
|
8985
|
+
if (REQUIRES_API_KEY.includes(cmd)) {
|
|
8986
|
+
if (!hasApiKey) {
|
|
8663
8987
|
return {
|
|
8664
|
-
output: chalk9.yellow("\
|
|
8988
|
+
output: chalk9.yellow("\u26A0\uFE0F \u8BF7\u5148\u914D\u7F6E API Key") + chalk9.gray("\n\n\u6267\u884C /model \u9009\u62E9\u6A21\u578B\u5E76\u914D\u7F6E API Key")
|
|
8665
8989
|
};
|
|
8666
8990
|
}
|
|
8667
|
-
|
|
8991
|
+
return this.executeSlashCommand(command, ctx);
|
|
8992
|
+
}
|
|
8993
|
+
if (!hasActiveWorkflow) {
|
|
8994
|
+
return {
|
|
8995
|
+
output: chalk9.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
|
|
8996
|
+
};
|
|
8997
|
+
}
|
|
8998
|
+
return this.executeSlashCommand(command, ctx);
|
|
8999
|
+
}
|
|
9000
|
+
if (command.type === "dollar" /* DOLLAR */) {
|
|
9001
|
+
if (!hasActiveWorkflow) {
|
|
8668
9002
|
return {
|
|
8669
9003
|
output: chalk9.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u8C03\u7528 Agent") + chalk9.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
|
|
8670
9004
|
};
|
|
8671
|
-
}
|
|
9005
|
+
}
|
|
9006
|
+
if (!hasApiKey) {
|
|
9007
|
+
return {
|
|
9008
|
+
output: chalk9.yellow("\u26A0\uFE0F \u8BF7\u5148\u914D\u7F6E API Key") + chalk9.gray("\n\n\u6267\u884C /model \u914D\u7F6E\u6A21\u578B")
|
|
9009
|
+
};
|
|
9010
|
+
}
|
|
9011
|
+
return this.executeAgent(command, ctx);
|
|
9012
|
+
}
|
|
9013
|
+
if (command.type === "shell" /* SHELL */) {
|
|
9014
|
+
if (!hasActiveWorkflow) {
|
|
8672
9015
|
return {
|
|
8673
9016
|
output: chalk9.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u6267\u884C Shell \u547D\u4EE4") + chalk9.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
|
|
8674
9017
|
};
|
|
8675
9018
|
}
|
|
9019
|
+
return this.executeShell(command, ctx);
|
|
8676
9020
|
}
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
return this.executeShell(command, ctx);
|
|
8686
|
-
case "natural" /* NATURAL */:
|
|
8687
|
-
return this.executeNaturalLanguage(command, ctx);
|
|
8688
|
-
case "yolo" /* YOLO */:
|
|
8689
|
-
return this.executeYolo(ctx);
|
|
8690
|
-
default:
|
|
8691
|
-
return { output: chalk9.red("\u672A\u77E5\u7684\u547D\u4EE4\u7C7B\u578B") };
|
|
9021
|
+
if (command.type === "at" /* AT */) {
|
|
9022
|
+
return this.executeFileReference(command, ctx);
|
|
9023
|
+
}
|
|
9024
|
+
if (command.type === "natural" /* NATURAL */) {
|
|
9025
|
+
return this.executeNaturalLanguage(command, ctx);
|
|
9026
|
+
}
|
|
9027
|
+
if (command.type === "yolo" /* YOLO */) {
|
|
9028
|
+
return this.executeYolo(ctx);
|
|
8692
9029
|
}
|
|
9030
|
+
return { output: chalk9.red("\u672A\u77E5\u7684\u547D\u4EE4\u7C7B\u578B") };
|
|
8693
9031
|
}
|
|
8694
9032
|
async executeSlashCommand(command, ctx) {
|
|
8695
9033
|
const result = await runSlashCommand(
|