@nick848/sf-cli 1.0.19 → 1.0.21

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 {
@@ -1912,107 +1929,115 @@ function getCategoryLabel(category) {
1912
1929
  async function executeDevelopment(ctx, session) {
1913
1930
  const workingDir = ctx.options.workingDirectory;
1914
1931
  const files = [];
1915
- const loader = new LoadingIndicator("AI \u6B63\u5728\u751F\u6210\u4EE3\u7801");
1916
- loader.start();
1917
- try {
1918
- const systemPrompt = buildDevelopmentPrompt(session);
1919
- const messages = [
1920
- {
1921
- role: "system",
1922
- 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
1932
+ console.log("");
1933
+ for (let i = 0; i < session.specItems.length; i++) {
1934
+ const item = session.specItems[i];
1935
+ const prefix = `[${i + 1}/${session.specItems.length}]`;
1936
+ if (item.title.includes("\u6D4B\u8BD5") || item.title.includes("test")) {
1937
+ continue;
1938
+ }
1939
+ const loader = new LoadingIndicator(`${prefix} \u751F\u6210: ${item.title.slice(0, 20)}...`);
1940
+ loader.start();
1941
+ try {
1942
+ const taskPrompt = buildTaskPrompt(session, item, i);
1943
+ const messages = [
1944
+ {
1945
+ role: "system",
1946
+ 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
1923
1947
 
1924
1948
  \u26A0\uFE0F \u91CD\u8981\u89C4\u5219\uFF1A
1925
- 1. \u6280\u672F\u5B9E\u73B0\u5FC5\u987B\u4E25\u683C\u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u5F00\u53D1\u89C4\u8303
1926
- 2. \u53C2\u8003\u8D44\u6E90\uFF08\u5982\u679C\u6709\uFF09\u4EC5\u7528\u4E8E\u7406\u89E3\u4E1A\u52A1\u529F\u80FD\uFF0C\u4E0D\u8981\u590D\u5236\u5176\u6280\u672F\u5B9E\u73B0
1927
- 3. \u4F7F\u7528\u9879\u76EE\u6307\u5B9A\u7684\u6280\u672F\u6808\u548C\u6846\u67B6
1928
-
1929
- \u4EE3\u7801\u8981\u6C42\uFF1A
1930
- 1. \u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801
1931
- 2. \u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u4EE3\u7801\u98CE\u683C\u548C\u89C4\u8303
1932
- 3. \u4F7F\u7528\u9879\u76EE\u6307\u5B9A\u7684\u6280\u672F\u6808
1933
- 4. \u4EE3\u7801\u8981\u6709\u9002\u5F53\u7684\u6CE8\u91CA
1934
- 5. \u8FD4\u56DE\u683C\u5F0F\uFF1A\u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u4EE3\u7801 \`\`\` \u5305\u88F9
1949
+ 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
1950
+ 2. \u6280\u672F\u5B9E\u73B0\u5FC5\u987B\u4E25\u683C\u9075\u5FAA\u9879\u76EE\u73B0\u6709\u7684\u5F00\u53D1\u89C4\u8303
1951
+ 3. \u751F\u6210\u5B8C\u6574\u3001\u53EF\u8FD0\u884C\u7684\u4EE3\u7801
1952
+ 4. \u8FD4\u56DE\u683C\u5F0F\uFF1A\u6BCF\u4E2A\u6587\u4EF6\u7528 \`\`\`filename \u4EE3\u7801 \`\`\` \u5305\u88F9
1935
1953
 
1936
1954
  \u9879\u76EE\u4FE1\u606F\uFF1A
1937
1955
  - \u540D\u79F0: ${session.context?.name}
1938
1956
  - \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
1939
1957
  - \u6280\u672F\u6808: ${session.context?.techStack.join(", ") || "\u672A\u6307\u5B9A"}
1940
1958
 
1941
- ${session.context?.devStandards ? `\u3010\u5FC5\u987B\u9075\u5FAA\u7684\u5F00\u53D1\u89C4\u8303\u3011
1942
- ${session.context.devStandards.slice(0, 2500)}` : ""}`
1943
- },
1944
- {
1945
- role: "user",
1946
- content: systemPrompt
1959
+ ${session.context?.devStandards ? `\u3010\u5F00\u53D1\u89C4\u8303\u3011
1960
+ ${session.context.devStandards.slice(0, 2e3)}` : ""}`
1961
+ },
1962
+ {
1963
+ role: "user",
1964
+ content: taskPrompt
1965
+ }
1966
+ ];
1967
+ const response = await ctx.modelService.sendMessage(messages, {
1968
+ temperature: 0.3,
1969
+ maxTokens: 4e3,
1970
+ // 单个任务减少 token
1971
+ agent: "frontend-dev",
1972
+ timeout: 12e4
1973
+ // 2分钟超时
1974
+ });
1975
+ const codeBlocks = parseCodeBlocks(response.content);
1976
+ if (codeBlocks.length > 0) {
1977
+ for (const block of codeBlocks) {
1978
+ const filePath = path5__namespace.join(workingDir, block.filename);
1979
+ const dir = path5__namespace.dirname(filePath);
1980
+ await fs5__namespace.mkdir(dir, { recursive: true });
1981
+ await fs5__namespace.writeFile(filePath, block.code, "utf-8");
1982
+ files.push(block.filename);
1983
+ }
1984
+ loader.stop(chalk9__default.default.green(`${prefix} \u2713 ${item.title.slice(0, 25)} (${codeBlocks.length} \u4E2A\u6587\u4EF6)`));
1985
+ } else {
1986
+ const implDir = path5__namespace.join(workingDir, "src");
1987
+ await fs5__namespace.mkdir(implDir, { recursive: true });
1988
+ const fileName = `${item.title.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, "_")}.ts`;
1989
+ const filePath = path5__namespace.join(implDir, fileName);
1990
+ await fs5__namespace.writeFile(filePath, `// TODO: ${item.title}
1991
+ // ${item.description}
1992
+ `, "utf-8");
1993
+ files.push(`src/${fileName}`);
1994
+ loader.stop(chalk9__default.default.yellow(`${prefix} \u26A0 \u751F\u6210\u57FA\u7840\u6A21\u677F: ${item.title.slice(0, 20)}`));
1995
+ }
1996
+ if (i < session.specItems.length - 1) {
1997
+ await new Promise((resolve5) => setTimeout(resolve5, 500));
1947
1998
  }
1948
- ];
1949
- loader.update("\u6B63\u5728\u8C03\u7528 AI \u6A21\u578B");
1950
- const response = await ctx.modelService.sendMessage(messages, {
1951
- temperature: 0.3,
1952
- maxTokens: 8e3,
1953
- agent: "frontend-dev",
1954
- timeout: 18e4
1955
- // 3 分钟超时
1956
- });
1957
- loader.update("\u6B63\u5728\u89E3\u6790\u4EE3\u7801");
1958
- const codeBlocks = parseCodeBlocks(response.content);
1959
- for (const block of codeBlocks) {
1960
- const filePath = path5__namespace.join(workingDir, block.filename);
1961
- const dir = path5__namespace.dirname(filePath);
1962
- await fs5__namespace.mkdir(dir, { recursive: true });
1963
- await fs5__namespace.writeFile(filePath, block.code, "utf-8");
1964
- files.push(block.filename);
1965
- }
1966
- if (files.length === 0) {
1967
- const implDir = path5__namespace.join(workingDir, "src", "features");
1968
- await fs5__namespace.mkdir(implDir, { recursive: true });
1969
- const featureName = session.specItems[0]?.title || "feature";
1970
- const fileName = `${featureName.replace(/[^a-zA-Z0-9]/g, "_")}.ts`;
1971
- const filePath = path5__namespace.join(implDir, fileName);
1972
- const stubCode = `/**
1973
- * ${session.requirement}
1974
- *
1975
- * TODO: \u6B64\u6587\u4EF6\u7531 AI \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u6839\u636E\u9700\u6C42\u5B8C\u5584\u5B9E\u73B0
1976
- */
1977
-
1978
- export function ${featureName.replace(/[^a-zA-Z0-9]/g, "")}() {
1979
- // TODO: \u5B9E\u73B0\u529F\u80FD
1980
- console.log('${featureName} - \u5F85\u5B9E\u73B0');
1981
- }
1982
- `;
1983
- await fs5__namespace.writeFile(filePath, stubCode, "utf-8");
1984
- files.push(`src/features/${fileName}`);
1999
+ } catch (error) {
2000
+ loader.stop(chalk9__default.default.red(`${prefix} \u2717 \u5931\u8D25: ${error.message.slice(0, 40)}`));
1985
2001
  }
1986
- loader.stop(chalk9__default.default.green(` \u2713 \u5DF2\u751F\u6210 ${files.length} \u4E2A\u6587\u4EF6`));
2002
+ }
2003
+ if (files.length > 0) {
1987
2004
  return { success: true, files };
1988
- } catch (error) {
1989
- loader.stop();
2005
+ } else {
1990
2006
  return {
1991
2007
  success: false,
1992
2008
  files: [],
1993
- error: error.message
2009
+ error: "\u6240\u6709\u4EFB\u52A1\u4EE3\u7801\u751F\u6210\u5931\u8D25"
1994
2010
  };
1995
2011
  }
1996
2012
  }
1997
- function buildDevelopmentPrompt(session) {
2013
+ function buildTaskPrompt(session, item, index) {
1998
2014
  const lines = [];
1999
- lines.push("## \u9700\u6C42\u63CF\u8FF0");
2000
- lines.push(session.refinedRequirement);
2001
- lines.push("");
2002
- lines.push("## BDD \u573A\u666F");
2003
- for (const scenario of session.bddScenarios) {
2004
- lines.push(`### ${scenario.feature}`);
2005
- for (const s of scenario.scenarios) {
2006
- lines.push(`- ${s.name}`);
2015
+ lines.push(`## \u5F53\u524D\u4EFB\u52A1 (#${index + 1})`);
2016
+ lines.push(`**\u6807\u9898**: ${item.title}`);
2017
+ lines.push(`**\u63CF\u8FF0**: ${item.description}`);
2018
+ lines.push(`**\u4F18\u5148\u7EA7**: ${item.priority}`);
2019
+ if (item.tests && item.tests.length > 0) {
2020
+ lines.push(`**\u9A8C\u6536\u6807\u51C6**:`);
2021
+ for (const t of item.tests) {
2022
+ lines.push(`- ${t}`);
2007
2023
  }
2008
2024
  }
2009
2025
  lines.push("");
2010
- lines.push("## \u4EFB\u52A1\u5217\u8868");
2011
- for (const item of session.specItems) {
2012
- lines.push(`- [${item.id}] ${item.title}: ${item.description}`);
2026
+ lines.push(`## \u6574\u4F53\u9700\u6C42\u80CC\u666F`);
2027
+ lines.push(session.requirement);
2028
+ const relatedScenario = session.bddScenarios.find(
2029
+ (s) => item.title.includes(s.feature) || s.feature.includes(item.title)
2030
+ );
2031
+ if (relatedScenario) {
2032
+ lines.push("");
2033
+ lines.push(`## \u76F8\u5173 BDD \u573A\u666F`);
2034
+ lines.push(`Feature: ${relatedScenario.feature}`);
2035
+ for (const s of relatedScenario.scenarios.slice(0, 2)) {
2036
+ lines.push(`- ${s.name}`);
2037
+ }
2013
2038
  }
2014
2039
  lines.push("");
2015
- lines.push("\u8BF7\u6839\u636E\u4EE5\u4E0A\u9700\u6C42\u89C4\u683C\u751F\u6210\u4EE3\u7801\u5B9E\u73B0\u3002");
2040
+ 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");
2016
2041
  return lines.join("\n");
2017
2042
  }
2018
2043
  function parseCodeBlocks(content) {
@@ -2479,6 +2504,111 @@ function generateSpecItems(requirement, context, bddScenarios, questions, refere
2479
2504
  });
2480
2505
  return items;
2481
2506
  }
2507
+ async function generateSpecItemsWithAI(requirement, context, bddScenarios, questions, references, ctx) {
2508
+ 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
2509
+
2510
+ ## \u9700\u6C42\u63CF\u8FF0
2511
+ ${requirement}
2512
+
2513
+ ## \u9879\u76EE\u4E0A\u4E0B\u6587
2514
+ - \u6280\u672F\u6808: ${context.techStack?.join(", ") || "TypeScript"}
2515
+ - \u6846\u67B6: ${context.framework || "\u672A\u6307\u5B9A"}
2516
+ ${context.devStandards ? `
2517
+ ## \u5F00\u53D1\u89C4\u8303\uFF08\u5FC5\u987B\u9075\u5FAA\uFF09
2518
+ ${context.devStandards.slice(0, 2e3)}
2519
+ ` : ""}
2520
+
2521
+ ## BDD \u573A\u666F\u53C2\u8003
2522
+ ${bddScenarios.map((s) => `- Feature: ${s.feature} (${s.scenarios.length} \u4E2A\u573A\u666F)`).join("\n")}
2523
+
2524
+ ## \u6F84\u6E05\u4FE1\u606F
2525
+ ${questions.filter((q) => q.answered).map((q) => `- ${q.question}: ${q.answer}`).join("\n") || "\u65E0"}
2526
+
2527
+ ## \u62C6\u5206\u8981\u6C42
2528
+
2529
+ \u8BF7\u5C06\u9700\u6C42\u62C6\u5206\u4E3A **\u7EC6\u7C92\u5EA6\u7684\u5F00\u53D1\u4EFB\u52A1**\uFF0C\u6BCF\u4E2A\u4EFB\u52A1\u5E94\u8BE5\uFF1A
2530
+ 1. **\u5355\u4E00\u804C\u8D23** - \u4E00\u4E2A\u4EFB\u52A1\u53EA\u505A\u4E00\u4EF6\u4E8B
2531
+ 2. **\u53EF\u72EC\u7ACB\u6D4B\u8BD5** - \u6709\u660E\u786E\u7684\u9A8C\u6536\u6807\u51C6
2532
+ 3. **2-4\u5C0F\u65F6\u53EF\u5B8C\u6210** - \u5982\u679C\u4EFB\u52A1\u592A\u5927\uFF0C\u7EE7\u7EED\u62C6\u5206
2533
+ 4. **\u6709\u660E\u786E\u7684\u8F93\u5165\u8F93\u51FA** - \u6E05\u695A\u77E5\u9053\u9700\u8981\u4EC0\u4E48\u3001\u4EA7\u51FA\u4EC0\u4E48
2534
+
2535
+ ## \u8F93\u51FA\u683C\u5F0F (JSON)
2536
+ \`\`\`json
2537
+ [
2538
+ {
2539
+ "id": "T001",
2540
+ "title": "\u4EFB\u52A1\u6807\u9898\uFF08\u7B80\u77ED\u660E\u786E\uFF09",
2541
+ "description": "\u8BE6\u7EC6\u63CF\u8FF0\uFF1A\u8981\u505A\u4EC0\u4E48\u3001\u5982\u4F55\u505A\u3001\u9A8C\u6536\u6807\u51C6",
2542
+ "priority": "high",
2543
+ "estimatedHours": 2,
2544
+ "dependencies": [],
2545
+ "acceptanceCriteria": ["\u9A8C\u6536\u6807\u51C61", "\u9A8C\u6536\u6807\u51C62"]
2546
+ }
2547
+ ]
2548
+ \`\`\`
2549
+
2550
+ ## \u62C6\u5206\u5EFA\u8BAE
2551
+ \u5BF9\u4E8E\u590D\u6742\u529F\u80FD\uFF08\u5982\u7B97\u6CD5\u7C7B\uFF09\uFF0C\u5E94\u8BE5\u62C6\u5206\u4E3A\uFF1A
2552
+ - \u6570\u636E\u7ED3\u6784/\u6A21\u578B\u5B9A\u4E49
2553
+ - \u6838\u5FC3\u7B97\u6CD5\u5206\u6B65\u5B9E\u73B0\uFF08\u6BCF\u4E2A\u8BA1\u7B97\u6B65\u9AA4\u4E00\u4E2A\u4EFB\u52A1\uFF09
2554
+ - \u8F93\u5165\u9A8C\u8BC1
2555
+ - \u7ED3\u679C\u683C\u5F0F\u5316
2556
+ - UI \u5C55\u793A\u7EC4\u4EF6
2557
+ - \u96C6\u6210\u6D4B\u8BD5
2558
+
2559
+ \u8BF7\u76F4\u63A5\u8F93\u51FA JSON \u6570\u7EC4\u3002`;
2560
+ const loader = new LoadingIndicator("AI \u6B63\u5728\u62C6\u5206\u89C4\u683C");
2561
+ loader.start();
2562
+ try {
2563
+ const response = await ctx.modelService.sendMessage([
2564
+ { role: "user", content: prompt2 }
2565
+ ], {
2566
+ temperature: 0.3,
2567
+ maxTokens: 4e3,
2568
+ timeout: 18e4
2569
+ // 增加到3分钟
2570
+ });
2571
+ const jsonMatch = response.content.match(/```json\s*([\s\S]*?)```/);
2572
+ if (jsonMatch) {
2573
+ try {
2574
+ const parsed = JSON.parse(jsonMatch[1].trim());
2575
+ loader.stop(chalk9__default.default.green(` \u2713 \u5DF2\u62C6\u5206 ${parsed.length} \u4E2A\u4EFB\u52A1`));
2576
+ return parsed.map((item, index) => ({
2577
+ id: item.id || `T${String(index + 1).padStart(3, "0")}`,
2578
+ title: item.title,
2579
+ description: item.description,
2580
+ priority: item.priority || "medium",
2581
+ files: [],
2582
+ tests: item.acceptanceCriteria || []
2583
+ }));
2584
+ } catch (parseError) {
2585
+ loader.stop(chalk9__default.default.yellow(` \u26A0 JSON \u89E3\u6790\u5931\u8D25: ${parseError.message.slice(0, 50)}`));
2586
+ return generateSpecItems(requirement, context, bddScenarios, questions, references);
2587
+ }
2588
+ }
2589
+ try {
2590
+ const parsed = JSON.parse(response.content);
2591
+ if (Array.isArray(parsed)) {
2592
+ loader.stop(chalk9__default.default.green(` \u2713 \u5DF2\u62C6\u5206 ${parsed.length} \u4E2A\u4EFB\u52A1`));
2593
+ return parsed.map((item, index) => ({
2594
+ id: item.id || `T${String(index + 1).padStart(3, "0")}`,
2595
+ title: item.title,
2596
+ description: item.description,
2597
+ priority: item.priority || "medium",
2598
+ files: [],
2599
+ tests: item.acceptanceCriteria || []
2600
+ }));
2601
+ }
2602
+ } catch {
2603
+ }
2604
+ loader.stop(chalk9__default.default.yellow(" \u26A0 \u672A\u80FD\u89E3\u6790 AI \u54CD\u5E94\uFF0C\u4F7F\u7528\u57FA\u7840\u62C6\u5206"));
2605
+ return generateSpecItems(requirement, context, bddScenarios, questions, references);
2606
+ } catch (error) {
2607
+ const errMsg = error.message.slice(0, 80);
2608
+ loader.stop(chalk9__default.default.yellow(` \u26A0 AI \u8C03\u7528\u5931\u8D25: ${errMsg}`));
2609
+ return generateSpecItems(requirement, context, bddScenarios, questions, references);
2610
+ }
2611
+ }
2482
2612
  async function saveSpecFile(workingDir, session) {
2483
2613
  const specDir = path5__namespace.join(workingDir, "openspec", "changes");
2484
2614
  await fs5__namespace.mkdir(specDir, { recursive: true });