@nick848/sf-cli 1.0.16 → 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/CHANGELOG.md +24 -0
- package/dist/cli/index.js +510 -35
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +508 -35
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +508 -35
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1414,6 +1414,7 @@ async function handleNew(args, ctx) {
|
|
|
1414
1414
|
context: null,
|
|
1415
1415
|
clarityScore: 0,
|
|
1416
1416
|
clarificationQuestions: [],
|
|
1417
|
+
referenceResources: [],
|
|
1417
1418
|
complexity: 0,
|
|
1418
1419
|
bddScenarios: [],
|
|
1419
1420
|
specItems: [],
|
|
@@ -1456,7 +1457,7 @@ async function executeWorkflow(ctx) {
|
|
|
1456
1457
|
const lines = [];
|
|
1457
1458
|
try {
|
|
1458
1459
|
if (activeSession.phase === "context") {
|
|
1459
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 1/
|
|
1460
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 1/9: \u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6 \u2501\u2501\u2501"));
|
|
1460
1461
|
lines.push("");
|
|
1461
1462
|
activeSession.context = await readProjectContext(ctx.options.workingDirectory);
|
|
1462
1463
|
lines.push(chalk9__default.default.gray(` \u9879\u76EE: ${activeSession.context.name}`));
|
|
@@ -1470,7 +1471,7 @@ async function executeWorkflow(ctx) {
|
|
|
1470
1471
|
}
|
|
1471
1472
|
if (activeSession.phase === "clarify") {
|
|
1472
1473
|
lines.push("");
|
|
1473
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 2/
|
|
1474
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 2/9: \u9700\u6C42\u6F84\u6E05 \u2501\u2501\u2501"));
|
|
1474
1475
|
lines.push("");
|
|
1475
1476
|
const clarityResult = analyzeRequirementClarity(
|
|
1476
1477
|
activeSession.requirement,
|
|
@@ -1496,11 +1497,40 @@ async function executeWorkflow(ctx) {
|
|
|
1496
1497
|
return { output: lines.join("\n") };
|
|
1497
1498
|
}
|
|
1498
1499
|
lines.push(chalk9__default.default.green(" \u2713 \u9700\u6C42\u6E05\u6670\uFF0C\u7EE7\u7EED\u4E0B\u4E00\u6B65"));
|
|
1500
|
+
activeSession.phase = "reference";
|
|
1501
|
+
}
|
|
1502
|
+
if (activeSession.phase === "reference") {
|
|
1503
|
+
lines.push("");
|
|
1504
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 3/9: \u53C2\u8003\u8D44\u6E90\u5206\u6790 \u2501\u2501\u2501"));
|
|
1505
|
+
lines.push("");
|
|
1506
|
+
const urls = extractUrls(activeSession.refinedRequirement);
|
|
1507
|
+
if (urls.length > 0) {
|
|
1508
|
+
lines.push(chalk9__default.default.gray(` \u53D1\u73B0 ${urls.length} \u4E2A\u53C2\u8003\u94FE\u63A5`));
|
|
1509
|
+
lines.push("");
|
|
1510
|
+
for (const url of urls) {
|
|
1511
|
+
lines.push(chalk9__default.default.gray(` \u{1F4CE} ${url}`));
|
|
1512
|
+
try {
|
|
1513
|
+
const resource = await fetchAndAnalyzeReference(url, ctx);
|
|
1514
|
+
activeSession.referenceResources.push(resource);
|
|
1515
|
+
lines.push(chalk9__default.default.green(` \u2713 \u5DF2\u5206\u6790`));
|
|
1516
|
+
activeSession.refinedRequirement += `
|
|
1517
|
+
|
|
1518
|
+
\u3010\u53C2\u8003\u8D44\u6E90\u5206\u6790 - ${url}\u3011
|
|
1519
|
+
${resource.analysis}`;
|
|
1520
|
+
} catch (error) {
|
|
1521
|
+
lines.push(chalk9__default.default.yellow(` \u26A0 \u83B7\u53D6\u5931\u8D25: ${error.message}`));
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
lines.push("");
|
|
1525
|
+
lines.push(chalk9__default.default.green(" \u2713 \u53C2\u8003\u8D44\u6E90\u5206\u6790\u5B8C\u6210"));
|
|
1526
|
+
} else {
|
|
1527
|
+
lines.push(chalk9__default.default.gray(" \u65E0\u5916\u90E8\u53C2\u8003\u94FE\u63A5"));
|
|
1528
|
+
}
|
|
1499
1529
|
activeSession.phase = "analysis";
|
|
1500
1530
|
}
|
|
1501
1531
|
if (activeSession.phase === "analysis") {
|
|
1502
1532
|
lines.push("");
|
|
1503
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1533
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 4/9: \u590D\u6742\u5EA6\u8BC4\u4F30 \u2501\u2501\u2501"));
|
|
1504
1534
|
lines.push("");
|
|
1505
1535
|
activeSession.complexity = analyzeComplexity(
|
|
1506
1536
|
activeSession.refinedRequirement,
|
|
@@ -1517,13 +1547,28 @@ async function executeWorkflow(ctx) {
|
|
|
1517
1547
|
}
|
|
1518
1548
|
if (activeSession.phase === "bdd") {
|
|
1519
1549
|
lines.push("");
|
|
1520
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1550
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 5/9: BDD \u573A\u666F\u62C6\u89E3 \u2501\u2501\u2501"));
|
|
1521
1551
|
lines.push("");
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
activeSession.
|
|
1526
|
-
|
|
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
|
+
}
|
|
1527
1572
|
for (const scenario of activeSession.bddScenarios) {
|
|
1528
1573
|
lines.push(chalk9__default.default.white(` Feature: ${scenario.feature}`));
|
|
1529
1574
|
for (const s of scenario.scenarios.slice(0, 3)) {
|
|
@@ -1537,13 +1582,14 @@ async function executeWorkflow(ctx) {
|
|
|
1537
1582
|
}
|
|
1538
1583
|
if (activeSession.phase === "spec") {
|
|
1539
1584
|
lines.push("");
|
|
1540
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1585
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 6/9: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
|
|
1541
1586
|
lines.push("");
|
|
1542
1587
|
activeSession.specItems = generateSpecItems(
|
|
1543
1588
|
activeSession.refinedRequirement,
|
|
1544
1589
|
activeSession.context,
|
|
1545
1590
|
activeSession.bddScenarios,
|
|
1546
|
-
activeSession.clarificationQuestions
|
|
1591
|
+
activeSession.clarificationQuestions,
|
|
1592
|
+
activeSession.referenceResources
|
|
1547
1593
|
);
|
|
1548
1594
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
1549
1595
|
lines.push(chalk9__default.default.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
@@ -1567,9 +1613,9 @@ async function executeWorkflow(ctx) {
|
|
|
1567
1613
|
}
|
|
1568
1614
|
if (activeSession.phase === "tdd") {
|
|
1569
1615
|
lines.push("");
|
|
1570
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1616
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 7/9: TDD \u6D4B\u8BD5\u751F\u6210 \u2501\u2501\u2501"));
|
|
1571
1617
|
lines.push("");
|
|
1572
|
-
activeSession.testFiles = await generateTests(ctx.options.workingDirectory, activeSession);
|
|
1618
|
+
activeSession.testFiles = await generateTests(ctx.options.workingDirectory, activeSession, ctx);
|
|
1573
1619
|
lines.push(chalk9__default.default.green(" \u2713 \u6D4B\u8BD5\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
1574
1620
|
for (const file of activeSession.testFiles) {
|
|
1575
1621
|
lines.push(chalk9__default.default.gray(` - ${file}`));
|
|
@@ -1578,7 +1624,7 @@ async function executeWorkflow(ctx) {
|
|
|
1578
1624
|
}
|
|
1579
1625
|
if (activeSession.phase === "develop") {
|
|
1580
1626
|
lines.push("");
|
|
1581
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1627
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 8/9: \u5F00\u53D1\u5B9E\u73B0 \u2501\u2501\u2501"));
|
|
1582
1628
|
lines.push("");
|
|
1583
1629
|
lines.push(chalk9__default.default.yellow(" \u{1F680} \u6B63\u5728\u8C03\u7528 AI \u751F\u6210\u4EE3\u7801..."));
|
|
1584
1630
|
try {
|
|
@@ -1603,7 +1649,7 @@ async function executeWorkflow(ctx) {
|
|
|
1603
1649
|
}
|
|
1604
1650
|
if (activeSession.phase === "review") {
|
|
1605
1651
|
lines.push("");
|
|
1606
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1652
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 9/9: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
|
|
1607
1653
|
lines.push("");
|
|
1608
1654
|
lines.push(chalk9__default.default.yellow(" \u{1F50D} \u6B63\u5728\u8FDB\u884C\u4EE3\u7801\u5BA1\u6838..."));
|
|
1609
1655
|
try {
|
|
@@ -1866,6 +1912,8 @@ function getCategoryLabel(category) {
|
|
|
1866
1912
|
async function executeDevelopment(ctx, session) {
|
|
1867
1913
|
const workingDir = ctx.options.workingDirectory;
|
|
1868
1914
|
const files = [];
|
|
1915
|
+
const loader = new LoadingIndicator("AI \u6B63\u5728\u751F\u6210\u4EE3\u7801");
|
|
1916
|
+
loader.start();
|
|
1869
1917
|
try {
|
|
1870
1918
|
const systemPrompt = buildDevelopmentPrompt(session);
|
|
1871
1919
|
const messages = [
|
|
@@ -1893,11 +1941,15 @@ ${session.context.devStandards.slice(0, 2e3)}` : ""}`
|
|
|
1893
1941
|
content: systemPrompt
|
|
1894
1942
|
}
|
|
1895
1943
|
];
|
|
1944
|
+
loader.update("\u6B63\u5728\u8C03\u7528 AI \u6A21\u578B");
|
|
1896
1945
|
const response = await ctx.modelService.sendMessage(messages, {
|
|
1897
1946
|
temperature: 0.3,
|
|
1898
1947
|
maxTokens: 8e3,
|
|
1899
|
-
agent: "frontend-dev"
|
|
1948
|
+
agent: "frontend-dev",
|
|
1949
|
+
timeout: 18e4
|
|
1950
|
+
// 3 分钟超时
|
|
1900
1951
|
});
|
|
1952
|
+
loader.update("\u6B63\u5728\u89E3\u6790\u4EE3\u7801");
|
|
1901
1953
|
const codeBlocks = parseCodeBlocks(response.content);
|
|
1902
1954
|
for (const block of codeBlocks) {
|
|
1903
1955
|
const filePath = path5__namespace.join(workingDir, block.filename);
|
|
@@ -1926,8 +1978,10 @@ export function ${featureName.replace(/[^a-zA-Z0-9]/g, "")}() {
|
|
|
1926
1978
|
await fs5__namespace.writeFile(filePath, stubCode, "utf-8");
|
|
1927
1979
|
files.push(`src/features/${fileName}`);
|
|
1928
1980
|
}
|
|
1981
|
+
loader.stop(chalk9__default.default.green(` \u2713 \u5DF2\u751F\u6210 ${files.length} \u4E2A\u6587\u4EF6`));
|
|
1929
1982
|
return { success: true, files };
|
|
1930
1983
|
} catch (error) {
|
|
1984
|
+
loader.stop();
|
|
1931
1985
|
return {
|
|
1932
1986
|
success: false,
|
|
1933
1987
|
files: [],
|
|
@@ -2145,13 +2199,41 @@ function analyzeComplexity(requirement, context) {
|
|
|
2145
2199
|
if (!context.framework) score += 0.5;
|
|
2146
2200
|
return Math.max(1, Math.min(10, Math.round(score)));
|
|
2147
2201
|
}
|
|
2148
|
-
function generateBDDScenarios(requirement, context, questions) {
|
|
2202
|
+
function generateBDDScenarios(requirement, context, questions, references = []) {
|
|
2149
2203
|
const scenarios = [];
|
|
2150
2204
|
questions.find((q) => q.category === "ui" && q.answered)?.answer;
|
|
2151
2205
|
const interactionAnswer = questions.find((q) => q.category === "interaction" && q.answered)?.answer;
|
|
2152
2206
|
const edgeAnswer = questions.find((q) => q.category === "edge" && q.answered)?.answer;
|
|
2207
|
+
if (references.length > 0) {
|
|
2208
|
+
for (const ref of references) {
|
|
2209
|
+
const refFeatures = extractFeaturesFromReference(ref);
|
|
2210
|
+
for (const feature of refFeatures) {
|
|
2211
|
+
const scenario = {
|
|
2212
|
+
feature: feature.title,
|
|
2213
|
+
description: feature.description,
|
|
2214
|
+
scenarios: []
|
|
2215
|
+
};
|
|
2216
|
+
scenario.scenarios.push({
|
|
2217
|
+
name: `\u6B63\u5E38\u6D41\u7A0B: ${feature.title}`,
|
|
2218
|
+
given: [`\u7528\u6237\u8FDB\u5165\u76F8\u5173\u9875\u9762`],
|
|
2219
|
+
when: [`\u7528\u6237\u6267\u884C "${feature.title}" \u64CD\u4F5C`],
|
|
2220
|
+
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u5E76\u8FD4\u56DE\u9884\u671F\u7ED3\u679C`]
|
|
2221
|
+
});
|
|
2222
|
+
if (feature.hasInput) {
|
|
2223
|
+
scenario.scenarios.push({
|
|
2224
|
+
name: `\u8FB9\u754C\u60C5\u51B5: \u8F93\u5165\u9A8C\u8BC1`,
|
|
2225
|
+
given: [`\u7528\u6237\u8FDB\u5165\u8F93\u5165\u754C\u9762`],
|
|
2226
|
+
when: [`\u7528\u6237\u8F93\u5165\u8FB9\u754C\u503C\u6216\u7A7A\u503C`],
|
|
2227
|
+
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u8FB9\u754C\u60C5\u51B5`]
|
|
2228
|
+
});
|
|
2229
|
+
}
|
|
2230
|
+
scenarios.push(scenario);
|
|
2231
|
+
}
|
|
2232
|
+
}
|
|
2233
|
+
}
|
|
2153
2234
|
const features = extractFeatures(requirement);
|
|
2154
2235
|
for (const feature of features) {
|
|
2236
|
+
if (scenarios.some((s) => s.feature === feature.title)) continue;
|
|
2155
2237
|
const scenario = {
|
|
2156
2238
|
feature: feature.title,
|
|
2157
2239
|
description: feature.description,
|
|
@@ -2183,6 +2265,135 @@ function generateBDDScenarios(requirement, context, questions) {
|
|
|
2183
2265
|
}
|
|
2184
2266
|
return scenarios;
|
|
2185
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
|
+
}
|
|
2329
|
+
function extractFeaturesFromReference(ref) {
|
|
2330
|
+
const features = [];
|
|
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
|
+
}
|
|
2342
|
+
}
|
|
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
|
+
}
|
|
2356
|
+
}
|
|
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
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
if (features.length === 0) {
|
|
2389
|
+
features.push({
|
|
2390
|
+
title: "\u53C2\u8003\u529F\u80FD\u5B9E\u73B0",
|
|
2391
|
+
description: `\u57FA\u4E8E\u53C2\u8003\u8D44\u6E90 ${ref.url} \u5B9E\u73B0\u7684\u529F\u80FD`,
|
|
2392
|
+
hasInput: true
|
|
2393
|
+
});
|
|
2394
|
+
}
|
|
2395
|
+
return features;
|
|
2396
|
+
}
|
|
2186
2397
|
function extractFeatures(requirement) {
|
|
2187
2398
|
const features = [];
|
|
2188
2399
|
const urlMatch = requirement.match(/https?:\/\/[^\s]+/);
|
|
@@ -2223,15 +2434,26 @@ function extractFeatures(requirement) {
|
|
|
2223
2434
|
}
|
|
2224
2435
|
return features;
|
|
2225
2436
|
}
|
|
2226
|
-
function generateSpecItems(requirement, context, bddScenarios, questions) {
|
|
2437
|
+
function generateSpecItems(requirement, context, bddScenarios, questions, references = []) {
|
|
2227
2438
|
const items = [];
|
|
2228
2439
|
let id = 1;
|
|
2440
|
+
for (const ref of references) {
|
|
2441
|
+
items.push({
|
|
2442
|
+
id: `T${id.toString().padStart(3, "0")}`,
|
|
2443
|
+
title: `\u53C2\u8003\u5206\u6790: ${ref.type}`,
|
|
2444
|
+
description: `\u5206\u6790\u53C2\u8003\u8D44\u6E90 ${ref.url}`,
|
|
2445
|
+
priority: "high",
|
|
2446
|
+
files: [],
|
|
2447
|
+
tests: []
|
|
2448
|
+
});
|
|
2449
|
+
id++;
|
|
2450
|
+
}
|
|
2229
2451
|
for (const scenario of bddScenarios) {
|
|
2230
2452
|
items.push({
|
|
2231
2453
|
id: `T${id.toString().padStart(3, "0")}`,
|
|
2232
2454
|
title: scenario.feature,
|
|
2233
2455
|
description: scenario.description,
|
|
2234
|
-
priority: id <=
|
|
2456
|
+
priority: id <= 3 ? "high" : "medium",
|
|
2235
2457
|
files: [],
|
|
2236
2458
|
tests: []
|
|
2237
2459
|
});
|
|
@@ -2274,6 +2496,19 @@ function formatSpecFile(session) {
|
|
|
2274
2496
|
lines.push("---");
|
|
2275
2497
|
lines.push("");
|
|
2276
2498
|
}
|
|
2499
|
+
if (session.referenceResources.length > 0) {
|
|
2500
|
+
lines.push("## \u53C2\u8003\u8D44\u6E90");
|
|
2501
|
+
lines.push("");
|
|
2502
|
+
for (const ref of session.referenceResources) {
|
|
2503
|
+
lines.push(`### ${ref.url}`);
|
|
2504
|
+
lines.push(`> \u7C7B\u578B: ${ref.type}`);
|
|
2505
|
+
lines.push("");
|
|
2506
|
+
lines.push(ref.analysis);
|
|
2507
|
+
lines.push("");
|
|
2508
|
+
}
|
|
2509
|
+
lines.push("---");
|
|
2510
|
+
lines.push("");
|
|
2511
|
+
}
|
|
2277
2512
|
if (session.clarificationQuestions.some((q) => q.answered)) {
|
|
2278
2513
|
lines.push("## \u9700\u6C42\u6F84\u6E05");
|
|
2279
2514
|
lines.push("");
|
|
@@ -2312,33 +2547,119 @@ function formatSpecFile(session) {
|
|
|
2312
2547
|
lines.push("**\u786E\u8BA4\u72B6\u6001**: \u23F3 \u7B49\u5F85\u786E\u8BA4");
|
|
2313
2548
|
return lines.join("\n");
|
|
2314
2549
|
}
|
|
2315
|
-
async function generateTests(workingDir, session) {
|
|
2550
|
+
async function generateTests(workingDir, session, ctx) {
|
|
2316
2551
|
const testDir = path5__namespace.join(workingDir, "tests");
|
|
2317
2552
|
await fs5__namespace.mkdir(testDir, { recursive: true });
|
|
2318
2553
|
const testFiles = [];
|
|
2319
|
-
|
|
2320
|
-
const
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
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
|
+
}
|
|
2325
2580
|
}
|
|
2326
2581
|
return testFiles;
|
|
2327
2582
|
}
|
|
2328
|
-
function
|
|
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) {
|
|
2329
2622
|
const lines = [];
|
|
2330
|
-
lines.push(`import { describe, it, expect } from 'vitest';`);
|
|
2623
|
+
lines.push(`import { describe, it, expect, beforeEach } from 'vitest';`);
|
|
2331
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(` */`);
|
|
2332
2633
|
lines.push(`describe('${scenario.feature}', () => {`);
|
|
2333
2634
|
for (const s of scenario.scenarios) {
|
|
2334
|
-
lines.push(` it('${s.name}', () => {`);
|
|
2335
|
-
lines.push(` // Given: ${s.given.join(", ")}`);
|
|
2336
|
-
lines.push(` // When: ${s.when.join(", ")}`);
|
|
2337
|
-
lines.push(` // Then: ${s.then.join(", ")}`);
|
|
2338
|
-
lines.push(` expect(true).toBe(true); // TODO: \u5B9E\u73B0\u6D4B\u8BD5`);
|
|
2339
|
-
lines.push(` });`);
|
|
2340
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(` });`);
|
|
2341
2661
|
}
|
|
2662
|
+
lines.push("");
|
|
2342
2663
|
lines.push(`});`);
|
|
2343
2664
|
return lines.join("\n");
|
|
2344
2665
|
}
|
|
@@ -2379,6 +2700,124 @@ function generateSessionId() {
|
|
|
2379
2700
|
const random = Math.random().toString(36).slice(2, 6);
|
|
2380
2701
|
return `WF-${timestamp}-${random}`.toUpperCase();
|
|
2381
2702
|
}
|
|
2703
|
+
function extractUrls(text) {
|
|
2704
|
+
const urlRegex = /https?:\/\/[^\s<>"{}|\\^`\[\]]+/gi;
|
|
2705
|
+
const matches = text.match(urlRegex);
|
|
2706
|
+
return matches ? [...new Set(matches)] : [];
|
|
2707
|
+
}
|
|
2708
|
+
async function fetchAndAnalyzeReference(url, ctx) {
|
|
2709
|
+
const type = detectResourceType(url);
|
|
2710
|
+
let content = "";
|
|
2711
|
+
let analysis = "";
|
|
2712
|
+
try {
|
|
2713
|
+
const response = await fetch(url, {
|
|
2714
|
+
headers: {
|
|
2715
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
|
2716
|
+
}
|
|
2717
|
+
});
|
|
2718
|
+
if (!response.ok) {
|
|
2719
|
+
throw new Error(`HTTP ${response.status}`);
|
|
2720
|
+
}
|
|
2721
|
+
content = await response.text();
|
|
2722
|
+
if (ctx.modelService.getCurrentModel()) {
|
|
2723
|
+
analysis = await analyzeReferenceContent(url, content, type, ctx);
|
|
2724
|
+
} else {
|
|
2725
|
+
analysis = extractBasicInfo(content, type);
|
|
2726
|
+
}
|
|
2727
|
+
} catch (error) {
|
|
2728
|
+
throw new Error(`\u65E0\u6CD5\u83B7\u53D6\u53C2\u8003\u8D44\u6E90: ${error.message}`);
|
|
2729
|
+
}
|
|
2730
|
+
return { url, type, content: content.slice(0, 1e4), analysis };
|
|
2731
|
+
}
|
|
2732
|
+
function detectResourceType(url) {
|
|
2733
|
+
if (url.includes("figma.com") || url.includes("lanhuapp.com")) {
|
|
2734
|
+
return "design";
|
|
2735
|
+
}
|
|
2736
|
+
if (/\.(png|jpg|jpeg|gif|webp|svg)$/i.test(url)) {
|
|
2737
|
+
return "image";
|
|
2738
|
+
}
|
|
2739
|
+
if (/api\//i.test(url)) {
|
|
2740
|
+
return "api";
|
|
2741
|
+
}
|
|
2742
|
+
return "webpage";
|
|
2743
|
+
}
|
|
2744
|
+
async function analyzeReferenceContent(url, content, type, ctx) {
|
|
2745
|
+
const prompt2 = `
|
|
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
|
|
2758
|
+
|
|
2759
|
+
\u8BF7\u6309\u7167\u4EE5\u4E0B\u7ED3\u6784\u8FDB\u884C\u8BE6\u7EC6\u5206\u6790\uFF1A
|
|
2760
|
+
|
|
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
|
|
2766
|
+
|
|
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
|
|
2772
|
+
|
|
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
|
|
2777
|
+
|
|
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
|
|
2791
|
+
`;
|
|
2792
|
+
const loader = new LoadingIndicator("AI \u6B63\u5728\u5206\u6790\u53C2\u8003\u8D44\u6E90");
|
|
2793
|
+
loader.start();
|
|
2794
|
+
try {
|
|
2795
|
+
const response = await ctx.modelService.sendMessage([
|
|
2796
|
+
{ role: "user", content: prompt2 }
|
|
2797
|
+
], {
|
|
2798
|
+
temperature: 0.3,
|
|
2799
|
+
maxTokens: 4e3
|
|
2800
|
+
});
|
|
2801
|
+
loader.stop(chalk9__default.default.green(" \u2713 \u5206\u6790\u5B8C\u6210"));
|
|
2802
|
+
return response.content;
|
|
2803
|
+
} catch (error) {
|
|
2804
|
+
loader.stop();
|
|
2805
|
+
throw error;
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
function extractBasicInfo(content, type) {
|
|
2809
|
+
const titleMatch = content.match(/<title[^>]*>([^<]+)<\/title>/i);
|
|
2810
|
+
const descMatch = content.match(/<meta[^>]*name=["']description["'][^>]*content=["']([^"']+)["']/i);
|
|
2811
|
+
const parts = [];
|
|
2812
|
+
if (titleMatch) {
|
|
2813
|
+
parts.push(`\u6807\u9898: ${titleMatch[1]}`);
|
|
2814
|
+
}
|
|
2815
|
+
if (descMatch) {
|
|
2816
|
+
parts.push(`\u63CF\u8FF0: ${descMatch[1]}`);
|
|
2817
|
+
}
|
|
2818
|
+
parts.push(`\u8D44\u6E90\u7C7B\u578B: ${type}`);
|
|
2819
|
+
return parts.join("\n");
|
|
2820
|
+
}
|
|
2382
2821
|
function generateComplexityBar(score) {
|
|
2383
2822
|
const filled = Math.round(score / 2);
|
|
2384
2823
|
const empty = 5 - filled;
|
|
@@ -2388,6 +2827,7 @@ function getPhaseLabel(phase) {
|
|
|
2388
2827
|
const labels = {
|
|
2389
2828
|
context: "\u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6",
|
|
2390
2829
|
clarify: "\u9700\u6C42\u6F84\u6E05",
|
|
2830
|
+
reference: "\u53C2\u8003\u8D44\u6E90\u5206\u6790",
|
|
2391
2831
|
analysis: "\u590D\u6742\u5EA6\u8BC4\u4F30",
|
|
2392
2832
|
bdd: "BDD \u573A\u666F\u62C6\u89E3",
|
|
2393
2833
|
spec: "OpenSpec \u89C4\u683C",
|
|
@@ -2403,10 +2843,43 @@ function getActiveSession() {
|
|
|
2403
2843
|
function clearActiveSession() {
|
|
2404
2844
|
activeSession = null;
|
|
2405
2845
|
}
|
|
2406
|
-
var MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, CLARITY_THRESHOLD, activeSession, new_default;
|
|
2846
|
+
var LoadingIndicator, MAX_FILE_SIZE2, COMPLEXITY_THRESHOLD, CLARITY_THRESHOLD, activeSession, new_default;
|
|
2407
2847
|
var init_new = __esm({
|
|
2408
2848
|
"src/commands/new.ts"() {
|
|
2409
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
|
+
};
|
|
2410
2883
|
MAX_FILE_SIZE2 = 1024 * 1024;
|
|
2411
2884
|
COMPLEXITY_THRESHOLD = 6;
|
|
2412
2885
|
CLARITY_THRESHOLD = 0.6;
|
|
@@ -7468,6 +7941,7 @@ var STEP_DISPLAY_NAMES = {
|
|
|
7468
7941
|
"archive": "\u5F52\u6863",
|
|
7469
7942
|
"context": "\u4E0A\u4E0B\u6587",
|
|
7470
7943
|
"clarify": "\u6F84\u6E05",
|
|
7944
|
+
"reference": "\u53C2\u8003\u5206\u6790",
|
|
7471
7945
|
"analysis": "\u5206\u6790",
|
|
7472
7946
|
"bdd": "BDD",
|
|
7473
7947
|
"spec": "\u89C4\u683C",
|
|
@@ -7484,6 +7958,7 @@ var STEP_COLORS = {
|
|
|
7484
7958
|
"archive": chalk9__default.default.gray,
|
|
7485
7959
|
"context": chalk9__default.default.magenta,
|
|
7486
7960
|
"clarify": chalk9__default.default.yellow,
|
|
7961
|
+
"reference": chalk9__default.default.blue,
|
|
7487
7962
|
"analysis": chalk9__default.default.blue,
|
|
7488
7963
|
"bdd": chalk9__default.default.cyan,
|
|
7489
7964
|
"spec": chalk9__default.default.green,
|