mcp-probe-kit 3.1.0 → 3.3.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 +15 -5
- package/build/index.js +5 -2
- package/build/lib/__tests__/memory-orchestration.unit.test.js +88 -0
- package/build/lib/__tests__/memory-payload.unit.test.js +35 -0
- package/build/lib/__tests__/quality-constraints.unit.test.d.ts +1 -0
- package/build/lib/__tests__/quality-constraints.unit.test.js +54 -0
- package/build/lib/__tests__/spec-validator.unit.test.d.ts +1 -0
- package/build/lib/__tests__/spec-validator.unit.test.js +147 -0
- package/build/lib/agents-md-template.js +32 -32
- package/build/lib/cursor-history-client.d.ts +54 -0
- package/build/lib/cursor-history-client.js +240 -0
- package/build/lib/memory-orchestration.js +29 -8
- package/build/lib/quality-constraints.d.ts +54 -0
- package/build/lib/quality-constraints.js +155 -0
- package/build/lib/skill-bridge.js +12 -12
- package/build/lib/spec-validator.d.ts +36 -0
- package/build/lib/spec-validator.js +116 -0
- package/build/lib/template-loader.js +223 -61
- package/build/lib/tool-annotations.d.ts +30 -0
- package/build/lib/tool-annotations.js +55 -0
- package/build/lib/toolset-manager.js +2 -0
- package/build/resources/ui-ux-data/guidelines/vercel-web-interface.json +1632 -1632
- package/build/resources/ui-ux-data/metadata.json +30 -30
- package/build/resources/ui-ux-data/shadcn/blocks.json +2541 -2541
- package/build/resources/ui-ux-data/shadcn/components.json +997 -997
- package/build/resources/ui-ux-data/themes/presets.json +483 -483
- package/build/schemas/index.d.ts +22 -0
- package/build/schemas/project-tools.d.ts +22 -0
- package/build/schemas/project-tools.js +23 -0
- package/build/tools/__tests__/cursor-history.unit.test.d.ts +1 -0
- package/build/tools/__tests__/cursor-history.unit.test.js +38 -0
- package/build/tools/check_spec.d.ts +7 -0
- package/build/tools/check_spec.js +81 -0
- package/build/tools/code_insight.js +41 -41
- package/build/tools/code_review.js +11 -4
- package/build/tools/cursor_read_conversation.d.ts +7 -0
- package/build/tools/cursor_read_conversation.js +36 -0
- package/build/tools/fix_bug.js +161 -161
- package/build/tools/gencommit.js +60 -60
- package/build/tools/index.d.ts +1 -0
- package/build/tools/index.js +1 -0
- package/build/tools/init_project_context.js +432 -432
- package/build/tools/start_bugfix.js +21 -10
- package/build/tools/start_feature.js +46 -11
- package/build/tools/start_product.js +1 -1
- package/build/tools/start_ui.js +44 -13
- package/build/tools/ui-ux-tools.d.ts +3 -0
- package/build/tools/ui-ux-tools.js +302 -290
- package/build/utils/__tests__/vercel-guidelines-sync.unit.test.js +12 -12
- package/build/utils/design-reasoning-engine.d.ts +2 -0
- package/build/utils/design-reasoning-engine.js +3 -0
- package/build/utils/themes-sync.js +8 -8
- package/package.json +4 -3
- package/build/resources/index.d.ts +0 -4
- package/build/resources/index.js +0 -4
- package/build/resources/tool-params-guide.d.ts +0 -571
- package/build/resources/tool-params-guide.js +0 -488
- package/build/tools/analyze_project.d.ts +0 -1
- package/build/tools/analyze_project.js +0 -527
- package/build/tools/check_deps.d.ts +0 -13
- package/build/tools/check_deps.js +0 -204
- package/build/tools/convert.d.ts +0 -13
- package/build/tools/convert.js +0 -599
- package/build/tools/css_order.d.ts +0 -13
- package/build/tools/css_order.js +0 -81
- package/build/tools/debug.d.ts +0 -13
- package/build/tools/debug.js +0 -131
- package/build/tools/design2code.d.ts +0 -20
- package/build/tools/design2code.js +0 -426
- package/build/tools/detect_shell.d.ts +0 -6
- package/build/tools/detect_shell.js +0 -151
- package/build/tools/explain.d.ts +0 -13
- package/build/tools/explain.js +0 -390
- package/build/tools/fix.d.ts +0 -13
- package/build/tools/fix.js +0 -303
- package/build/tools/gen_mock.d.ts +0 -22
- package/build/tools/gen_mock.js +0 -269
- package/build/tools/gen_skill.d.ts +0 -13
- package/build/tools/gen_skill.js +0 -560
- package/build/tools/genapi.d.ts +0 -13
- package/build/tools/genapi.js +0 -174
- package/build/tools/genchangelog.d.ts +0 -13
- package/build/tools/genchangelog.js +0 -250
- package/build/tools/gendoc.d.ts +0 -13
- package/build/tools/gendoc.js +0 -232
- package/build/tools/genpr.d.ts +0 -13
- package/build/tools/genpr.js +0 -194
- package/build/tools/genreadme.d.ts +0 -13
- package/build/tools/genreadme.js +0 -626
- package/build/tools/gensql.d.ts +0 -13
- package/build/tools/gensql.js +0 -320
- package/build/tools/genui.d.ts +0 -13
- package/build/tools/genui.js +0 -803
- package/build/tools/init_component_catalog.d.ts +0 -22
- package/build/tools/init_component_catalog.js +0 -809
- package/build/tools/init_setting.d.ts +0 -13
- package/build/tools/init_setting.js +0 -47
- package/build/tools/perf.d.ts +0 -13
- package/build/tools/perf.js +0 -409
- package/build/tools/render_ui.d.ts +0 -22
- package/build/tools/render_ui.js +0 -384
- package/build/tools/resolve_conflict.d.ts +0 -13
- package/build/tools/resolve_conflict.js +0 -349
- package/build/tools/security_scan.d.ts +0 -22
- package/build/tools/security_scan.js +0 -323
- package/build/tools/split.d.ts +0 -13
- package/build/tools/split.js +0 -599
- package/build/tools/start_api.d.ts +0 -13
- package/build/tools/start_api.js +0 -193
- package/build/tools/start_doc.d.ts +0 -13
- package/build/tools/start_doc.js +0 -207
- package/build/tools/start_refactor.d.ts +0 -13
- package/build/tools/start_refactor.js +0 -188
- package/build/tools/start_release.d.ts +0 -13
- package/build/tools/start_release.js +0 -167
- package/build/tools/start_review.d.ts +0 -13
- package/build/tools/start_review.js +0 -175
- /package/build/{utils/design-docs-generator.d.ts → lib/__tests__/memory-orchestration.unit.test.d.ts} +0 -0
- /package/build/{utils/design-docs-generator.js → lib/__tests__/memory-payload.unit.test.d.ts} +0 -0
package/build/schemas/index.d.ts
CHANGED
|
@@ -281,6 +281,28 @@ export declare const allToolSchemas: ({
|
|
|
281
281
|
readonly required: readonly [];
|
|
282
282
|
readonly additionalProperties: true;
|
|
283
283
|
};
|
|
284
|
+
} | {
|
|
285
|
+
readonly name: "check_spec";
|
|
286
|
+
readonly description: "校验已落盘的功能规格(docs/specs/<feature_name>/requirements|design|tasks.md)是否完整:检测残留 [填写] 占位、缺失章节、缺 FR/验收标准、FR 未进覆盖矩阵。写完规格后、进入实现前调用;未通过按报告补全后重跑。";
|
|
287
|
+
readonly inputSchema: {
|
|
288
|
+
readonly type: "object";
|
|
289
|
+
readonly properties: {
|
|
290
|
+
readonly feature_name: {
|
|
291
|
+
readonly type: "string";
|
|
292
|
+
readonly description: "要校验的规格目录名,对应 docs/specs/<feature_name>/";
|
|
293
|
+
};
|
|
294
|
+
readonly docs_dir: {
|
|
295
|
+
readonly type: "string";
|
|
296
|
+
readonly description: "文档根目录,默认为 docs";
|
|
297
|
+
};
|
|
298
|
+
readonly project_root: {
|
|
299
|
+
readonly type: "string";
|
|
300
|
+
readonly description: "项目根目录绝对路径。可选,默认自动探测工作区根";
|
|
301
|
+
};
|
|
302
|
+
};
|
|
303
|
+
readonly required: readonly [];
|
|
304
|
+
readonly additionalProperties: true;
|
|
305
|
+
};
|
|
284
306
|
} | {
|
|
285
307
|
readonly name: "start_feature";
|
|
286
308
|
readonly description: "当用户需要完整的新功能开发流程时使用。编排:检查上下文→生成规格→估算工作量。若只需规格文档请用 add_feature";
|
|
@@ -89,4 +89,26 @@ export declare const projectToolSchemas: readonly [{
|
|
|
89
89
|
readonly required: readonly [];
|
|
90
90
|
readonly additionalProperties: true;
|
|
91
91
|
};
|
|
92
|
+
}, {
|
|
93
|
+
readonly name: "check_spec";
|
|
94
|
+
readonly description: "校验已落盘的功能规格(docs/specs/<feature_name>/requirements|design|tasks.md)是否完整:检测残留 [填写] 占位、缺失章节、缺 FR/验收标准、FR 未进覆盖矩阵。写完规格后、进入实现前调用;未通过按报告补全后重跑。";
|
|
95
|
+
readonly inputSchema: {
|
|
96
|
+
readonly type: "object";
|
|
97
|
+
readonly properties: {
|
|
98
|
+
readonly feature_name: {
|
|
99
|
+
readonly type: "string";
|
|
100
|
+
readonly description: "要校验的规格目录名,对应 docs/specs/<feature_name>/";
|
|
101
|
+
};
|
|
102
|
+
readonly docs_dir: {
|
|
103
|
+
readonly type: "string";
|
|
104
|
+
readonly description: "文档根目录,默认为 docs";
|
|
105
|
+
};
|
|
106
|
+
readonly project_root: {
|
|
107
|
+
readonly type: "string";
|
|
108
|
+
readonly description: "项目根目录绝对路径。可选,默认自动探测工作区根";
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
readonly required: readonly [];
|
|
112
|
+
readonly additionalProperties: true;
|
|
113
|
+
};
|
|
92
114
|
}];
|
|
@@ -93,4 +93,27 @@ export const projectToolSchemas = [
|
|
|
93
93
|
additionalProperties: true,
|
|
94
94
|
},
|
|
95
95
|
},
|
|
96
|
+
{
|
|
97
|
+
name: "check_spec",
|
|
98
|
+
description: "校验已落盘的功能规格(docs/specs/<feature_name>/requirements|design|tasks.md)是否完整:检测残留 [填写] 占位、缺失章节、缺 FR/验收标准、FR 未进覆盖矩阵。写完规格后、进入实现前调用;未通过按报告补全后重跑。",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: "object",
|
|
101
|
+
properties: {
|
|
102
|
+
feature_name: {
|
|
103
|
+
type: "string",
|
|
104
|
+
description: "要校验的规格目录名,对应 docs/specs/<feature_name>/",
|
|
105
|
+
},
|
|
106
|
+
docs_dir: {
|
|
107
|
+
type: "string",
|
|
108
|
+
description: "文档根目录,默认为 docs",
|
|
109
|
+
},
|
|
110
|
+
project_root: {
|
|
111
|
+
type: "string",
|
|
112
|
+
description: "项目根目录绝对路径。可选,默认自动探测工作区根",
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
required: [],
|
|
116
|
+
additionalProperties: true,
|
|
117
|
+
},
|
|
118
|
+
},
|
|
96
119
|
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
const readConversationMock = vi.fn();
|
|
3
|
+
vi.mock('../../lib/cursor-history-client.js', () => ({
|
|
4
|
+
createCursorHistoryClient: () => ({
|
|
5
|
+
readConversation: readConversationMock,
|
|
6
|
+
}),
|
|
7
|
+
}));
|
|
8
|
+
import { cursorReadConversation } from '../cursor_read_conversation.js';
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
readConversationMock.mockReset();
|
|
11
|
+
});
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
vi.clearAllMocks();
|
|
14
|
+
});
|
|
15
|
+
describe('cursor history tools', () => {
|
|
16
|
+
test('cursor_read_conversation 返回消息时间线', async () => {
|
|
17
|
+
readConversationMock.mockResolvedValue({
|
|
18
|
+
composerId: 'c1',
|
|
19
|
+
messages: [
|
|
20
|
+
{ bubbleId: 'b1', type: 1, text: '我们先聊需求' },
|
|
21
|
+
{ bubbleId: 'b2', type: 2, text: '听懂了' },
|
|
22
|
+
],
|
|
23
|
+
});
|
|
24
|
+
const result = await cursorReadConversation({ composer_id: 'c1', limit: 50, include_empty: true });
|
|
25
|
+
expect(result.isError).toBe(false);
|
|
26
|
+
expect('structuredContent' in result).toBe(true);
|
|
27
|
+
if (!('structuredContent' in result)) {
|
|
28
|
+
throw new Error('structuredContent 缺失');
|
|
29
|
+
}
|
|
30
|
+
expect(result.content[0].text).toContain('共 2 条消息');
|
|
31
|
+
expect(result.structuredContent.messageCount).toBe(2);
|
|
32
|
+
expect(readConversationMock).toHaveBeenCalledWith({
|
|
33
|
+
composerId: 'c1',
|
|
34
|
+
limit: 50,
|
|
35
|
+
includeEmpty: true,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { parseArgs, getString } from '../utils/parseArgs.js';
|
|
4
|
+
import { okStructured } from '../lib/response.js';
|
|
5
|
+
import { handleToolError } from '../utils/error-handler.js';
|
|
6
|
+
import { resolveWorkspaceRoot } from '../lib/workspace-root.js';
|
|
7
|
+
import { validateSpecDocuments } from '../lib/spec-validator.js';
|
|
8
|
+
/**
|
|
9
|
+
* check_spec 工具(P1「填写后校验」闸门)
|
|
10
|
+
*
|
|
11
|
+
* 读取 docs/specs/{feature_name}/{requirements,design,tasks}.md,
|
|
12
|
+
* 机械校验完整性。未通过则列出逐条待修项并要求补全后重跑,通过前不应进入实现。
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_DOCS_DIR = 'docs';
|
|
15
|
+
function readIfExists(filePath) {
|
|
16
|
+
try {
|
|
17
|
+
return fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf-8') : null;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function formatIssue(issue) {
|
|
24
|
+
const tag = issue.severity === 'error' ? '必须修复' : '提醒';
|
|
25
|
+
return `- [${tag}] (${issue.file}) ${issue.message}`;
|
|
26
|
+
}
|
|
27
|
+
export async function checkSpec(args) {
|
|
28
|
+
try {
|
|
29
|
+
const parsed = parseArgs(args, {
|
|
30
|
+
defaultValues: {
|
|
31
|
+
feature_name: '',
|
|
32
|
+
docs_dir: DEFAULT_DOCS_DIR,
|
|
33
|
+
},
|
|
34
|
+
primaryField: 'feature_name',
|
|
35
|
+
fieldAliases: {
|
|
36
|
+
feature_name: ['name', 'feature', 'spec', '功能名', '功能名称', '规格'],
|
|
37
|
+
docs_dir: ['dir', 'output', '目录', '文档目录'],
|
|
38
|
+
project_root: ['projectRoot', 'project_path', 'projectPath', 'root', '项目路径', '项目根目录'],
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
const featureName = getString(parsed.feature_name);
|
|
42
|
+
const docsDir = getString(parsed.docs_dir) || DEFAULT_DOCS_DIR;
|
|
43
|
+
const projectRoot = resolveWorkspaceRoot(getString(parsed.project_root));
|
|
44
|
+
if (!featureName) {
|
|
45
|
+
throw new Error('请提供 feature_name(要校验的规格目录名,对应 docs/specs/<feature_name>/)');
|
|
46
|
+
}
|
|
47
|
+
const specDir = path.join(projectRoot, docsDir, 'specs', featureName);
|
|
48
|
+
const report = validateSpecDocuments({
|
|
49
|
+
requirements: readIfExists(path.join(specDir, 'requirements.md')),
|
|
50
|
+
design: readIfExists(path.join(specDir, 'design.md')),
|
|
51
|
+
tasks: readIfExists(path.join(specDir, 'tasks.md')),
|
|
52
|
+
});
|
|
53
|
+
const relDir = `${docsDir}/specs/${featureName}`;
|
|
54
|
+
const issueLines = report.issues.length > 0
|
|
55
|
+
? report.issues.map(formatIssue).join('\n')
|
|
56
|
+
: '- 无';
|
|
57
|
+
const text = report.passed
|
|
58
|
+
? `# ✅ 规格校验通过:${featureName}
|
|
59
|
+
|
|
60
|
+
${report.summary}
|
|
61
|
+
|
|
62
|
+
**需求清单**: ${report.frIds.join(', ') || '(未发现 FR)'}
|
|
63
|
+
${report.warningCount > 0 ? `\n仍有 ${report.warningCount} 个提醒(非阻塞,建议处理):\n${issueLines}\n` : ''}
|
|
64
|
+
**下一步**: 规格已具备可实现性,可进入实现/估算阶段。`
|
|
65
|
+
: `# ❌ 规格校验未通过:${featureName}
|
|
66
|
+
|
|
67
|
+
${report.summary}
|
|
68
|
+
|
|
69
|
+
## 待修复(${relDir})
|
|
70
|
+
${issueLines}
|
|
71
|
+
|
|
72
|
+
## 处理方式
|
|
73
|
+
1. 按上述每一条补全 \`${relDir}/\` 下的 requirements.md / design.md / tasks.md
|
|
74
|
+
2. **重新运行** \`check_spec\`(同样的 feature_name)直到通过
|
|
75
|
+
3. **校验通过前不要开始写实现代码** —— 这是为了确保需求被完整实现,而不是写到一半才发现规格有缺口`;
|
|
76
|
+
return okStructured(text, report);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
return handleToolError(error, 'check_spec');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -136,10 +136,10 @@ function createProjectDocsPlan(layout, docsSnapshot) {
|
|
|
136
136
|
latestJsonFilePath: layout.latestJsonPath,
|
|
137
137
|
archiveMarkdownFilePath: docsSnapshot.markdownFilePath,
|
|
138
138
|
archiveJsonFilePath: docsSnapshot.jsonFilePath,
|
|
139
|
-
navigationSnippet: `### [代码图谱洞察](./graph-insights/latest.md)
|
|
140
|
-
最近一次 code_insight 分析结果,包含调用链、上下文与影响面摘要
|
|
139
|
+
navigationSnippet: `### [代码图谱洞察](./graph-insights/latest.md)
|
|
140
|
+
最近一次 code_insight 分析结果,包含调用链、上下文与影响面摘要
|
|
141
141
|
`,
|
|
142
|
-
devGuideSnippet: `- **代码图谱洞察**: [graph-insights/latest.md](./graph-insights/latest.md) - 需要理解模块依赖、调用链和影响面时优先查看
|
|
142
|
+
devGuideSnippet: `- **代码图谱洞察**: [graph-insights/latest.md](./graph-insights/latest.md) - 需要理解模块依赖、调用链和影响面时优先查看
|
|
143
143
|
`,
|
|
144
144
|
};
|
|
145
145
|
}
|
|
@@ -187,15 +187,15 @@ export function buildCodeInsightDelegatedPlan(input) {
|
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
189
|
function renderUsageGuide() {
|
|
190
|
-
return `## 使用场景指南
|
|
191
|
-
- 探索调用链: \`{ mode: "query", query: "login", goal: "理解登录认证流程" }\`
|
|
192
|
-
- 深入函数上下文: \`{ mode: "context", target: "login", file_path: "src/auth/login.ts" }\`
|
|
193
|
-
- 评估影响范围: \`{ mode: "impact", target: "login", direction: "upstream", file_path: "..." }\`
|
|
194
|
-
- 查看代码内容: \`{ mode: "context", target: "login", include_content: true }\`
|
|
195
|
-
|
|
196
|
-
## 下一步建议
|
|
197
|
-
- 查询不精确: 增加 \`goal\`(例如“理解登录认证流程”)
|
|
198
|
-
- 出现歧义: 传入 \`uid\` 或 \`file_path\` 重新执行
|
|
190
|
+
return `## 使用场景指南
|
|
191
|
+
- 探索调用链: \`{ mode: "query", query: "login", goal: "理解登录认证流程" }\`
|
|
192
|
+
- 深入函数上下文: \`{ mode: "context", target: "login", file_path: "src/auth/login.ts" }\`
|
|
193
|
+
- 评估影响范围: \`{ mode: "impact", target: "login", direction: "upstream", file_path: "..." }\`
|
|
194
|
+
- 查看代码内容: \`{ mode: "context", target: "login", include_content: true }\`
|
|
195
|
+
|
|
196
|
+
## 下一步建议
|
|
197
|
+
- 查询不精确: 增加 \`goal\`(例如“理解登录认证流程”)
|
|
198
|
+
- 出现歧义: 传入 \`uid\` 或 \`file_path\` 重新执行
|
|
199
199
|
- 需要落盘: 传 \`save_to_docs: true\`,再按 delegated plan 写入 docs/graph-insights`;
|
|
200
200
|
}
|
|
201
201
|
export function resolveCodeInsightQuery(input) {
|
|
@@ -307,22 +307,22 @@ export async function codeInsight(args, context) {
|
|
|
307
307
|
status: item.status,
|
|
308
308
|
})));
|
|
309
309
|
const ambiguityText = formatAmbiguities(result.ambiguities);
|
|
310
|
-
const message = `# code_insight 图谱分析结果
|
|
311
|
-
|
|
312
|
-
状态: ${formatStatusLabel(status)}
|
|
313
|
-
模式: ${result.modeRequested} -> ${result.modeResolved}
|
|
314
|
-
来源: ${result.provider}
|
|
315
|
-
启动策略: ${result.launcherStrategy}
|
|
316
|
-
工作区: ${result.workspaceMode}
|
|
317
|
-
源目录: ${result.sourceRoot}
|
|
318
|
-
|
|
319
|
-
摘要:
|
|
320
|
-
${result.summary}
|
|
321
|
-
|
|
322
|
-
执行详情:
|
|
323
|
-
${executionSummary}
|
|
324
|
-
|
|
325
|
-
${ambiguityText ? `歧义候选:\n${ambiguityText}\n\n` : ""}\
|
|
310
|
+
const message = `# code_insight 图谱分析结果
|
|
311
|
+
|
|
312
|
+
状态: ${formatStatusLabel(status)}
|
|
313
|
+
模式: ${result.modeRequested} -> ${result.modeResolved}
|
|
314
|
+
来源: ${result.provider}
|
|
315
|
+
启动策略: ${result.launcherStrategy}
|
|
316
|
+
工作区: ${result.workspaceMode}
|
|
317
|
+
源目录: ${result.sourceRoot}
|
|
318
|
+
|
|
319
|
+
摘要:
|
|
320
|
+
${result.summary}
|
|
321
|
+
|
|
322
|
+
执行详情:
|
|
323
|
+
${executionSummary}
|
|
324
|
+
|
|
325
|
+
${ambiguityText ? `歧义候选:\n${ambiguityText}\n\n` : ""}\
|
|
326
326
|
${result.warnings.length > 0 ? `警告: ${result.warnings.join(", ")}` : ""}`.trim();
|
|
327
327
|
const usageGuide = renderUsageGuide();
|
|
328
328
|
const structured = {
|
|
@@ -391,20 +391,20 @@ ${result.warnings.length > 0 ? `警告: ${result.warnings.join(", ")}` : ""}`.tr
|
|
|
391
391
|
`工作区模式: ${result.workspaceMode}`,
|
|
392
392
|
`来源目录: ${result.sourceRoot}`,
|
|
393
393
|
],
|
|
394
|
-
})}${message}
|
|
395
|
-
|
|
396
|
-
## delegated plan
|
|
397
|
-
${renderPlanSteps(delegatedPlan.steps)}
|
|
398
|
-
|
|
399
|
-
${delegatedPlan.kind === "docs" && projectDocs ? `后续操作:
|
|
400
|
-
- 如需落盘,写入 ${projectDocs.latestMarkdownFilePath} 与 ${projectDocs.latestJsonFilePath}
|
|
401
|
-
- 如需长期沉淀,可再补充 ${projectDocs.projectContextFilePath} 的图谱入口` : `后续操作:
|
|
402
|
-
- 请先从 candidates 中选定唯一符号
|
|
403
|
-
- 重新传入 uid 或 file_path 后再继续 context / impact 分析`}
|
|
404
|
-
|
|
394
|
+
})}${message}
|
|
395
|
+
|
|
396
|
+
## delegated plan
|
|
397
|
+
${renderPlanSteps(delegatedPlan.steps)}
|
|
398
|
+
|
|
399
|
+
${delegatedPlan.kind === "docs" && projectDocs ? `后续操作:
|
|
400
|
+
- 如需落盘,写入 ${projectDocs.latestMarkdownFilePath} 与 ${projectDocs.latestJsonFilePath}
|
|
401
|
+
- 如需长期沉淀,可再补充 ${projectDocs.projectContextFilePath} 的图谱入口` : `后续操作:
|
|
402
|
+
- 请先从 candidates 中选定唯一符号
|
|
403
|
+
- 重新传入 uid 或 file_path 后再继续 context / impact 分析`}
|
|
404
|
+
|
|
405
405
|
${usageGuide}`
|
|
406
|
-
: `${message}
|
|
407
|
-
|
|
406
|
+
: `${message}
|
|
407
|
+
|
|
408
408
|
${usageGuide}`, structured);
|
|
409
409
|
}
|
|
410
410
|
catch (error) {
|
|
@@ -2,6 +2,7 @@ import { parseArgs, getString } from "../utils/parseArgs.js";
|
|
|
2
2
|
import { okText } from "../lib/response.js";
|
|
3
3
|
import { renderGuidanceHeader } from "../lib/guidance.js";
|
|
4
4
|
import { handleToolError } from "../utils/error-handler.js";
|
|
5
|
+
import { renderCodeLimits, renderBannedPatterns, CODE_LIMITS } from "../lib/quality-constraints.js";
|
|
5
6
|
// code_review 工具实现
|
|
6
7
|
export async function codeReview(args) {
|
|
7
8
|
try {
|
|
@@ -38,11 +39,13 @@ ${code || "请提供需要审查的代码"}
|
|
|
38
39
|
|
|
39
40
|
### 1️⃣ 代码质量检查
|
|
40
41
|
|
|
42
|
+
${renderCodeLimits()}
|
|
43
|
+
|
|
41
44
|
**代码坏味道(Code Smells)**:
|
|
42
45
|
- [ ] 重复代码(Duplicated Code)
|
|
43
|
-
- [ ] 过长函数(Long Function)>
|
|
44
|
-
- [ ] 过长参数列表(Long Parameter List)>
|
|
45
|
-
- [ ] 复杂条件判断(Complex Conditional)>
|
|
46
|
+
- [ ] 过长函数(Long Function)> ${CODE_LIMITS.maxFunctionLines} 行
|
|
47
|
+
- [ ] 过长参数列表(Long Parameter List)> ${CODE_LIMITS.maxParameters} 个
|
|
48
|
+
- [ ] 复杂条件判断(Complex Conditional)> ${CODE_LIMITS.maxNestingDepth} 层嵌套
|
|
46
49
|
- [ ] 魔法数字(Magic Numbers)
|
|
47
50
|
- [ ] 命名不清晰(Poor Naming)
|
|
48
51
|
|
|
@@ -88,7 +91,11 @@ ${code || "请提供需要审查的代码"}
|
|
|
88
91
|
- [ ] 大列表未虚拟化
|
|
89
92
|
- [ ] 状态管理不当
|
|
90
93
|
|
|
91
|
-
### 4️⃣
|
|
94
|
+
### 4️⃣ 完整性检查
|
|
95
|
+
|
|
96
|
+
${renderBannedPatterns()}
|
|
97
|
+
|
|
98
|
+
### 5️⃣ 最佳实践检查
|
|
92
99
|
|
|
93
100
|
**TypeScript/JavaScript**:
|
|
94
101
|
- [ ] 类型定义完整(避免 any)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { parseArgs, getString, getNumber, getBoolean } from '../utils/parseArgs.js';
|
|
2
|
+
import { okStructured } from '../lib/response.js';
|
|
3
|
+
import { handleToolError } from '../utils/error-handler.js';
|
|
4
|
+
import { createCursorHistoryClient } from '../lib/cursor-history-client.js';
|
|
5
|
+
export async function cursorReadConversation(args) {
|
|
6
|
+
try {
|
|
7
|
+
const parsed = parseArgs(args, {
|
|
8
|
+
defaultValues: {
|
|
9
|
+
composer_id: '',
|
|
10
|
+
limit: 200,
|
|
11
|
+
include_empty: false,
|
|
12
|
+
},
|
|
13
|
+
fieldAliases: {
|
|
14
|
+
composer_id: ['conversation_id', 'chat_id'],
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
const composerId = getString(parsed.composer_id).trim();
|
|
18
|
+
if (!composerId) {
|
|
19
|
+
throw new Error('缺少必填参数: composer_id');
|
|
20
|
+
}
|
|
21
|
+
const client = createCursorHistoryClient();
|
|
22
|
+
const conversation = await client.readConversation({
|
|
23
|
+
composerId,
|
|
24
|
+
limit: getNumber(parsed.limit, 200),
|
|
25
|
+
includeEmpty: getBoolean(parsed.include_empty, false),
|
|
26
|
+
});
|
|
27
|
+
return okStructured(`已读取 Cursor 会话 ${composerId},共 ${conversation.messages.length} 条消息。`, {
|
|
28
|
+
composerId,
|
|
29
|
+
messageCount: conversation.messages.length,
|
|
30
|
+
conversation,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return handleToolError(error, 'cursor_read_conversation');
|
|
35
|
+
}
|
|
36
|
+
}
|