mcp-probe-kit 3.0.17 → 3.0.19
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 +77 -50
- package/build/lib/__tests__/agents-md-template.unit.test.d.ts +1 -0
- package/build/lib/__tests__/agents-md-template.unit.test.js +25 -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 +55 -0
- package/build/lib/memory-orchestration.d.ts +3 -1
- package/build/lib/memory-orchestration.js +71 -5
- 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 +25 -3
- package/build/schemas/memory-tools.d.ts +1 -1
- package/build/schemas/memory-tools.js +1 -1
- 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/init_project_context.js +563 -506
- package/build/tools/start_bugfix.js +254 -248
- package/build/tools/start_feature.js +137 -131
- package/build/tools/start_ui.js +402 -402
- package/docs/.mcp-probe/layout.json +11 -0
- package/docs/i18n/en.json +36 -5
- package/docs/i18n/ja.json +9 -2
- package/docs/i18n/ko.json +9 -2
- package/docs/i18n/zh-CN.json +36 -5
- package/docs/memory-local-setup.md +314 -0
- package/docs/memory-local-setup.zh-CN.md +280 -0
- package/docs/pages/getting-started.html +249 -31
- package/package.json +1 -1
|
@@ -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;
|