bmall-mcp 1.8.3 → 1.8.6
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 +19 -0
- package/dist/tools/requirements/index.d.ts.map +1 -1
- package/dist/tools/requirements/index.js +50 -42
- package/dist/tools/requirements/index.js.map +1 -1
- package/dist/tools/requirements/requirement-processor.d.ts +1 -6
- package/dist/tools/requirements/requirement-processor.d.ts.map +1 -1
- package/dist/tools/requirements/requirement-processor.js +78 -25
- package/dist/tools/requirements/requirement-processor.js.map +1 -1
- package/package.json +1 -1
- package/src/tools/requirements/index.ts +53 -47
- package/src/tools/requirements/requirement-processor.ts +79 -33
package/README.md
CHANGED
|
@@ -204,6 +204,25 @@ src/
|
|
|
204
204
|
|
|
205
205
|
## Changelog
|
|
206
206
|
|
|
207
|
+
### v1.8.6 (2026-03-16)
|
|
208
|
+
- ✅ 修复 TypeScript 编译错误:删除多余的 `}` 语法错误
|
|
209
|
+
- ✅ 修复设计稿处理逻辑中的代码结构问题
|
|
210
|
+
- ✅ 确保代码正确编译和运行
|
|
211
|
+
|
|
212
|
+
### v1.8.5 (2026-03-16)
|
|
213
|
+
- ✅ 优化逐个文档处理:PRD、设计稿、后端文档**一次只处理一个**
|
|
214
|
+
- ✅ 避免上下文累积:每读取成功一个文档就立即返回,重新调用工具
|
|
215
|
+
- ✅ 统一处理流程:所有文档都应用相同的增量处理逻辑
|
|
216
|
+
- ✅ 智能状态检查:自动检测已保存的文档,跳过已完成的步骤
|
|
217
|
+
- ✅ 明确指令提示:每次都强调"立即保存,不要把内容放在上下文中"
|
|
218
|
+
|
|
219
|
+
### v1.8.4 (2026-03-16)
|
|
220
|
+
- ✅ 优化增量处理流程:支持逐个文档处理,避免上下文累积过长
|
|
221
|
+
- ✅ 完善 PDF 分步读取:text 和 OCR 分别处理,每次立即保存不放入上下文
|
|
222
|
+
- ✅ 统一文档处理逻辑:PRD、设计稿、后端文档都应用同样的分步处理
|
|
223
|
+
- ✅ 智能文件检查:自动检测已完成的步骤,避免重复处理
|
|
224
|
+
- ✅ 明确处理指令:每次都提示"立即保存,不要把内容放在上下文中"
|
|
225
|
+
|
|
207
226
|
### v1.8.3 (2026-03-16)
|
|
208
227
|
- ✅ 优化 PDF 读取策略:采用**分两步读取**策略(text + OCR)
|
|
209
228
|
- ✅ 新增 PDF 语言自动检测:根据文件名自动识别中文/英文文档
|
|
@@ -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":"AAyBA,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,CA2KD"}
|
|
@@ -41,92 +41,100 @@ export async function generateRequirements(params) {
|
|
|
41
41
|
if (!validation.valid) {
|
|
42
42
|
return validation.error;
|
|
43
43
|
}
|
|
44
|
-
// 2.
|
|
45
|
-
// 2.0 计算项目根目录(从输入路径提取)
|
|
44
|
+
// 2. 计算项目根目录(从输入路径提取)
|
|
46
45
|
let projectRoot = process.cwd();
|
|
47
46
|
if (params.requirementSource.type === "file" && params.requirementSource.path) {
|
|
48
47
|
projectRoot = getProjectRoot(params.requirementSource.path);
|
|
49
48
|
}
|
|
50
49
|
debugLog(`计算项目根目录`, { projectRoot, cwd: process.cwd() });
|
|
51
|
-
// 2.1
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
debugLog(`未找到缓存,处理需求文档输入`);
|
|
56
|
-
// 2.2 没有缓存,处理需求文档输入
|
|
50
|
+
// 2.1 处理需求文档(优先处理)
|
|
51
|
+
const savedRequirement = await tryReadSavedRequirement(params.featureName, projectRoot);
|
|
52
|
+
if (!savedRequirement) {
|
|
53
|
+
debugLog(`未找到需求文档,需要处理`);
|
|
57
54
|
const requirementResult = await processRequirementDocument(params.requirementSource, params.featureName);
|
|
58
|
-
// 2.2.1 如果需要执行操作(读取 PDF/网页),直接返回
|
|
59
55
|
if (!requirementResult.success) {
|
|
60
|
-
debugLog(
|
|
56
|
+
debugLog(`需求文档需要进一步处理`, { requirementResult });
|
|
61
57
|
return {
|
|
62
58
|
success: false,
|
|
63
59
|
message: requirementResult.message,
|
|
64
60
|
needsAction: requirementResult.needsAction,
|
|
65
61
|
};
|
|
66
62
|
}
|
|
67
|
-
|
|
63
|
+
debugLog(`需求文档已保存`);
|
|
68
64
|
}
|
|
69
65
|
else {
|
|
70
|
-
debugLog(
|
|
66
|
+
debugLog(`需求文档已存在`, { contentLength: savedRequirement.length });
|
|
71
67
|
}
|
|
72
|
-
//
|
|
68
|
+
// 2.2 检查设计稿(如果有且未保存)
|
|
73
69
|
let designSourceInfo = "";
|
|
74
70
|
if (params.designSource) {
|
|
75
|
-
|
|
76
|
-
const savedDesign = await tryReadSavedDesign(params.featureName);
|
|
71
|
+
const savedDesign = await tryReadSavedDesign(params.featureName, projectRoot);
|
|
77
72
|
if (!savedDesign) {
|
|
78
|
-
|
|
73
|
+
debugLog(`设计稿未保存,需要处理`);
|
|
74
|
+
let designResult;
|
|
79
75
|
if (params.designSource.type === "file") {
|
|
80
|
-
// 从设计稿路径重新计算项目根目录
|
|
81
76
|
const designProjectRoot = getProjectRoot(params.designSource.path);
|
|
82
77
|
debugLog(`设计稿项目根目录`, { designProjectRoot });
|
|
83
|
-
|
|
84
|
-
if (!designResult.success) {
|
|
85
|
-
return {
|
|
86
|
-
success: false,
|
|
87
|
-
message: designResult.message,
|
|
88
|
-
needsAction: designResult.needsAction,
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
designSourceInfo = `**设计稿位置**:${buildOutputPath(params.featureName, "design-doc.md", designProjectRoot)}\n`;
|
|
78
|
+
designResult = await processRequirementDocument(params.designSource, params.featureName, "design-doc.md");
|
|
92
79
|
}
|
|
93
80
|
else if (params.designSource.type === "figma") {
|
|
94
|
-
|
|
81
|
+
// Figma 链接类型,返回提示让 AI 处理
|
|
82
|
+
designResult = {
|
|
83
|
+
success: false,
|
|
84
|
+
message: `🎨 检测到 Figma 设计稿链接
|
|
85
|
+
|
|
86
|
+
请使用 Figma MCP 读取设计稿并保存到文件`,
|
|
87
|
+
needsAction: {
|
|
88
|
+
type: "analyze_content",
|
|
89
|
+
instruction: `使用 Figma MCP 读取设计稿 ${params.designSource.url},保存到 ${buildOutputPath(params.featureName, "design-doc.md", projectRoot)}。完成后立即保存文件,不要把内容放在上下文中。保存后重新调用 generate_requirements 工具。`,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// 未知类型,默认返回成功
|
|
95
|
+
debugLog(`设计稿类型未知,跳过`);
|
|
96
|
+
designResult = { success: true, message: "设计稿已处理" };
|
|
97
|
+
}
|
|
98
|
+
if (!designResult.success) {
|
|
99
|
+
debugLog(`设计稿需要进一步处理`, { designResult });
|
|
100
|
+
return {
|
|
101
|
+
success: false,
|
|
102
|
+
message: designResult.message,
|
|
103
|
+
needsAction: designResult.needsAction,
|
|
104
|
+
};
|
|
95
105
|
}
|
|
106
|
+
debugLog(`设计稿已保存`);
|
|
107
|
+
designSourceInfo = `**设计稿位置**:${buildOutputPath(params.featureName, "design-doc.md", projectRoot)}\n`;
|
|
96
108
|
}
|
|
97
109
|
else {
|
|
98
|
-
|
|
110
|
+
debugLog(`设计稿已存在`);
|
|
99
111
|
designSourceInfo = `**设计稿位置**:${buildOutputPath(params.featureName, "design-doc.md", projectRoot)}\n`;
|
|
100
112
|
}
|
|
101
113
|
}
|
|
102
|
-
//
|
|
114
|
+
// 2.3 检查后端文档(如果有且未保存)
|
|
103
115
|
let backendSourceInfo = "";
|
|
104
116
|
if (params.backendSource) {
|
|
105
|
-
|
|
106
|
-
const savedBackend = await tryReadSavedBackend(params.featureName);
|
|
117
|
+
const savedBackend = await tryReadSavedBackend(params.featureName, projectRoot);
|
|
107
118
|
if (!savedBackend) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
debugLog(`后端文档未保存,需要处理`);
|
|
120
|
+
const backendProjectRoot = params.backendSource.type === "file"
|
|
121
|
+
? getProjectRoot(params.backendSource.path)
|
|
122
|
+
: projectRoot;
|
|
111
123
|
debugLog(`后端文档项目根目录`, { backendProjectRoot });
|
|
112
124
|
const backendResult = await processRequirementDocument(params.backendSource, params.featureName, "backend-doc.md");
|
|
113
125
|
if (!backendResult.success) {
|
|
126
|
+
debugLog(`后端文档需要进一步处理`, { backendResult });
|
|
114
127
|
return {
|
|
115
128
|
success: false,
|
|
116
129
|
message: backendResult.message,
|
|
117
130
|
needsAction: backendResult.needsAction,
|
|
118
131
|
};
|
|
119
132
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
backendSourceInfo = `**后端文档位置**:${buildOutputPath(params.featureName, "backend-doc.md", backendProjectRoot)}\n`;
|
|
123
|
-
}
|
|
124
|
-
else if (params.backendSource.type === "url") {
|
|
125
|
-
backendSourceInfo = `**后端文档网页**:${params.backendSource.url || "后端文档网页 URL 未提供"}(请使用 Chrome DevTools MCP 读取并保存到 .specs/requirements/${params.featureName}/backend-doc.md)\n`;
|
|
126
|
-
}
|
|
133
|
+
debugLog(`后端文档已保存`);
|
|
134
|
+
backendSourceInfo = `**后端文档位置**:${buildOutputPath(params.featureName, "backend-doc.md", backendProjectRoot)}\n`;
|
|
127
135
|
}
|
|
128
136
|
else {
|
|
129
|
-
|
|
137
|
+
debugLog(`后端文档已存在`);
|
|
130
138
|
backendSourceInfo = `**后端文档位置**:${buildOutputPath(params.featureName, "backend-doc.md", projectRoot)}\n`;
|
|
131
139
|
}
|
|
132
140
|
}
|
|
@@ -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;AAG9D,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EACL,0BAA0B,EAC1B,uBAAuB,EAEvB,kBAAkB,EAElB,mBAAmB,EACnB,cAAc,EACd,eAAe,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/requirements/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ interface RequirementSource {
|
|
|
13
13
|
path?: string;
|
|
14
14
|
url?: string;
|
|
15
15
|
}
|
|
16
|
-
interface ProcessResult {
|
|
16
|
+
export interface ProcessResult {
|
|
17
17
|
success: boolean;
|
|
18
18
|
content?: string;
|
|
19
19
|
message?: string;
|
|
@@ -22,11 +22,6 @@ interface ProcessResult {
|
|
|
22
22
|
instruction: string;
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
interface RequirementSource {
|
|
26
|
-
type: "file" | "url";
|
|
27
|
-
path?: string;
|
|
28
|
-
url?: string;
|
|
29
|
-
}
|
|
30
25
|
/**
|
|
31
26
|
* 步骤 2:处理需求文档输入
|
|
32
27
|
* 这是整体流程的第二步,专门处理需求文档
|
|
@@ -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,
|
|
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,CAqMxB;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"}
|
|
@@ -81,40 +81,93 @@ export async function processRequirementDocument(requirementSource, featureName,
|
|
|
81
81
|
if (ext === "pdf") {
|
|
82
82
|
const projectRoot = getProjectRoot(filePath);
|
|
83
83
|
const outputMdPath = buildOutputPath(featureName, outputFileName, projectRoot);
|
|
84
|
-
//
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
84
|
+
// 检查是否已经存在输出文件
|
|
85
|
+
try {
|
|
86
|
+
await fs.access(outputMdPath);
|
|
87
|
+
debugLog(`输出文件已存在`, { outputMdPath });
|
|
88
|
+
// 文件已存在,跳过处理
|
|
89
|
+
return {
|
|
90
|
+
success: true,
|
|
91
|
+
content: "已存在",
|
|
92
|
+
message: `✅ 文档已存在:${outputMdPath}`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// 文件不存在,需要处理
|
|
97
|
+
debugLog(`输出文件不存在,需要处理`, { outputMdPath });
|
|
98
|
+
// 检查是否已经完成了部分步骤
|
|
99
|
+
const textPath = outputMdPath.replace('.md', '-text.md');
|
|
100
|
+
const ocrPath = outputMdPath.replace('.md', '-ocr.md');
|
|
101
|
+
try {
|
|
102
|
+
await fs.access(textPath);
|
|
103
|
+
try {
|
|
104
|
+
await fs.access(ocrPath);
|
|
105
|
+
// 两个文件都存在,可以合并
|
|
106
|
+
debugLog(`发现text和ocr文件,准备合并`);
|
|
107
|
+
return {
|
|
108
|
+
success: false,
|
|
109
|
+
message: `✅ PDF 的两个中间文件已存在,现在合并它们
|
|
91
110
|
|
|
92
|
-
|
|
111
|
+
**步骤 3:合并文件**
|
|
112
|
+
- 读取 \`${textPath}\` 的内容
|
|
113
|
+
- 读取 \`${ocrPath}\` 的内容
|
|
114
|
+
- 将两者合并保存到 \`${outputMdPath}\`
|
|
93
115
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
116
|
+
⚠️ **重要**:合并完成后立即保存文件,不要把内容放在上下文中。完成后重新调用本工具。`,
|
|
117
|
+
needsAction: {
|
|
118
|
+
type: "read_pdf",
|
|
119
|
+
instruction: `合并两个PDF读取结果:
|
|
120
|
+
1. 读取 ${textPath} 的内容
|
|
121
|
+
2. 读取 ${ocrPath} 的内容
|
|
122
|
+
3. 将两者合并保存到 ${outputMdPath}
|
|
123
|
+
4. 保存文件
|
|
124
|
+
5. 重新调用 generate_requirements 工具(不要把文件内容放在上下文中)`,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// 只有text文件存在,进行OCR
|
|
130
|
+
const fileName = filePath.split('/').pop() || '';
|
|
131
|
+
const isChinese = /[\u4e00-\u9fa5]/.test(fileName);
|
|
132
|
+
const language = isChinese ? 'chi_sim' : 'eng';
|
|
133
|
+
debugLog(`发现text文件,准备OCR`);
|
|
134
|
+
return {
|
|
135
|
+
success: false,
|
|
136
|
+
message: `✅ PDF 文本层已提取(${textPath}),现在进行 OCR
|
|
97
137
|
|
|
98
138
|
**步骤 2:使用 \`read_by_ocr\` 提取图片和表格**
|
|
99
139
|
- 优势:可提取图片、表格、扫描件等非文本内容
|
|
100
140
|
- 语言:\`${language}\`(中文文档使用 \`chi_sim\`,英文使用 \`eng\`)
|
|
101
141
|
- DPI:\`300\`(默认值)
|
|
102
|
-
- 保存到:\`${
|
|
142
|
+
- 保存到:\`${ocrPath}\`
|
|
103
143
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
144
|
+
⚠️ **重要**:OCR完成后立即保存文件,不要把文件内容放在上下文中。保存后重新调用本工具。`,
|
|
145
|
+
needsAction: {
|
|
146
|
+
type: "read_pdf",
|
|
147
|
+
instruction: `使用 PDF Reader MCP 的 read_by_ocr 工具读取 ${filePath},设置 language="${language}",dpi=300,保存到 ${ocrPath}。完成后立即保存文件,然后重新调用 generate_requirements 工具。不要把文件内容放在上下文中,避免上下文过长。`,
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// 还没有任何文件,先提取文本
|
|
154
|
+
debugLog(`未发现中间文件,先提取文本层`);
|
|
155
|
+
return {
|
|
156
|
+
success: false,
|
|
157
|
+
message: `📄 检测到 PDF 文件
|
|
107
158
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
159
|
+
**步骤 1:使用 \`read_pdf_text\` 提取文本层**
|
|
160
|
+
- 优势:快速、准确、保留原始格式
|
|
161
|
+
- 保存到:\`${textPath}\`
|
|
162
|
+
|
|
163
|
+
⚠️ **重要**:文本提取完成后立即保存文件,不要把文件内容放在上下文中。保存后重新调用本工具。`,
|
|
164
|
+
needsAction: {
|
|
165
|
+
type: "read_pdf",
|
|
166
|
+
instruction: `使用 PDF Reader MCP 的 read_pdf_text 工具读取 ${filePath},保存到 ${textPath}。完成后立即保存文件,然后重新调用 generate_requirements 工具。不要把文件内容放在上下文中,避免上下文过长。`,
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
118
171
|
}
|
|
119
172
|
// 2.2.2 Markdown 文件 - 保存到固定位置
|
|
120
173
|
if (ext === "md" || ext === "markdown") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirement-processor.js","sourceRoot":"","sources":["../../../src/tools/requirements/requirement-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB;;GAEG;AACH,SAAS,QAAQ,CAAC,OAAe,EAAE,IAAU;IAC3C,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,UAAU,SAAS,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACxG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,gCAAgC;QAChC,8CAA8C;QAC9C,0BAA0B;QAC1B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACnB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnD,CAAC;QACD,yBAAyB;QACzB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;IACD,kBAAkB;IAClB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB,EAAE,QAAgB,EAAE,WAAmB;IACxF,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;AACjF,CAAC;
|
|
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
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
saveBackendDocument,
|
|
11
11
|
tryReadSavedBackend,
|
|
12
12
|
getProjectRoot,
|
|
13
|
-
buildOutputPath
|
|
13
|
+
buildOutputPath,
|
|
14
|
+
ProcessResult
|
|
14
15
|
} from "./requirement-processor.js";
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -100,88 +101,97 @@ export async function generateRequirements(
|
|
|
100
101
|
return validation.error!;
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
// 2.
|
|
104
|
-
|
|
105
|
-
// 2.0 计算项目根目录(从输入路径提取)
|
|
104
|
+
// 2. 计算项目根目录(从输入路径提取)
|
|
106
105
|
let projectRoot = process.cwd();
|
|
107
106
|
if (params.requirementSource.type === "file" && params.requirementSource.path) {
|
|
108
107
|
projectRoot = getProjectRoot(params.requirementSource.path);
|
|
109
108
|
}
|
|
110
109
|
debugLog(`计算项目根目录`, { projectRoot, cwd: process.cwd() });
|
|
111
110
|
|
|
112
|
-
// 2.1
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
debugLog(`未找到缓存,处理需求文档输入`);
|
|
117
|
-
// 2.2 没有缓存,处理需求文档输入
|
|
111
|
+
// 2.1 处理需求文档(优先处理)
|
|
112
|
+
const savedRequirement = await tryReadSavedRequirement(params.featureName, projectRoot);
|
|
113
|
+
if (!savedRequirement) {
|
|
114
|
+
debugLog(`未找到需求文档,需要处理`);
|
|
118
115
|
const requirementResult = await processRequirementDocument(
|
|
119
116
|
params.requirementSource,
|
|
120
117
|
params.featureName
|
|
121
118
|
);
|
|
122
119
|
|
|
123
|
-
// 2.2.1 如果需要执行操作(读取 PDF/网页),直接返回
|
|
124
120
|
if (!requirementResult.success) {
|
|
125
|
-
debugLog(
|
|
121
|
+
debugLog(`需求文档需要进一步处理`, { requirementResult });
|
|
126
122
|
return {
|
|
127
123
|
success: false,
|
|
128
124
|
message: requirementResult.message!,
|
|
129
125
|
needsAction: requirementResult.needsAction,
|
|
130
126
|
};
|
|
131
127
|
}
|
|
132
|
-
|
|
133
|
-
// 2.2.2 需求文档已读取并保存(Markdown 文件)
|
|
128
|
+
debugLog(`需求文档已保存`);
|
|
134
129
|
} else {
|
|
135
|
-
debugLog(
|
|
130
|
+
debugLog(`需求文档已存在`, { contentLength: savedRequirement.length });
|
|
136
131
|
}
|
|
137
132
|
|
|
138
|
-
//
|
|
133
|
+
// 2.2 检查设计稿(如果有且未保存)
|
|
139
134
|
let designSourceInfo = "";
|
|
140
135
|
if (params.designSource) {
|
|
141
|
-
|
|
142
|
-
const savedDesign = await tryReadSavedDesign(params.featureName);
|
|
136
|
+
const savedDesign = await tryReadSavedDesign(params.featureName, projectRoot);
|
|
143
137
|
|
|
144
138
|
if (!savedDesign) {
|
|
145
|
-
|
|
139
|
+
debugLog(`设计稿未保存,需要处理`);
|
|
140
|
+
let designResult: ProcessResult;
|
|
141
|
+
|
|
146
142
|
if (params.designSource.type === "file") {
|
|
147
|
-
// 从设计稿路径重新计算项目根目录
|
|
148
143
|
const designProjectRoot = getProjectRoot(params.designSource.path!);
|
|
149
144
|
debugLog(`设计稿项目根目录`, { designProjectRoot });
|
|
150
145
|
|
|
151
|
-
|
|
146
|
+
designResult = await processRequirementDocument(
|
|
152
147
|
params.designSource as any,
|
|
153
148
|
params.featureName,
|
|
154
149
|
"design-doc.md"
|
|
155
150
|
);
|
|
156
|
-
|
|
157
|
-
if (!designResult.success) {
|
|
158
|
-
return {
|
|
159
|
-
success: false,
|
|
160
|
-
message: designResult.message!,
|
|
161
|
-
needsAction: designResult.needsAction,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
designSourceInfo = `**设计稿位置**:${buildOutputPath(params.featureName, "design-doc.md", designProjectRoot)}\n`;
|
|
166
151
|
} else if (params.designSource.type === "figma") {
|
|
167
|
-
|
|
152
|
+
// Figma 链接类型,返回提示让 AI 处理
|
|
153
|
+
designResult = {
|
|
154
|
+
success: false,
|
|
155
|
+
message: `🎨 检测到 Figma 设计稿链接
|
|
156
|
+
|
|
157
|
+
请使用 Figma MCP 读取设计稿并保存到文件`,
|
|
158
|
+
needsAction: {
|
|
159
|
+
type: "analyze_content" as any,
|
|
160
|
+
instruction: `使用 Figma MCP 读取设计稿 ${params.designSource.url},保存到 ${buildOutputPath(params.featureName, "design-doc.md", projectRoot)}。完成后立即保存文件,不要把内容放在上下文中。保存后重新调用 generate_requirements 工具。`,
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
} else {
|
|
164
|
+
// 未知类型,默认返回成功
|
|
165
|
+
debugLog(`设计稿类型未知,跳过`);
|
|
166
|
+
designResult = { success: true, message: "设计稿已处理" };
|
|
168
167
|
}
|
|
168
|
+
|
|
169
|
+
if (!designResult.success) {
|
|
170
|
+
debugLog(`设计稿需要进一步处理`, { designResult });
|
|
171
|
+
return {
|
|
172
|
+
success: false,
|
|
173
|
+
message: designResult.message!,
|
|
174
|
+
needsAction: designResult.needsAction,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
debugLog(`设计稿已保存`);
|
|
178
|
+
designSourceInfo = `**设计稿位置**:${buildOutputPath(params.featureName, "design-doc.md", projectRoot)}\n`;
|
|
169
179
|
} else {
|
|
170
|
-
|
|
180
|
+
debugLog(`设计稿已存在`);
|
|
171
181
|
designSourceInfo = `**设计稿位置**:${buildOutputPath(params.featureName, "design-doc.md", projectRoot)}\n`;
|
|
172
182
|
}
|
|
173
183
|
}
|
|
174
184
|
|
|
175
|
-
//
|
|
185
|
+
// 2.3 检查后端文档(如果有且未保存)
|
|
176
186
|
let backendSourceInfo = "";
|
|
177
187
|
if (params.backendSource) {
|
|
178
|
-
|
|
179
|
-
const savedBackend = await tryReadSavedBackend(params.featureName);
|
|
188
|
+
const savedBackend = await tryReadSavedBackend(params.featureName, projectRoot);
|
|
180
189
|
|
|
181
190
|
if (!savedBackend) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
191
|
+
debugLog(`后端文档未保存,需要处理`);
|
|
192
|
+
const backendProjectRoot = params.backendSource.type === "file"
|
|
193
|
+
? getProjectRoot(params.backendSource.path!)
|
|
194
|
+
: projectRoot;
|
|
185
195
|
debugLog(`后端文档项目根目录`, { backendProjectRoot });
|
|
186
196
|
|
|
187
197
|
const backendResult = await processRequirementDocument(
|
|
@@ -191,21 +201,17 @@ export async function generateRequirements(
|
|
|
191
201
|
);
|
|
192
202
|
|
|
193
203
|
if (!backendResult.success) {
|
|
204
|
+
debugLog(`后端文档需要进一步处理`, { backendResult });
|
|
194
205
|
return {
|
|
195
206
|
success: false,
|
|
196
207
|
message: backendResult.message!,
|
|
197
208
|
needsAction: backendResult.needsAction,
|
|
198
209
|
};
|
|
199
210
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
if (params.backendSource.type === "file") {
|
|
203
|
-
backendSourceInfo = `**后端文档位置**:${buildOutputPath(params.featureName, "backend-doc.md", backendProjectRoot)}\n`;
|
|
204
|
-
} else if (params.backendSource.type === "url") {
|
|
205
|
-
backendSourceInfo = `**后端文档网页**:${params.backendSource.url || "后端文档网页 URL 未提供"}(请使用 Chrome DevTools MCP 读取并保存到 .specs/requirements/${params.featureName}/backend-doc.md)\n`;
|
|
206
|
-
}
|
|
211
|
+
debugLog(`后端文档已保存`);
|
|
212
|
+
backendSourceInfo = `**后端文档位置**:${buildOutputPath(params.featureName, "backend-doc.md", backendProjectRoot)}\n`;
|
|
207
213
|
} else {
|
|
208
|
-
|
|
214
|
+
debugLog(`后端文档已存在`);
|
|
209
215
|
backendSourceInfo = `**后端文档位置**:${buildOutputPath(params.featureName, "backend-doc.md", projectRoot)}\n`;
|
|
210
216
|
}
|
|
211
217
|
}
|
|
@@ -47,7 +47,7 @@ interface RequirementSource {
|
|
|
47
47
|
url?: string;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
interface ProcessResult {
|
|
50
|
+
export interface ProcessResult {
|
|
51
51
|
success: boolean;
|
|
52
52
|
content?: string;
|
|
53
53
|
message?: string;
|
|
@@ -57,12 +57,6 @@ interface ProcessResult {
|
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
interface RequirementSource {
|
|
61
|
-
type: "file" | "url";
|
|
62
|
-
path?: string;
|
|
63
|
-
url?: string;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
60
|
/**
|
|
67
61
|
* 步骤 2:处理需求文档输入
|
|
68
62
|
* 这是整体流程的第二步,专门处理需求文档
|
|
@@ -115,41 +109,93 @@ export async function processRequirementDocument(
|
|
|
115
109
|
const projectRoot = getProjectRoot(filePath);
|
|
116
110
|
const outputMdPath = buildOutputPath(featureName, outputFileName, projectRoot);
|
|
117
111
|
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
112
|
+
// 检查是否已经存在输出文件
|
|
113
|
+
try {
|
|
114
|
+
await fs.access(outputMdPath);
|
|
115
|
+
debugLog(`输出文件已存在`, { outputMdPath });
|
|
116
|
+
// 文件已存在,跳过处理
|
|
117
|
+
return {
|
|
118
|
+
success: true,
|
|
119
|
+
content: "已存在",
|
|
120
|
+
message: `✅ 文档已存在:${outputMdPath}`,
|
|
121
|
+
};
|
|
122
|
+
} catch {
|
|
123
|
+
// 文件不存在,需要处理
|
|
124
|
+
debugLog(`输出文件不存在,需要处理`, { outputMdPath });
|
|
125
|
+
|
|
126
|
+
// 检查是否已经完成了部分步骤
|
|
127
|
+
const textPath = outputMdPath.replace('.md', '-text.md');
|
|
128
|
+
const ocrPath = outputMdPath.replace('.md', '-ocr.md');
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
await fs.access(textPath);
|
|
132
|
+
try {
|
|
133
|
+
await fs.access(ocrPath);
|
|
134
|
+
// 两个文件都存在,可以合并
|
|
135
|
+
debugLog(`发现text和ocr文件,准备合并`);
|
|
136
|
+
return {
|
|
137
|
+
success: false,
|
|
138
|
+
message: `✅ PDF 的两个中间文件已存在,现在合并它们
|
|
126
139
|
|
|
127
|
-
|
|
140
|
+
**步骤 3:合并文件**
|
|
141
|
+
- 读取 \`${textPath}\` 的内容
|
|
142
|
+
- 读取 \`${ocrPath}\` 的内容
|
|
143
|
+
- 将两者合并保存到 \`${outputMdPath}\`
|
|
128
144
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
145
|
+
⚠️ **重要**:合并完成后立即保存文件,不要把内容放在上下文中。完成后重新调用本工具。`,
|
|
146
|
+
needsAction: {
|
|
147
|
+
type: "read_pdf",
|
|
148
|
+
instruction: `合并两个PDF读取结果:
|
|
149
|
+
1. 读取 ${textPath} 的内容
|
|
150
|
+
2. 读取 ${ocrPath} 的内容
|
|
151
|
+
3. 将两者合并保存到 ${outputMdPath}
|
|
152
|
+
4. 保存文件
|
|
153
|
+
5. 重新调用 generate_requirements 工具(不要把文件内容放在上下文中)`,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
} catch {
|
|
157
|
+
// 只有text文件存在,进行OCR
|
|
158
|
+
const fileName = filePath.split('/').pop() || '';
|
|
159
|
+
const isChinese = /[\u4e00-\u9fa5]/.test(fileName);
|
|
160
|
+
const language = isChinese ? 'chi_sim' : 'eng';
|
|
161
|
+
|
|
162
|
+
debugLog(`发现text文件,准备OCR`);
|
|
163
|
+
return {
|
|
164
|
+
success: false,
|
|
165
|
+
message: `✅ PDF 文本层已提取(${textPath}),现在进行 OCR
|
|
132
166
|
|
|
133
167
|
**步骤 2:使用 \`read_by_ocr\` 提取图片和表格**
|
|
134
168
|
- 优势:可提取图片、表格、扫描件等非文本内容
|
|
135
169
|
- 语言:\`${language}\`(中文文档使用 \`chi_sim\`,英文使用 \`eng\`)
|
|
136
170
|
- DPI:\`300\`(默认值)
|
|
137
|
-
- 保存到:\`${
|
|
171
|
+
- 保存到:\`${ocrPath}\`
|
|
138
172
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
173
|
+
⚠️ **重要**:OCR完成后立即保存文件,不要把文件内容放在上下文中。保存后重新调用本工具。`,
|
|
174
|
+
needsAction: {
|
|
175
|
+
type: "read_pdf",
|
|
176
|
+
instruction: `使用 PDF Reader MCP 的 read_by_ocr 工具读取 ${filePath},设置 language="${language}",dpi=300,保存到 ${ocrPath}。完成后立即保存文件,然后重新调用 generate_requirements 工具。不要把文件内容放在上下文中,避免上下文过长。`,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
} catch {
|
|
181
|
+
// 还没有任何文件,先提取文本
|
|
182
|
+
debugLog(`未发现中间文件,先提取文本层`);
|
|
183
|
+
return {
|
|
184
|
+
success: false,
|
|
185
|
+
message: `📄 检测到 PDF 文件
|
|
142
186
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
187
|
+
**步骤 1:使用 \`read_pdf_text\` 提取文本层**
|
|
188
|
+
- 优势:快速、准确、保留原始格式
|
|
189
|
+
- 保存到:\`${textPath}\`
|
|
190
|
+
|
|
191
|
+
⚠️ **重要**:文本提取完成后立即保存文件,不要把文件内容放在上下文中。保存后重新调用本工具。`,
|
|
192
|
+
needsAction: {
|
|
193
|
+
type: "read_pdf",
|
|
194
|
+
instruction: `使用 PDF Reader MCP 的 read_pdf_text 工具读取 ${filePath},保存到 ${textPath}。完成后立即保存文件,然后重新调用 generate_requirements 工具。不要把文件内容放在上下文中,避免上下文过长。`,
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
153
199
|
}
|
|
154
200
|
|
|
155
201
|
// 2.2.2 Markdown 文件 - 保存到固定位置
|