@nick848/sf-cli 1.0.17 → 1.0.18

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
@@ -1549,12 +1549,26 @@ ${resource.analysis}`;
1549
1549
  lines.push("");
1550
1550
  lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 5/9: BDD \u573A\u666F\u62C6\u89E3 \u2501\u2501\u2501"));
1551
1551
  lines.push("");
1552
- activeSession.bddScenarios = generateBDDScenarios(
1553
- activeSession.refinedRequirement,
1554
- activeSession.context,
1555
- activeSession.clarificationQuestions,
1556
- activeSession.referenceResources
1557
- );
1552
+ const loader = new LoadingIndicator("AI \u6B63\u5728\u751F\u6210 BDD \u573A\u666F");
1553
+ loader.start();
1554
+ try {
1555
+ activeSession.bddScenarios = await generateBDDScenariosWithAI(
1556
+ activeSession.refinedRequirement,
1557
+ activeSession.context,
1558
+ activeSession.clarificationQuestions,
1559
+ activeSession.referenceResources,
1560
+ ctx
1561
+ );
1562
+ loader.stop(chalk9__default.default.green(" \u2713 BDD \u573A\u666F\u5DF2\u751F\u6210"));
1563
+ } catch {
1564
+ loader.stop(chalk9__default.default.yellow(" \u26A0 \u4F7F\u7528\u57FA\u7840 BDD \u751F\u6210"));
1565
+ activeSession.bddScenarios = generateBDDScenarios(
1566
+ activeSession.refinedRequirement,
1567
+ activeSession.context,
1568
+ activeSession.clarificationQuestions,
1569
+ activeSession.referenceResources
1570
+ );
1571
+ }
1558
1572
  for (const scenario of activeSession.bddScenarios) {
1559
1573
  lines.push(chalk9__default.default.white(` Feature: ${scenario.feature}`));
1560
1574
  for (const s of scenario.scenarios.slice(0, 3)) {
@@ -1601,7 +1615,7 @@ ${resource.analysis}`;
1601
1615
  lines.push("");
1602
1616
  lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 7/9: TDD \u6D4B\u8BD5\u751F\u6210 \u2501\u2501\u2501"));
1603
1617
  lines.push("");
1604
- activeSession.testFiles = await generateTests(ctx.options.workingDirectory, activeSession);
1618
+ activeSession.testFiles = await generateTests(ctx.options.workingDirectory, activeSession, ctx);
1605
1619
  lines.push(chalk9__default.default.green(" \u2713 \u6D4B\u8BD5\u6587\u4EF6\u5DF2\u751F\u6210"));
