@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 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
- activeSession.specItems = generateSpecItems(
1588
- activeSession.refinedRequirement,
1589
- activeSession.context,
1590
- activeSession.bddScenarios,
1591
- activeSession.clarificationQuestions,
1592
- activeSession.referenceResources
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, 5)) {
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 > 5) {
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 });