@nick848/sf-cli 1.0.19 → 1.0.20
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 +111 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +111 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +111 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1584,23 +1584,38 @@ ${resource.analysis}`;
|
|
|
1584
1584
|
lines.push("");
|
|
1585
1585
|
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 6/9: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
|
|
1586
1586
|
lines.push("");
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
activeSession.
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1587
|
+
const loader = new LoadingIndicator("AI \u6B63\u5728\u62C6\u5206\u89C4\u683C");
|
|
1588
|
+
loader.start();
|
|
1589
|
+
try {
|
|
1590
|
+
activeSession.specItems = await generateSpecItemsWithAI(
|
|
1591
|
+
activeSession.refinedRequirement,
|
|
1592
|
+
activeSession.context,
|
|
1593
|
+
activeSession.bddScenarios,
|
|
1594
|
+
activeSession.clarificationQuestions,
|
|
1595
|
+
activeSession.referenceResources,
|
|
1596
|
+
ctx
|
|
1597
|
+
);
|
|
1598
|
+
loader.stop();
|
|
1599
|
+
} catch {
|
|
1600
|
+
loader.stop(chalk9__default.default.yellow(" \u26A0 \u4F7F\u7528\u57FA\u7840\u89C4\u683C\u62C6\u5206"));
|
|
1601
|
+
activeSession.specItems = generateSpecItems(
|
|
1602
|
+
activeSession.refinedRequirement,
|
|
1603
|
+
activeSession.context,
|
|
1604
|
+
activeSession.bddScenarios,
|
|
1605
|
+
activeSession.clarificationQuestions,
|
|
1606
|
+
activeSession.referenceResources
|
|
1607
|
+
);
|
|
1608
|
+
}
|
|
1594
1609
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
1595
1610
|
lines.push(chalk9__default.default.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
1596
1611
|
lines.push(chalk9__default.default.gray(` \u8DEF\u5F84: ${specPath}`));
|
|
1597
1612
|
lines.push("");
|
|
1598
1613
|
lines.push(chalk9__default.default.cyan(" \u4EFB\u52A1\u6982\u89C8:"));
|
|
1599
|
-
for (const item of activeSession.specItems.slice(0,
|
|
1614
|
+
for (const item of activeSession.specItems.slice(0, 8)) {
|
|
1600
1615
|
const icon = item.priority === "high" ? "\u{1F534}" : item.priority === "medium" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
1601
1616
|
lines.push(chalk9__default.default.gray(` ${icon} [${item.id}] ${item.title}`));
|
|
1602
1617
|
}
|
|
1603
|
-
if (activeSession.specItems.length >
|
|
1618
|
+
if (activeSession.specItems.length > 8) {
|
|
1604
1619
|
lines.push(chalk9__default.default.gray(` ... \u5171 ${activeSession.specItems.length} \u4E2A\u4EFB\u52A1`));
|
|
1605
1620
|
}
|
|
1606
1621
|
lines.push("");
|
|
@@ -1747,13 +1762,15 @@ async function handleWorkflowInput(input, ctx) {
|
|
|
1747
1762
|
activeSession.bddScenarios = generateBDDScenarios(
|
|
1748
1763
|
activeSession.refinedRequirement,
|
|
1749
1764
|
activeSession.context,
|
|
1750
|
-
activeSession.clarificationQuestions
|
|
1765
|
+
activeSession.clarificationQuestions,
|
|
1766
|
+
activeSession.referenceResources
|
|
1751
1767
|
);
|
|
1752
1768
|
activeSession.specItems = generateSpecItems(
|
|
1753
1769
|
activeSession.refinedRequirement,
|
|
1754
1770
|
activeSession.context,
|
|
1755
1771
|
activeSession.bddScenarios,
|
|
1756
|
-
activeSession.clarificationQuestions
|
|
1772
|
+
activeSession.clarificationQuestions,
|
|
1773
|
+
activeSession.referenceResources
|
|
1757
1774
|
);
|
|
1758
1775
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
1759
1776
|
return {
|
|
@@ -2479,6 +2496,89 @@ function generateSpecItems(requirement, context, bddScenarios, questions, refere
|
|
|
2479
2496
|
});
|
|
2480
2497
|
return items;
|
|
2481
2498
|
}
|
|
2499
|
+
async function generateSpecItemsWithAI(requirement, context, bddScenarios, questions, references, ctx) {
|
|
2500
|
+
const prompt2 = `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u9879\u76EE\u7ECF\u7406\u548C\u6280\u672F\u67B6\u6784\u5E08\u3002\u8BF7\u5C06\u4EE5\u4E0B\u9700\u6C42\u62C6\u5206\u4E3A\u7CBE\u7EC6\u5316\u7684\u5F00\u53D1\u4EFB\u52A1\u3002
|
|
2501
|
+
|
|
2502
|
+
## \u9700\u6C42\u63CF\u8FF0
|
|
2503
|
+
${requirement}
|
|
2504
|
+
|
|
2505
|
+
## \u9879\u76EE\u4E0A\u4E0B\u6587
|
|
2506
|
+
- \u6280\u672F\u6808: ${context.techStack?.join(", ") || "TypeScript"}
|
|
2507
|
+
- \u6846\u67B6: ${context.framework || "\u672A\u6307\u5B9A"}
|
|
2508
|
+
${context.devStandards ? `
|
|
2509
|
+
## \u5F00\u53D1\u89C4\u8303\uFF08\u5FC5\u987B\u9075\u5FAA\uFF09
|
|
2510
|
+
${context.devStandards.slice(0, 2e3)}
|
|
2511
|
+
` : ""}
|
|
2512
|
+
|
|
2513
|
+
## BDD \u573A\u666F\u53C2\u8003
|
|
2514
|
+
${bddScenarios.map((s) => `- Feature: ${s.feature} (${s.scenarios.length} \u4E2A\u573A\u666F)`).join("\n")}
|
|
2515
|
+
|
|
2516
|
+
## \u6F84\u6E05\u4FE1\u606F
|
|
2517
|
+
${questions.filter((q) => q.answered).map((q) => `- ${q.question}: ${q.answer}`).join("\n") || "\u65E0"}
|
|
2518
|
+
|
|
2519
|
+
## \u62C6\u5206\u8981\u6C42
|
|
2520
|
+
|
|
2521
|
+
\u8BF7\u5C06\u9700\u6C42\u62C6\u5206\u4E3A **\u7EC6\u7C92\u5EA6\u7684\u5F00\u53D1\u4EFB\u52A1**\uFF0C\u6BCF\u4E2A\u4EFB\u52A1\u5E94\u8BE5\uFF1A
|
|
2522
|
+
1. **\u5355\u4E00\u804C\u8D23** - \u4E00\u4E2A\u4EFB\u52A1\u53EA\u505A\u4E00\u4EF6\u4E8B
|
|
2523
|
+
2. **\u53EF\u72EC\u7ACB\u6D4B\u8BD5** - \u6709\u660E\u786E\u7684\u9A8C\u6536\u6807\u51C6
|
|
2524
|
+
3. **2-4\u5C0F\u65F6\u53EF\u5B8C\u6210** - \u5982\u679C\u4EFB\u52A1\u592A\u5927\uFF0C\u7EE7\u7EED\u62C6\u5206
|
|
2525
|
+
4. **\u6709\u660E\u786E\u7684\u8F93\u5165\u8F93\u51FA** - \u6E05\u695A\u77E5\u9053\u9700\u8981\u4EC0\u4E48\u3001\u4EA7\u51FA\u4EC0\u4E48
|
|
2526
|
+
|
|
2527
|
+
## \u8F93\u51FA\u683C\u5F0F (JSON)
|
|
2528
|
+
\`\`\`json
|
|
2529
|
+
[
|
|
2530
|
+
{
|
|
2531
|
+
"id": "T001",
|
|
2532
|
+
"title": "\u4EFB\u52A1\u6807\u9898\uFF08\u7B80\u77ED\u660E\u786E\uFF09",
|
|
2533
|
+
"description": "\u8BE6\u7EC6\u63CF\u8FF0\uFF1A\u8981\u505A\u4EC0\u4E48\u3001\u5982\u4F55\u505A\u3001\u9A8C\u6536\u6807\u51C6",
|
|
2534
|
+
"priority": "high",
|
|
2535
|
+
"estimatedHours": 2,
|
|
2536
|
+
"dependencies": [],
|
|
2537
|
+
"acceptanceCriteria": ["\u9A8C\u6536\u6807\u51C61", "\u9A8C\u6536\u6807\u51C62"]
|
|
2538
|
+
}
|
|
2539
|
+
]
|
|
2540
|
+
\`\`\`
|
|
2541
|
+
|
|
2542
|
+
## \u62C6\u5206\u5EFA\u8BAE
|
|
2543
|
+
\u5BF9\u4E8E\u590D\u6742\u529F\u80FD\uFF08\u5982\u7B97\u6CD5\u7C7B\uFF09\uFF0C\u5E94\u8BE5\u62C6\u5206\u4E3A\uFF1A
|
|
2544
|
+
- \u6570\u636E\u7ED3\u6784/\u6A21\u578B\u5B9A\u4E49
|
|
2545
|
+
- \u6838\u5FC3\u7B97\u6CD5\u5206\u6B65\u5B9E\u73B0\uFF08\u6BCF\u4E2A\u8BA1\u7B97\u6B65\u9AA4\u4E00\u4E2A\u4EFB\u52A1\uFF09
|
|
2546
|
+
- \u8F93\u5165\u9A8C\u8BC1
|
|
2547
|
+
- \u7ED3\u679C\u683C\u5F0F\u5316
|
|
2548
|
+
- UI \u5C55\u793A\u7EC4\u4EF6
|
|
2549
|
+
- \u96C6\u6210\u6D4B\u8BD5
|
|
2550
|
+
|
|
2551
|
+
\u8BF7\u76F4\u63A5\u8F93\u51FA JSON \u6570\u7EC4\u3002`;
|
|
2552
|
+
const loader = new LoadingIndicator("AI \u6B63\u5728\u62C6\u5206\u89C4\u683C");
|
|
2553
|
+
loader.start();
|
|
2554
|
+
try {
|
|
2555
|
+
const response = await ctx.modelService.sendMessage([
|
|
2556
|
+
{ role: "user", content: prompt2 }
|
|
2557
|
+
], {
|
|
2558
|
+
temperature: 0.3,
|
|
2559
|
+
maxTokens: 4e3,
|
|
2560
|
+
timeout: 12e4
|
|
2561
|
+
});
|
|
2562
|
+
const jsonMatch = response.content.match(/```json\s*([\s\S]*?)```/);
|
|
2563
|
+
if (jsonMatch) {
|
|
2564
|
+
const parsed = JSON.parse(jsonMatch[1].trim());
|
|
2565
|
+
loader.stop(chalk9__default.default.green(` \u2713 \u5DF2\u62C6\u5206 ${parsed.length} \u4E2A\u4EFB\u52A1`));
|
|
2566
|
+
return parsed.map((item) => ({
|
|
2567
|
+
id: item.id || `T${String(parsed.indexOf(item) + 1).padStart(3, "0")}`,
|
|
2568
|
+
title: item.title,
|
|
2569
|
+
description: item.description,
|
|
2570
|
+
priority: item.priority || "medium",
|
|
2571
|
+
files: [],
|
|
2572
|
+
tests: item.acceptanceCriteria || []
|
|
2573
|
+
}));
|
|
2574
|
+
}
|
|
2575
|
+
loader.stop(chalk9__default.default.yellow(" \u26A0 \u89E3\u6790\u5931\u8D25\uFF0C\u4F7F\u7528\u57FA\u7840\u62C6\u5206"));
|
|
2576
|
+
return generateSpecItems(requirement, context, bddScenarios, questions, references);
|
|
2577
|
+
} catch (error) {
|
|
2578
|
+
loader.stop(chalk9__default.default.yellow(" \u26A0 AI \u62C6\u5206\u5931\u8D25\uFF0C\u4F7F\u7528\u57FA\u7840\u62C6\u5206"));
|
|
2579
|
+
return generateSpecItems(requirement, context, bddScenarios, questions, references);
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2482
2582
|
async function saveSpecFile(workingDir, session) {
|
|
2483
2583
|
const specDir = path5__namespace.join(workingDir, "openspec", "changes");
|
|
2484
2584
|
await fs5__namespace.mkdir(specDir, { recursive: true });
|