mcp-probe-kit 3.0.18 → 3.0.21
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 +87 -55
- package/build/index.js +3 -1
- package/build/lib/__tests__/agents-md-template.unit.test.d.ts +1 -0
- package/build/lib/__tests__/agents-md-template.unit.test.js +27 -0
- package/build/lib/__tests__/memory-config.unit.test.js +9 -0
- package/build/lib/__tests__/memory-injection.unit.test.d.ts +1 -0
- package/build/lib/__tests__/memory-injection.unit.test.js +51 -0
- package/build/lib/__tests__/memory-orchestration.unit.test.d.ts +1 -0
- package/build/lib/__tests__/memory-orchestration.unit.test.js +84 -0
- package/build/lib/__tests__/memory-payload.unit.test.d.ts +1 -0
- package/build/lib/__tests__/memory-payload.unit.test.js +35 -0
- package/build/lib/__tests__/project-context-layout.unit.test.d.ts +1 -0
- package/build/lib/__tests__/project-context-layout.unit.test.js +80 -0
- package/build/lib/agents-md-template.d.ts +25 -0
- package/build/lib/agents-md-template.js +57 -0
- package/build/lib/memory-client.d.ts +8 -1
- package/build/lib/memory-client.js +53 -44
- package/build/lib/memory-config.d.ts +8 -0
- package/build/lib/memory-config.js +19 -0
- package/build/lib/memory-orchestration.d.ts +10 -3
- package/build/lib/memory-orchestration.js +146 -7
- package/build/lib/memory-payload.d.ts +21 -0
- package/build/lib/memory-payload.js +65 -0
- package/build/lib/merge-agents-md.d.ts +6 -0
- package/build/lib/merge-agents-md.js +51 -0
- package/build/lib/project-context-layout.d.ts +78 -0
- package/build/lib/project-context-layout.js +350 -0
- package/build/lib/workspace-root.js +6 -1
- package/build/resources/ui-ux-data/metadata.json +1 -1
- package/build/schemas/index.d.ts +62 -11
- package/build/schemas/memory-tools.d.ts +38 -9
- package/build/schemas/memory-tools.js +24 -9
- package/build/schemas/project-tools.d.ts +24 -2
- package/build/schemas/project-tools.js +24 -2
- package/build/tools/__tests__/code_insight.unit.test.js +3 -3
- package/build/tools/__tests__/init_project_context.unit.test.js +32 -21
- package/build/tools/__tests__/start_feature.unit.test.js +2 -1
- package/build/tools/code_insight.js +11 -9
- package/build/tools/index.d.ts +1 -0
- package/build/tools/index.js +1 -0
- package/build/tools/init_project_context.js +563 -506
- package/build/tools/memorize_asset.js +12 -0
- package/build/tools/scan_and_extract_patterns.js +7 -7
- package/build/tools/search_memory.d.ts +7 -0
- package/build/tools/search_memory.js +57 -0
- package/build/tools/start_bugfix.js +257 -251
- package/build/tools/start_feature.js +140 -134
- package/build/tools/start_ui.js +405 -405
- package/docs/.mcp-probe/layout.json +11 -0
- package/docs/data/tools.js +18 -0
- package/docs/i18n/all-tools/en.json +6 -1
- package/docs/i18n/all-tools/ja.json +2 -1
- package/docs/i18n/all-tools/ko.json +2 -1
- package/docs/i18n/all-tools/zh-CN.json +7 -2
- package/docs/i18n/en.json +38 -7
- package/docs/i18n/ja.json +9 -2
- package/docs/i18n/ko.json +9 -2
- package/docs/i18n/zh-CN.json +40 -9
- package/docs/memory-local-setup.md +314 -0
- package/docs/memory-local-setup.zh-CN.md +283 -0
- package/docs/pages/getting-started.html +252 -33
- package/package.json +2 -2
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
export declare const memoryToolSchemas: readonly [{
|
|
2
|
+
readonly name: "search_memory";
|
|
3
|
+
readonly description: "按语义检索共享记忆库。适合在 start_* 之外主动查找历史 Bug 修复或可复用模式;命中后用 read_memory_asset 读取全文。";
|
|
4
|
+
readonly inputSchema: {
|
|
5
|
+
readonly type: "object";
|
|
6
|
+
readonly properties: {
|
|
7
|
+
readonly query: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "检索 query(现象、报错、关键词、功能描述等)";
|
|
10
|
+
};
|
|
11
|
+
readonly type: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
readonly description: "优先匹配的资产类型,如 bugfix、pattern、component";
|
|
14
|
+
};
|
|
15
|
+
readonly tags: {
|
|
16
|
+
readonly type: "array";
|
|
17
|
+
readonly items: {
|
|
18
|
+
readonly type: "string";
|
|
19
|
+
};
|
|
20
|
+
readonly description: "优先匹配的标签";
|
|
21
|
+
};
|
|
22
|
+
readonly limit: {
|
|
23
|
+
readonly type: "number";
|
|
24
|
+
readonly description: "返回条数,默认 MEMORY_SEARCH_LIMIT";
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
readonly required: readonly ["query"];
|
|
28
|
+
readonly additionalProperties: true;
|
|
29
|
+
};
|
|
30
|
+
}, {
|
|
2
31
|
readonly name: "read_memory_asset";
|
|
3
32
|
readonly description: "当编排阶段已检索到记忆摘要,且 AI 需要查看完整沉淀代码或详细规范时使用。根据 asset_id 读取记忆资产详情。";
|
|
4
33
|
readonly inputSchema: {
|
|
@@ -14,7 +43,7 @@ export declare const memoryToolSchemas: readonly [{
|
|
|
14
43
|
};
|
|
15
44
|
}, {
|
|
16
45
|
readonly name: "memorize_asset";
|
|
17
|
-
readonly description: "
|
|
46
|
+
readonly description: "沉淀可检索资产到共享记忆库。Bug 修复后必须 type=bugfix,content 含【现象】【根因】【修复】【验证】。跨仓库共享时勿填 source_project/source_path,路径写入 content 即可。";
|
|
18
47
|
readonly inputSchema: {
|
|
19
48
|
readonly type: "object";
|
|
20
49
|
readonly properties: {
|
|
@@ -24,7 +53,7 @@ export declare const memoryToolSchemas: readonly [{
|
|
|
24
53
|
};
|
|
25
54
|
readonly type: {
|
|
26
55
|
readonly type: "string";
|
|
27
|
-
readonly description: "
|
|
56
|
+
readonly description: "资产类型:bugfix / pattern / component / code 等";
|
|
28
57
|
};
|
|
29
58
|
readonly description: {
|
|
30
59
|
readonly type: "string";
|
|
@@ -32,11 +61,11 @@ export declare const memoryToolSchemas: readonly [{
|
|
|
32
61
|
};
|
|
33
62
|
readonly summary: {
|
|
34
63
|
readonly type: "string";
|
|
35
|
-
readonly description: "
|
|
64
|
+
readonly description: "检索用一句话摘要(关键词 + 根因/要点)";
|
|
36
65
|
};
|
|
37
66
|
readonly content: {
|
|
38
67
|
readonly type: "string";
|
|
39
|
-
readonly description: "
|
|
68
|
+
readonly description: "完整内容(bugfix 建议结构化四段)";
|
|
40
69
|
};
|
|
41
70
|
readonly code_snippet: {
|
|
42
71
|
readonly type: "string";
|
|
@@ -44,15 +73,15 @@ export declare const memoryToolSchemas: readonly [{
|
|
|
44
73
|
};
|
|
45
74
|
readonly file_path: {
|
|
46
75
|
readonly type: "string";
|
|
47
|
-
readonly description: "
|
|
76
|
+
readonly description: "已废弃:勿用于跨仓库沉淀,路径写入 content";
|
|
48
77
|
};
|
|
49
78
|
readonly source_project: {
|
|
50
79
|
readonly type: "string";
|
|
51
|
-
readonly description: "
|
|
80
|
+
readonly description: "已废弃:仅同仓库追溯时可选";
|
|
52
81
|
};
|
|
53
82
|
readonly source_path: {
|
|
54
83
|
readonly type: "string";
|
|
55
|
-
readonly description: "
|
|
84
|
+
readonly description: "已废弃:仅同仓库追溯时可选";
|
|
56
85
|
};
|
|
57
86
|
readonly usage: {
|
|
58
87
|
readonly type: "string";
|
|
@@ -67,7 +96,7 @@ export declare const memoryToolSchemas: readonly [{
|
|
|
67
96
|
readonly items: {
|
|
68
97
|
readonly type: "string";
|
|
69
98
|
};
|
|
70
|
-
readonly description: "
|
|
99
|
+
readonly description: "标签列表,如 bugfix, root-cause";
|
|
71
100
|
};
|
|
72
101
|
};
|
|
73
102
|
readonly required: readonly ["name", "description", "summary"];
|
|
@@ -89,7 +118,7 @@ export declare const memoryToolSchemas: readonly [{
|
|
|
89
118
|
};
|
|
90
119
|
readonly project_name: {
|
|
91
120
|
readonly type: "string";
|
|
92
|
-
readonly description: "
|
|
121
|
+
readonly description: "已废弃,扫描结果不再写入 source_project";
|
|
93
122
|
};
|
|
94
123
|
readonly directory_path: {
|
|
95
124
|
readonly type: "string";
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
export const memoryToolSchemas = [
|
|
2
|
+
{
|
|
3
|
+
name: 'search_memory',
|
|
4
|
+
description: '按语义检索共享记忆库。适合在 start_* 之外主动查找历史 Bug 修复或可复用模式;命中后用 read_memory_asset 读取全文。',
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
query: { type: 'string', description: '检索 query(现象、报错、关键词、功能描述等)' },
|
|
9
|
+
type: { type: 'string', description: '优先匹配的资产类型,如 bugfix、pattern、component' },
|
|
10
|
+
tags: { type: 'array', items: { type: 'string' }, description: '优先匹配的标签' },
|
|
11
|
+
limit: { type: 'number', description: '返回条数,默认 MEMORY_SEARCH_LIMIT' },
|
|
12
|
+
},
|
|
13
|
+
required: ['query'],
|
|
14
|
+
additionalProperties: true,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
2
17
|
{
|
|
3
18
|
name: 'read_memory_asset',
|
|
4
19
|
description: '当编排阶段已检索到记忆摘要,且 AI 需要查看完整沉淀代码或详细规范时使用。根据 asset_id 读取记忆资产详情。',
|
|
@@ -16,22 +31,22 @@ export const memoryToolSchemas = [
|
|
|
16
31
|
},
|
|
17
32
|
{
|
|
18
33
|
name: 'memorize_asset',
|
|
19
|
-
description: '
|
|
34
|
+
description: '沉淀可检索资产到共享记忆库。Bug 修复后必须 type=bugfix,content 含【现象】【根因】【修复】【验证】。跨仓库共享时勿填 source_project/source_path,路径写入 content 即可。',
|
|
20
35
|
inputSchema: {
|
|
21
36
|
type: 'object',
|
|
22
37
|
properties: {
|
|
23
38
|
name: { type: 'string', description: '资产名称' },
|
|
24
|
-
type: { type: 'string', description: '
|
|
39
|
+
type: { type: 'string', description: '资产类型:bugfix / pattern / component / code 等' },
|
|
25
40
|
description: { type: 'string', description: '资产描述' },
|
|
26
|
-
summary: { type: 'string', description: '
|
|
27
|
-
content: { type: 'string', description: '
|
|
41
|
+
summary: { type: 'string', description: '检索用一句话摘要(关键词 + 根因/要点)' },
|
|
42
|
+
content: { type: 'string', description: '完整内容(bugfix 建议结构化四段)' },
|
|
28
43
|
code_snippet: { type: 'string', description: '代码片段,content 的别名' },
|
|
29
|
-
file_path: { type: 'string', description: '
|
|
30
|
-
source_project: { type: 'string', description: '
|
|
31
|
-
source_path: { type: 'string', description: '
|
|
44
|
+
file_path: { type: 'string', description: '已废弃:勿用于跨仓库沉淀,路径写入 content' },
|
|
45
|
+
source_project: { type: 'string', description: '已废弃:仅同仓库追溯时可选' },
|
|
46
|
+
source_path: { type: 'string', description: '已废弃:仅同仓库追溯时可选' },
|
|
32
47
|
usage: { type: 'string', description: '适用场景/使用方式' },
|
|
33
48
|
confidence: { type: 'number', description: '置信度,0-1' },
|
|
34
|
-
tags: { type: 'array', items: { type: 'string' }, description: '
|
|
49
|
+
tags: { type: 'array', items: { type: 'string' }, description: '标签列表,如 bugfix, root-cause' },
|
|
35
50
|
},
|
|
36
51
|
required: ['name', 'description', 'summary'],
|
|
37
52
|
additionalProperties: true,
|
|
@@ -45,7 +60,7 @@ export const memoryToolSchemas = [
|
|
|
45
60
|
properties: {
|
|
46
61
|
content: { type: 'string', description: '待分析的代码或文本内容。传入该字段时走单段分析模式' },
|
|
47
62
|
file_path: { type: 'string', description: '来源文件路径。单段分析时作为来源路径使用' },
|
|
48
|
-
project_name: { type: 'string', description: '
|
|
63
|
+
project_name: { type: 'string', description: '已废弃,扫描结果不再写入 source_project' },
|
|
49
64
|
directory_path: { type: 'string', description: '要扫描的目录路径。最佳实践是传相对 `project_root` 的路径,例如 `app/utils`;如果拿不到 `project_root`,才传目录绝对路径。不要传带项目名的半相对路径,例如 `font-miniapp-api/app/utils`。' },
|
|
50
65
|
project_root: { type: 'string', description: '项目根目录绝对路径。目录扫描时建议始终传入;传入后,`directory_path` 应写成相对项目根的路径。' },
|
|
51
66
|
max_files: { type: 'number', description: '最多扫描多少个文件,默认 30,最大 200' },
|
|
@@ -3,13 +3,35 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export declare const projectToolSchemas: readonly [{
|
|
5
5
|
readonly name: "init_project_context";
|
|
6
|
-
readonly description: "
|
|
6
|
+
readonly description: "生成/更新项目上下文:默认写入 AGENTS.md(含 MCP 与 GitNexus 触发规则)及 docs/project-context/。新功能请先 start_feature,修 bug 请先 start_bugfix。完成后 Agent 应阅读 AGENTS.md。";
|
|
7
7
|
readonly inputSchema: {
|
|
8
8
|
readonly type: "object";
|
|
9
9
|
readonly properties: {
|
|
10
10
|
readonly docs_dir: {
|
|
11
11
|
readonly type: "string";
|
|
12
|
-
readonly description: "
|
|
12
|
+
readonly description: "附属文档根目录(project-context、graph-insights)。默认 docs";
|
|
13
|
+
};
|
|
14
|
+
readonly index_style: {
|
|
15
|
+
readonly type: "string";
|
|
16
|
+
readonly enum: readonly ["auto", "agents", "legacy"];
|
|
17
|
+
readonly description: "索引风格:auto(默认 AGENTS.md)、agents、legacy(docs/project-context.md)";
|
|
18
|
+
};
|
|
19
|
+
readonly output: {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
readonly description: "高级:索引文件相对路径,如 AGENTS.md";
|
|
22
|
+
};
|
|
23
|
+
readonly output_dir: {
|
|
24
|
+
readonly type: "string";
|
|
25
|
+
readonly description: "高级:索引所在目录,如 .claude/rules";
|
|
26
|
+
};
|
|
27
|
+
readonly filename: {
|
|
28
|
+
readonly type: "string";
|
|
29
|
+
readonly description: "高级:与 output_dir 合用,默认 project-context.md";
|
|
30
|
+
};
|
|
31
|
+
readonly locale: {
|
|
32
|
+
readonly type: "string";
|
|
33
|
+
readonly enum: readonly ["en", "zh-CN"];
|
|
34
|
+
readonly description: "AGENTS.md 语言;默认根据 README 探测";
|
|
13
35
|
};
|
|
14
36
|
};
|
|
15
37
|
readonly required: readonly [];
|
|
@@ -4,13 +4,35 @@
|
|
|
4
4
|
export const projectToolSchemas = [
|
|
5
5
|
{
|
|
6
6
|
name: "init_project_context",
|
|
7
|
-
description: "
|
|
7
|
+
description: "生成/更新项目上下文:默认写入 AGENTS.md(含 MCP 与 GitNexus 触发规则)及 docs/project-context/。新功能请先 start_feature,修 bug 请先 start_bugfix。完成后 Agent 应阅读 AGENTS.md。",
|
|
8
8
|
inputSchema: {
|
|
9
9
|
type: "object",
|
|
10
10
|
properties: {
|
|
11
11
|
docs_dir: {
|
|
12
12
|
type: "string",
|
|
13
|
-
description: "
|
|
13
|
+
description: "附属文档根目录(project-context、graph-insights)。默认 docs",
|
|
14
|
+
},
|
|
15
|
+
index_style: {
|
|
16
|
+
type: "string",
|
|
17
|
+
enum: ["auto", "agents", "legacy"],
|
|
18
|
+
description: "索引风格:auto(默认 AGENTS.md)、agents、legacy(docs/project-context.md)",
|
|
19
|
+
},
|
|
20
|
+
output: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "高级:索引文件相对路径,如 AGENTS.md",
|
|
23
|
+
},
|
|
24
|
+
output_dir: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "高级:索引所在目录,如 .claude/rules",
|
|
27
|
+
},
|
|
28
|
+
filename: {
|
|
29
|
+
type: "string",
|
|
30
|
+
description: "高级:与 output_dir 合用,默认 project-context.md",
|
|
31
|
+
},
|
|
32
|
+
locale: {
|
|
33
|
+
type: "string",
|
|
34
|
+
enum: ["en", "zh-CN"],
|
|
35
|
+
description: "AGENTS.md 语言;默认根据 README 探测",
|
|
14
36
|
},
|
|
15
37
|
},
|
|
16
38
|
required: [],
|
|
@@ -144,15 +144,15 @@ describe("code_insight 单元测试", () => {
|
|
|
144
144
|
expect(text).toMatch(/不要只口头总结而不写文件/);
|
|
145
145
|
expect(text).toMatch(/docs\/graph-insights\/latest\.md/);
|
|
146
146
|
expect(text).toMatch(/使用场景指南/);
|
|
147
|
-
expect(structured.projectDocs.latestMarkdownFilePath).
|
|
147
|
+
expect(structured.projectDocs.latestMarkdownFilePath).toMatch(/docs\/graph-insights\/latest\.md$/);
|
|
148
148
|
expect(structured.projectDocs.archiveMarkdownFilePath).toContain("/docs/graph-insights/");
|
|
149
|
-
expect(structured.projectDocs.projectContextFilePath).
|
|
149
|
+
expect(structured.projectDocs.projectContextFilePath).toMatch(/\/(AGENTS\.md|docs\/project-context\.md)$/);
|
|
150
150
|
expect(structured.projectDocs.navigationSnippet).toMatch(/代码图谱洞察/);
|
|
151
151
|
expect(structured.plan.mode).toBe("delegated");
|
|
152
152
|
expect(structured.plan.steps).toHaveLength(2);
|
|
153
153
|
expect(structured.plan.steps[0].id).toBe("consume-result");
|
|
154
154
|
expect(structured.plan.steps[1].id).toBe("optional-save");
|
|
155
|
-
expect(structured.plan.steps[1].outputs[0]).
|
|
155
|
+
expect(structured.plan.steps[1].outputs[0]).toMatch(/docs\/graph-insights\/latest\.md$/);
|
|
156
156
|
expect(fs.existsSync(path.join(projectRoot, "docs", "graph-insights", "latest.md"))).toBe(false);
|
|
157
157
|
}
|
|
158
158
|
finally {
|
|
@@ -4,10 +4,11 @@ import path from 'node:path';
|
|
|
4
4
|
import { describe, expect, test } from 'vitest';
|
|
5
5
|
import { initProjectContext } from '../init_project_context.js';
|
|
6
6
|
describe('init_project_context 单元测试', () => {
|
|
7
|
-
test('返回 delegated plan
|
|
7
|
+
test('返回 delegated plan,含 finalize-agents-md 与 AGENTS.md 模板', async () => {
|
|
8
|
+
const projectRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mcp-probe-kit-init-'));
|
|
8
9
|
const result = await initProjectContext({
|
|
9
10
|
docs_dir: 'docs',
|
|
10
|
-
project_root:
|
|
11
|
+
project_root: projectRoot,
|
|
11
12
|
});
|
|
12
13
|
expect(result.isError).toBeFalsy();
|
|
13
14
|
expect('structuredContent' in result).toBe(true);
|
|
@@ -15,49 +16,59 @@ describe('init_project_context 单元测试', () => {
|
|
|
15
16
|
throw new Error('structuredContent 缺失');
|
|
16
17
|
}
|
|
17
18
|
const structured = result.structuredContent;
|
|
19
|
+
expect(structured.documentation.some((item) => item.path === 'AGENTS.md')).toBe(true);
|
|
18
20
|
expect(structured.documentation.some((item) => item.path === 'docs/graph-insights/latest.md')).toBe(true);
|
|
19
|
-
expect(structured.
|
|
20
|
-
expect(structured.metadata?.
|
|
21
|
+
expect(structured.metadata?.layout?.indexPath).toBe('AGENTS.md');
|
|
22
|
+
expect(structured.metadata?.agentsMdTemplate).toMatch(/mcp-probe:context begin/);
|
|
23
|
+
expect(structured.metadata?.manifestWritten).toBe('docs/.mcp-probe/layout.json');
|
|
24
|
+
expect(fs.existsSync(path.join(projectRoot, 'docs', '.mcp-probe', 'layout.json'))).toBe(true);
|
|
21
25
|
const plan = structured.metadata?.plan;
|
|
22
26
|
expect(plan?.mode).toBe('delegated');
|
|
23
27
|
expect(plan.steps.map((step) => step.id)).toEqual([
|
|
24
|
-
'write-
|
|
28
|
+
'write-modular-docs',
|
|
25
29
|
'bootstrap-code-insight',
|
|
26
30
|
'persist-graph-docs',
|
|
31
|
+
'finalize-agents-md',
|
|
27
32
|
]);
|
|
28
|
-
expect(plan.steps[
|
|
33
|
+
expect(plan.steps[0].outputs).toContain('docs/project-context.md');
|
|
34
|
+
expect(plan.steps[3].id).toBe('finalize-agents-md');
|
|
29
35
|
});
|
|
30
|
-
test('输出文本包含
|
|
36
|
+
test('输出文本包含 AGENTS.md 与 MCP 触发规则', async () => {
|
|
37
|
+
const projectRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mcp-probe-kit-init-'));
|
|
31
38
|
const result = await initProjectContext({
|
|
32
|
-
|
|
33
|
-
project_root: 'E:/workspace/github/mcp-probe-kit',
|
|
39
|
+
project_root: projectRoot,
|
|
34
40
|
});
|
|
35
41
|
const text = result.content[0].text;
|
|
36
|
-
expect(text).toMatch(/
|
|
37
|
-
expect(text).toMatch(/
|
|
38
|
-
expect(text).toMatch(/
|
|
42
|
+
expect(text).toMatch(/AGENTS\.md/);
|
|
43
|
+
expect(text).toMatch(/start_feature/);
|
|
44
|
+
expect(text).toMatch(/finalize-agents-md/);
|
|
39
45
|
});
|
|
40
|
-
test('已存在 project-context
|
|
46
|
+
test('已存在 project-context 分类文档时跳过重写 modular', async () => {
|
|
41
47
|
const projectRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mcp-probe-kit-context-'));
|
|
42
|
-
fs.mkdirSync(path.join(projectRoot, 'docs'), { recursive: true });
|
|
48
|
+
fs.mkdirSync(path.join(projectRoot, 'docs', 'project-context'), { recursive: true });
|
|
43
49
|
fs.writeFileSync(path.join(projectRoot, 'docs', 'project-context.md'), '# existing context\n', 'utf8');
|
|
44
50
|
const result = await initProjectContext({
|
|
45
51
|
docs_dir: 'docs',
|
|
46
52
|
project_root: projectRoot,
|
|
47
53
|
});
|
|
48
54
|
expect(result.isError).toBeFalsy();
|
|
49
|
-
expect('structuredContent' in result).toBe(true);
|
|
50
|
-
if (!('structuredContent' in result)) {
|
|
51
|
-
throw new Error('structuredContent 缺失');
|
|
52
|
-
}
|
|
53
55
|
const structured = result.structuredContent;
|
|
54
|
-
expect(structured.metadata?.
|
|
56
|
+
expect(structured.metadata?.legacyProjectContextExists).toBe(true);
|
|
55
57
|
expect(structured.metadata?.plan?.steps.map((step) => step.id)).toEqual([
|
|
56
58
|
'bootstrap-code-insight',
|
|
57
59
|
'persist-graph-docs',
|
|
60
|
+
'finalize-agents-md',
|
|
58
61
|
]);
|
|
59
62
|
const text = result.content[0].text;
|
|
60
|
-
expect(text).toMatch(
|
|
61
|
-
|
|
63
|
+
expect(text).toMatch(/保留/);
|
|
64
|
+
});
|
|
65
|
+
test('已有 AGENTS.md 用户内容时 prepend merge', async () => {
|
|
66
|
+
const projectRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'mcp-probe-kit-agents-'));
|
|
67
|
+
fs.writeFileSync(path.join(projectRoot, 'AGENTS.md'), '# Custom rules\n', 'utf8');
|
|
68
|
+
const result = await initProjectContext({ project_root: projectRoot });
|
|
69
|
+
const structured = result.structuredContent;
|
|
70
|
+
expect(structured.metadata?.agentsMdMergeMode).toBe('prepended');
|
|
71
|
+
expect(structured.metadata?.agentsMdTemplate).toMatch(/<!-- mcp-probe:context begin/);
|
|
72
|
+
expect(structured.metadata?.agentsMdTemplate).toContain('# Custom rules');
|
|
62
73
|
});
|
|
63
74
|
});
|
|
@@ -25,12 +25,13 @@ describe('start_feature 单元测试', () => {
|
|
|
25
25
|
expect(plan).toBeTruthy();
|
|
26
26
|
expect(plan.mode).toBe('delegated');
|
|
27
27
|
expect(Array.isArray(plan.steps)).toBe(true);
|
|
28
|
-
expect(plan.steps.length).
|
|
28
|
+
expect(plan.steps.length).toBeGreaterThanOrEqual(3);
|
|
29
29
|
const tools = plan.steps.map((step) => step.tool);
|
|
30
30
|
expect(tools).toContain('init_project_context');
|
|
31
31
|
expect(tools).toContain('add_feature');
|
|
32
32
|
expect(tools).toContain('estimate');
|
|
33
33
|
const contextStep = plan.steps.find((step) => step.tool === 'init_project_context');
|
|
34
|
+
expect(contextStep.outputs).toContain('AGENTS.md');
|
|
34
35
|
expect(contextStep.outputs).toContain('docs/graph-insights/latest.md');
|
|
35
36
|
expect(contextStep.outputs).toContain('docs/graph-insights/latest.json');
|
|
36
37
|
expect(contextStep.when).toMatch(/graph-insights\/latest\.md/);
|
|
@@ -5,7 +5,8 @@ import { okStructured } from "../lib/response.js";
|
|
|
5
5
|
import { renderOrchestrationHeader } from "../lib/orchestration-guidance.js";
|
|
6
6
|
import { runCodeInsightBridge, } from "../lib/gitnexus-bridge.js";
|
|
7
7
|
import { throwIfAborted, } from "../lib/tool-execution-context.js";
|
|
8
|
-
import { isLikelyProjectNamedRelativePath, buildProjectRootRetryHint } from "../lib/workspace-root.js";
|
|
8
|
+
import { isLikelyProjectNamedRelativePath, buildProjectRootRetryHint, resolveWorkspaceRoot } from "../lib/workspace-root.js";
|
|
9
|
+
import { layoutAbsPath, parseLayoutArgsFromRecord, resolveProjectContextLayout, } from "../lib/project-context-layout.js";
|
|
9
10
|
const ALLOWED_MODES = new Set(["auto", "query", "context", "impact"]);
|
|
10
11
|
const ALLOWED_DIRECTIONS = new Set(["upstream", "downstream"]);
|
|
11
12
|
const DEFAULT_AUTO_QUERY = "项目整体架构 核心流程 关键模块 依赖关系 入口点";
|
|
@@ -25,7 +26,7 @@ function buildProjectDocsOutputs(input) {
|
|
|
25
26
|
if (!projectRoot) {
|
|
26
27
|
return null;
|
|
27
28
|
}
|
|
28
|
-
const docsRoot = path.join(path.resolve(projectRoot), input.
|
|
29
|
+
const docsRoot = path.join(path.resolve(projectRoot), input.graphDir || "docs/graph-insights");
|
|
29
30
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
30
31
|
const suffix = makeSafeSegment(input.structured.summary || input.mode);
|
|
31
32
|
const baseName = `${timestamp}-${input.mode}-${suffix}`;
|
|
@@ -126,13 +127,13 @@ function formatAmbiguities(ambiguities) {
|
|
|
126
127
|
})
|
|
127
128
|
.join("\n");
|
|
128
129
|
}
|
|
129
|
-
function createProjectDocsPlan(
|
|
130
|
-
const docsDir =
|
|
130
|
+
function createProjectDocsPlan(layout, docsSnapshot) {
|
|
131
|
+
const docsDir = layout.contextRoot;
|
|
131
132
|
return {
|
|
132
133
|
docsDir,
|
|
133
|
-
projectContextFilePath: toPosixPath(
|
|
134
|
-
latestMarkdownFilePath:
|
|
135
|
-
latestJsonFilePath:
|
|
134
|
+
projectContextFilePath: toPosixPath(layoutAbsPath(layout, layout.indexPath)),
|
|
135
|
+
latestMarkdownFilePath: layout.latestMarkdownPath,
|
|
136
|
+
latestJsonFilePath: layout.latestJsonPath,
|
|
136
137
|
archiveMarkdownFilePath: docsSnapshot.markdownFilePath,
|
|
137
138
|
archiveJsonFilePath: docsSnapshot.jsonFilePath,
|
|
138
139
|
navigationSnippet: `### [代码图谱洞察](./graph-insights/latest.md)
|
|
@@ -264,6 +265,7 @@ export async function codeInsight(args, context) {
|
|
|
264
265
|
};
|
|
265
266
|
}
|
|
266
267
|
const docsDirName = getString(parsedArgs.docs_dir) || "docs";
|
|
268
|
+
const layout = resolveProjectContextLayout(projectRoot ? resolveWorkspaceRoot(projectRoot) : resolveWorkspaceRoot(), parseLayoutArgsFromRecord({ docs_dir: docsDirName }));
|
|
267
269
|
const goal = getString(parsedArgs.goal);
|
|
268
270
|
const taskContext = getString(parsedArgs.task_context);
|
|
269
271
|
const direction = normalizeDirection(getString(parsedArgs.direction));
|
|
@@ -344,12 +346,12 @@ ${result.warnings.length > 0 ? `警告: ${result.warnings.join(", ")}` : ""}`.tr
|
|
|
344
346
|
const docsProjectRoot = saveToDocs ? (projectRoot || result.sourceRoot) : "";
|
|
345
347
|
const docsSnapshot = buildProjectDocsOutputs({
|
|
346
348
|
projectRoot: docsProjectRoot,
|
|
347
|
-
|
|
349
|
+
graphDir: layout.graphDir,
|
|
348
350
|
mode,
|
|
349
351
|
structured,
|
|
350
352
|
});
|
|
351
353
|
const projectDocs = docsSnapshot
|
|
352
|
-
? createProjectDocsPlan(
|
|
354
|
+
? createProjectDocsPlan(layout, docsSnapshot)
|
|
353
355
|
: undefined;
|
|
354
356
|
if (projectDocs) {
|
|
355
357
|
structured.projectDocs = projectDocs;
|
package/build/tools/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export { interview } from "./interview.js";
|
|
|
16
16
|
export { askUser } from "./ask_user.js";
|
|
17
17
|
export { uiDesignSystem, uiSearch, syncUiData } from "./ui-ux-tools.js";
|
|
18
18
|
export { startUi } from "./start_ui.js";
|
|
19
|
+
export { searchMemory } from "./search_memory.js";
|
|
19
20
|
export { readMemoryAsset } from "./read_memory_asset.js";
|
|
20
21
|
export { memorizeAsset } from "./memorize_asset.js";
|
|
21
22
|
export { scanAndExtractPatterns } from "./scan_and_extract_patterns.js";
|
package/build/tools/index.js
CHANGED
|
@@ -20,6 +20,7 @@ export { askUser } from "./ask_user.js";
|
|
|
20
20
|
export { uiDesignSystem, uiSearch, syncUiData } from "./ui-ux-tools.js";
|
|
21
21
|
export { startUi } from "./start_ui.js";
|
|
22
22
|
// 记忆工具
|
|
23
|
+
export { searchMemory } from "./search_memory.js";
|
|
23
24
|
export { readMemoryAsset } from "./read_memory_asset.js";
|
|
24
25
|
export { memorizeAsset } from "./memorize_asset.js";
|
|
25
26
|
export { scanAndExtractPatterns } from "./scan_and_extract_patterns.js";
|