mcp-probe-kit 3.0.15 → 3.0.17
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 +618 -410
- package/build/index.js +13 -1
- package/build/lib/__tests__/memory-client.unit.test.d.ts +1 -0
- package/build/lib/__tests__/memory-client.unit.test.js +83 -0
- package/build/lib/__tests__/memory-config.unit.test.d.ts +1 -0
- package/build/lib/__tests__/memory-config.unit.test.js +33 -0
- package/build/lib/cursor-history-client.d.ts +54 -0
- package/build/lib/cursor-history-client.js +240 -0
- package/build/lib/gitnexus-bridge.js +6 -8
- package/build/lib/memory-client.d.ts +61 -0
- package/build/lib/memory-client.js +293 -0
- package/build/lib/memory-config.d.ts +14 -0
- package/build/lib/memory-config.js +31 -0
- package/build/lib/memory-orchestration.d.ts +26 -0
- package/build/lib/memory-orchestration.js +65 -0
- package/build/lib/project-detector.js +6 -4
- package/build/lib/skill-bridge.d.ts +31 -0
- package/build/lib/skill-bridge.js +100 -0
- package/build/lib/workspace-root.d.ts +12 -0
- package/build/lib/workspace-root.js +153 -0
- package/build/resources/ui-ux-data/charts.json +302 -0
- package/build/resources/ui-ux-data/colors.json +1058 -0
- package/build/resources/ui-ux-data/icons.json +1102 -0
- package/build/resources/ui-ux-data/landing.json +262 -0
- package/build/resources/ui-ux-data/metadata.json +6 -0
- package/build/resources/ui-ux-data/products.json +1058 -0
- package/build/resources/ui-ux-data/react-performance.json +574 -0
- package/build/resources/ui-ux-data/stacks/astro.json +266 -0
- package/build/resources/ui-ux-data/stacks/flutter.json +626 -0
- package/build/resources/ui-ux-data/stacks/html-tailwind.json +662 -0
- package/build/resources/ui-ux-data/stacks/jetpack-compose.json +626 -0
- package/build/resources/ui-ux-data/stacks/nextjs.json +218 -0
- package/build/resources/ui-ux-data/stacks/nuxt-ui.json +14 -0
- package/build/resources/ui-ux-data/stacks/nuxtjs.json +182 -0
- package/build/resources/ui-ux-data/stacks/react-native.json +350 -0
- package/build/resources/ui-ux-data/stacks/react.json +530 -0
- package/build/resources/ui-ux-data/stacks/shadcn.json +566 -0
- package/build/resources/ui-ux-data/stacks/svelte.json +134 -0
- package/build/resources/ui-ux-data/stacks/swiftui.json +26 -0
- package/build/resources/ui-ux-data/stacks/vue.json +170 -0
- package/build/resources/ui-ux-data/styles.json +1610 -0
- package/build/resources/ui-ux-data/typography.json +743 -0
- package/build/resources/ui-ux-data/ui-reasoning.json +1431 -0
- package/build/resources/ui-ux-data/ux-guidelines.json +1190 -0
- package/build/resources/ui-ux-data/web-interface.json +389 -0
- package/build/schemas/code-analysis-tools.d.ts +1 -1
- package/build/schemas/code-analysis-tools.js +1 -1
- package/build/schemas/index.d.ts +198 -4
- package/build/schemas/index.js +2 -0
- package/build/schemas/memory-tools.d.ts +191 -0
- package/build/schemas/memory-tools.js +106 -0
- package/build/schemas/orchestration-tools.d.ts +3 -3
- package/build/schemas/orchestration-tools.js +3 -3
- package/build/schemas/ui-ux-schemas.d.ts +8 -0
- package/build/schemas/ui-ux-schemas.js +5 -1
- package/build/tools/__tests__/cursor-history.unit.test.d.ts +1 -0
- package/build/tools/__tests__/cursor-history.unit.test.js +87 -0
- package/build/tools/__tests__/memorize_asset.unit.test.d.ts +1 -0
- package/build/tools/__tests__/memorize_asset.unit.test.js +68 -0
- package/build/tools/code_insight.d.ts +20 -0
- package/build/tools/code_insight.js +15 -0
- package/build/tools/cursor_list_conversations.d.ts +7 -0
- package/build/tools/cursor_list_conversations.js +35 -0
- package/build/tools/cursor_read_conversation.d.ts +7 -0
- package/build/tools/cursor_read_conversation.js +36 -0
- package/build/tools/cursor_search_conversations.d.ts +7 -0
- package/build/tools/cursor_search_conversations.js +36 -0
- package/build/tools/index.d.ts +6 -0
- package/build/tools/index.js +7 -0
- package/build/tools/init_project_context.d.ts +20 -1
- package/build/tools/init_project_context.js +114 -99
- package/build/tools/memorize_asset.d.ts +7 -0
- package/build/tools/memorize_asset.js +66 -0
- package/build/tools/read_memory_asset.d.ts +7 -0
- package/build/tools/read_memory_asset.js +26 -0
- package/build/tools/scan_and_extract_patterns.d.ts +27 -0
- package/build/tools/scan_and_extract_patterns.js +346 -0
- package/build/tools/start_bugfix.d.ts +20 -0
- package/build/tools/start_bugfix.js +97 -69
- package/build/tools/start_feature.d.ts +20 -0
- package/build/tools/start_feature.js +61 -31
- package/build/tools/start_onboard.d.ts +20 -0
- package/build/tools/start_onboard.js +15 -0
- package/build/tools/start_product.js +8 -1
- package/build/tools/start_ui.d.ts +20 -0
- package/build/tools/start_ui.js +79 -34
- package/build/tools/ui-ux-tools.js +21 -17
- package/build/utils/ui-data-loader.d.ts +18 -2
- package/build/utils/ui-data-loader.js +74 -12
- package/docs/data/tools.js +472 -373
- package/docs/i18n/all-tools/en.json +38 -5
- package/docs/i18n/all-tools/ja.json +14 -4
- package/docs/i18n/all-tools/ko.json +13 -3
- package/docs/i18n/all-tools/zh-CN.json +38 -5
- package/docs/i18n/en.json +48 -10
- package/docs/i18n/ja.json +47 -9
- package/docs/i18n/ko.json +47 -9
- package/docs/i18n/zh-CN.json +48 -10
- package/docs/pages/all-tools.html +515 -515
- package/docs/pages/examples.html +661 -661
- package/docs/pages/getting-started.html +673 -582
- package/docs/pages/migration.html +291 -291
- package/package.json +83 -81
- package/docs/debug-i18n.html +0 -163
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
export declare const memoryToolSchemas: readonly [{
|
|
2
|
+
readonly name: "read_memory_asset";
|
|
3
|
+
readonly description: "当编排阶段已检索到记忆摘要,且 AI 需要查看完整沉淀代码或详细规范时使用。根据 asset_id 读取记忆资产详情。";
|
|
4
|
+
readonly inputSchema: {
|
|
5
|
+
readonly type: "object";
|
|
6
|
+
readonly properties: {
|
|
7
|
+
readonly asset_id: {
|
|
8
|
+
readonly type: "string";
|
|
9
|
+
readonly description: "记忆资产 ID";
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
readonly required: readonly ["asset_id"];
|
|
13
|
+
readonly additionalProperties: true;
|
|
14
|
+
};
|
|
15
|
+
}, {
|
|
16
|
+
readonly name: "memorize_asset";
|
|
17
|
+
readonly description: "当 AI 完成开发并确认存在可复用代码、模式或规范时使用。将高价值资产沉淀到记忆系统。";
|
|
18
|
+
readonly inputSchema: {
|
|
19
|
+
readonly type: "object";
|
|
20
|
+
readonly properties: {
|
|
21
|
+
readonly name: {
|
|
22
|
+
readonly type: "string";
|
|
23
|
+
readonly description: "资产名称";
|
|
24
|
+
};
|
|
25
|
+
readonly type: {
|
|
26
|
+
readonly type: "string";
|
|
27
|
+
readonly description: "资产类型,如 code/component/pattern/spec";
|
|
28
|
+
};
|
|
29
|
+
readonly description: {
|
|
30
|
+
readonly type: "string";
|
|
31
|
+
readonly description: "资产描述";
|
|
32
|
+
};
|
|
33
|
+
readonly summary: {
|
|
34
|
+
readonly type: "string";
|
|
35
|
+
readonly description: "用于检索的凝练摘要";
|
|
36
|
+
};
|
|
37
|
+
readonly content: {
|
|
38
|
+
readonly type: "string";
|
|
39
|
+
readonly description: "完整内容";
|
|
40
|
+
};
|
|
41
|
+
readonly code_snippet: {
|
|
42
|
+
readonly type: "string";
|
|
43
|
+
readonly description: "代码片段,content 的别名";
|
|
44
|
+
};
|
|
45
|
+
readonly file_path: {
|
|
46
|
+
readonly type: "string";
|
|
47
|
+
readonly description: "来源文件路径";
|
|
48
|
+
};
|
|
49
|
+
readonly source_project: {
|
|
50
|
+
readonly type: "string";
|
|
51
|
+
readonly description: "来源项目";
|
|
52
|
+
};
|
|
53
|
+
readonly source_path: {
|
|
54
|
+
readonly type: "string";
|
|
55
|
+
readonly description: "来源路径";
|
|
56
|
+
};
|
|
57
|
+
readonly usage: {
|
|
58
|
+
readonly type: "string";
|
|
59
|
+
readonly description: "适用场景/使用方式";
|
|
60
|
+
};
|
|
61
|
+
readonly confidence: {
|
|
62
|
+
readonly type: "number";
|
|
63
|
+
readonly description: "置信度,0-1";
|
|
64
|
+
};
|
|
65
|
+
readonly tags: {
|
|
66
|
+
readonly type: "array";
|
|
67
|
+
readonly items: {
|
|
68
|
+
readonly type: "string";
|
|
69
|
+
};
|
|
70
|
+
readonly description: "标签列表";
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
readonly required: readonly ["name", "description", "summary"];
|
|
74
|
+
readonly additionalProperties: true;
|
|
75
|
+
};
|
|
76
|
+
}, {
|
|
77
|
+
readonly name: "scan_and_extract_patterns";
|
|
78
|
+
readonly description: "当需要从单段代码、单文件或整个目录中抽取可复用模式,再决定是否沉淀到记忆系统时使用。目录扫描时,优先传 `project_root` 为项目根目录绝对路径,并让 `directory_path` 传相对项目根的路径,例如 `app/utils`;只有无法确定项目根时,才把 `directory_path` 直接设为绝对路径。不要传带项目名的半相对路径,例如 `font-miniapp-api/app/utils`。";
|
|
79
|
+
readonly inputSchema: {
|
|
80
|
+
readonly type: "object";
|
|
81
|
+
readonly properties: {
|
|
82
|
+
readonly content: {
|
|
83
|
+
readonly type: "string";
|
|
84
|
+
readonly description: "待分析的代码或文本内容。传入该字段时走单段分析模式";
|
|
85
|
+
};
|
|
86
|
+
readonly file_path: {
|
|
87
|
+
readonly type: "string";
|
|
88
|
+
readonly description: "来源文件路径。单段分析时作为来源路径使用";
|
|
89
|
+
};
|
|
90
|
+
readonly project_name: {
|
|
91
|
+
readonly type: "string";
|
|
92
|
+
readonly description: "来源项目名";
|
|
93
|
+
};
|
|
94
|
+
readonly directory_path: {
|
|
95
|
+
readonly type: "string";
|
|
96
|
+
readonly description: "要扫描的目录路径。最佳实践是传相对 `project_root` 的路径,例如 `app/utils`;如果拿不到 `project_root`,才传目录绝对路径。不要传带项目名的半相对路径,例如 `font-miniapp-api/app/utils`。";
|
|
97
|
+
};
|
|
98
|
+
readonly project_root: {
|
|
99
|
+
readonly type: "string";
|
|
100
|
+
readonly description: "项目根目录绝对路径。目录扫描时建议始终传入;传入后,`directory_path` 应写成相对项目根的路径。";
|
|
101
|
+
};
|
|
102
|
+
readonly max_files: {
|
|
103
|
+
readonly type: "number";
|
|
104
|
+
readonly description: "最多扫描多少个文件,默认 30,最大 200";
|
|
105
|
+
};
|
|
106
|
+
readonly max_patterns: {
|
|
107
|
+
readonly type: "number";
|
|
108
|
+
readonly description: "最多返回多少个候选模式,默认 20,最大 100";
|
|
109
|
+
};
|
|
110
|
+
readonly include_extensions: {
|
|
111
|
+
readonly type: "array";
|
|
112
|
+
readonly items: {
|
|
113
|
+
readonly type: "string";
|
|
114
|
+
};
|
|
115
|
+
readonly description: "允许扫描的文件扩展名列表,例如 [\".ts\", \".tsx\", \".py\"]";
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
readonly required: readonly [];
|
|
119
|
+
readonly additionalProperties: true;
|
|
120
|
+
};
|
|
121
|
+
}, {
|
|
122
|
+
readonly name: "cursor_list_conversations";
|
|
123
|
+
readonly description: "读取 Cursor 本地历史会话摘要。适合按标题、工作区列出最近会话,用于续接旧上下文。";
|
|
124
|
+
readonly inputSchema: {
|
|
125
|
+
readonly type: "object";
|
|
126
|
+
readonly properties: {
|
|
127
|
+
readonly title_query: {
|
|
128
|
+
readonly type: "string";
|
|
129
|
+
readonly description: "按会话标题过滤,支持部分匹配";
|
|
130
|
+
};
|
|
131
|
+
readonly workspace_query: {
|
|
132
|
+
readonly type: "string";
|
|
133
|
+
readonly description: "按工作区路径过滤,支持部分匹配";
|
|
134
|
+
};
|
|
135
|
+
readonly include_archived: {
|
|
136
|
+
readonly type: "boolean";
|
|
137
|
+
readonly description: "是否包含已归档会话,默认 false";
|
|
138
|
+
};
|
|
139
|
+
readonly limit: {
|
|
140
|
+
readonly type: "number";
|
|
141
|
+
readonly description: "最多返回多少条,默认 20,最大 200";
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
readonly required: readonly [];
|
|
145
|
+
readonly additionalProperties: true;
|
|
146
|
+
};
|
|
147
|
+
}, {
|
|
148
|
+
readonly name: "cursor_search_conversations";
|
|
149
|
+
readonly description: "在 Cursor 本地历史消息里按关键词、request id 搜索命中内容,可选限定某个会话。";
|
|
150
|
+
readonly inputSchema: {
|
|
151
|
+
readonly type: "object";
|
|
152
|
+
readonly properties: {
|
|
153
|
+
readonly query: {
|
|
154
|
+
readonly type: "string";
|
|
155
|
+
readonly description: "搜索关键词,可传标题片段、正文片段或 request id";
|
|
156
|
+
};
|
|
157
|
+
readonly composer_id: {
|
|
158
|
+
readonly type: "string";
|
|
159
|
+
readonly description: "可选,限定某个 Cursor 会话 ID";
|
|
160
|
+
};
|
|
161
|
+
readonly limit: {
|
|
162
|
+
readonly type: "number";
|
|
163
|
+
readonly description: "最多返回多少条,默认 20,最大 200";
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
readonly required: readonly ["query"];
|
|
167
|
+
readonly additionalProperties: true;
|
|
168
|
+
};
|
|
169
|
+
}, {
|
|
170
|
+
readonly name: "cursor_read_conversation";
|
|
171
|
+
readonly description: "按 composer_id 读取一条 Cursor 本地会话的消息时间线。";
|
|
172
|
+
readonly inputSchema: {
|
|
173
|
+
readonly type: "object";
|
|
174
|
+
readonly properties: {
|
|
175
|
+
readonly composer_id: {
|
|
176
|
+
readonly type: "string";
|
|
177
|
+
readonly description: "Cursor 会话 ID";
|
|
178
|
+
};
|
|
179
|
+
readonly limit: {
|
|
180
|
+
readonly type: "number";
|
|
181
|
+
readonly description: "最多返回多少条消息,默认 200,最大 2000";
|
|
182
|
+
};
|
|
183
|
+
readonly include_empty: {
|
|
184
|
+
readonly type: "boolean";
|
|
185
|
+
readonly description: "是否包含空文本消息,默认 false";
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
readonly required: readonly ["composer_id"];
|
|
189
|
+
readonly additionalProperties: true;
|
|
190
|
+
};
|
|
191
|
+
}];
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export const memoryToolSchemas = [
|
|
2
|
+
{
|
|
3
|
+
name: 'read_memory_asset',
|
|
4
|
+
description: '当编排阶段已检索到记忆摘要,且 AI 需要查看完整沉淀代码或详细规范时使用。根据 asset_id 读取记忆资产详情。',
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
asset_id: {
|
|
9
|
+
type: 'string',
|
|
10
|
+
description: '记忆资产 ID',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
required: ['asset_id'],
|
|
14
|
+
additionalProperties: true,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: 'memorize_asset',
|
|
19
|
+
description: '当 AI 完成开发并确认存在可复用代码、模式或规范时使用。将高价值资产沉淀到记忆系统。',
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
name: { type: 'string', description: '资产名称' },
|
|
24
|
+
type: { type: 'string', description: '资产类型,如 code/component/pattern/spec' },
|
|
25
|
+
description: { type: 'string', description: '资产描述' },
|
|
26
|
+
summary: { type: 'string', description: '用于检索的凝练摘要' },
|
|
27
|
+
content: { type: 'string', description: '完整内容' },
|
|
28
|
+
code_snippet: { type: 'string', description: '代码片段,content 的别名' },
|
|
29
|
+
file_path: { type: 'string', description: '来源文件路径' },
|
|
30
|
+
source_project: { type: 'string', description: '来源项目' },
|
|
31
|
+
source_path: { type: 'string', description: '来源路径' },
|
|
32
|
+
usage: { type: 'string', description: '适用场景/使用方式' },
|
|
33
|
+
confidence: { type: 'number', description: '置信度,0-1' },
|
|
34
|
+
tags: { type: 'array', items: { type: 'string' }, description: '标签列表' },
|
|
35
|
+
},
|
|
36
|
+
required: ['name', 'description', 'summary'],
|
|
37
|
+
additionalProperties: true,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'scan_and_extract_patterns',
|
|
42
|
+
description: '当需要从单段代码、单文件或整个目录中抽取可复用模式,再决定是否沉淀到记忆系统时使用。目录扫描时,优先传 `project_root` 为项目根目录绝对路径,并让 `directory_path` 传相对项目根的路径,例如 `app/utils`;只有无法确定项目根时,才把 `directory_path` 直接设为绝对路径。不要传带项目名的半相对路径,例如 `font-miniapp-api/app/utils`。',
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
properties: {
|
|
46
|
+
content: { type: 'string', description: '待分析的代码或文本内容。传入该字段时走单段分析模式' },
|
|
47
|
+
file_path: { type: 'string', description: '来源文件路径。单段分析时作为来源路径使用' },
|
|
48
|
+
project_name: { type: 'string', description: '来源项目名' },
|
|
49
|
+
directory_path: { type: 'string', description: '要扫描的目录路径。最佳实践是传相对 `project_root` 的路径,例如 `app/utils`;如果拿不到 `project_root`,才传目录绝对路径。不要传带项目名的半相对路径,例如 `font-miniapp-api/app/utils`。' },
|
|
50
|
+
project_root: { type: 'string', description: '项目根目录绝对路径。目录扫描时建议始终传入;传入后,`directory_path` 应写成相对项目根的路径。' },
|
|
51
|
+
max_files: { type: 'number', description: '最多扫描多少个文件,默认 30,最大 200' },
|
|
52
|
+
max_patterns: { type: 'number', description: '最多返回多少个候选模式,默认 20,最大 100' },
|
|
53
|
+
include_extensions: {
|
|
54
|
+
type: 'array',
|
|
55
|
+
items: { type: 'string' },
|
|
56
|
+
description: '允许扫描的文件扩展名列表,例如 [".ts", ".tsx", ".py"]'
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
required: [],
|
|
60
|
+
additionalProperties: true,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: 'cursor_list_conversations',
|
|
65
|
+
description: '读取 Cursor 本地历史会话摘要。适合按标题、工作区列出最近会话,用于续接旧上下文。',
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: 'object',
|
|
68
|
+
properties: {
|
|
69
|
+
title_query: { type: 'string', description: '按会话标题过滤,支持部分匹配' },
|
|
70
|
+
workspace_query: { type: 'string', description: '按工作区路径过滤,支持部分匹配' },
|
|
71
|
+
include_archived: { type: 'boolean', description: '是否包含已归档会话,默认 false' },
|
|
72
|
+
limit: { type: 'number', description: '最多返回多少条,默认 20,最大 200' },
|
|
73
|
+
},
|
|
74
|
+
required: [],
|
|
75
|
+
additionalProperties: true,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'cursor_search_conversations',
|
|
80
|
+
description: '在 Cursor 本地历史消息里按关键词、request id 搜索命中内容,可选限定某个会话。',
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: 'object',
|
|
83
|
+
properties: {
|
|
84
|
+
query: { type: 'string', description: '搜索关键词,可传标题片段、正文片段或 request id' },
|
|
85
|
+
composer_id: { type: 'string', description: '可选,限定某个 Cursor 会话 ID' },
|
|
86
|
+
limit: { type: 'number', description: '最多返回多少条,默认 20,最大 200' },
|
|
87
|
+
},
|
|
88
|
+
required: ['query'],
|
|
89
|
+
additionalProperties: true,
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'cursor_read_conversation',
|
|
94
|
+
description: '按 composer_id 读取一条 Cursor 本地会话的消息时间线。',
|
|
95
|
+
inputSchema: {
|
|
96
|
+
type: 'object',
|
|
97
|
+
properties: {
|
|
98
|
+
composer_id: { type: 'string', description: 'Cursor 会话 ID' },
|
|
99
|
+
limit: { type: 'number', description: '最多返回多少条消息,默认 200,最大 2000' },
|
|
100
|
+
include_empty: { type: 'boolean', description: '是否包含空文本消息,默认 false' },
|
|
101
|
+
},
|
|
102
|
+
required: ['composer_id'],
|
|
103
|
+
additionalProperties: true,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
];
|
|
@@ -21,7 +21,7 @@ export declare const orchestrationToolSchemas: readonly [{
|
|
|
21
21
|
};
|
|
22
22
|
readonly project_root: {
|
|
23
23
|
readonly type: "string";
|
|
24
|
-
readonly description: "
|
|
24
|
+
readonly description: "项目根目录绝对路径。建议显式传入;docs_dir 等相对路径参数应统一相对该项目根目录解析,避免依赖客户端 cwd。";
|
|
25
25
|
};
|
|
26
26
|
readonly template_profile: {
|
|
27
27
|
readonly type: "string";
|
|
@@ -67,7 +67,7 @@ export declare const orchestrationToolSchemas: readonly [{
|
|
|
67
67
|
};
|
|
68
68
|
readonly project_root: {
|
|
69
69
|
readonly type: "string";
|
|
70
|
-
readonly description: "
|
|
70
|
+
readonly description: "项目根目录绝对路径。建议显式传入;docs_dir 等相对路径参数应统一相对该项目根目录解析,避免依赖客户端 cwd。";
|
|
71
71
|
};
|
|
72
72
|
readonly analysis_mode: {
|
|
73
73
|
readonly type: "string";
|
|
@@ -105,7 +105,7 @@ export declare const orchestrationToolSchemas: readonly [{
|
|
|
105
105
|
readonly properties: {
|
|
106
106
|
readonly project_path: {
|
|
107
107
|
readonly type: "string";
|
|
108
|
-
readonly description: "
|
|
108
|
+
readonly description: "项目根目录绝对路径。建议显式传入;如果还传 docs_dir 等相对路径,应统一相对该项目根目录解析。";
|
|
109
109
|
};
|
|
110
110
|
readonly docs_dir: {
|
|
111
111
|
readonly type: "string";
|
|
@@ -22,7 +22,7 @@ export const orchestrationToolSchemas = [
|
|
|
22
22
|
},
|
|
23
23
|
project_root: {
|
|
24
24
|
type: "string",
|
|
25
|
-
description: "
|
|
25
|
+
description: "项目根目录绝对路径。建议显式传入;docs_dir 等相对路径参数应统一相对该项目根目录解析,避免依赖客户端 cwd。",
|
|
26
26
|
},
|
|
27
27
|
template_profile: {
|
|
28
28
|
type: "string",
|
|
@@ -69,7 +69,7 @@ export const orchestrationToolSchemas = [
|
|
|
69
69
|
},
|
|
70
70
|
project_root: {
|
|
71
71
|
type: "string",
|
|
72
|
-
description: "
|
|
72
|
+
description: "项目根目录绝对路径。建议显式传入;docs_dir 等相对路径参数应统一相对该项目根目录解析,避免依赖客户端 cwd。",
|
|
73
73
|
},
|
|
74
74
|
analysis_mode: {
|
|
75
75
|
type: "string",
|
|
@@ -108,7 +108,7 @@ export const orchestrationToolSchemas = [
|
|
|
108
108
|
properties: {
|
|
109
109
|
project_path: {
|
|
110
110
|
type: "string",
|
|
111
|
-
description: "
|
|
111
|
+
description: "项目根目录绝对路径。建议显式传入;如果还传 docs_dir 等相对路径,应统一相对该项目根目录解析。",
|
|
112
112
|
},
|
|
113
113
|
docs_dir: {
|
|
114
114
|
type: "string",
|
|
@@ -105,6 +105,10 @@ export declare const startUiSchema: {
|
|
|
105
105
|
type: string;
|
|
106
106
|
description: string;
|
|
107
107
|
};
|
|
108
|
+
project_root: {
|
|
109
|
+
type: string;
|
|
110
|
+
description: string;
|
|
111
|
+
};
|
|
108
112
|
template_profile: {
|
|
109
113
|
type: string;
|
|
110
114
|
description: string;
|
|
@@ -236,6 +240,10 @@ export declare const uiUxSchemas: ({
|
|
|
236
240
|
type: string;
|
|
237
241
|
description: string;
|
|
238
242
|
};
|
|
243
|
+
project_root: {
|
|
244
|
+
type: string;
|
|
245
|
+
description: string;
|
|
246
|
+
};
|
|
239
247
|
template_profile: {
|
|
240
248
|
type: string;
|
|
241
249
|
description: string;
|
|
@@ -69,7 +69,7 @@ export const uiSearchSchema = {
|
|
|
69
69
|
};
|
|
70
70
|
export const syncUiDataSchema = {
|
|
71
71
|
name: "sync_ui_data",
|
|
72
|
-
description: "同步 UI/UX 数据到本地缓存。从 npm 包 uipro-cli 下载最新数据,支持自动检查更新和强制同步。数据存储在 ~/.mcp-probe-kit/ui-ux-data
|
|
72
|
+
description: "同步 UI/UX 数据到本地缓存。从 npm 包 uipro-cli 下载最新数据,支持自动检查更新和强制同步。数据存储在 ~/.mcp-probe-kit/ui-ux-data/,默认在下次启动时生效以保证当前会话一致性。",
|
|
73
73
|
inputSchema: {
|
|
74
74
|
type: "object",
|
|
75
75
|
properties: {
|
|
@@ -105,6 +105,10 @@ export const startUiSchema = {
|
|
|
105
105
|
type: "string",
|
|
106
106
|
description: "模板名称(可选,不提供则自动生成)",
|
|
107
107
|
},
|
|
108
|
+
project_root: {
|
|
109
|
+
type: "string",
|
|
110
|
+
description: "项目根目录绝对路径。建议显式传入;如果存在 docs 或模板等相对路径解析,应统一相对该项目根目录处理,避免依赖客户端 cwd。",
|
|
111
|
+
},
|
|
108
112
|
template_profile: {
|
|
109
113
|
type: "string",
|
|
110
114
|
description: "模板档位:auto(默认,自动选择 guided/strict)、guided(普通模型友好)或 strict(结构更紧凑)",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
const listConversationsMock = vi.fn();
|
|
3
|
+
const searchHistoryMock = vi.fn();
|
|
4
|
+
const readConversationMock = vi.fn();
|
|
5
|
+
vi.mock('../../lib/cursor-history-client.js', () => ({
|
|
6
|
+
createCursorHistoryClient: () => ({
|
|
7
|
+
listConversations: listConversationsMock,
|
|
8
|
+
searchHistory: searchHistoryMock,
|
|
9
|
+
readConversation: readConversationMock,
|
|
10
|
+
}),
|
|
11
|
+
}));
|
|
12
|
+
import { cursorListConversations } from '../cursor_list_conversations.js';
|
|
13
|
+
import { cursorSearchConversations } from '../cursor_search_conversations.js';
|
|
14
|
+
import { cursorReadConversation } from '../cursor_read_conversation.js';
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
listConversationsMock.mockReset();
|
|
17
|
+
searchHistoryMock.mockReset();
|
|
18
|
+
readConversationMock.mockReset();
|
|
19
|
+
});
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
vi.clearAllMocks();
|
|
22
|
+
});
|
|
23
|
+
describe('cursor history tools', () => {
|
|
24
|
+
test('cursor_list_conversations 返回摘要列表', async () => {
|
|
25
|
+
listConversationsMock.mockResolvedValue([
|
|
26
|
+
{ composerId: 'c1', name: '新需求', source: 'composerHeaders' },
|
|
27
|
+
]);
|
|
28
|
+
const result = await cursorListConversations({ title_query: '新需求', limit: 10 });
|
|
29
|
+
expect(result.isError).toBe(false);
|
|
30
|
+
expect('structuredContent' in result).toBe(true);
|
|
31
|
+
if (!('structuredContent' in result)) {
|
|
32
|
+
throw new Error('structuredContent 缺失');
|
|
33
|
+
}
|
|
34
|
+
expect(result.content[0].text).toContain('已获取 1 条 Cursor 会话摘要');
|
|
35
|
+
expect(result.structuredContent.count).toBe(1);
|
|
36
|
+
expect(listConversationsMock).toHaveBeenCalledWith({
|
|
37
|
+
titleQuery: '新需求',
|
|
38
|
+
workspaceQuery: '',
|
|
39
|
+
includeArchived: false,
|
|
40
|
+
limit: 10,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
test('cursor_search_conversations 缺少 query 时返回错误', async () => {
|
|
44
|
+
const result = await cursorSearchConversations({});
|
|
45
|
+
expect(result.isError).toBe(true);
|
|
46
|
+
expect(result.content[0].text).toContain('缺少必填参数: query');
|
|
47
|
+
});
|
|
48
|
+
test('cursor_search_conversations 返回命中结果', async () => {
|
|
49
|
+
searchHistoryMock.mockResolvedValue([
|
|
50
|
+
{ composerId: 'c1', conversationName: '新需求', bubbleId: 'b1', type: 1, text: '我们先聊需求' },
|
|
51
|
+
]);
|
|
52
|
+
const result = await cursorSearchConversations({ query: '需求', composer_id: 'c1', limit: 5 });
|
|
53
|
+
expect(result.isError).toBe(false);
|
|
54
|
+
expect('structuredContent' in result).toBe(true);
|
|
55
|
+
if (!('structuredContent' in result)) {
|
|
56
|
+
throw new Error('structuredContent 缺失');
|
|
57
|
+
}
|
|
58
|
+
expect(result.structuredContent.count).toBe(1);
|
|
59
|
+
expect(searchHistoryMock).toHaveBeenCalledWith({
|
|
60
|
+
query: '需求',
|
|
61
|
+
composerId: 'c1',
|
|
62
|
+
limit: 5,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
test('cursor_read_conversation 返回消息时间线', async () => {
|
|
66
|
+
readConversationMock.mockResolvedValue({
|
|
67
|
+
composerId: 'c1',
|
|
68
|
+
messages: [
|
|
69
|
+
{ bubbleId: 'b1', type: 1, text: '我们先聊需求' },
|
|
70
|
+
{ bubbleId: 'b2', type: 2, text: '听懂了' },
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
const result = await cursorReadConversation({ composer_id: 'c1', limit: 50, include_empty: true });
|
|
74
|
+
expect(result.isError).toBe(false);
|
|
75
|
+
expect('structuredContent' in result).toBe(true);
|
|
76
|
+
if (!('structuredContent' in result)) {
|
|
77
|
+
throw new Error('structuredContent 缺失');
|
|
78
|
+
}
|
|
79
|
+
expect(result.content[0].text).toContain('共 2 条消息');
|
|
80
|
+
expect(result.structuredContent.messageCount).toBe(2);
|
|
81
|
+
expect(readConversationMock).toHaveBeenCalledWith({
|
|
82
|
+
composerId: 'c1',
|
|
83
|
+
limit: 50,
|
|
84
|
+
includeEmpty: true,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
+
const upsertAssetMock = vi.fn();
|
|
3
|
+
const isEnabledMock = vi.fn();
|
|
4
|
+
vi.mock('../../lib/memory-client.js', () => ({
|
|
5
|
+
createMemoryClient: () => ({
|
|
6
|
+
isEnabled: isEnabledMock,
|
|
7
|
+
upsertAsset: upsertAssetMock,
|
|
8
|
+
}),
|
|
9
|
+
}));
|
|
10
|
+
import { memorizeAsset } from '../memorize_asset.js';
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
isEnabledMock.mockReset();
|
|
13
|
+
upsertAssetMock.mockReset();
|
|
14
|
+
});
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
vi.clearAllMocks();
|
|
17
|
+
});
|
|
18
|
+
describe('memorize_asset 单元测试', () => {
|
|
19
|
+
const validArgs = {
|
|
20
|
+
name: 'AppError',
|
|
21
|
+
description: '统一错误封装',
|
|
22
|
+
summary: '用于标准化应用错误处理',
|
|
23
|
+
content: 'export class AppError extends Error {}',
|
|
24
|
+
};
|
|
25
|
+
test('记忆服务未开启时返回跳过结果而不是报错', async () => {
|
|
26
|
+
isEnabledMock.mockReturnValue(false);
|
|
27
|
+
const result = await memorizeAsset(validArgs);
|
|
28
|
+
expect(result.isError).toBe(false);
|
|
29
|
+
expect('structuredContent' in result).toBe(true);
|
|
30
|
+
if (!('structuredContent' in result)) {
|
|
31
|
+
throw new Error('structuredContent 缺失');
|
|
32
|
+
}
|
|
33
|
+
expect(result.content[0].text).toContain('记忆服务未开启');
|
|
34
|
+
expect(result.structuredContent).toEqual({ enabled: false, stored: false });
|
|
35
|
+
expect(upsertAssetMock).not.toHaveBeenCalled();
|
|
36
|
+
});
|
|
37
|
+
test('记忆服务开启时写入资产', async () => {
|
|
38
|
+
isEnabledMock.mockReturnValue(true);
|
|
39
|
+
upsertAssetMock.mockResolvedValue({
|
|
40
|
+
id: 'asset-1',
|
|
41
|
+
name: 'AppError',
|
|
42
|
+
type: 'code',
|
|
43
|
+
description: '统一错误封装',
|
|
44
|
+
summary: '用于标准化应用错误处理',
|
|
45
|
+
content: 'export class AppError extends Error {}',
|
|
46
|
+
tags: [],
|
|
47
|
+
confidence: 0.7,
|
|
48
|
+
createdAt: '2026-01-01T00:00:00.000Z',
|
|
49
|
+
updatedAt: '2026-01-01T00:00:00.000Z',
|
|
50
|
+
});
|
|
51
|
+
const result = await memorizeAsset(validArgs);
|
|
52
|
+
expect(result.isError).toBe(false);
|
|
53
|
+
expect('structuredContent' in result).toBe(true);
|
|
54
|
+
if (!('structuredContent' in result)) {
|
|
55
|
+
throw new Error('structuredContent 缺失');
|
|
56
|
+
}
|
|
57
|
+
expect(result.content[0].text).toContain('已沉淀记忆资产: AppError');
|
|
58
|
+
expect(result.structuredContent.enabled).toBe(true);
|
|
59
|
+
expect(result.structuredContent.stored).toBe(true);
|
|
60
|
+
expect(upsertAssetMock).toHaveBeenCalledTimes(1);
|
|
61
|
+
expect(upsertAssetMock).toHaveBeenCalledWith(expect.objectContaining({
|
|
62
|
+
name: 'AppError',
|
|
63
|
+
description: '统一错误封装',
|
|
64
|
+
summary: '用于标准化应用错误处理',
|
|
65
|
+
content: 'export class AppError extends Error {}',
|
|
66
|
+
}));
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -44,5 +44,25 @@ export declare function codeInsight(args: any, context?: ToolExecutionContext):
|
|
|
44
44
|
text: string;
|
|
45
45
|
}[];
|
|
46
46
|
isError: boolean;
|
|
47
|
+
structuredContent: {
|
|
48
|
+
error_code: string;
|
|
49
|
+
rejected_project_root: string;
|
|
50
|
+
retry_hint: {
|
|
51
|
+
preferred: {
|
|
52
|
+
project_root: string;
|
|
53
|
+
path: string;
|
|
54
|
+
};
|
|
55
|
+
fallback: {
|
|
56
|
+
project_root: string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
} | {
|
|
61
|
+
content: {
|
|
62
|
+
type: string;
|
|
63
|
+
text: string;
|
|
64
|
+
}[];
|
|
65
|
+
isError: boolean;
|
|
66
|
+
structuredContent?: undefined;
|
|
47
67
|
}>;
|
|
48
68
|
export {};
|
|
@@ -5,6 +5,7 @@ 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
9
|
const ALLOWED_MODES = new Set(["auto", "query", "context", "impact"]);
|
|
9
10
|
const ALLOWED_DIRECTIONS = new Set(["upstream", "downstream"]);
|
|
10
11
|
const DEFAULT_AUTO_QUERY = "项目整体架构 核心流程 关键模块 依赖关系 入口点";
|
|
@@ -248,6 +249,20 @@ export async function codeInsight(args, context) {
|
|
|
248
249
|
const filePath = getString(parsedArgs.file_path);
|
|
249
250
|
const repo = getString(parsedArgs.repo);
|
|
250
251
|
const projectRoot = getString(parsedArgs.project_root);
|
|
252
|
+
if (isLikelyProjectNamedRelativePath(projectRoot)) {
|
|
253
|
+
return {
|
|
254
|
+
content: [{
|
|
255
|
+
type: "text",
|
|
256
|
+
text: `拒绝执行 code_insight:project_root 不能传带项目名的半相对路径,例如 ${projectRoot}。请改为传项目根目录绝对路径。`,
|
|
257
|
+
}],
|
|
258
|
+
isError: true,
|
|
259
|
+
structuredContent: {
|
|
260
|
+
error_code: "INVALID_PROJECT_ROOT",
|
|
261
|
+
rejected_project_root: projectRoot,
|
|
262
|
+
retry_hint: buildProjectRootRetryHint(projectRoot),
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
251
266
|
const docsDirName = getString(parsedArgs.docs_dir) || "docs";
|
|
252
267
|
const goal = getString(parsedArgs.goal);
|
|
253
268
|
const taskContext = getString(parsedArgs.task_context);
|
|
@@ -0,0 +1,35 @@
|
|
|
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 cursorListConversations(args) {
|
|
6
|
+
try {
|
|
7
|
+
const parsed = parseArgs(args, {
|
|
8
|
+
defaultValues: {
|
|
9
|
+
title_query: '',
|
|
10
|
+
workspace_query: '',
|
|
11
|
+
include_archived: false,
|
|
12
|
+
limit: 20,
|
|
13
|
+
},
|
|
14
|
+
fieldAliases: {
|
|
15
|
+
title_query: ['title', 'name_query', 'query'],
|
|
16
|
+
workspace_query: ['workspace', 'workspace_path'],
|
|
17
|
+
include_archived: ['archived'],
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
const client = createCursorHistoryClient();
|
|
21
|
+
const conversations = await client.listConversations({
|
|
22
|
+
titleQuery: getString(parsed.title_query),
|
|
23
|
+
workspaceQuery: getString(parsed.workspace_query),
|
|
24
|
+
includeArchived: getBoolean(parsed.include_archived, false),
|
|
25
|
+
limit: getNumber(parsed.limit, 20),
|
|
26
|
+
});
|
|
27
|
+
return okStructured(`已获取 ${conversations.length} 条 Cursor 会话摘要。`, {
|
|
28
|
+
count: conversations.length,
|
|
29
|
+
conversations,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return handleToolError(error, 'cursor_list_conversations');
|
|
34
|
+
}
|
|
35
|
+
}
|