bmall-mcp 1.9.2 → 1.10.0
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/README.md +8 -0
- package/dist/server/tools.js +4 -4
- package/dist/server/tools.js.map +1 -1
- package/dist/tools/requirements/index.d.ts.map +1 -1
- package/dist/tools/requirements/index.js +111 -260
- package/dist/tools/requirements/index.js.map +1 -1
- package/dist/tools/requirements/requirement-processor.d.ts.map +1 -1
- package/dist/tools/requirements/requirement-processor.js +10 -31
- package/dist/tools/requirements/requirement-processor.js.map +1 -1
- package/package.json +1 -1
- package/src/server/tools.ts +4 -4
- package/src/tools/requirements/index.ts +125 -294
- package/src/tools/requirements/requirement-processor.ts +11 -34
package/README.md
CHANGED
|
@@ -204,6 +204,14 @@ src/
|
|
|
204
204
|
|
|
205
205
|
## Changelog
|
|
206
206
|
|
|
207
|
+
### v1.10.0 (2026-03-16)
|
|
208
|
+
- ✅ 优化 generate_requirements 工具流程:精简提示词,提升效率
|
|
209
|
+
- ✅ 优化 PDF 处理:删除冗余的步骤化格式和重复强调
|
|
210
|
+
- ✅ 优化 Figma 处理:删除 nodeId 提取和语言/框架指定
|
|
211
|
+
- ✅ 优化分析提示词:保留前端开发 10 个重点,确保需求文档完整性
|
|
212
|
+
- ✅ 明确路径要求:工具参数描述中明确说明必须使用绝对路径
|
|
213
|
+
- ✅ 提供路径示例:/Users/xxx/Documents/prd.pdf
|
|
214
|
+
|
|
207
215
|
### v1.9.2 (2026-03-16)
|
|
208
216
|
- ✅ 添加绝对路径检测:自动检测文件路径是否为绝对路径
|
|
209
217
|
- ✅ 明确路径要求:相对路径时提示AI使用绝对路径
|
package/dist/server/tools.js
CHANGED
|
@@ -132,7 +132,7 @@ export const toolDefinitions = [
|
|
|
132
132
|
},
|
|
133
133
|
{
|
|
134
134
|
name: "generate_requirements",
|
|
135
|
-
description: "需求文档生成:从需求文档(PRD/文件/网页)和可选的设计稿、后端文档生成结构化的 requirements.md
|
|
135
|
+
description: "需求文档生成:从需求文档(PRD/文件/网页)和可选的设计稿、后端文档生成结构化的 requirements.md。工具会按顺序处理输入材料,最终生成到 .specs/requirements/{featureName}/requirements.md。触发词:生成需求文档、需求分析、requirements",
|
|
136
136
|
inputSchema: {
|
|
137
137
|
type: "object",
|
|
138
138
|
properties: {
|
|
@@ -147,7 +147,7 @@ export const toolDefinitions = [
|
|
|
147
147
|
},
|
|
148
148
|
path: {
|
|
149
149
|
type: "string",
|
|
150
|
-
description: "
|
|
150
|
+
description: "文件绝对路径(.md/.pdf),例如:/Users/xxx/Documents/prd.pdf,当 type 为 file 时必填",
|
|
151
151
|
},
|
|
152
152
|
url: {
|
|
153
153
|
type: "string",
|
|
@@ -175,7 +175,7 @@ export const toolDefinitions = [
|
|
|
175
175
|
},
|
|
176
176
|
path: {
|
|
177
177
|
type: "string",
|
|
178
|
-
description: "
|
|
178
|
+
description: "设计稿文件绝对路径,例如:/Users/xxx/Documents/design.pdf,当 type 为 file 时必填",
|
|
179
179
|
},
|
|
180
180
|
},
|
|
181
181
|
},
|
|
@@ -190,7 +190,7 @@ export const toolDefinitions = [
|
|
|
190
190
|
},
|
|
191
191
|
path: {
|
|
192
192
|
type: "string",
|
|
193
|
-
description: "
|
|
193
|
+
description: "文件绝对路径(.md/.pdf),例如:/Users/xxx/Documents/backend-api.pdf,当 type 为 file 时必填",
|
|
194
194
|
},
|
|
195
195
|
url: {
|
|
196
196
|
type: "string",
|
package/dist/server/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/server/tools.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/server/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/requirements/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/requirements/index.ts"],"names":[],"mappings":"AAoBA,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,UAAU,0BAA0B;IAClC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE;QACb,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;QACvB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,aAAa,CAAC,EAAE;QACd,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAmCD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,iBAAiB,CAAC;QAClD,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH,CAAC,CAwKD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
2
2
|
import * as os from "os";
|
|
3
|
-
import { processRequirementDocument, tryReadSavedRequirement, tryReadSavedDesign, tryReadSavedBackend, getProjectRoot, buildOutputPath } from "./requirement-processor.js";
|
|
3
|
+
import { processRequirementDocument, tryReadSavedRequirement, tryReadSavedDesign, tryReadSavedBackend, getProjectRoot, buildOutputPath, } from "./requirement-processor.js";
|
|
4
4
|
/**
|
|
5
5
|
* 调试日志输出
|
|
6
6
|
*/
|
|
@@ -36,149 +36,114 @@ export async function generateRequirements(params) {
|
|
|
36
36
|
homedir: os.homedir()
|
|
37
37
|
});
|
|
38
38
|
try {
|
|
39
|
-
// 1
|
|
39
|
+
// 步骤 1:验证必填参数
|
|
40
40
|
const validation = validateRequiredParams(params);
|
|
41
41
|
if (!validation.valid) {
|
|
42
42
|
return validation.error;
|
|
43
43
|
}
|
|
44
|
-
// 2
|
|
44
|
+
// 步骤 2:计算项目根目录
|
|
45
45
|
let projectRoot = process.cwd();
|
|
46
46
|
if (params.requirementSource.type === "file" && params.requirementSource.path) {
|
|
47
47
|
projectRoot = getProjectRoot(params.requirementSource.path);
|
|
48
48
|
}
|
|
49
49
|
debugLog(`计算项目根目录`, { projectRoot, cwd: process.cwd() });
|
|
50
|
-
// 2.1 检查所有文档状态,收集需要处理的文档
|
|
51
50
|
const originDocPath = buildOutputPath(params.featureName, "origin-requirement.md", projectRoot);
|
|
52
51
|
const designDocPath = params.designSource ? buildOutputPath(params.featureName, "design-doc.md", projectRoot) : null;
|
|
53
52
|
const backendDocPath = params.backendSource ? buildOutputPath(params.featureName, "backend-doc.md", projectRoot) : null;
|
|
54
|
-
|
|
55
|
-
//
|
|
53
|
+
// 步骤 3:按顺序检查和处理文档
|
|
54
|
+
// 3.1 处理需求文档(PRD)
|
|
56
55
|
const savedRequirement = await tryReadSavedRequirement(params.featureName, projectRoot);
|
|
57
|
-
const savedDesign = params.designSource ? await tryReadSavedDesign(params.featureName, projectRoot) : null;
|
|
58
|
-
const savedBackend = params.backendSource ? await tryReadSavedBackend(params.featureName, projectRoot) : null;
|
|
59
|
-
debugLog(`文档状态检查结果`, {
|
|
60
|
-
savedRequirement: !!savedRequirement,
|
|
61
|
-
savedDesign: !!savedDesign,
|
|
62
|
-
savedBackend: !!savedBackend
|
|
63
|
-
});
|
|
64
|
-
// 收集需要处理的文档
|
|
65
|
-
const tasks = [];
|
|
66
|
-
// 检查需求文档
|
|
67
56
|
if (!savedRequirement) {
|
|
68
|
-
debugLog(
|
|
57
|
+
debugLog(`需求文档未找到,开始处理`);
|
|
69
58
|
const requirementResult = await processRequirementDocument(params.requirementSource, params.featureName, "origin-requirement.md");
|
|
70
59
|
if (!requirementResult.success) {
|
|
71
60
|
debugLog(`需求文档需要进一步处理`, { requirementResult });
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
processingInstruction: requirementResult.message
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
debugLog(`需求文档已处理`);
|
|
61
|
+
return {
|
|
62
|
+
success: false,
|
|
63
|
+
message: requirementResult.message,
|
|
64
|
+
needsAction: requirementResult.needsAction
|
|
65
|
+
};
|
|
82
66
|
}
|
|
67
|
+
debugLog(`需求文档已处理完成`);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
debugLog(`需求文档已存在,跳过处理`);
|
|
83
71
|
}
|
|
84
|
-
//
|
|
85
|
-
if (params.designSource
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
72
|
+
// 3.2 处理设计稿
|
|
73
|
+
if (params.designSource) {
|
|
74
|
+
const savedDesign = await tryReadSavedDesign(params.featureName, projectRoot);
|
|
75
|
+
if (!savedDesign) {
|
|
76
|
+
debugLog(`设计稿未找到,开始处理`);
|
|
77
|
+
if (params.designSource.type === "figma") {
|
|
78
|
+
// Figma 设计稿
|
|
79
|
+
const figmaUrl = params.designSource.url || "";
|
|
80
|
+
return {
|
|
81
|
+
success: false,
|
|
82
|
+
message: `🎨 检测到 Figma 设计稿链接
|
|
83
|
+
|
|
84
|
+
使用 Figma MCP 工具读取设计稿内容:
|
|
85
|
+
- Figma URL: ${figmaUrl}
|
|
86
|
+
|
|
87
|
+
保存到:\`${designDocPath}\`
|
|
88
|
+
|
|
89
|
+
完成后重新调用 \`generate_requirements\` 工具`,
|
|
90
|
+
needsAction: {
|
|
91
|
+
type: "read_web",
|
|
92
|
+
instruction: `使用 Figma MCP 工具读取 ${figmaUrl},保存到 ${designDocPath},然后重新调用 generate_requirements`
|
|
93
|
+
}
|
|
94
|
+
};
|
|
101
95
|
}
|
|
102
|
-
else {
|
|
103
|
-
|
|
96
|
+
else if (params.designSource.type === "file") {
|
|
97
|
+
// 文件类型设计稿
|
|
98
|
+
const designResult = await processRequirementDocument({
|
|
99
|
+
type: "file",
|
|
100
|
+
path: params.designSource.path
|
|
101
|
+
}, params.featureName, "design-doc.md");
|
|
102
|
+
if (!designResult.success) {
|
|
103
|
+
debugLog(`设计稿需要进一步处理`, { designResult });
|
|
104
|
+
return {
|
|
105
|
+
success: false,
|
|
106
|
+
message: designResult.message,
|
|
107
|
+
needsAction: designResult.needsAction
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
debugLog(`设计稿已处理完成`);
|
|
104
111
|
}
|
|
105
112
|
}
|
|
106
|
-
else
|
|
107
|
-
|
|
108
|
-
name: "设计稿 (Figma)",
|
|
109
|
-
outputPath: designDocPath,
|
|
110
|
-
source: params.designSource,
|
|
111
|
-
status: "needs_processing",
|
|
112
|
-
processingInstruction: `🎨 检测到 Figma 设计稿链接
|
|
113
|
-
|
|
114
|
-
请读取以下 Figma 设计稿并保存到文件:
|
|
115
|
-
|
|
116
|
-
- Figma 链接:${params.designSource.url}
|
|
117
|
-
- 保存到:\`${designDocPath}\``
|
|
118
|
-
});
|
|
113
|
+
else {
|
|
114
|
+
debugLog(`设计稿已存在,跳过处理`);
|
|
119
115
|
}
|
|
120
116
|
}
|
|
121
|
-
//
|
|
122
|
-
if (params.backendSource
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
117
|
+
// 3.3 处理后端文档
|
|
118
|
+
if (params.backendSource) {
|
|
119
|
+
const savedBackend = await tryReadSavedBackend(params.featureName, projectRoot);
|
|
120
|
+
if (!savedBackend) {
|
|
121
|
+
debugLog(`后端文档未找到,开始处理`);
|
|
122
|
+
const backendResult = await processRequirementDocument(params.backendSource, params.featureName, "backend-doc.md");
|
|
123
|
+
if (!backendResult.success) {
|
|
124
|
+
debugLog(`后端文档需要进一步处理`, { backendResult });
|
|
125
|
+
return {
|
|
126
|
+
success: false,
|
|
127
|
+
message: backendResult.message,
|
|
128
|
+
needsAction: backendResult.needsAction
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
debugLog(`后端文档已处理完成`);
|
|
134
132
|
}
|
|
135
133
|
else {
|
|
136
|
-
debugLog(
|
|
134
|
+
debugLog(`后端文档已存在,跳过处理`);
|
|
137
135
|
}
|
|
138
136
|
}
|
|
139
|
-
//
|
|
140
|
-
|
|
141
|
-
debugLog(`发现 ${tasks.length} 个需要处理的任务`);
|
|
142
|
-
let message = `📋 需要处理以下文档(共 ${tasks.length} 个)\n\n`;
|
|
143
|
-
tasks.forEach((task, index) => {
|
|
144
|
-
message += `### 任务 ${index + 1}:${task.name}\n`;
|
|
145
|
-
message += task.processingInstruction;
|
|
146
|
-
message += `\n\n`;
|
|
147
|
-
});
|
|
148
|
-
message += `⚠️ **重要提示**:\n`;
|
|
149
|
-
message += `- **推荐并行处理**:可以同时处理多个任务,提高效率\n`;
|
|
150
|
-
message += `- 每个任务处理完成后,立即保存文件,**不要把文件内容放在上下文中**\n`;
|
|
151
|
-
message += `- 所有任务完成后,重新调用 \`generate_requirements\` 工具(工具会自动检查已完成任务)\n`;
|
|
152
|
-
message += `- 这样可以避免上下文过长,同时减少重复调用\n`;
|
|
153
|
-
return {
|
|
154
|
-
success: false,
|
|
155
|
-
message,
|
|
156
|
-
needsAction: {
|
|
157
|
-
type: "process_documents",
|
|
158
|
-
instruction: `按顺序或并行处理上述 ${tasks.length} 个任务,每个任务完成后立即保存文件。所有任务完成后重新调用 generate_requirements 工具。`
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
// 所有文档都已准备好
|
|
163
|
-
debugLog(`所有文档已准备完毕`);
|
|
164
|
-
let designSourceInfo = "";
|
|
165
|
-
if (savedDesign) {
|
|
166
|
-
designSourceInfo = `**设计稿位置**:${designDocPath}\n`;
|
|
167
|
-
}
|
|
168
|
-
let backendSourceInfo = "";
|
|
169
|
-
if (savedBackend) {
|
|
170
|
-
backendSourceInfo = `**后端文档位置**:${backendDocPath}\n`;
|
|
171
|
-
}
|
|
172
|
-
// 5. 生成分析提示词
|
|
137
|
+
// 步骤 4:所有文档已准备完毕,生成分析提示词
|
|
138
|
+
debugLog(`所有文档已准备完毕,生成分析提示词`);
|
|
173
139
|
const outputPath = buildOutputPath(params.featureName, "requirements.md", projectRoot);
|
|
174
|
-
debugLog(`生成输出路径`, { outputPath, originDocPath, projectRoot });
|
|
175
140
|
let message = "📝 需求文档已准备完毕\n\n";
|
|
176
141
|
message += `**原始文档位置**:${originDocPath}\n`;
|
|
177
|
-
if (
|
|
178
|
-
message +=
|
|
142
|
+
if (designDocPath) {
|
|
143
|
+
message += `**设计稿位置**:${designDocPath}\n`;
|
|
179
144
|
}
|
|
180
|
-
if (
|
|
181
|
-
message +=
|
|
145
|
+
if (backendDocPath) {
|
|
146
|
+
message += `**后端文档位置**:${backendDocPath}\n`;
|
|
182
147
|
}
|
|
183
148
|
message += `**目标输出位置**:${outputPath}\n\n`;
|
|
184
149
|
message += buildAnalysisPrompt(originDocPath, outputPath, params.designSource, params.backendSource);
|
|
@@ -208,154 +173,40 @@ export async function generateRequirements(params) {
|
|
|
208
173
|
}
|
|
209
174
|
function buildAnalysisPrompt(originDocPath, outputPath, designSource, backendSource) {
|
|
210
175
|
const featureName = outputPath.split('/')[2];
|
|
211
|
-
let prompt =
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
-
|
|
241
|
-
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
- **用户故事**:作为角色,我希望功能,以便价值
|
|
246
|
-
- **验收标准**:WHEN 触发条件 THEN 预期行为(至少 3-6 条)
|
|
247
|
-
- **说明**:补充必要的细节(不涉及技术实现)
|
|
248
|
-
|
|
249
|
-
#### 3. 交互细节
|
|
250
|
-
- **视觉反馈**:选中、不可用、加载、错误的视觉表现
|
|
251
|
-
- **动画效果**:展开/收起、弹出、跳转的动画时长和方式
|
|
252
|
-
- **错误处理**:各种错误场景的用户提示和处理方式
|
|
253
|
-
- **确认弹窗**:需要用户确认的场景和确认内容
|
|
254
|
-
|
|
255
|
-
#### 4. 技术要求与限制
|
|
256
|
-
- **性能需求**:响应时间、加载速度、动画流畅度
|
|
257
|
-
- **可用性需求**:状态清晰性、错误提示友好性、操作便捷性
|
|
258
|
-
- **兼容性需求**:支持的系统版本、设备类型、浏览器要求
|
|
259
|
-
- **限制说明**:不支持的场景、已知的兼容性问题、特殊边界情况
|
|
260
|
-
|
|
261
|
-
### 内容要求
|
|
262
|
-
|
|
263
|
-
#### 必须包含的关键内容
|
|
264
|
-
|
|
265
|
-
**1. 功能范围**
|
|
266
|
-
- 业务场景、平台范围、排除范围
|
|
267
|
-
|
|
268
|
-
**2. 页面结构**
|
|
269
|
-
- 页面/模块布局、组件层级关系
|
|
270
|
-
|
|
271
|
-
**3. 数据展示**
|
|
272
|
-
- 数据来源(用"由系统返回"替代接口名)
|
|
273
|
-
- 数据展示规则
|
|
274
|
-
- 空数据/加载/错误状态的表现
|
|
275
|
-
|
|
276
|
-
**4. 交互逻辑**
|
|
277
|
-
- 操作入口、触发条件、即时反馈、结果处理
|
|
278
|
-
|
|
279
|
-
**5. 状态管理**
|
|
280
|
-
- 状态触发条件、转换逻辑、数据保持/重置
|
|
281
|
-
|
|
282
|
-
**6. 页面跳转**
|
|
283
|
-
- 跳转触发、目标页面、参数传递(只说明内容,不涉及字段)、返回逻辑
|
|
284
|
-
|
|
285
|
-
**7. 跨系统交互**
|
|
286
|
-
- 交互触发、返回处理、结果查询和展示
|
|
287
|
-
|
|
288
|
-
**8. 异常处理**
|
|
289
|
-
- 异常场景、提示方式、恢复机制
|
|
290
|
-
|
|
291
|
-
**9. 交互细节**
|
|
292
|
-
- 视觉反馈(选中/不可用等)
|
|
293
|
-
- 动画效果(展开/收起/弹出等)
|
|
294
|
-
- 确认弹窗
|
|
295
|
-
|
|
296
|
-
**10. 性能要求**
|
|
297
|
-
- 加载速度、响应时间、动画流畅度
|
|
298
|
-
|
|
299
|
-
#### 视角要求
|
|
300
|
-
|
|
301
|
-
**从用户视角描述**
|
|
302
|
-
- ✅ 描述"用户能看到什么"、"用户能做什么"、"操作后有什么反馈"
|
|
303
|
-
|
|
304
|
-
**避免技术细节**
|
|
305
|
-
- ❌ 不要描述"轮询 5 次"、"骨架屏 vs 局部加载"、"调用 XXX 接口"、"使用 XXX SDK"
|
|
306
|
-
- ✅ 用"查询超时"、"加载状态"、"由系统返回"替代
|
|
307
|
-
|
|
308
|
-
#### 格式化要求
|
|
309
|
-
- 用户故事:作为[角色],我希望[功能],以便[价值]
|
|
310
|
-
- 验收标准:WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
311
|
-
- 验收标准必须可测试:使用具体的时间、数量、状态,避免"快速响应"等模糊描述
|
|
312
|
-
|
|
313
|
-
### 格式要求
|
|
314
|
-
|
|
315
|
-
#### 用户故事格式
|
|
316
|
-
\`\`\`
|
|
317
|
-
**用户故事**:作为[角色],我希望[功能],以便[价值]。
|
|
318
|
-
\`\`\`
|
|
319
|
-
|
|
320
|
-
#### 验收标准格式
|
|
321
|
-
\`\`\`
|
|
322
|
-
#### 验收标准
|
|
323
|
-
|
|
324
|
-
1. WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
325
|
-
2. WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
326
|
-
3. WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
327
|
-
...
|
|
328
|
-
\`\`\`
|
|
329
|
-
|
|
330
|
-
#### 可测试性要求
|
|
331
|
-
- 每个验收标准必须可测试、可验证
|
|
332
|
-
- 避免模糊的描述(如"快速响应")
|
|
333
|
-
- 使用具体的时间、数量、状态描述
|
|
334
|
-
|
|
335
|
-
## 核心约束
|
|
336
|
-
|
|
337
|
-
### 1. 内容完整性
|
|
338
|
-
- 必须包含所有 4 个章节(介绍、功能需求、交互细节、技术要求与限制)
|
|
339
|
-
- 每个功能需求必须有用户故事和 3-6 条验收标准
|
|
340
|
-
- 必须覆盖 10 个前端开发重点
|
|
341
|
-
|
|
342
|
-
### 2. 视角正确性
|
|
343
|
-
- 从用户视角描述功能
|
|
344
|
-
- 不涉及技术实现细节(接口、SDK、轮询机制等)
|
|
345
|
-
- 用"由系统返回"、"加载状态"、"查询超时"替代技术术语
|
|
346
|
-
|
|
347
|
-
### 3. 内容独立性
|
|
348
|
-
- 不要生成接口文档(放在设计文档)
|
|
349
|
-
- 不要生成数据模型(放在设计文档)
|
|
350
|
-
- 不要生成技术架构(放在设计文档)
|
|
351
|
-
- 不要生成代码示例(放在开发阶段)
|
|
352
|
-
|
|
353
|
-
## 开始执行
|
|
354
|
-
|
|
355
|
-
请按照以上要求,从输入的 PRD ${designSource ? "和设计稿" : ""} 中提取信息,生成完整的需求文档到:\`${outputPath}\`
|
|
356
|
-
|
|
357
|
-
生成过程中,如果遇到不明确的内容,必须向用户确认,不要假设答案。
|
|
358
|
-
`;
|
|
176
|
+
let prompt = `请根据以下材料生成需求文档:
|
|
177
|
+
|
|
178
|
+
**输入材料**:
|
|
179
|
+
- PRD:\`${originDocPath}\`
|
|
180
|
+
${designSource ? `- 设计稿:\`.specs/requirements/${featureName}/design-doc.md\`` : ''}
|
|
181
|
+
${backendSource ? `- 后端文档:\`.specs/requirements/${featureName}/backend-doc.md\`` : ''}
|
|
182
|
+
|
|
183
|
+
**输出位置**:\`${outputPath}\`
|
|
184
|
+
|
|
185
|
+
**文档结构**:
|
|
186
|
+
1. 介绍(功能概述、核心价值、涉及范围、术语表)
|
|
187
|
+
2. 功能需求(用户故事 + 验收标准)
|
|
188
|
+
3. 交互细节(视觉反馈、动画效果、错误处理)
|
|
189
|
+
4. 技术要求与限制(性能、可用性、兼容性)
|
|
190
|
+
|
|
191
|
+
**前端开发必须覆盖的 10 个重点**:
|
|
192
|
+
1. 功能范围(业务场景、平台范围、排除范围)
|
|
193
|
+
2. 页面结构(页面/模块布局、组件层级关系)
|
|
194
|
+
3. 数据展示(数据来源、展示规则、空数据/加载/错误状态)
|
|
195
|
+
4. 交互逻辑(操作入口、触发条件、即时反馈、结果处理)
|
|
196
|
+
5. 状态管理(状态触发条件、转换逻辑、数据保持/重置)
|
|
197
|
+
6. 页面跳转(跳转触发、目标页面、参数传递、返回逻辑)
|
|
198
|
+
7. 跨系统交互(交互触发、返回处理、结果查询和展示)
|
|
199
|
+
8. 异常处理(异常场景、提示方式、恢复机制)
|
|
200
|
+
9. 交互细节(视觉反馈、动画效果、确认弹窗)
|
|
201
|
+
10. 性能要求(加载速度、响应时间、动画流畅度)
|
|
202
|
+
|
|
203
|
+
**关键要求**:
|
|
204
|
+
- 从用户视角描述(用户能看到什么、能做什么、操作后有什么反馈)
|
|
205
|
+
- 避免技术细节(不要提接口名、SDK、轮询机制等,用"由系统返回"、"加载状态"、"查询超时"替代)
|
|
206
|
+
- 验收标准格式:WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
207
|
+
- 每个需求 3-6 条验收标准,必须可测试(使用具体的时间、数量、状态)
|
|
208
|
+
|
|
209
|
+
遇到不明确的内容,向用户确认,不要假设答案。`;
|
|
359
210
|
return prompt;
|
|
360
211
|
}
|
|
361
212
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/requirements/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/requirements/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirement-processor.d.ts","sourceRoot":"","sources":["../../../src/tools/requirements/requirement-processor.ts"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAexD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAElG;AAED,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,iBAAiB,CAAC;QAClD,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,EAChD,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,MAAgC,GAC/C,OAAO,CAAC,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"requirement-processor.d.ts","sourceRoot":"","sources":["../../../src/tools/requirements/requirement-processor.ts"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAexD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAElG;AAED,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE;QACZ,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,iBAAiB,CAAC;QAClD,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,EAChD,WAAW,EAAE,MAAM,EACnB,cAAc,GAAE,MAAgC,GAC/C,OAAO,CAAC,aAAa,CAAC,CA+IxB;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB"}
|
|
@@ -95,42 +95,21 @@ export async function processRequirementDocument(requirementSource, featureName,
|
|
|
95
95
|
catch {
|
|
96
96
|
// 文件不存在,需要处理
|
|
97
97
|
debugLog(`输出文件不存在,需要处理PDF`, { outputMdPath });
|
|
98
|
-
|
|
99
|
-
const fileName = filePath.split('/').pop() || '';
|
|
100
|
-
const isChinese = /[\u4e00-\u9fa5]/.test(fileName);
|
|
101
|
-
const language = isChinese ? 'chi_sim' : 'eng';
|
|
102
|
-
debugLog(`准备提取PDF内容`, { filePath, language });
|
|
103
|
-
// 判断是否需要提示使用绝对路径
|
|
104
|
-
const needAbsolutePathHint = !path.isAbsolute(filePath);
|
|
98
|
+
debugLog(`准备提取PDF内容`, { filePath });
|
|
105
99
|
return {
|
|
106
100
|
success: false,
|
|
107
|
-
message: `📄 检测到 PDF
|
|
108
|
-
|
|
109
|
-
请执行以下操作:
|
|
101
|
+
message: `📄 检测到 PDF 文件
|
|
110
102
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
- server_name: "pdf-reader"
|
|
119
|
-
- tool_name: "read_by_ocr"
|
|
120
|
-
- arguments: { "file_path": "${needAbsolutePathHint ? '<请使用绝对路径>' : filePath}", "language": "${language}", "dpi": 300 }
|
|
121
|
-
${needAbsolutePathHint ? ' ⚠️ **重要**:file_path 参数必须是绝对路径,例如:/Users/xxx/Documents/prd.pdf' : ''}
|
|
122
|
-
|
|
123
|
-
3. 将两次读取的内容合并(文本层 + OCR内容)
|
|
124
|
-
|
|
125
|
-
4. 保存合并后的内容到:\`${outputMdPath}\``,
|
|
103
|
+
使用 PDF Reader MCP 工具读取 PDF 内容:
|
|
104
|
+
- 文件路径: ${filePath}
|
|
105
|
+
- 同时使用文本层(include_full_text: true)和 OCR(include_images: true)两种方式读取,避免内容遗漏
|
|
106
|
+
|
|
107
|
+
保存到:\`${outputMdPath}\`
|
|
108
|
+
|
|
109
|
+
完成后重新调用 \`generate_requirements\` 工具(不要把文件内容放在上下文中)`,
|
|
126
110
|
needsAction: {
|
|
127
111
|
type: "read_pdf",
|
|
128
|
-
instruction:
|
|
129
|
-
1. 调用 mcp_execute_tool,使用 pdf-reader 的 read_pdf_text 工具,参数为 { "file_path": "${filePath}" }
|
|
130
|
-
2. 调用 mcp_execute_tool,使用 pdf-reader 的 read_by_ocr 工具,参数为 { "file_path": "${filePath}", "language": "${language}", "dpi": 300 }
|
|
131
|
-
3. 将两次读取的内容合并(text + ocr)
|
|
132
|
-
4. 保存合并后的内容到文件:${outputMdPath}
|
|
133
|
-
5. 保存完成后重新调用 generate_requirements 工具(不要把文件内容放在上下文中)`,
|
|
112
|
+
instruction: `使用 PDF Reader MCP 工具读取 ${filePath}(同时使用文本层和 OCR),保存到 ${outputMdPath},然后重新调用 generate_requirements(不要把文件内容放在上下文中)`,
|
|
134
113
|
},
|
|
135
114
|
};
|
|
136
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirement-processor.js","sourceRoot":"","sources":["../../../src/tools/requirements/requirement-processor.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"requirement-processor.js","sourceRoot":"","sources":["../../../src/tools/requirements/requirement-processor.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/server/tools.ts
CHANGED
|
@@ -133,7 +133,7 @@ export const toolDefinitions = [
|
|
|
133
133
|
},
|
|
134
134
|
{
|
|
135
135
|
name: "generate_requirements",
|
|
136
|
-
description: "需求文档生成:从需求文档(PRD/文件/网页)和可选的设计稿、后端文档生成结构化的 requirements.md
|
|
136
|
+
description: "需求文档生成:从需求文档(PRD/文件/网页)和可选的设计稿、后端文档生成结构化的 requirements.md。工具会按顺序处理输入材料,最终生成到 .specs/requirements/{featureName}/requirements.md。触发词:生成需求文档、需求分析、requirements",
|
|
137
137
|
inputSchema: {
|
|
138
138
|
type: "object",
|
|
139
139
|
properties: {
|
|
@@ -148,7 +148,7 @@ export const toolDefinitions = [
|
|
|
148
148
|
},
|
|
149
149
|
path: {
|
|
150
150
|
type: "string",
|
|
151
|
-
description: "
|
|
151
|
+
description: "文件绝对路径(.md/.pdf),例如:/Users/xxx/Documents/prd.pdf,当 type 为 file 时必填",
|
|
152
152
|
},
|
|
153
153
|
url: {
|
|
154
154
|
type: "string",
|
|
@@ -176,7 +176,7 @@ export const toolDefinitions = [
|
|
|
176
176
|
},
|
|
177
177
|
path: {
|
|
178
178
|
type: "string",
|
|
179
|
-
description: "
|
|
179
|
+
description: "设计稿文件绝对路径,例如:/Users/xxx/Documents/design.pdf,当 type 为 file 时必填",
|
|
180
180
|
},
|
|
181
181
|
},
|
|
182
182
|
},
|
|
@@ -191,7 +191,7 @@ export const toolDefinitions = [
|
|
|
191
191
|
},
|
|
192
192
|
path: {
|
|
193
193
|
type: "string",
|
|
194
|
-
description: "
|
|
194
|
+
description: "文件绝对路径(.md/.pdf),例如:/Users/xxx/Documents/backend-api.pdf,当 type 为 file 时必填",
|
|
195
195
|
},
|
|
196
196
|
url: {
|
|
197
197
|
type: "string",
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
-
import * as fs from "fs/promises";
|
|
3
|
-
import * as path from "path";
|
|
4
2
|
import * as os from "os";
|
|
5
3
|
import {
|
|
6
4
|
processRequirementDocument,
|
|
7
5
|
tryReadSavedRequirement,
|
|
8
|
-
saveDesignDocument,
|
|
9
6
|
tryReadSavedDesign,
|
|
10
|
-
saveBackendDocument,
|
|
11
7
|
tryReadSavedBackend,
|
|
12
8
|
getProjectRoot,
|
|
13
9
|
buildOutputPath,
|
|
14
|
-
ProcessResult
|
|
15
10
|
} from "./requirement-processor.js";
|
|
16
11
|
|
|
17
12
|
/**
|
|
@@ -95,49 +90,29 @@ export async function generateRequirements(
|
|
|
95
90
|
});
|
|
96
91
|
|
|
97
92
|
try {
|
|
98
|
-
// 1
|
|
93
|
+
// 步骤 1:验证必填参数
|
|
99
94
|
const validation = validateRequiredParams(params);
|
|
100
95
|
if (!validation.valid) {
|
|
101
96
|
return validation.error!;
|
|
102
97
|
}
|
|
103
98
|
|
|
104
|
-
// 2
|
|
99
|
+
// 步骤 2:计算项目根目录
|
|
105
100
|
let projectRoot = process.cwd();
|
|
106
101
|
if (params.requirementSource.type === "file" && params.requirementSource.path) {
|
|
107
102
|
projectRoot = getProjectRoot(params.requirementSource.path);
|
|
108
103
|
}
|
|
109
104
|
debugLog(`计算项目根目录`, { projectRoot, cwd: process.cwd() });
|
|
110
105
|
|
|
111
|
-
// 2.1 检查所有文档状态,收集需要处理的文档
|
|
112
106
|
const originDocPath = buildOutputPath(params.featureName, "origin-requirement.md", projectRoot);
|
|
113
107
|
const designDocPath = params.designSource ? buildOutputPath(params.featureName, "design-doc.md", projectRoot) : null;
|
|
114
108
|
const backendDocPath = params.backendSource ? buildOutputPath(params.featureName, "backend-doc.md", projectRoot) : null;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
//
|
|
109
|
+
|
|
110
|
+
// 步骤 3:按顺序检查和处理文档
|
|
111
|
+
|
|
112
|
+
// 3.1 处理需求文档(PRD)
|
|
119
113
|
const savedRequirement = await tryReadSavedRequirement(params.featureName, projectRoot);
|
|
120
|
-
const savedDesign = params.designSource ? await tryReadSavedDesign(params.featureName, projectRoot) : null;
|
|
121
|
-
const savedBackend = params.backendSource ? await tryReadSavedBackend(params.featureName, projectRoot) : null;
|
|
122
|
-
|
|
123
|
-
debugLog(`文档状态检查结果`, {
|
|
124
|
-
savedRequirement: !!savedRequirement,
|
|
125
|
-
savedDesign: !!savedDesign,
|
|
126
|
-
savedBackend: !!savedBackend
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// 收集需要处理的文档
|
|
130
|
-
const tasks: Array<{
|
|
131
|
-
name: string;
|
|
132
|
-
outputPath: string;
|
|
133
|
-
source?: any;
|
|
134
|
-
status: "exists" | "needs_processing";
|
|
135
|
-
processingInstruction?: string;
|
|
136
|
-
}> = [];
|
|
137
|
-
|
|
138
|
-
// 检查需求文档
|
|
139
114
|
if (!savedRequirement) {
|
|
140
|
-
debugLog(
|
|
115
|
+
debugLog(`需求文档未找到,开始处理`);
|
|
141
116
|
const requirementResult = await processRequirementDocument(
|
|
142
117
|
params.requirementSource,
|
|
143
118
|
params.featureName,
|
|
@@ -146,135 +121,105 @@ export async function generateRequirements(
|
|
|
146
121
|
|
|
147
122
|
if (!requirementResult.success) {
|
|
148
123
|
debugLog(`需求文档需要进一步处理`, { requirementResult });
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
124
|
+
return {
|
|
125
|
+
success: false,
|
|
126
|
+
message: requirementResult.message!,
|
|
127
|
+
needsAction: requirementResult.needsAction
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
debugLog(`需求文档已处理完成`);
|
|
131
|
+
} else {
|
|
132
|
+
debugLog(`需求文档已存在,跳过处理`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 3.2 处理设计稿
|
|
136
|
+
if (params.designSource) {
|
|
137
|
+
const savedDesign = await tryReadSavedDesign(params.featureName, projectRoot);
|
|
138
|
+
if (!savedDesign) {
|
|
139
|
+
debugLog(`设计稿未找到,开始处理`);
|
|
140
|
+
|
|
141
|
+
if (params.designSource.type === "figma") {
|
|
142
|
+
// Figma 设计稿
|
|
143
|
+
const figmaUrl = params.designSource.url || "";
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
success: false,
|
|
147
|
+
message: `🎨 检测到 Figma 设计稿链接
|
|
148
|
+
|
|
149
|
+
使用 Figma MCP 工具读取设计稿内容:
|
|
150
|
+
- Figma URL: ${figmaUrl}
|
|
151
|
+
|
|
152
|
+
保存到:\`${designDocPath}\`
|
|
153
|
+
|
|
154
|
+
完成后重新调用 \`generate_requirements\` 工具`,
|
|
155
|
+
needsAction: {
|
|
156
|
+
type: "read_web",
|
|
157
|
+
instruction: `使用 Figma MCP 工具读取 ${figmaUrl},保存到 ${designDocPath},然后重新调用 generate_requirements`
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
} else if (params.designSource.type === "file") {
|
|
161
|
+
// 文件类型设计稿
|
|
162
|
+
const designResult = await processRequirementDocument(
|
|
163
|
+
{
|
|
164
|
+
type: "file",
|
|
165
|
+
path: params.designSource.path
|
|
166
|
+
},
|
|
167
|
+
params.featureName,
|
|
168
|
+
"design-doc.md"
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
if (!designResult.success) {
|
|
172
|
+
debugLog(`设计稿需要进一步处理`, { designResult });
|
|
173
|
+
return {
|
|
174
|
+
success: false,
|
|
175
|
+
message: designResult.message!,
|
|
176
|
+
needsAction: designResult.needsAction
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
debugLog(`设计稿已处理完成`);
|
|
180
|
+
}
|
|
156
181
|
} else {
|
|
157
|
-
debugLog(
|
|
182
|
+
debugLog(`设计稿已存在,跳过处理`);
|
|
158
183
|
}
|
|
159
184
|
}
|
|
160
|
-
|
|
161
|
-
//
|
|
162
|
-
if (params.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
type: "file",
|
|
169
|
-
path: params.designSource.path
|
|
170
|
-
},
|
|
185
|
+
|
|
186
|
+
// 3.3 处理后端文档
|
|
187
|
+
if (params.backendSource) {
|
|
188
|
+
const savedBackend = await tryReadSavedBackend(params.featureName, projectRoot);
|
|
189
|
+
if (!savedBackend) {
|
|
190
|
+
debugLog(`后端文档未找到,开始处理`);
|
|
191
|
+
const backendResult = await processRequirementDocument(
|
|
192
|
+
params.backendSource,
|
|
171
193
|
params.featureName,
|
|
172
|
-
"
|
|
194
|
+
"backend-doc.md"
|
|
173
195
|
);
|
|
174
196
|
|
|
175
|
-
if (!
|
|
176
|
-
debugLog(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
processingInstruction: designResult.message!
|
|
183
|
-
});
|
|
184
|
-
} else {
|
|
185
|
-
debugLog(`设计稿已处理`);
|
|
197
|
+
if (!backendResult.success) {
|
|
198
|
+
debugLog(`后端文档需要进一步处理`, { backendResult });
|
|
199
|
+
return {
|
|
200
|
+
success: false,
|
|
201
|
+
message: backendResult.message!,
|
|
202
|
+
needsAction: backendResult.needsAction
|
|
203
|
+
};
|
|
186
204
|
}
|
|
187
|
-
|
|
188
|
-
tasks.push({
|
|
189
|
-
name: "设计稿 (Figma)",
|
|
190
|
-
outputPath: designDocPath!,
|
|
191
|
-
source: params.designSource,
|
|
192
|
-
status: "needs_processing",
|
|
193
|
-
processingInstruction: `🎨 检测到 Figma 设计稿链接
|
|
194
|
-
|
|
195
|
-
请读取以下 Figma 设计稿并保存到文件:
|
|
196
|
-
|
|
197
|
-
- Figma 链接:${params.designSource.url}
|
|
198
|
-
- 保存到:\`${designDocPath}\``
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// 检查后端文档
|
|
204
|
-
if (params.backendSource && !savedBackend) {
|
|
205
|
-
debugLog(`后端文档未找到,需要处理`);
|
|
206
|
-
const backendResult = await processRequirementDocument(
|
|
207
|
-
params.backendSource,
|
|
208
|
-
params.featureName,
|
|
209
|
-
"backend-doc.md"
|
|
210
|
-
);
|
|
211
|
-
|
|
212
|
-
if (!backendResult.success) {
|
|
213
|
-
debugLog(`后端文档需要进一步处理`, { backendResult });
|
|
214
|
-
tasks.push({
|
|
215
|
-
name: "后端文档",
|
|
216
|
-
outputPath: backendDocPath!,
|
|
217
|
-
source: params.backendSource,
|
|
218
|
-
status: "needs_processing",
|
|
219
|
-
processingInstruction: backendResult.message!
|
|
220
|
-
});
|
|
205
|
+
debugLog(`后端文档已处理完成`);
|
|
221
206
|
} else {
|
|
222
|
-
debugLog(
|
|
207
|
+
debugLog(`后端文档已存在,跳过处理`);
|
|
223
208
|
}
|
|
224
209
|
}
|
|
225
|
-
|
|
226
|
-
// 如果有需要处理的任务,返回完整工作流
|
|
227
|
-
if (tasks.length > 0) {
|
|
228
|
-
debugLog(`发现 ${tasks.length} 个需要处理的任务`);
|
|
229
|
-
|
|
230
|
-
let message = `📋 需要处理以下文档(共 ${tasks.length} 个)\n\n`;
|
|
231
|
-
|
|
232
|
-
tasks.forEach((task, index) => {
|
|
233
|
-
message += `### 任务 ${index + 1}:${task.name}\n`;
|
|
234
|
-
message += task.processingInstruction;
|
|
235
|
-
message += `\n\n`;
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
message += `⚠️ **重要提示**:\n`;
|
|
239
|
-
message += `- **推荐并行处理**:可以同时处理多个任务,提高效率\n`;
|
|
240
|
-
message += `- 每个任务处理完成后,立即保存文件,**不要把文件内容放在上下文中**\n`;
|
|
241
|
-
message += `- 所有任务完成后,重新调用 \`generate_requirements\` 工具(工具会自动检查已完成任务)\n`;
|
|
242
|
-
message += `- 这样可以避免上下文过长,同时减少重复调用\n`;
|
|
243
|
-
|
|
244
|
-
return {
|
|
245
|
-
success: false,
|
|
246
|
-
message,
|
|
247
|
-
needsAction: {
|
|
248
|
-
type: "process_documents" as any,
|
|
249
|
-
instruction: `按顺序或并行处理上述 ${tasks.length} 个任务,每个任务完成后立即保存文件。所有任务完成后重新调用 generate_requirements 工具。`
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// 所有文档都已准备好
|
|
255
|
-
debugLog(`所有文档已准备完毕`);
|
|
256
|
-
|
|
257
|
-
let designSourceInfo = "";
|
|
258
|
-
if (savedDesign) {
|
|
259
|
-
designSourceInfo = `**设计稿位置**:${designDocPath}\n`;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
let backendSourceInfo = "";
|
|
263
|
-
if (savedBackend) {
|
|
264
|
-
backendSourceInfo = `**后端文档位置**:${backendDocPath}\n`;
|
|
265
|
-
}
|
|
266
210
|
|
|
267
|
-
//
|
|
211
|
+
// 步骤 4:所有文档已准备完毕,生成分析提示词
|
|
212
|
+
debugLog(`所有文档已准备完毕,生成分析提示词`);
|
|
213
|
+
|
|
268
214
|
const outputPath = buildOutputPath(params.featureName, "requirements.md", projectRoot);
|
|
269
|
-
|
|
270
|
-
|
|
215
|
+
|
|
271
216
|
let message = "📝 需求文档已准备完毕\n\n";
|
|
272
217
|
message += `**原始文档位置**:${originDocPath}\n`;
|
|
273
|
-
if (
|
|
274
|
-
message +=
|
|
218
|
+
if (designDocPath) {
|
|
219
|
+
message += `**设计稿位置**:${designDocPath}\n`;
|
|
275
220
|
}
|
|
276
|
-
if (
|
|
277
|
-
message +=
|
|
221
|
+
if (backendDocPath) {
|
|
222
|
+
message += `**后端文档位置**:${backendDocPath}\n`;
|
|
278
223
|
}
|
|
279
224
|
message += `**目标输出位置**:${outputPath}\n\n`;
|
|
280
225
|
message += buildAnalysisPrompt(originDocPath, outputPath, params.designSource, params.backendSource);
|
|
@@ -314,154 +259,40 @@ function buildAnalysisPrompt(
|
|
|
314
259
|
): string {
|
|
315
260
|
const featureName = outputPath.split('/')[2];
|
|
316
261
|
|
|
317
|
-
let prompt =
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
-
|
|
347
|
-
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
- **用户故事**:作为角色,我希望功能,以便价值
|
|
352
|
-
- **验收标准**:WHEN 触发条件 THEN 预期行为(至少 3-6 条)
|
|
353
|
-
- **说明**:补充必要的细节(不涉及技术实现)
|
|
354
|
-
|
|
355
|
-
#### 3. 交互细节
|
|
356
|
-
- **视觉反馈**:选中、不可用、加载、错误的视觉表现
|
|
357
|
-
- **动画效果**:展开/收起、弹出、跳转的动画时长和方式
|
|
358
|
-
- **错误处理**:各种错误场景的用户提示和处理方式
|
|
359
|
-
- **确认弹窗**:需要用户确认的场景和确认内容
|
|
360
|
-
|
|
361
|
-
#### 4. 技术要求与限制
|
|
362
|
-
- **性能需求**:响应时间、加载速度、动画流畅度
|
|
363
|
-
- **可用性需求**:状态清晰性、错误提示友好性、操作便捷性
|
|
364
|
-
- **兼容性需求**:支持的系统版本、设备类型、浏览器要求
|
|
365
|
-
- **限制说明**:不支持的场景、已知的兼容性问题、特殊边界情况
|
|
366
|
-
|
|
367
|
-
### 内容要求
|
|
368
|
-
|
|
369
|
-
#### 必须包含的关键内容
|
|
370
|
-
|
|
371
|
-
**1. 功能范围**
|
|
372
|
-
- 业务场景、平台范围、排除范围
|
|
373
|
-
|
|
374
|
-
**2. 页面结构**
|
|
375
|
-
- 页面/模块布局、组件层级关系
|
|
376
|
-
|
|
377
|
-
**3. 数据展示**
|
|
378
|
-
- 数据来源(用"由系统返回"替代接口名)
|
|
379
|
-
- 数据展示规则
|
|
380
|
-
- 空数据/加载/错误状态的表现
|
|
381
|
-
|
|
382
|
-
**4. 交互逻辑**
|
|
383
|
-
- 操作入口、触发条件、即时反馈、结果处理
|
|
384
|
-
|
|
385
|
-
**5. 状态管理**
|
|
386
|
-
- 状态触发条件、转换逻辑、数据保持/重置
|
|
387
|
-
|
|
388
|
-
**6. 页面跳转**
|
|
389
|
-
- 跳转触发、目标页面、参数传递(只说明内容,不涉及字段)、返回逻辑
|
|
390
|
-
|
|
391
|
-
**7. 跨系统交互**
|
|
392
|
-
- 交互触发、返回处理、结果查询和展示
|
|
393
|
-
|
|
394
|
-
**8. 异常处理**
|
|
395
|
-
- 异常场景、提示方式、恢复机制
|
|
396
|
-
|
|
397
|
-
**9. 交互细节**
|
|
398
|
-
- 视觉反馈(选中/不可用等)
|
|
399
|
-
- 动画效果(展开/收起/弹出等)
|
|
400
|
-
- 确认弹窗
|
|
401
|
-
|
|
402
|
-
**10. 性能要求**
|
|
403
|
-
- 加载速度、响应时间、动画流畅度
|
|
404
|
-
|
|
405
|
-
#### 视角要求
|
|
406
|
-
|
|
407
|
-
**从用户视角描述**
|
|
408
|
-
- ✅ 描述"用户能看到什么"、"用户能做什么"、"操作后有什么反馈"
|
|
409
|
-
|
|
410
|
-
**避免技术细节**
|
|
411
|
-
- ❌ 不要描述"轮询 5 次"、"骨架屏 vs 局部加载"、"调用 XXX 接口"、"使用 XXX SDK"
|
|
412
|
-
- ✅ 用"查询超时"、"加载状态"、"由系统返回"替代
|
|
413
|
-
|
|
414
|
-
#### 格式化要求
|
|
415
|
-
- 用户故事:作为[角色],我希望[功能],以便[价值]
|
|
416
|
-
- 验收标准:WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
417
|
-
- 验收标准必须可测试:使用具体的时间、数量、状态,避免"快速响应"等模糊描述
|
|
418
|
-
|
|
419
|
-
### 格式要求
|
|
420
|
-
|
|
421
|
-
#### 用户故事格式
|
|
422
|
-
\`\`\`
|
|
423
|
-
**用户故事**:作为[角色],我希望[功能],以便[价值]。
|
|
424
|
-
\`\`\`
|
|
425
|
-
|
|
426
|
-
#### 验收标准格式
|
|
427
|
-
\`\`\`
|
|
428
|
-
#### 验收标准
|
|
429
|
-
|
|
430
|
-
1. WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
431
|
-
2. WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
432
|
-
3. WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
433
|
-
...
|
|
434
|
-
\`\`\`
|
|
435
|
-
|
|
436
|
-
#### 可测试性要求
|
|
437
|
-
- 每个验收标准必须可测试、可验证
|
|
438
|
-
- 避免模糊的描述(如"快速响应")
|
|
439
|
-
- 使用具体的时间、数量、状态描述
|
|
440
|
-
|
|
441
|
-
## 核心约束
|
|
442
|
-
|
|
443
|
-
### 1. 内容完整性
|
|
444
|
-
- 必须包含所有 4 个章节(介绍、功能需求、交互细节、技术要求与限制)
|
|
445
|
-
- 每个功能需求必须有用户故事和 3-6 条验收标准
|
|
446
|
-
- 必须覆盖 10 个前端开发重点
|
|
447
|
-
|
|
448
|
-
### 2. 视角正确性
|
|
449
|
-
- 从用户视角描述功能
|
|
450
|
-
- 不涉及技术实现细节(接口、SDK、轮询机制等)
|
|
451
|
-
- 用"由系统返回"、"加载状态"、"查询超时"替代技术术语
|
|
452
|
-
|
|
453
|
-
### 3. 内容独立性
|
|
454
|
-
- 不要生成接口文档(放在设计文档)
|
|
455
|
-
- 不要生成数据模型(放在设计文档)
|
|
456
|
-
- 不要生成技术架构(放在设计文档)
|
|
457
|
-
- 不要生成代码示例(放在开发阶段)
|
|
458
|
-
|
|
459
|
-
## 开始执行
|
|
460
|
-
|
|
461
|
-
请按照以上要求,从输入的 PRD ${designSource ? "和设计稿" : ""} 中提取信息,生成完整的需求文档到:\`${outputPath}\`
|
|
462
|
-
|
|
463
|
-
生成过程中,如果遇到不明确的内容,必须向用户确认,不要假设答案。
|
|
464
|
-
`;
|
|
262
|
+
let prompt = `请根据以下材料生成需求文档:
|
|
263
|
+
|
|
264
|
+
**输入材料**:
|
|
265
|
+
- PRD:\`${originDocPath}\`
|
|
266
|
+
${designSource ? `- 设计稿:\`.specs/requirements/${featureName}/design-doc.md\`` : ''}
|
|
267
|
+
${backendSource ? `- 后端文档:\`.specs/requirements/${featureName}/backend-doc.md\`` : ''}
|
|
268
|
+
|
|
269
|
+
**输出位置**:\`${outputPath}\`
|
|
270
|
+
|
|
271
|
+
**文档结构**:
|
|
272
|
+
1. 介绍(功能概述、核心价值、涉及范围、术语表)
|
|
273
|
+
2. 功能需求(用户故事 + 验收标准)
|
|
274
|
+
3. 交互细节(视觉反馈、动画效果、错误处理)
|
|
275
|
+
4. 技术要求与限制(性能、可用性、兼容性)
|
|
276
|
+
|
|
277
|
+
**前端开发必须覆盖的 10 个重点**:
|
|
278
|
+
1. 功能范围(业务场景、平台范围、排除范围)
|
|
279
|
+
2. 页面结构(页面/模块布局、组件层级关系)
|
|
280
|
+
3. 数据展示(数据来源、展示规则、空数据/加载/错误状态)
|
|
281
|
+
4. 交互逻辑(操作入口、触发条件、即时反馈、结果处理)
|
|
282
|
+
5. 状态管理(状态触发条件、转换逻辑、数据保持/重置)
|
|
283
|
+
6. 页面跳转(跳转触发、目标页面、参数传递、返回逻辑)
|
|
284
|
+
7. 跨系统交互(交互触发、返回处理、结果查询和展示)
|
|
285
|
+
8. 异常处理(异常场景、提示方式、恢复机制)
|
|
286
|
+
9. 交互细节(视觉反馈、动画效果、确认弹窗)
|
|
287
|
+
10. 性能要求(加载速度、响应时间、动画流畅度)
|
|
288
|
+
|
|
289
|
+
**关键要求**:
|
|
290
|
+
- 从用户视角描述(用户能看到什么、能做什么、操作后有什么反馈)
|
|
291
|
+
- 避免技术细节(不要提接口名、SDK、轮询机制等,用"由系统返回"、"加载状态"、"查询超时"替代)
|
|
292
|
+
- 验收标准格式:WHEN [触发条件] THEN THE System SHALL [预期行为]
|
|
293
|
+
- 每个需求 3-6 条验收标准,必须可测试(使用具体的时间、数量、状态)
|
|
294
|
+
|
|
295
|
+
遇到不明确的内容,向用户确认,不要假设答案。`;
|
|
465
296
|
|
|
466
297
|
return prompt;
|
|
467
298
|
}
|
|
@@ -123,45 +123,22 @@ export async function processRequirementDocument(
|
|
|
123
123
|
// 文件不存在,需要处理
|
|
124
124
|
debugLog(`输出文件不存在,需要处理PDF`, { outputMdPath });
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
const fileName = filePath.split('/').pop() || '';
|
|
128
|
-
const isChinese = /[\u4e00-\u9fa5]/.test(fileName);
|
|
129
|
-
const language = isChinese ? 'chi_sim' : 'eng';
|
|
126
|
+
debugLog(`准备提取PDF内容`, { filePath });
|
|
130
127
|
|
|
131
|
-
debugLog(`准备提取PDF内容`, { filePath, language });
|
|
132
|
-
|
|
133
|
-
// 判断是否需要提示使用绝对路径
|
|
134
|
-
const needAbsolutePathHint = !path.isAbsolute(filePath);
|
|
135
|
-
|
|
136
128
|
return {
|
|
137
129
|
success: false,
|
|
138
|
-
message: `📄 检测到 PDF
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
2. 调用 \`mcp_execute_tool\` 工具读取图片和表格(OCR):
|
|
149
|
-
- server_name: "pdf-reader"
|
|
150
|
-
- tool_name: "read_by_ocr"
|
|
151
|
-
- arguments: { "file_path": "${needAbsolutePathHint ? '<请使用绝对路径>' : filePath}", "language": "${language}", "dpi": 300 }
|
|
152
|
-
${needAbsolutePathHint ? ' ⚠️ **重要**:file_path 参数必须是绝对路径,例如:/Users/xxx/Documents/prd.pdf' : ''}
|
|
153
|
-
|
|
154
|
-
3. 将两次读取的内容合并(文本层 + OCR内容)
|
|
155
|
-
|
|
156
|
-
4. 保存合并后的内容到:\`${outputMdPath}\``,
|
|
130
|
+
message: `📄 检测到 PDF 文件
|
|
131
|
+
|
|
132
|
+
使用 PDF Reader MCP 工具读取 PDF 内容:
|
|
133
|
+
- 文件路径: ${filePath}
|
|
134
|
+
- 同时使用文本层(include_full_text: true)和 OCR(include_images: true)两种方式读取,避免内容遗漏
|
|
135
|
+
|
|
136
|
+
保存到:\`${outputMdPath}\`
|
|
137
|
+
|
|
138
|
+
完成后重新调用 \`generate_requirements\` 工具(不要把文件内容放在上下文中)`,
|
|
157
139
|
needsAction: {
|
|
158
140
|
type: "read_pdf",
|
|
159
|
-
instruction:
|
|
160
|
-
1. 调用 mcp_execute_tool,使用 pdf-reader 的 read_pdf_text 工具,参数为 { "file_path": "${filePath}" }
|
|
161
|
-
2. 调用 mcp_execute_tool,使用 pdf-reader 的 read_by_ocr 工具,参数为 { "file_path": "${filePath}", "language": "${language}", "dpi": 300 }
|
|
162
|
-
3. 将两次读取的内容合并(text + ocr)
|
|
163
|
-
4. 保存合并后的内容到文件:${outputMdPath}
|
|
164
|
-
5. 保存完成后重新调用 generate_requirements 工具(不要把文件内容放在上下文中)`,
|
|
141
|
+
instruction: `使用 PDF Reader MCP 工具读取 ${filePath}(同时使用文本层和 OCR),保存到 ${outputMdPath},然后重新调用 generate_requirements(不要把文件内容放在上下文中)`,
|
|
165
142
|
},
|
|
166
143
|
};
|
|
167
144
|
}
|