@nick848/sf-cli 1.0.16 → 1.0.17
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 +230 -13
- 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 +228 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +228 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## v1.0.16 (2026-03-22)
|
|
9
|
+
|
|
10
|
+
**新增参考资源分析阶段**
|
|
11
|
+
|
|
12
|
+
- ✨ 新增「阶段 3/9: 参考资源分析」- 自动提取需求中的 URL 并分析
|
|
13
|
+
- ✨ 支持网页、设计稿、图片、API 等多种参考类型
|
|
14
|
+
- ✨ 使用 AI 分析参考内容,提取功能点、UI 结构、交互方式
|
|
15
|
+
- 🔧 规格拆分前先获取并理解参考内容,生成更精准的任务
|
|
16
|
+
|
|
17
|
+
**新工作流**:
|
|
18
|
+
```
|
|
19
|
+
阶段 1: 项目上下文获取
|
|
20
|
+
阶段 2: 需求澄清
|
|
21
|
+
阶段 3: 参考资源分析 ← 新增
|
|
22
|
+
- 自动提取 URL
|
|
23
|
+
- 获取资源内容
|
|
24
|
+
- AI 分析功能/结构
|
|
25
|
+
- 追加到精炼需求
|
|
26
|
+
阶段 4: 复杂度评估
|
|
27
|
+
阶段 5: BDD 场景拆解
|
|
28
|
+
阶段 6: OpenSpec 规格
|
|
29
|
+
阶段 7-9: TDD → 开发 → 审核
|
|
30
|
+
```
|
|
31
|
+
|
|
8
32
|
## v1.0.13 (2026-03-22)
|
|
9
33
|
|
|
10
34
|
**修复 DeepSeek API Key 验证**
|
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,12 +1547,13 @@ 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
1552
|
activeSession.bddScenarios = generateBDDScenarios(
|
|
1523
1553
|
activeSession.refinedRequirement,
|
|
1524
1554
|
activeSession.context,
|
|
1525
|
-
activeSession.clarificationQuestions
|
|
1555
|
+
activeSession.clarificationQuestions,
|
|
1556
|
+
activeSession.referenceResources
|
|
1526
1557
|
);
|
|
1527
1558
|
for (const scenario of activeSession.bddScenarios) {
|
|
1528
1559
|
lines.push(chalk9__default.default.white(` Feature: ${scenario.feature}`));
|
|
@@ -1537,13 +1568,14 @@ async function executeWorkflow(ctx) {
|
|
|
1537
1568
|
}
|
|
1538
1569
|
if (activeSession.phase === "spec") {
|
|
1539
1570
|
lines.push("");
|
|
1540
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1571
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 6/9: OpenSpec \u89C4\u683C \u2501\u2501\u2501"));
|
|
1541
1572
|
lines.push("");
|
|
1542
1573
|
activeSession.specItems = generateSpecItems(
|
|
1543
1574
|
activeSession.refinedRequirement,
|
|
1544
1575
|
activeSession.context,
|
|
1545
1576
|
activeSession.bddScenarios,
|
|
1546
|
-
activeSession.clarificationQuestions
|
|
1577
|
+
activeSession.clarificationQuestions,
|
|
1578
|
+
activeSession.referenceResources
|
|
1547
1579
|
);
|
|
1548
1580
|
const specPath = await saveSpecFile(ctx.options.workingDirectory, activeSession);
|
|
1549
1581
|
lines.push(chalk9__default.default.green(" \u2713 \u89C4\u683C\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
@@ -1567,7 +1599,7 @@ async function executeWorkflow(ctx) {
|
|
|
1567
1599
|
}
|
|
1568
1600
|
if (activeSession.phase === "tdd") {
|
|
1569
1601
|
lines.push("");
|
|
1570
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1602
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 7/9: TDD \u6D4B\u8BD5\u751F\u6210 \u2501\u2501\u2501"));
|
|
1571
1603
|
lines.push("");
|
|
1572
1604
|
activeSession.testFiles = await generateTests(ctx.options.workingDirectory, activeSession);
|
|
1573
1605
|
lines.push(chalk9__default.default.green(" \u2713 \u6D4B\u8BD5\u6587\u4EF6\u5DF2\u751F\u6210"));
|
|
@@ -1578,7 +1610,7 @@ async function executeWorkflow(ctx) {
|
|
|
1578
1610
|
}
|
|
1579
1611
|
if (activeSession.phase === "develop") {
|
|
1580
1612
|
lines.push("");
|
|
1581
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1613
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 8/9: \u5F00\u53D1\u5B9E\u73B0 \u2501\u2501\u2501"));
|
|
1582
1614
|
lines.push("");
|
|
1583
1615
|
lines.push(chalk9__default.default.yellow(" \u{1F680} \u6B63\u5728\u8C03\u7528 AI \u751F\u6210\u4EE3\u7801..."));
|
|
1584
1616
|
try {
|
|
@@ -1603,7 +1635,7 @@ async function executeWorkflow(ctx) {
|
|
|
1603
1635
|
}
|
|
1604
1636
|
if (activeSession.phase === "review") {
|
|
1605
1637
|
lines.push("");
|
|
1606
|
-
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5
|
|
1638
|
+
lines.push(chalk9__default.default.cyan("\u2501\u2501\u2501 \u9636\u6BB5 9/9: \u4EE3\u7801\u5BA1\u6838 \u2501\u2501\u2501"));
|
|
1607
1639
|
lines.push("");
|
|
1608
1640
|
lines.push(chalk9__default.default.yellow(" \u{1F50D} \u6B63\u5728\u8FDB\u884C\u4EE3\u7801\u5BA1\u6838..."));
|
|
1609
1641
|
try {
|
|
@@ -2145,13 +2177,41 @@ function analyzeComplexity(requirement, context) {
|
|
|
2145
2177
|
if (!context.framework) score += 0.5;
|
|
2146
2178
|
return Math.max(1, Math.min(10, Math.round(score)));
|
|
2147
2179
|
}
|
|
2148
|
-
function generateBDDScenarios(requirement, context, questions) {
|
|
2180
|
+
function generateBDDScenarios(requirement, context, questions, references = []) {
|
|
2149
2181
|
const scenarios = [];
|
|
2150
2182
|
questions.find((q) => q.category === "ui" && q.answered)?.answer;
|
|
2151
2183
|
const interactionAnswer = questions.find((q) => q.category === "interaction" && q.answered)?.answer;
|
|
2152
2184
|
const edgeAnswer = questions.find((q) => q.category === "edge" && q.answered)?.answer;
|
|
2185
|
+
if (references.length > 0) {
|
|
2186
|
+
for (const ref of references) {
|
|
2187
|
+
const refFeatures = extractFeaturesFromReference(ref);
|
|
2188
|
+
for (const feature of refFeatures) {
|
|
2189
|
+
const scenario = {
|
|
2190
|
+
feature: feature.title,
|
|
2191
|
+
description: feature.description,
|
|
2192
|
+
scenarios: []
|
|
2193
|
+
};
|
|
2194
|
+
scenario.scenarios.push({
|
|
2195
|
+
name: `\u6B63\u5E38\u6D41\u7A0B: ${feature.title}`,
|
|
2196
|
+
given: [`\u7528\u6237\u8FDB\u5165\u76F8\u5173\u9875\u9762`],
|
|
2197
|
+
when: [`\u7528\u6237\u6267\u884C "${feature.title}" \u64CD\u4F5C`],
|
|
2198
|
+
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u5E76\u8FD4\u56DE\u9884\u671F\u7ED3\u679C`]
|
|
2199
|
+
});
|
|
2200
|
+
if (feature.hasInput) {
|
|
2201
|
+
scenario.scenarios.push({
|
|
2202
|
+
name: `\u8FB9\u754C\u60C5\u51B5: \u8F93\u5165\u9A8C\u8BC1`,
|
|
2203
|
+
given: [`\u7528\u6237\u8FDB\u5165\u8F93\u5165\u754C\u9762`],
|
|
2204
|
+
when: [`\u7528\u6237\u8F93\u5165\u8FB9\u754C\u503C\u6216\u7A7A\u503C`],
|
|
2205
|
+
then: [`\u7CFB\u7EDF\u5E94\u6B63\u786E\u5904\u7406\u8FB9\u754C\u60C5\u51B5`]
|
|
2206
|
+
});
|
|
2207
|
+
}
|
|
2208
|
+
scenarios.push(scenario);
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2153
2212
|
const features = extractFeatures(requirement);
|
|
2154
2213
|
for (const feature of features) {
|
|
2214
|
+
if (scenarios.some((s) => s.feature === feature.title)) continue;
|
|
2155
2215
|
const scenario = {
|
|
2156
2216
|
feature: feature.title,
|
|
2157
2217
|
description: feature.description,
|
|
@@ -2183,6 +2243,46 @@ function generateBDDScenarios(requirement, context, questions) {
|
|
|
2183
2243
|
}
|
|
2184
2244
|
return scenarios;
|
|
2185
2245
|
}
|
|
2246
|
+
function extractFeaturesFromReference(ref) {
|
|
2247
|
+
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
|
+
});
|
|
2262
|
+
}
|
|
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
|
+
});
|
|
2269
|
+
}
|
|
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
|
+
});
|
|
2276
|
+
}
|
|
2277
|
+
if (features.length === 0) {
|
|
2278
|
+
features.push({
|
|
2279
|
+
title: "\u53C2\u8003\u529F\u80FD\u5B9E\u73B0",
|
|
2280
|
+
description: `\u57FA\u4E8E\u53C2\u8003\u8D44\u6E90 ${ref.url} \u5B9E\u73B0\u7684\u529F\u80FD`,
|
|
2281
|
+
hasInput: true
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
return features;
|
|
2285
|
+
}
|
|
2186
2286
|
function extractFeatures(requirement) {
|
|
2187
2287
|
const features = [];
|
|
2188
2288
|
const urlMatch = requirement.match(/https?:\/\/[^\s]+/);
|
|
@@ -2223,15 +2323,26 @@ function extractFeatures(requirement) {
|
|
|
2223
2323
|
}
|
|
2224
2324
|
return features;
|
|
2225
2325
|
}
|
|
2226
|
-
function generateSpecItems(requirement, context, bddScenarios, questions) {
|
|
2326
|
+
function generateSpecItems(requirement, context, bddScenarios, questions, references = []) {
|
|
2227
2327
|
const items = [];
|
|
2228
2328
|
let id = 1;
|
|
2329
|
+
for (const ref of references) {
|
|
2330
|
+
items.push({
|
|
2331
|
+
id: `T${id.toString().padStart(3, "0")}`,
|
|
2332
|
+
title: `\u53C2\u8003\u5206\u6790: ${ref.type}`,
|
|
2333
|
+
description: `\u5206\u6790\u53C2\u8003\u8D44\u6E90 ${ref.url}`,
|
|
2334
|
+
priority: "high",
|
|
2335
|
+
files: [],
|
|
2336
|
+
tests: []
|
|
2337
|
+
});
|
|
2338
|
+
id++;
|
|
2339
|
+
}
|
|
2229
2340
|
for (const scenario of bddScenarios) {
|
|
2230
2341
|
items.push({
|
|
2231
2342
|
id: `T${id.toString().padStart(3, "0")}`,
|
|
2232
2343
|
title: scenario.feature,
|
|
2233
2344
|
description: scenario.description,
|
|
2234
|
-
priority: id <=
|
|
2345
|
+
priority: id <= 3 ? "high" : "medium",
|
|
2235
2346
|
files: [],
|
|
2236
2347
|
tests: []
|
|
2237
2348
|
});
|
|
@@ -2274,6 +2385,19 @@ function formatSpecFile(session) {
|
|
|
2274
2385
|
lines.push("---");
|
|
2275
2386
|
lines.push("");
|
|
2276
2387
|
}
|
|
2388
|
+
if (session.referenceResources.length > 0) {
|
|
2389
|
+
lines.push("## \u53C2\u8003\u8D44\u6E90");
|
|
2390
|
+
lines.push("");
|
|
2391
|
+
for (const ref of session.referenceResources) {
|
|
2392
|
+
lines.push(`### ${ref.url}`);
|
|
2393
|
+
lines.push(`> \u7C7B\u578B: ${ref.type}`);
|
|
2394
|
+
lines.push("");
|
|
2395
|
+
lines.push(ref.analysis);
|
|
2396
|
+
lines.push("");
|
|
2397
|
+
}
|
|
2398
|
+
lines.push("---");
|
|
2399
|
+
lines.push("");
|
|
2400
|
+
}
|
|
2277
2401
|
if (session.clarificationQuestions.some((q) => q.answered)) {
|
|
2278
2402
|
lines.push("## \u9700\u6C42\u6F84\u6E05");
|
|
2279
2403
|
lines.push("");
|
|
@@ -2379,6 +2503,96 @@ function generateSessionId() {
|
|
|
2379
2503
|
const random = Math.random().toString(36).slice(2, 6);
|
|
2380
2504
|
return `WF-${timestamp}-${random}`.toUpperCase();
|
|
2381
2505
|
}
|
|
2506
|
+
function extractUrls(text) {
|
|
2507
|
+
const urlRegex = /https?:\/\/[^\s<>"{}|\\^`\[\]]+/gi;
|
|
2508
|
+
const matches = text.match(urlRegex);
|
|
2509
|
+
return matches ? [...new Set(matches)] : [];
|
|
2510
|
+
}
|
|
2511
|
+
async function fetchAndAnalyzeReference(url, ctx) {
|
|
2512
|
+
const type = detectResourceType(url);
|
|
2513
|
+
let content = "";
|
|
2514
|
+
let analysis = "";
|
|
2515
|
+
try {
|
|
2516
|
+
const response = await fetch(url, {
|
|
2517
|
+
headers: {
|
|
2518
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
|
2519
|
+
}
|
|
2520
|
+
});
|
|
2521
|
+
if (!response.ok) {
|
|
2522
|
+
throw new Error(`HTTP ${response.status}`);
|
|
2523
|
+
}
|
|
2524
|
+
content = await response.text();
|
|
2525
|
+
if (ctx.modelService.getCurrentModel()) {
|
|
2526
|
+
analysis = await analyzeReferenceContent(url, content, type, ctx);
|
|
2527
|
+
} else {
|
|
2528
|
+
analysis = extractBasicInfo(content, type);
|
|
2529
|
+
}
|
|
2530
|
+
} catch (error) {
|
|
2531
|
+
throw new Error(`\u65E0\u6CD5\u83B7\u53D6\u53C2\u8003\u8D44\u6E90: ${error.message}`);
|
|
2532
|
+
}
|
|
2533
|
+
return { url, type, content: content.slice(0, 1e4), analysis };
|
|
2534
|
+
}
|
|
2535
|
+
function detectResourceType(url) {
|
|
2536
|
+
if (url.includes("figma.com") || url.includes("lanhuapp.com")) {
|
|
2537
|
+
return "design";
|
|
2538
|
+
}
|
|
2539
|
+
if (/\.(png|jpg|jpeg|gif|webp|svg)$/i.test(url)) {
|
|
2540
|
+
return "image";
|
|
2541
|
+
}
|
|
2542
|
+
if (/api\//i.test(url)) {
|
|
2543
|
+
return "api";
|
|
2544
|
+
}
|
|
2545
|
+
return "webpage";
|
|
2546
|
+
}
|
|
2547
|
+
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
|
+
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
|
|
2556
|
+
|
|
2557
|
+
URL: ${url}
|
|
2558
|
+
\u7C7B\u578B: ${type}
|
|
2559
|
+
|
|
2560
|
+
\u5185\u5BB9\u6458\u8981:
|
|
2561
|
+
${content.slice(0, 5e3)}
|
|
2562
|
+
|
|
2563
|
+
${typePrompts[type]}
|
|
2564
|
+
|
|
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
|
|
2571
|
+
|
|
2572
|
+
\u4EE5\u7B80\u6D01\u7684\u8981\u70B9\u5F62\u5F0F\u8F93\u51FA\u3002
|
|
2573
|
+
`;
|
|
2574
|
+
try {
|
|
2575
|
+
const response = await ctx.modelService.sendMessage([
|
|
2576
|
+
{ role: "user", content: prompt2 }
|
|
2577
|
+
], { temperature: 0.3, maxTokens: 2e3 });
|
|
2578
|
+
return response.content;
|
|
2579
|
+
} catch {
|
|
2580
|
+
return extractBasicInfo(content, type);
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
function extractBasicInfo(content, type) {
|
|
2584
|
+
const titleMatch = content.match(/<title[^>]*>([^<]+)<\/title>/i);
|
|
2585
|
+
const descMatch = content.match(/<meta[^>]*name=["']description["'][^>]*content=["']([^"']+)["']/i);
|
|
2586
|
+
const parts = [];
|
|
2587
|
+
if (titleMatch) {
|
|
2588
|
+
parts.push(`\u6807\u9898: ${titleMatch[1]}`);
|
|
2589
|
+
}
|
|
2590
|
+
if (descMatch) {
|
|
2591
|
+
parts.push(`\u63CF\u8FF0: ${descMatch[1]}`);
|
|
2592
|
+
}
|
|
2593
|
+
parts.push(`\u8D44\u6E90\u7C7B\u578B: ${type}`);
|
|
2594
|
+
return parts.join("\n");
|
|
2595
|
+
}
|
|
2382
2596
|
function generateComplexityBar(score) {
|
|
2383
2597
|
const filled = Math.round(score / 2);
|
|
2384
2598
|
const empty = 5 - filled;
|
|
@@ -2388,6 +2602,7 @@ function getPhaseLabel(phase) {
|
|
|
2388
2602
|
const labels = {
|
|
2389
2603
|
context: "\u9879\u76EE\u4E0A\u4E0B\u6587\u83B7\u53D6",
|
|
2390
2604
|
clarify: "\u9700\u6C42\u6F84\u6E05",
|
|
2605
|
+
reference: "\u53C2\u8003\u8D44\u6E90\u5206\u6790",
|
|
2391
2606
|
analysis: "\u590D\u6742\u5EA6\u8BC4\u4F30",
|
|
2392
2607
|
bdd: "BDD \u573A\u666F\u62C6\u89E3",
|
|
2393
2608
|
spec: "OpenSpec \u89C4\u683C",
|
|
@@ -7468,6 +7683,7 @@ var STEP_DISPLAY_NAMES = {
|
|
|
7468
7683
|
"archive": "\u5F52\u6863",
|
|
7469
7684
|
"context": "\u4E0A\u4E0B\u6587",
|
|
7470
7685
|
"clarify": "\u6F84\u6E05",
|
|
7686
|
+
"reference": "\u53C2\u8003\u5206\u6790",
|
|
7471
7687
|
"analysis": "\u5206\u6790",
|
|
7472
7688
|
"bdd": "BDD",
|
|
7473
7689
|
"spec": "\u89C4\u683C",
|
|
@@ -7484,6 +7700,7 @@ var STEP_COLORS = {
|
|
|
7484
7700
|
"archive": chalk9__default.default.gray,
|
|
7485
7701
|
"context": chalk9__default.default.magenta,
|
|
7486
7702
|
"clarify": chalk9__default.default.yellow,
|
|
7703
|
+
"reference": chalk9__default.default.blue,
|
|
7487
7704
|
"analysis": chalk9__default.default.blue,
|
|
7488
7705
|
"bdd": chalk9__default.default.cyan,
|
|
7489
7706
|
"spec": chalk9__default.default.green,
|