1606
1620
  for (const file of activeSession.testFiles) {
1607
1621
  lines.push(chalk9__default.default.gray(` - ${file}`));
@@ -1898,6 +1912,8 @@ function getCategoryLabel(category) {
1898
1912
  async function executeDevelopment(ctx, session) {
1899
1913
  const workingDir = ctx.options.workingDirectory;
1900
1914
  const files = [];
1915
+ const loader = new LoadingIndicator("AI \u6B63\u5728\u751F\u6210\u4EE3\u7801");
1916
+ loader.start();
1901
1917
  try {
1902
1918
  const systemPrompt = buildDevelopmentPrompt(session);
1903
1919
  const messages = [
@@ -1925,11 +1941,15 @@ ${session.context.devStandards.slice(0, 2e3)}` : ""}`
1925
1941
  content: systemPrompt
1926
1942
  }
1927
1943
  ];
1944
+ loader.update("\u6B63\u5728\u8C03\u7528 AI \u6A21\u578B");
1928
1945
  const response = await ctx.modelService.sendMessage(messages, {
1929
1946
  temperature: 0.3,
1930
1947
  maxTokens: 8e3,
1931
- agent: "frontend-dev"
1948
+ agent: "frontend-dev",
1949
+ timeout: 18e4
1950
+ // 3 分钟超时
1932
1951
  });
1952
+ loader.update("\u6B63\u5728\u89E3\u6790\u4EE3\u7801");
1933
1953
  const codeBlocks = parseCodeBlocks(response.content);
1934
1954
  for (const block of codeBlocks) {
1935
1955
  const filePath = path5__namespace.join(workingDir, block.filename);
@@ -1958,8 +1978,10 @@ export function ${featureName.replace(/[^a-zA-Z0-9]/g, "")}() {
1958
1978
  await fs5__namespace.writeFile(filePath, stubCode, "utf-8");
1959
1979
  files.push(`src/features/${fileName}`);
1960
1980
  }
1981
+ loader.stop(chalk9__default.default.green(` \u2713 \u5DF2\u751F\u6210 ${files.length} \u4E2A\u6587\u4EF6`));
1961
1982
  return { success: true, files };
1962
1983
  } catch (error) {
1984
+ loader.stop();
1963
1985
  return {
1964
1986
  success: false,
1965
1987
  files: [],
@@ -2243,36 +2265,125 @@ function generateBDDScenarios(requirement, context, questions, references = [])
2243
2265
  }
2244
2266
  return scenarios;
2245
2267
  }
2268
+ async function generateBDDScenariosWithAI(requirement, context, questions, references, ctx) {
2269
+ const prompt2 = `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u6D4B\u8BD5\u5DE5\u7A0B\u5E08\u548C\u4E1A\u52A1\u5206\u6790\u5E08\u3002\u8BF7\u6839\u636E\u4EE5\u4E0B\u9700\u6C42\u751F\u6210\u8BE6\u7EC6\u7684 BDD (Behavior Driven Development) \u573A\u666F\u3002
2270
+
2271
+ ## \u9700\u6C42\u63CF\u8FF0
2272
+ ${requirement}
2273
+
2274
+ ## \u9879\u76EE\u4E0A\u4E0B\u6587
2275
+ - \u6280\u672F\u6808: ${context.techStack?.join(", ") || "\u672A\u6307\u5B9A"}
2276
+ - \u6846\u67B6: ${context.framework || "\u672A\u6307\u5B9A"}
2277
+
2278
+ ## \u6F84\u6E05\u95EE\u7B54
2279
+ ${questions.filter((q) => q.answered).map((q) => `- Q: ${q.question}
2280
+ A: ${q.answer}`).join("\n")}
2281
+
2282
+ ## \u53C2\u8003\u8D44\u6E90\u5206\u6790
2283
+ ${references.map((r) => `### ${r.url}
2284
+ ${r.analysis}`).join("\n\n")}
2285
+
2286
+ ## \u8981\u6C42
2287
+ 1. \u6BCF\u4E2A\u529F\u80FD\u6A21\u5757\u751F\u6210\u4E00\u4E2A\u72EC\u7ACB\u7684 Feature
2288
+ 2. \u6BCF\u4E2A Feature \u5305\u542B\u591A\u4E2A\u5177\u4F53\u7684 Scenario
2289
+ 3. \u4F7F\u7528 Given-When-Then \u683C\u5F0F
2290
+ 4. \u573A\u666F\u8981\u8986\u76D6: \u6B63\u5E38\u6D41\u7A0B\u3001\u8FB9\u754C\u60C5\u51B5\u3001\u5F02\u5E38\u5904\u7406
2291
+ 5. \u573A\u666F\u8981\u5177\u4F53\u53EF\u6D4B\u8BD5\uFF0C\u4E0D\u8981\u6CDB\u6CDB\u800C\u8C08
2292
+
2293
+ ## \u8F93\u51FA\u683C\u5F0F (JSON)
2294
+ \`\`\`json
2295
+ [
2296
+ {
2297
+ "feature": "\u529F\u80FD\u540D\u79F0",
2298
+ "description": "\u529F\u80FD\u63CF\u8FF0",
2299
+ "scenarios": [
2300
+ {
2301
+ "name": "\u573A\u666F\u540D\u79F0",
2302
+ "given": ["\u524D\u7F6E\u6761\u4EF61", "\u524D\u7F6E\u6761\u4EF62"],
2303
+ "when": ["\u64CD\u4F5C1", "\u64CD\u4F5C2"],
2304
+ "then": ["\u9884\u671F\u7ED3\u679C1", "\u9884\u671F\u7ED3\u679C2"]
2305
+ }
2306
+ ]
2307
+ }
2308
+ ]
2309
+ \`\`\`
2310
+
2311
+ \u8BF7\u76F4\u63A5\u8F93\u51FA JSON \u6570\u7EC4\uFF0C\u4E0D\u8981\u6709\u5176\u4ED6\u5185\u5BB9\u3002`;
2312
+ const response = await ctx.modelService.sendMessage([
2313
+ { role: "user", content: prompt2 }
2314
+ ], {
2315
+ temperature: 0.3,
2316
+ maxTokens: 4e3,
2317
+ timeout: 12e4
2318
+ });
2319
+ try {
2320
+ const jsonMatch = response.content.match(/```json\s*([\s\S]*?)```/);
2321
+ if (jsonMatch) {
2322
+ return JSON.parse(jsonMatch[1].trim());
2323
+ }
2324
+ return JSON.parse(response.content);
2325
+ } catch {
2326
+ return generateBDDScenarios(requirement, context, questions, references);
2327
+ }
2328
+ }
2246
2329
  function extractFeaturesFromReference(ref) {
2247
2330
  const features = [];
2248
- const analysis = ref.analysis.toLowerCase();
2249
- if (analysis.includes("\u8F93\u5165") || analysis.includes("\u8868\u5355")) {
2250
- features.push({
2251
- title: "\u8F93\u5165\u8868\u5355",
2252
- description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u8F93\u5165\u8868\u5355\u529F\u80FD",
2253
- hasInput: true
2254
- });
2255
- }
2256
- if (analysis.includes("\u6309\u94AE") || analysis.includes("\u64CD\u4F5C")) {
2257
- features.push({
2258
- title: "\u4EA4\u4E92\u6309\u94AE",
2259
- description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u6309\u94AE\u4EA4\u4E92",
2260
- hasInput: false
2261
- });
2331
+ const analysis = ref.analysis;
2332
+ const featureSection = analysis.match(/###?\s*4\.\s*功能拆分建议[\s\S]*?(?=###?\s*\d|$)/i);
2333
+ if (featureSection) {
2334
+ const taskMatches = featureSection[0].matchAll(/[-*]\s*\*\*([^*]+)\*\*[::]?\s*([^\n]+)/g);
2335
+ for (const match of taskMatches) {
2336
+ features.push({
2337
+ title: match[1].trim(),
2338
+ description: match[2].trim(),
2339
+ hasInput: match[2].includes("\u8F93\u5165") || match[2].includes("\u8868\u5355") || match[2].includes("\u7528\u6237")
2340
+ });
2341
+ }
2262
2342
  }
2263
- if (analysis.includes("\u8868\u683C") || analysis.includes("\u5217\u8868")) {
2264
- features.push({
2265
- title: "\u6570\u636E\u5217\u8868",
2266
- description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u6570\u636E\u5C55\u793A",
2267
- hasInput: false
2268
- });
2343
+ const bizSection = analysis.match(/###?\s*1\.\s*业务功能分析[\s\S]*?(?=###?\s*\d|$)/i);
2344
+ if (bizSection && features.length === 0) {
2345
+ const lines = bizSection[0].split("\n").filter((l) => l.trim().startsWith("-") || l.trim().startsWith("*"));
2346
+ for (const line of lines.slice(0, 5)) {
2347
+ const content = line.replace(/^[-*]\s*/, "").trim();
2348
+ if (content.length > 5) {
2349
+ features.push({
2350
+ title: content.slice(0, 20),
2351
+ description: content,
2352
+ hasInput: content.includes("\u8F93\u5165") || content.includes("\u586B\u5199")
2353
+ });
2354
+ }
2355
+ }
2269
2356
  }
2270
- if (analysis.includes("\u56FE\u8868") || analysis.includes("\u53EF\u89C6\u5316")) {
2271
- features.push({
2272
- title: "\u56FE\u8868\u5C55\u793A",
2273
- description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u56FE\u8868\u53EF\u89C6\u5316",
2274
- hasInput: false
2275
- });
2357
+ if (features.length === 0) {
2358
+ const lowerAnalysis = analysis.toLowerCase();
2359
+ if (lowerAnalysis.includes("\u8F93\u5165") || lowerAnalysis.includes("\u8868\u5355")) {
2360
+ features.push({
2361
+ title: "\u8F93\u5165\u8868\u5355",
2362
+ description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u8F93\u5165\u8868\u5355\u529F\u80FD",
2363
+ hasInput: true
2364
+ });
2365
+ }
2366
+ if (lowerAnalysis.includes("\u6309\u94AE") || lowerAnalysis.includes("\u64CD\u4F5C")) {
2367
+ features.push({
2368
+ title: "\u4EA4\u4E92\u6309\u94AE",
2369
+ description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u6309\u94AE\u4EA4\u4E92",
2370
+ hasInput: false
2371
+ });
2372
+ }
2373
+ if (lowerAnalysis.includes("\u8868\u683C") || lowerAnalysis.includes("\u5217\u8868")) {
2374
+ features.push({
2375
+ title: "\u6570\u636E\u5217\u8868",
2376
+ description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u6570\u636E\u5C55\u793A",
2377
+ hasInput: false
2378
+ });
2379
+ }
2380
+ if (lowerAnalysis.includes("\u56FE\u8868") || lowerAnalysis.includes("\u53EF\u89C6\u5316")) {
2381
+ features.push({
2382
+ title: "\u56FE\u8868\u5C55\u793A",
2383
+ description: "\u53C2\u8003\u754C\u9762\u4E2D\u7684\u56FE\u8868\u53EF\u89C6\u5316",
2384
+ hasInput: false
2385
+ });
2386
+ }
2276
2387
  }
2277
2388
  if (features.length === 0) {
2278
2389
  features.push({
@@ -2436,33 +2547,119 @@ function formatSpecFile(session) {
2436
2547
  lines.push("**\u786E\u8BA4\u72B6\u6001**: \u23F3 \u7B49\u5F85\u786E\u8BA4");
2437
2548
  return lines.join("\n");
2438
2549
  }
2439
- async function generateTests(workingDir, session) {
2550
+ async function generateTests(workingDir, session, ctx) {
2440
2551
  const testDir = path5__namespace.join(workingDir, "tests");
2441
2552
  await fs5__namespace.mkdir(testDir, { recursive: true });
2442
2553
  const testFiles = [];
2443
- for (const scenario of session.bddScenarios) {
2444
- const testName = scenario.feature.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, "_");
2445
- const testPath = path5__namespace.join(testDir, `${testName}.test.ts`);
2446
- const content = generateTestFile(scenario);
2447
- await fs5__namespace.writeFile(testPath, content, "utf-8");
2448
- testFiles.push(`tests/${testName}.test.ts`);
2554
+ if (ctx?.modelService) {
2555
+ for (const scenario of session.bddScenarios) {
2556
+ const testName = scenario.feature.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, "_");
2557
+ const testPath = path5__namespace.join(testDir, `${testName}.test.ts`);
2558
+ const loader = new LoadingIndicator(`\u751F\u6210\u6D4B\u8BD5: ${scenario.feature.slice(0, 20)}...`);
2559
+ loader.start();
2560
+ try {
2561
+ const content = await generateTestFileWithAI(scenario, session, ctx);
2562
+ await fs5__namespace.writeFile(testPath, content, "utf-8");
2563
+ testFiles.push(`tests/${testName}.test.ts`);
2564
+ loader.stop(chalk9__default.default.green(` \u2713 \u6D4B\u8BD5\u6587\u4EF6\u5DF2\u751F\u6210`));
2565
+ } catch {
2566
+ const content = generateTestFile(scenario, session);
2567
+ await fs5__namespace.writeFile(testPath, content, "utf-8");
2568
+ testFiles.push(`tests/${testName}.test.ts`);
2569
+ loader.stop(chalk9__default.default.yellow(" \u26A0 \u4F7F\u7528\u57FA\u7840\u6D4B\u8BD5\u6A21\u677F"));
2570
+ }
2571
+ }
2572
+ } else {
2573
+ for (const scenario of session.bddScenarios) {
2574
+ const testName = scenario.feature.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, "_");
2575
+ const testPath = path5__namespace.join(testDir, `${testName}.test.ts`);
2576
+ const content = generateTestFile(scenario, session);
2577
+ await fs5__namespace.writeFile(testPath, content, "utf-8");
2578
+ testFiles.push(`tests/${testName}.test.ts`);
2579
+ }
2449
2580
  }
2450
2581
  return testFiles;
2451
2582
  }
2452
- function generateTestFile(scenario) {
2583
+ async function generateTestFileWithAI(scenario, session, ctx) {
2584
+ const prompt2 = `\u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u6D4B\u8BD5\u5DE5\u7A0B\u5E08\u3002\u8BF7\u6839\u636E\u4EE5\u4E0B BDD \u573A\u666F\u751F\u6210\u5B8C\u6574\u7684 Vitest \u6D4B\u8BD5\u4EE3\u7801\u3002
2585
+
2586
+ ## \u529F\u80FD\u540D\u79F0
2587
+ ${scenario.feature}
2588
+
2589
+ ## BDD \u573A\u666F
2590
+ ${scenario.scenarios.map((s) => `
2591
+ ### ${s.name}
2592
+ - Given: ${s.given.join(", ")}
2593
+ - When: ${s.when.join(", ")}
2594
+ - Then: ${s.then.join(", ")}
2595
+ `).join("\n")}
2596
+
2597
+ ## \u9879\u76EE\u4E0A\u4E0B\u6587
2598
+ - \u6280\u672F\u6808: ${session.context?.techStack?.join(", ") || "TypeScript"}
2599
+ - \u6846\u67B6: ${session.context?.framework || "\u672A\u6307\u5B9A"}
2600
+
2601
+ ## \u8981\u6C42
2602
+ 1. \u4F7F\u7528 vitest \u6D4B\u8BD5\u6846\u67B6 (describe, it, expect, beforeEach \u7B49)
2603
+ 2. \u6BCF\u4E2A\u573A\u666F\u751F\u6210\u4E00\u4E2A\u72EC\u7ACB\u7684\u6D4B\u8BD5\u7528\u4F8B
2604
+ 3. \u6D4B\u8BD5\u4EE3\u7801\u8981\u5B8C\u6574\u53EF\u8FD0\u884C\uFF0C\u5305\u542B\u5FC5\u8981\u7684 mock \u548C setup
2605
+ 4. \u4F7F\u7528\u4E2D\u6587\u6CE8\u91CA\u8BF4\u660E\u6D4B\u8BD5\u610F\u56FE
2606
+ 5. \u6D4B\u8BD5\u8981\u8986\u76D6\u6B63\u5E38\u6D41\u7A0B\u548C\u8FB9\u754C\u60C5\u51B5
2607
+
2608
+ \u8BF7\u76F4\u63A5\u8F93\u51FA\u6D4B\u8BD5\u4EE3\u7801\uFF0C\u4E0D\u9700\u8981\u89E3\u91CA\u3002`;
2609
+ const response = await ctx.modelService.sendMessage([
2610
+ { role: "user", content: prompt2 }
2611
+ ], {
2612
+ temperature: 0.3,
2613
+ maxTokens: 4e3
2614
+ });
2615
+ const codeMatch = response.content.match(/```(?:typescript|ts|javascript|js)?\n([\s\S]*?)```/);
2616
+ if (codeMatch) {
2617
+ return codeMatch[1].trim();
2618
+ }
2619
+ return response.content;
2620
+ }
2621
+ function generateTestFile(scenario, session) {
2453
2622
  const lines = [];
2454
- lines.push(`import { describe, it, expect } from 'vitest';`);
2623
+ lines.push(`import { describe, it, expect, beforeEach } from 'vitest';`);
2455
2624
  lines.push("");
2625
+ lines.push(`/**`);
2626
+ lines.push(` * ${scenario.feature} \u529F\u80FD\u6D4B\u8BD5`);
2627
+ lines.push(` * `);
2628
+ lines.push(` * BDD \u573A\u666F\u6570\u91CF: ${scenario.scenarios.length}`);
2629
+ if (session?.context?.techStack) {
2630
+ lines.push(` * \u6280\u672F\u6808: ${session.context.techStack.join(", ")}`);
2631
+ }
2632
+ lines.push(` */`);
2456
2633
  lines.push(`describe('${scenario.feature}', () => {`);
2457
2634
  for (const s of scenario.scenarios) {
2458
- lines.push(` it('${s.name}', () => {`);
2459
- lines.push(` // Given: ${s.given.join(", ")}`);
2460
- lines.push(` // When: ${s.when.join(", ")}`);
2461
- lines.push(` // Then: ${s.then.join(", ")}`);
2462
- lines.push(` expect(true).toBe(true); // TODO: \u5B9E\u73B0\u6D4B\u8BD5`);
2463
- lines.push(` });`);
2464
2635
  lines.push("");
2636
+ lines.push(` /**`);
2637
+ lines.push(` * \u573A\u666F: ${s.name}`);
2638
+ lines.push(` * Given: ${s.given.join(", ")}`);
2639
+ lines.push(` * When: ${s.when.join(", ")}`);
2640
+ lines.push(` * Then: ${s.then.join(", ")}`);
2641
+ lines.push(` */`);
2642
+ lines.push(` it('${s.name}', async () => {`);
2643
+ lines.push(` // Arrange (Given)`);
2644
+ for (const g of s.given) {
2645
+ lines.push(` // ${g}`);
2646
+ }
2647
+ lines.push(` const input = {}; // TODO: \u8BBE\u7F6E\u521D\u59CB\u72B6\u6001`);
2648
+ lines.push("");
2649
+ lines.push(` // Act (When)`);
2650
+ for (const w of s.when) {
2651
+ lines.push(` // ${w}`);
2652
+ }
2653
+ lines.push(` const result = {}; // TODO: \u6267\u884C\u64CD\u4F5C`);
2654
+ lines.push("");
2655
+ lines.push(` // Assert (Then)`);
2656
+ for (const t of s.then) {
2657
+ lines.push(` // ${t}`);
2658
+ }
2659
+ lines.push(` expect(result).toBeDefined(); // TODO: \u5B8C\u5584\u65AD\u8A00`);
2660
+ lines.push(` });`);
2465
2661
  }
2662
+ lines.push("");
2466
2663
  lines.push(`});`);
2467
2664
  return lines.join("\n");
2468
2665
  }
@@ -2545,39 +2742,67 @@ function detectResourceType(url) {
2545
2742
  return "webpage";
2546
2743
  }
2547
2744
  async function analyzeReferenceContent(url, content, type, ctx) {
2548
- const typePrompts = {
2549
- webpage: "\u5206\u6790\u8FD9\u4E2A\u7F51\u9875\u7684\u529F\u80FD\u3001UI\u7EC4\u4EF6\u548C\u4EA4\u4E92\u65B9\u5F0F",
2550
- design: "\u5206\u6790\u8FD9\u4E2A\u8BBE\u8BA1\u7A3F\u7684\u5E03\u5C40\u3001\u7EC4\u4EF6\u548C\u6837\u5F0F",
2551
- image: "\u63CF\u8FF0\u8FD9\u4E2A\u56FE\u7247\u7684\u5185\u5BB9\u548C\u8BBE\u8BA1\u5143\u7D20",
2552
- api: "\u5206\u6790\u8FD9\u4E2AAPI\u7684\u7ED3\u6784\u548C\u53C2\u6570"
2553
- };
2554
2745
  const prompt2 = `
2555
- \u8BF7\u5206\u6790\u4EE5\u4E0B\u53C2\u8003\u8D44\u6E90\u7684 URL\uFF0C\u63D0\u53D6\u5BF9\u5F00\u53D1\u6709\u7528\u7684\u4FE1\u606F\uFF1A
2746
+ \u4F60\u662F\u4E00\u4E2A\u4E13\u4E1A\u7684\u4EA7\u54C1\u7ECF\u7406\u548C\u524D\u7AEF\u5F00\u53D1\u5DE5\u7A0B\u5E08\u3002\u8BF7\u6DF1\u5165\u5206\u6790\u4EE5\u4E0B\u53C2\u8003\u8D44\u6E90\uFF0C\u63D0\u53D6\u4E1A\u52A1\u529F\u80FD\u548C\u6280\u672F\u5B9E\u73B0\u7EC6\u8282\u3002
2747
+
2748
+ ## \u53C2\u8003\u8D44\u6E90\u4FE1\u606F
2749
+ - URL: ${url}
2750
+ - \u7C7B\u578B: ${type}
2751
+
2752
+ ## \u7F51\u9875\u5185\u5BB9
2753
+ \`\`\`html
2754
+ ${content.slice(0, 8e3)}
2755
+ \`\`\`
2756
+
2757
+ ## \u5206\u6790\u8981\u6C42
2556
2758
 
2557
- URL: ${url}
2558
- \u7C7B\u578B: ${type}
2759
+ \u8BF7\u6309\u7167\u4EE5\u4E0B\u7ED3\u6784\u8FDB\u884C\u8BE6\u7EC6\u5206\u6790\uFF1A
2559
2760
 
2560
- \u5185\u5BB9\u6458\u8981:
2561
- ${content.slice(0, 5e3)}
2761
+ ### 1. \u4E1A\u52A1\u529F\u80FD\u5206\u6790
2762
+ - \u6838\u5FC3\u4E1A\u52A1\u529F\u80FD\u662F\u4EC0\u4E48\uFF1F\uFF08\u8BE6\u7EC6\u63CF\u8FF0\uFF09
2763
+ - \u7528\u6237\u53EF\u4EE5\u505A\u4EC0\u4E48\u64CD\u4F5C\uFF1F
2764
+ - \u4E1A\u52A1\u6D41\u7A0B\u662F\u4EC0\u4E48\uFF1F
2765
+ - \u6570\u636E\u8F93\u5165\u8F93\u51FA\u662F\u4EC0\u4E48\uFF1F
2562
2766
 
2563
- ${typePrompts[type]}
2767
+ ### 2. UI/UX \u7ED3\u6784\u5206\u6790
2768
+ - \u9875\u9762\u5E03\u5C40\u7ED3\u6784
2769
+ - \u4E3B\u8981\u7EC4\u4EF6\u6709\u54EA\u4E9B\uFF1F
2770
+ - \u7EC4\u4EF6\u4E4B\u95F4\u7684\u5173\u7CFB
2771
+ - \u4EA4\u4E92\u65B9\u5F0F\uFF08\u70B9\u51FB\u3001\u8F93\u5165\u3001\u62D6\u62FD\u7B49\uFF09
2564
2772
 
2565
- \u8BF7\u63D0\u53D6\uFF1A
2566
- 1. \u4E3B\u8981\u529F\u80FD\u70B9
2567
- 2. UI\u7EC4\u4EF6\u7ED3\u6784
2568
- 3. \u4EA4\u4E92\u65B9\u5F0F
2569
- 4. \u6570\u636E\u7ED3\u6784\uFF08\u5982\u679C\u6709\uFF09
2570
- 5. \u6280\u672F\u5B9E\u73B0\u5EFA\u8BAE
2773
+ ### 3. \u6570\u636E\u6A21\u578B\u5206\u6790
2774
+ - \u9700\u8981\u54EA\u4E9B\u6570\u636E\uFF1F
2775
+ - \u6570\u636E\u4E4B\u95F4\u7684\u5173\u7CFB
2776
+ - \u6570\u636E\u6765\u6E90\uFF08\u7528\u6237\u8F93\u5165/\u8BA1\u7B97/API\uFF09
2571
2777
 
2572
- \u4EE5\u7B80\u6D01\u7684\u8981\u70B9\u5F62\u5F0F\u8F93\u51FA\u3002
2778
+ ### 4. \u529F\u80FD\u62C6\u5206\u5EFA\u8BAE
2779
+ \u8BF7\u5C06\u529F\u80FD\u62C6\u5206\u4E3A\u53EF\u72EC\u7ACB\u5F00\u53D1\u7684\u4EFB\u52A1\uFF0C\u6BCF\u4E2A\u4EFB\u52A1\u5305\u542B\uFF1A
2780
+ - \u4EFB\u52A1\u540D\u79F0
2781
+ - \u4EFB\u52A1\u63CF\u8FF0
2782
+ - \u6280\u672F\u8981\u70B9
2783
+ - \u4F9D\u8D56\u5173\u7CFB
2784
+
2785
+ ### 5. \u6280\u672F\u5B9E\u73B0\u5EFA\u8BAE
2786
+ - \u63A8\u8350\u7684\u6280\u672F\u65B9\u6848
2787
+ - \u9700\u8981\u6CE8\u610F\u7684\u6280\u672F\u96BE\u70B9
2788
+ - \u6027\u80FD\u4F18\u5316\u5EFA\u8BAE
2789
+
2790
+ \u8BF7\u4EE5 Markdown \u683C\u5F0F\u8F93\u51FA\uFF0C\u91CD\u70B9\u7A81\u51FA\u4E1A\u52A1\u903B\u8F91\u548C\u529F\u80FD\u5B9E\u73B0\u7EC6\u8282\u3002
2573
2791
  `;
2792
+ const loader = new LoadingIndicator("AI \u6B63\u5728\u5206\u6790\u53C2\u8003\u8D44\u6E90");
2793
+ loader.start();
2574
2794
  try {
2575
2795
  const response = await ctx.modelService.sendMessage([
2576
2796
  { role: "user", content: prompt2 }
2577
- ], { temperature: 0.3, maxTokens: 2e3 });
2797
+ ], {
2798
+ temperature: 0.3,
2799
+ maxTokens: 4e3
2800
+ });
2801
+ loader.stop(chalk9__default.default.green(" \u2713 \u5206\u6790\u5B8C\u6210"));
2578
2802
  return response.content;
2579
- } catch {
2580
- return extractBasicInfo(content, type);
2803
+ } catch (error) {
2804
+ loader.stop();
2805
+ throw error;
2581
2806
  }
2582
2807
  }
2583
2808
  function extractBasicInfo(content, type) {
@@ -2618,10 +2843,43 @@ function getActiveSession() {
2618
2843
  function clearActiveSession() {
2619
2844
  activeSession = null;
2620
2845
  }
2621
- var MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, CLARITY_THRESHOLD, activeSession, new_default;
2846
+ var LoadingIndicator, MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, CLARITY_THRESHOLD, activeSession, new_default;
2622
2847
  var init_new = __esm({
2623
2848
  "src/commands/new.ts"() {
2624
2849
  init_cjs_shims();
2850
+ LoadingIndicator = class {
2851
+ frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
2852
+ frameIndex = 0;
2853
+ interval = null;
2854
+ message;
2855
+ constructor(message) {
2856
+ this.message = message;
2857
+ }
2858
+ start() {
2859
+ process.stdout.write("\x1B[?25l");
2860
+ this.interval = setInterval(() => {
2861
+ const frame = this.frames[this.frameIndex];
2862
+ process.stdout.write(`\r${chalk9__default.default.cyan(frame)} ${this.message}...`);
2863
+ this.frameIndex = (this.frameIndex + 1) % this.frames.length;
2864
+ }, 80);
2865
+ }
2866
+ update(message) {
2867
+ this.message = message;
2868
+ }
2869
+ stop(finalMessage) {
2870
+ if (this.interval) {
2871
+ clearInterval(this.interval);
2872
+ this.interval = null;
2873
+ }
2874
+ process.stdout.write("\x1B[?25h");
2875
+ if (finalMessage) {
2876
+ process.stdout.write(`\r${finalMessage}
2877
+ `);
2878
+ } else {
2879
+ process.stdout.write("\r" + " ".repeat(60) + "\r");
2880
+ }
2881
+ }
2882
+ };
2625
2883
  MAX_FILE_SIZE2 = 1024 * 1024;
2626
2884
  COMPLEXITY_THRESHOLD = 6;
2627
2885
  CLARITY_THRESHOLD = 0.6;