apifox-workspace-mcp 1.2.0 → 2.0.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/dist/core/index.d.ts +0 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +0 -2
- package/dist/core/index.js.map +1 -1
- package/dist/server/handlers/error-handler.d.ts.map +1 -1
- package/dist/server/handlers/error-handler.js +27 -18
- package/dist/server/handlers/error-handler.js.map +1 -1
- package/dist/server/handlers/generate-artifacts.d.ts.map +1 -1
- package/dist/server/handlers/generate-artifacts.js +10 -2
- package/dist/server/handlers/generate-artifacts.js.map +1 -1
- package/dist/server/handlers/get-interface-detail.d.ts.map +1 -1
- package/dist/server/handlers/get-interface-detail.js +5 -1
- package/dist/server/handlers/get-interface-detail.js.map +1 -1
- package/dist/server/handlers/index.d.ts +0 -1
- package/dist/server/handlers/index.d.ts.map +1 -1
- package/dist/server/handlers/index.js +0 -1
- package/dist/server/handlers/index.js.map +1 -1
- package/dist/server/handlers/list-project-interfaces.d.ts.map +1 -1
- package/dist/server/handlers/list-project-interfaces.js +12 -6
- package/dist/server/handlers/list-project-interfaces.js.map +1 -1
- package/dist/server/handlers/list-projects.d.ts.map +1 -1
- package/dist/server/handlers/list-projects.js +9 -2
- package/dist/server/handlers/list-projects.js.map +1 -1
- package/dist/server/handlers/parse-and-add-project.d.ts.map +1 -1
- package/dist/server/handlers/parse-and-add-project.js +11 -3
- package/dist/server/handlers/parse-and-add-project.js.map +1 -1
- package/dist/server/handlers/query-interfaces.d.ts.map +1 -1
- package/dist/server/handlers/query-interfaces.js +15 -13
- package/dist/server/handlers/query-interfaces.js.map +1 -1
- package/dist/server/handlers/select-interfaces.d.ts +13 -1
- package/dist/server/handlers/select-interfaces.d.ts.map +1 -1
- package/dist/server/handlers/select-interfaces.js +13 -4
- package/dist/server/handlers/select-interfaces.js.map +1 -1
- package/dist/server/index.js +29 -43
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/__tests__/intent.test.d.ts +0 -2
- package/dist/__tests__/intent.test.d.ts.map +0 -1
- package/dist/__tests__/intent.test.js +0 -58
- package/dist/__tests__/intent.test.js.map +0 -1
- package/dist/core/intent.d.ts +0 -28
- package/dist/core/intent.d.ts.map +0 -1
- package/dist/core/intent.js +0 -307
- package/dist/core/intent.js.map +0 -1
- package/dist/server/handlers/assistant.d.ts +0 -20
- package/dist/server/handlers/assistant.d.ts.map +0 -1
- package/dist/server/handlers/assistant.js +0 -308
- package/dist/server/handlers/assistant.js.map +0 -1
package/dist/core/intent.js
DELETED
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
const GENERATE_KEYWORDS = ['生成', '导出', '输出', 'mock', '类型', '封装', '代码'];
|
|
2
|
-
const DETAIL_KEYWORDS = ['详情', '具体', '字段', '参数', '文档'];
|
|
3
|
-
const SEARCH_KEYWORDS = ['查询', '搜索', '找', '接口列表', '有哪些', '列出'];
|
|
4
|
-
const SELECT_KEYWORDS = ['选择', '勾选', '要这些', '要这些接口', '选中', '标记'];
|
|
5
|
-
export function parseIntent(promptRaw, context) {
|
|
6
|
-
// 移除 @apifox 前缀(如果存在)
|
|
7
|
-
const prompt = promptRaw
|
|
8
|
-
.trim()
|
|
9
|
-
.replace(/^@apifox\s+/i, '')
|
|
10
|
-
.trim();
|
|
11
|
-
if (!prompt) {
|
|
12
|
-
return { action: 'help' };
|
|
13
|
-
}
|
|
14
|
-
// 优先检测 URL(如果 prompt 中包含 URL)
|
|
15
|
-
const urlMatch = prompt.match(/https?:\/\/[^\s]+/);
|
|
16
|
-
if (urlMatch) {
|
|
17
|
-
const url = urlMatch[0];
|
|
18
|
-
// 检查是否是 Apifox 分享链接格式
|
|
19
|
-
const isApifoxUrl = /\/apidoc\/shared\//.test(url);
|
|
20
|
-
if (!isApifoxUrl) {
|
|
21
|
-
// 不是 Apifox 链接,返回错误提示
|
|
22
|
-
return {
|
|
23
|
-
action: 'unknown',
|
|
24
|
-
url,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
// 提取 shareId 和 interfaceId
|
|
28
|
-
const shareMatch = url.match(/\/apidoc\/shared\/([^\/]+)(?:\/api-([^\/]+))?/);
|
|
29
|
-
if (shareMatch) {
|
|
30
|
-
const shareId = shareMatch[1];
|
|
31
|
-
const interfaceId = shareMatch[2];
|
|
32
|
-
// 如果包含接口ID,识别为获取接口详情
|
|
33
|
-
if (interfaceId) {
|
|
34
|
-
return {
|
|
35
|
-
action: 'getInterfaceDetail',
|
|
36
|
-
interfaceId,
|
|
37
|
-
shareId,
|
|
38
|
-
url,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
// 否则是项目整体链接,列出所有接口
|
|
42
|
-
return {
|
|
43
|
-
action: 'listProjectInterfaces',
|
|
44
|
-
shareId,
|
|
45
|
-
url,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
// Detect select interfaces (natural language selection)
|
|
50
|
-
if (SELECT_KEYWORDS.some((kw) => prompt.includes(kw))) {
|
|
51
|
-
const criteria = parseSelectionCriteria(prompt, context?.lastInterfaceListNames);
|
|
52
|
-
if (criteria) {
|
|
53
|
-
return { action: 'selectInterfaces', selectionCriteria: criteria };
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
// Detect generate artifacts
|
|
57
|
-
// 检查是否包含生成关键词
|
|
58
|
-
const hasGenerateKeyword = GENERATE_KEYWORDS.some((kw) => prompt.includes(kw));
|
|
59
|
-
// 检查是否包含类型相关关键词
|
|
60
|
-
const hasTypeKeyword = prompt.includes('类型') ||
|
|
61
|
-
prompt.toLowerCase().includes('type') ||
|
|
62
|
-
prompt.includes('mock') ||
|
|
63
|
-
prompt.toLowerCase().includes('mock') ||
|
|
64
|
-
prompt.includes('封装') ||
|
|
65
|
-
prompt.toLowerCase().includes('request') ||
|
|
66
|
-
prompt.includes('测试') ||
|
|
67
|
-
prompt.toLowerCase().includes('test');
|
|
68
|
-
if (hasGenerateKeyword && hasTypeKeyword) {
|
|
69
|
-
const type = detectArtifactType(prompt);
|
|
70
|
-
// 尝试提取多个接口 ID(如"给我2386 和 2392的接口类型")
|
|
71
|
-
const interfaceIds = extractMultipleInterfaceIds(prompt);
|
|
72
|
-
return {
|
|
73
|
-
action: 'generateArtifacts',
|
|
74
|
-
artifactType: type,
|
|
75
|
-
targetName: extractInterfaceName(prompt, context?.lastInterfaceListNames),
|
|
76
|
-
interfaceIds: interfaceIds.length > 0 ? interfaceIds : undefined,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
// Detect get detail by ID or name
|
|
80
|
-
// 先检查是否有接口ID(api-xxx格式),优先级更高
|
|
81
|
-
const interfaceId = extractInterfaceId(prompt);
|
|
82
|
-
if (interfaceId) {
|
|
83
|
-
return {
|
|
84
|
-
action: 'getInterfaceDetail',
|
|
85
|
-
interfaceId,
|
|
86
|
-
targetName: undefined,
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
if (DETAIL_KEYWORDS.some((kw) => prompt.includes(kw))) {
|
|
90
|
-
return {
|
|
91
|
-
action: 'getInterfaceDetail',
|
|
92
|
-
interfaceId: undefined,
|
|
93
|
-
targetName: extractInterfaceName(prompt, context?.lastInterfaceListNames),
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
// 检测接口数量查询(如"几个接口"、"接口数量"、"接口总数")
|
|
97
|
-
const countKeywords = [
|
|
98
|
-
'几个接口',
|
|
99
|
-
'接口数量',
|
|
100
|
-
'接口总数',
|
|
101
|
-
'有多少接口',
|
|
102
|
-
'接口个数',
|
|
103
|
-
'共几个接口',
|
|
104
|
-
'一共几个接口',
|
|
105
|
-
];
|
|
106
|
-
const hasCountKeyword = countKeywords.some((kw) => prompt.includes(kw));
|
|
107
|
-
// 放宽项目上下文检查:如果有上下文项目信息,也认为有项目上下文
|
|
108
|
-
const hasProjectContext = prompt.includes('这个项目') ||
|
|
109
|
-
prompt.includes('当前项目') ||
|
|
110
|
-
prompt.includes('项目') ||
|
|
111
|
-
!!context?.lastProjectName;
|
|
112
|
-
// 检测"列出所有接口"或"查看所有接口"(优先级最高,在搜索之前)
|
|
113
|
-
// 使用更灵活的匹配,支持"我想查看所有接口信息"等表达
|
|
114
|
-
const listInterfacesPatterns = [
|
|
115
|
-
/列出所有接口/i,
|
|
116
|
-
/显示所有接口/i,
|
|
117
|
-
/查看所有接口/i,
|
|
118
|
-
/所有接口信息/i,
|
|
119
|
-
/查看所有接口信息/i,
|
|
120
|
-
/显示接口列表/i,
|
|
121
|
-
/(?:我想|我要|帮我).*查看.*所有接口/i,
|
|
122
|
-
/(?:我想|我要|帮我).*列出.*所有接口/i,
|
|
123
|
-
/(?:我想|我要|帮我).*显示.*所有接口/i,
|
|
124
|
-
/(?:我想|我要|帮我).*所有接口.*信息/i, // 匹配"我想查看所有接口信息"
|
|
125
|
-
/查看.*所有接口.*信息/i, // 匹配"查看所有接口信息"
|
|
126
|
-
];
|
|
127
|
-
// 也检查简单的关键词匹配(向后兼容)
|
|
128
|
-
const listInterfacesKeywords = ['所有接口', '全部接口', '接口列表'];
|
|
129
|
-
// 先检查正则表达式(更精确)
|
|
130
|
-
if (listInterfacesPatterns.some((pattern) => pattern.test(prompt))) {
|
|
131
|
-
return {
|
|
132
|
-
action: 'listProjectInterfaces',
|
|
133
|
-
projectName: context?.lastProjectName,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
// 再检查关键词(但排除包含"查询"、"搜索"的情况,避免误判)
|
|
137
|
-
if (listInterfacesKeywords.some((kw) => prompt.includes(kw)) &&
|
|
138
|
-
!SEARCH_KEYWORDS.some((kw) => prompt.includes(kw))) {
|
|
139
|
-
return {
|
|
140
|
-
action: 'listProjectInterfaces',
|
|
141
|
-
projectName: context?.lastProjectName,
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
if (hasCountKeyword && hasProjectContext) {
|
|
145
|
-
// 查询项目接口数量,使用专门的 countInterfaces 动作
|
|
146
|
-
return {
|
|
147
|
-
action: 'countInterfaces',
|
|
148
|
-
projectName: context?.lastProjectName,
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
// Default search/list(在列出所有接口之后)
|
|
152
|
-
if (SEARCH_KEYWORDS.some((kw) => prompt.includes(kw)) || prompt.startsWith('接口')) {
|
|
153
|
-
return {
|
|
154
|
-
action: 'searchInterfaces',
|
|
155
|
-
keyword: extractKeyword(prompt),
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
// 检测"列出项目"(明确要求列出所有项目)
|
|
159
|
-
const listProjectKeywords = ['列出项目', '所有项目', '项目列表', '有哪些项目', '项目有哪些'];
|
|
160
|
-
if (listProjectKeywords.some((kw) => prompt.includes(kw))) {
|
|
161
|
-
return { action: 'listProjects' };
|
|
162
|
-
}
|
|
163
|
-
// 如果只是提到"项目"但没有其他上下文,且没有接口相关关键词,才列出项目
|
|
164
|
-
if (prompt.includes('项目') && !prompt.includes('接口') && !hasCountKeyword) {
|
|
165
|
-
return { action: 'listProjects' };
|
|
166
|
-
}
|
|
167
|
-
// 检测版本查询
|
|
168
|
-
const versionKeywords = ['版本', 'version', '版本号', '当前版本', '什么版本'];
|
|
169
|
-
if (versionKeywords.some((kw) => prompt.toLowerCase().includes(kw.toLowerCase()))) {
|
|
170
|
-
return { action: 'getVersion' };
|
|
171
|
-
}
|
|
172
|
-
return { action: 'unknown' };
|
|
173
|
-
}
|
|
174
|
-
function detectArtifactType(prompt) {
|
|
175
|
-
if (prompt.includes('mock')) {
|
|
176
|
-
return 'mock_data';
|
|
177
|
-
}
|
|
178
|
-
if (prompt.includes('封装') || prompt.toLowerCase().includes('request')) {
|
|
179
|
-
return 'request_wrappers';
|
|
180
|
-
}
|
|
181
|
-
if (prompt.includes('测试')) {
|
|
182
|
-
return 'test_scripts';
|
|
183
|
-
}
|
|
184
|
-
return 'ts_types';
|
|
185
|
-
}
|
|
186
|
-
function extractInterfaceId(prompt) {
|
|
187
|
-
// 匹配 api-12345 或 接口12345 或 12345 格式
|
|
188
|
-
const match = prompt.match(/(?:api-|接口)?(\d{4,})/);
|
|
189
|
-
return match ? match[1] : undefined;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* 提取多个接口 ID(如"给我2386 和 2392的接口类型")
|
|
193
|
-
*/
|
|
194
|
-
function extractMultipleInterfaceIds(prompt) {
|
|
195
|
-
// 匹配所有4位或以上的数字(接口 ID 通常是4位以上)
|
|
196
|
-
// 排除明显不是接口 ID 的数字(如年份、版本号等)
|
|
197
|
-
const matches = prompt.matchAll(/\b(\d{4,})\b/g);
|
|
198
|
-
const ids = [];
|
|
199
|
-
for (const match of matches) {
|
|
200
|
-
const id = match[1];
|
|
201
|
-
// 排除一些明显不是接口 ID 的数字
|
|
202
|
-
// 例如:年份(2020-2099)、版本号(如 2.28)、过长的数字(可能是其他标识符)
|
|
203
|
-
if (id.length >= 4 && id.length <= 6) {
|
|
204
|
-
// 接口 ID 通常在 4-6 位之间
|
|
205
|
-
ids.push(id);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return ids;
|
|
209
|
-
}
|
|
210
|
-
function extractKeyword(prompt) {
|
|
211
|
-
const trimmed = prompt
|
|
212
|
-
.replace(/\/?apifox/gi, '')
|
|
213
|
-
.replace(/接口列表|有哪些|搜索|查询|找|帮我|一下/g, '')
|
|
214
|
-
.trim();
|
|
215
|
-
return trimmed || undefined;
|
|
216
|
-
}
|
|
217
|
-
function extractInterfaceName(prompt, candidates) {
|
|
218
|
-
if (!candidates || candidates.length === 0) {
|
|
219
|
-
return undefined;
|
|
220
|
-
}
|
|
221
|
-
return (candidates.find((name) => prompt.includes(name)) ||
|
|
222
|
-
candidates.find((name) => prompt.toLowerCase().includes(name.toLowerCase())));
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* 解析选择条件
|
|
226
|
-
* 支持多种表达方式:
|
|
227
|
-
* - 编号:1, 3, 5 或 1-5 或 1,3,5-10
|
|
228
|
-
* - 关键词:包含"支付"和"退款"的接口
|
|
229
|
-
* - 名称:选择"退款接口"和"支付接口"
|
|
230
|
-
*/
|
|
231
|
-
function parseSelectionCriteria(prompt, candidates) {
|
|
232
|
-
const criteria = {};
|
|
233
|
-
// 1. 解析编号选择(如:1, 3, 5 或 1-5 或 1,3,5-10)
|
|
234
|
-
const numberPattern = /(\d+)(?:-(\d+))?/g;
|
|
235
|
-
const numberMatches = Array.from(prompt.matchAll(numberPattern));
|
|
236
|
-
if (numberMatches.length > 0) {
|
|
237
|
-
const indices = [];
|
|
238
|
-
const ranges = [];
|
|
239
|
-
for (const match of numberMatches) {
|
|
240
|
-
const start = parseInt(match[1], 10);
|
|
241
|
-
const end = match[2] ? parseInt(match[2], 10) : null;
|
|
242
|
-
if (end !== null) {
|
|
243
|
-
// 范围选择
|
|
244
|
-
ranges.push({ start, end: Math.max(start, end) });
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
// 单个编号
|
|
248
|
-
indices.push(start);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
if (indices.length > 0) {
|
|
252
|
-
criteria.indices = indices;
|
|
253
|
-
}
|
|
254
|
-
if (ranges.length > 0) {
|
|
255
|
-
criteria.ranges = ranges;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
// 2. 解析关键词选择(如:包含"支付"和"退款")
|
|
259
|
-
const keywordPatterns = [
|
|
260
|
-
/包含["']?([^"']+)["']?/g,
|
|
261
|
-
/["']([^"']+)["']/g,
|
|
262
|
-
/(?:包含|选择|要)(?:.*?)(?:和|与|、)(.*?)(?:的|接口)/g,
|
|
263
|
-
];
|
|
264
|
-
const keywords = [];
|
|
265
|
-
for (const pattern of keywordPatterns) {
|
|
266
|
-
const matches = Array.from(prompt.matchAll(pattern));
|
|
267
|
-
for (const match of matches) {
|
|
268
|
-
const keyword = match[1]?.trim();
|
|
269
|
-
if (keyword && keyword.length > 1 && !keyword.match(/^\d+$/)) {
|
|
270
|
-
keywords.push(keyword);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
// 如果没有通过模式匹配到,尝试提取引号内的内容
|
|
275
|
-
if (keywords.length === 0) {
|
|
276
|
-
const quotedMatches = prompt.match(/["']([^"']+)["']/g);
|
|
277
|
-
if (quotedMatches) {
|
|
278
|
-
for (const quoted of quotedMatches) {
|
|
279
|
-
const keyword = quoted.replace(/["']/g, '').trim();
|
|
280
|
-
if (keyword.length > 1) {
|
|
281
|
-
keywords.push(keyword);
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
if (keywords.length > 0) {
|
|
287
|
-
criteria.keywords = keywords;
|
|
288
|
-
}
|
|
289
|
-
// 3. 解析接口名称选择(从候选列表中匹配)
|
|
290
|
-
if (candidates && candidates.length > 0) {
|
|
291
|
-
const names = [];
|
|
292
|
-
for (const candidate of candidates) {
|
|
293
|
-
if (prompt.includes(candidate) || prompt.toLowerCase().includes(candidate.toLowerCase())) {
|
|
294
|
-
names.push(candidate);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
if (names.length > 0) {
|
|
298
|
-
criteria.names = names;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
// 如果没有任何选择条件,返回 null
|
|
302
|
-
if (Object.keys(criteria).length === 0) {
|
|
303
|
-
return null;
|
|
304
|
-
}
|
|
305
|
-
return criteria;
|
|
306
|
-
}
|
|
307
|
-
//# sourceMappingURL=intent.js.map
|
package/dist/core/intent.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/core/intent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { ConfigManager, McpBridge, ContextStore } from '../../core/index.js';
|
|
2
|
-
export interface AssistantArgs {
|
|
3
|
-
prompt: string;
|
|
4
|
-
}
|
|
5
|
-
export interface AssistantContext {
|
|
6
|
-
projectRoot: string;
|
|
7
|
-
configManager: ConfigManager;
|
|
8
|
-
mcpBridge: McpBridge;
|
|
9
|
-
contextStore: ContextStore;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* 处理自然语言助手请求
|
|
13
|
-
*/
|
|
14
|
-
export declare function handleAssistant(args: AssistantArgs, ctx: AssistantContext): Promise<{
|
|
15
|
-
content: {
|
|
16
|
-
type: string;
|
|
17
|
-
text: string;
|
|
18
|
-
}[];
|
|
19
|
-
}>;
|
|
20
|
-
//# sourceMappingURL=assistant.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/assistant.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,SAAS,EACT,YAAY,EAIb,MAAM,qBAAqB,CAAC;AAsD7B,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,gBAAgB;;;;;GAuV/E"}
|
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { parseIntent, UnifiedCacheManager, } from '../../core/index.js';
|
|
2
|
-
import { readFileSync } from 'fs';
|
|
3
|
-
import { join } from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import { dirname } from 'path';
|
|
6
|
-
import { handleListProjects } from './list-projects.js';
|
|
7
|
-
import { handleListProjectInterfaces } from './list-project-interfaces.js';
|
|
8
|
-
import { handleQueryInterfaces } from './query-interfaces.js';
|
|
9
|
-
import { handleGetInterfaceDetail } from './get-interface-detail.js';
|
|
10
|
-
import { handleGenerateArtifacts } from './generate-artifacts.js';
|
|
11
|
-
import { handleSelectInterfaces } from './select-interfaces.js';
|
|
12
|
-
import { buildTextResponse, resolveProjectInfo } from './utils.js';
|
|
13
|
-
import { findProjectRoot } from '../../lib/project-root.js';
|
|
14
|
-
// 用于智能推断的关键词常量
|
|
15
|
-
const GENERATE_KEYWORDS = ['生成', '导出', '输出', 'mock', '类型', '封装', '代码'];
|
|
16
|
-
/**
|
|
17
|
-
* 检测产物类型
|
|
18
|
-
*/
|
|
19
|
-
function detectArtifactType(prompt) {
|
|
20
|
-
if (prompt.includes('mock')) {
|
|
21
|
-
return 'mock_data';
|
|
22
|
-
}
|
|
23
|
-
if (prompt.includes('封装') || prompt.toLowerCase().includes('request')) {
|
|
24
|
-
return 'request_wrappers';
|
|
25
|
-
}
|
|
26
|
-
if (prompt.includes('测试')) {
|
|
27
|
-
return 'test_scripts';
|
|
28
|
-
}
|
|
29
|
-
return 'ts_types';
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* 从 prompt 中提取搜索关键词
|
|
33
|
-
*/
|
|
34
|
-
function extractSearchKeyword(prompt) {
|
|
35
|
-
// 移除常见的查询关键词
|
|
36
|
-
const cleaned = prompt.replace(/查询|搜索|找|帮我|一下|接口/g, '').trim();
|
|
37
|
-
return cleaned || undefined || '';
|
|
38
|
-
}
|
|
39
|
-
import { handleMissingProjectError, handleMissingInterfaceError, handleCacheNotFoundError, } from './error-handler.js';
|
|
40
|
-
// 获取项目根目录(MCP Server 的根目录)
|
|
41
|
-
// 从当前文件位置向上查找,直到找到包含 package.json 的目录
|
|
42
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
43
|
-
const __dirname = dirname(__filename);
|
|
44
|
-
// 从 dist/server/handlers 向上查找项目根目录
|
|
45
|
-
const serverRoot = findProjectRoot(__dirname);
|
|
46
|
-
/**
|
|
47
|
-
* 处理自然语言助手请求
|
|
48
|
-
*/
|
|
49
|
-
export async function handleAssistant(args, ctx) {
|
|
50
|
-
const { projectRoot, configManager, mcpBridge, contextStore } = ctx;
|
|
51
|
-
const lastProject = contextStore.getLastProject();
|
|
52
|
-
const lastList = contextStore.getLastInterfaceList();
|
|
53
|
-
const intent = parseIntent(args.prompt, {
|
|
54
|
-
lastProjectName: lastProject?.projectName,
|
|
55
|
-
lastInterfaceListNames: lastList?.list.map((item) => item.name),
|
|
56
|
-
});
|
|
57
|
-
switch (intent.action) {
|
|
58
|
-
case 'listProjects':
|
|
59
|
-
return handleListProjects(projectRoot);
|
|
60
|
-
case 'countInterfaces': {
|
|
61
|
-
// 查询接口数量
|
|
62
|
-
let targetProjectName = intent.projectName || lastProject?.projectName;
|
|
63
|
-
let targetProjectId = intent.projectId || lastProject?.projectId;
|
|
64
|
-
// 如果还没有项目信息,尝试从缓存中查找
|
|
65
|
-
if (!targetProjectId && !targetProjectName) {
|
|
66
|
-
const cacheManager = new UnifiedCacheManager(projectRoot);
|
|
67
|
-
const projects = cacheManager.listProjects();
|
|
68
|
-
if (projects.length === 1) {
|
|
69
|
-
// 如果只有一个项目,使用它
|
|
70
|
-
targetProjectName = projects[0].name;
|
|
71
|
-
targetProjectId = projects[0].id;
|
|
72
|
-
}
|
|
73
|
-
else if (projects.length > 1 && lastProject) {
|
|
74
|
-
// 如果有多个项目,但上下文中有项目信息,使用上下文的
|
|
75
|
-
targetProjectName = lastProject.projectName;
|
|
76
|
-
targetProjectId = lastProject.projectId;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (!targetProjectId && !targetProjectName) {
|
|
80
|
-
return buildTextResponse('无法确定项目信息。\n\n你可以:\n1. 提供项目 URL:直接粘贴项目的分享链接\n2. 或者先查询接口列表:说"列出所有接口"');
|
|
81
|
-
}
|
|
82
|
-
const cacheManager = new UnifiedCacheManager(projectRoot);
|
|
83
|
-
const projectInfo = resolveProjectInfo(projectRoot, contextStore, targetProjectName, targetProjectId);
|
|
84
|
-
if (!projectInfo || !projectInfo.projectId) {
|
|
85
|
-
return handleMissingProjectError({
|
|
86
|
-
lastProject,
|
|
87
|
-
projectRoot,
|
|
88
|
-
contextStore,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
const cachedProject = cacheManager.findProjectById(projectInfo.projectId);
|
|
92
|
-
if (!cachedProject) {
|
|
93
|
-
return handleCacheNotFoundError(projectInfo.projectName || projectInfo.projectId, {
|
|
94
|
-
lastProject,
|
|
95
|
-
projectRoot,
|
|
96
|
-
contextStore,
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
const interfaceCount = cachedProject.interfaces.length;
|
|
100
|
-
return buildTextResponse(`**项目名称**: ${cachedProject.projectName}\n**项目 ID**: ${projectInfo.projectId}\n**接口数量**: ${interfaceCount} 个`);
|
|
101
|
-
}
|
|
102
|
-
case 'listProjectInterfaces':
|
|
103
|
-
// 如果 intent 中没有指定项目,但上下文中有,使用上下文中的项目
|
|
104
|
-
const targetProjectName = intent.projectName || lastProject?.projectName;
|
|
105
|
-
const targetProjectId = intent.projectId || lastProject?.projectId;
|
|
106
|
-
return handleListProjectInterfaces({
|
|
107
|
-
shareId: intent.shareId,
|
|
108
|
-
url: intent.url,
|
|
109
|
-
projectName: targetProjectName,
|
|
110
|
-
projectId: targetProjectId,
|
|
111
|
-
}, { projectRoot, configManager, mcpBridge, contextStore });
|
|
112
|
-
case 'searchInterfaces':
|
|
113
|
-
return handleQueryInterfaces({
|
|
114
|
-
projectName: intent.projectName ?? lastProject?.projectName,
|
|
115
|
-
keyword: intent.keyword,
|
|
116
|
-
}, { projectRoot, configManager, mcpBridge, contextStore });
|
|
117
|
-
case 'getInterfaceDetail': {
|
|
118
|
-
let targetId = intent.interfaceId;
|
|
119
|
-
if (!targetId && intent.targetName && lastList) {
|
|
120
|
-
const match = lastList.list.find((item) => item.name.toLowerCase().includes(intent.targetName.toLowerCase()));
|
|
121
|
-
targetId = match?.id;
|
|
122
|
-
}
|
|
123
|
-
if (!targetId) {
|
|
124
|
-
return handleMissingInterfaceError({
|
|
125
|
-
lastProject,
|
|
126
|
-
projectRoot,
|
|
127
|
-
contextStore,
|
|
128
|
-
}, intent.targetName);
|
|
129
|
-
}
|
|
130
|
-
return handleGetInterfaceDetail({
|
|
131
|
-
projectName: intent.projectName ?? lastProject?.projectName,
|
|
132
|
-
projectId: intent.projectId,
|
|
133
|
-
shareId: intent.shareId,
|
|
134
|
-
interfaceId: targetId,
|
|
135
|
-
url: intent.url,
|
|
136
|
-
}, { projectRoot, configManager, mcpBridge, contextStore });
|
|
137
|
-
}
|
|
138
|
-
case 'generateArtifacts': {
|
|
139
|
-
const preselected = [];
|
|
140
|
-
// 优先使用从 prompt 中提取的接口 ID
|
|
141
|
-
if (intent.interfaceIds && intent.interfaceIds.length > 0) {
|
|
142
|
-
preselected.push(...intent.interfaceIds);
|
|
143
|
-
}
|
|
144
|
-
// 如果没有提取到 ID,尝试从接口名称匹配
|
|
145
|
-
if (preselected.length === 0 && intent.targetName && lastList) {
|
|
146
|
-
const match = lastList.list.find((item) => item.name.toLowerCase().includes(intent.targetName.toLowerCase()));
|
|
147
|
-
if (match) {
|
|
148
|
-
preselected.push(match.id);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
return handleGenerateArtifacts({
|
|
152
|
-
projectName: intent.projectName ?? lastProject?.projectName,
|
|
153
|
-
interfaceIds: preselected.length > 0 ? preselected : undefined,
|
|
154
|
-
artifactType: intent.artifactType ?? 'ts_types',
|
|
155
|
-
}, { projectRoot, configManager, mcpBridge, contextStore });
|
|
156
|
-
}
|
|
157
|
-
case 'selectInterfaces':
|
|
158
|
-
return handleSelectInterfaces({
|
|
159
|
-
projectName: intent.projectName ?? lastProject?.projectName,
|
|
160
|
-
selectionCriteria: intent.selectionCriteria,
|
|
161
|
-
}, { projectRoot, configManager, contextStore });
|
|
162
|
-
case 'getVersion': {
|
|
163
|
-
// 读取 package.json 中的版本信息
|
|
164
|
-
try {
|
|
165
|
-
const packageJsonPath = join(serverRoot, 'package.json');
|
|
166
|
-
const packageJsonContent = readFileSync(packageJsonPath, 'utf-8');
|
|
167
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
168
|
-
const version = packageJson.version || 'unknown';
|
|
169
|
-
return buildTextResponse(`当前 Apifox Workspace MCP Server 版本: **${version}**`);
|
|
170
|
-
}
|
|
171
|
-
catch (error) {
|
|
172
|
-
return buildTextResponse(`无法获取版本信息: ${error instanceof Error ? error.message : String(error)}`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
case 'help':
|
|
176
|
-
return buildTextResponse('我可以帮你:\n\n' +
|
|
177
|
-
'1. 搜索接口:说"查询支付接口"或"搜索退款"(支持关键词搜索)\n' +
|
|
178
|
-
'2. 查看接口详情:提供接口的分享链接,或从查询结果中选择接口\n' +
|
|
179
|
-
'3. 生成接口类型:查询接口后选择,然后说"生成这些接口的类型"\n' +
|
|
180
|
-
'4. 列出所有接口:说"列出所有接口"或"显示接口列表"');
|
|
181
|
-
case 'unknown':
|
|
182
|
-
default: {
|
|
183
|
-
// 检查是否是无效的 URL
|
|
184
|
-
if (intent.url && !intent.url.includes('/apidoc/shared/')) {
|
|
185
|
-
return buildTextResponse(`❌ 检测到非 Apifox 链接: ${intent.url}\n\n请提供有效的 Apifox 分享链接。`);
|
|
186
|
-
}
|
|
187
|
-
// 智能推断用户意图并尝试处理
|
|
188
|
-
const prompt = args.prompt.trim();
|
|
189
|
-
// 1. 检查是否包含生成关键词 + 路径模式(如"生成/api/xxx的类型")
|
|
190
|
-
const hasGenerateKeyword = GENERATE_KEYWORDS.some((kw) => prompt.includes(kw));
|
|
191
|
-
const hasTypeKeyword = prompt.includes('类型') ||
|
|
192
|
-
prompt.toLowerCase().includes('type') ||
|
|
193
|
-
prompt.includes('mock') ||
|
|
194
|
-
prompt.includes('封装') ||
|
|
195
|
-
prompt.includes('测试');
|
|
196
|
-
// 检测路径模式(如 /api/xxx 或 api/xxx)
|
|
197
|
-
const pathPattern = /\/?api\/[^\s"']+/i;
|
|
198
|
-
const pathMatch = prompt.match(pathPattern);
|
|
199
|
-
if (hasGenerateKeyword && hasTypeKeyword && pathMatch) {
|
|
200
|
-
// 用户想要生成某个路径的接口类型
|
|
201
|
-
const path = pathMatch[0].replace(/^\/?/, '/'); // 确保以 / 开头
|
|
202
|
-
if (lastProject?.projectName || lastProject?.projectId) {
|
|
203
|
-
// 先搜索该路径的接口
|
|
204
|
-
const searchResult = await handleQueryInterfaces({
|
|
205
|
-
projectName: lastProject.projectName,
|
|
206
|
-
projectId: lastProject.projectId,
|
|
207
|
-
keyword: path,
|
|
208
|
-
}, { projectRoot, configManager, mcpBridge, contextStore });
|
|
209
|
-
// 如果搜索到接口,尝试自动生成
|
|
210
|
-
if (searchResult.content && Array.isArray(searchResult.content)) {
|
|
211
|
-
const textContent = searchResult.content[0];
|
|
212
|
-
if (textContent.type === 'text' && textContent.text.includes('找到')) {
|
|
213
|
-
// 提取第一个接口 ID(从搜索结果中)
|
|
214
|
-
const lastList = contextStore.getLastInterfaceList();
|
|
215
|
-
if (lastList && lastList.list.length > 0) {
|
|
216
|
-
const firstInterface = lastList.list[0];
|
|
217
|
-
// 自动生成第一个匹配接口的类型
|
|
218
|
-
return handleGenerateArtifacts({
|
|
219
|
-
projectName: lastProject.projectName,
|
|
220
|
-
projectId: lastProject.projectId,
|
|
221
|
-
interfaceIds: [firstInterface.id],
|
|
222
|
-
artifactType: detectArtifactType(prompt),
|
|
223
|
-
}, { projectRoot, configManager, mcpBridge, contextStore });
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
// 如果搜索失败,返回搜索结果让用户选择
|
|
228
|
-
return searchResult;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
// 2. 如果上下文中有项目信息,尝试推断用户意图并处理
|
|
232
|
-
if (lastProject?.projectName || lastProject?.projectId) {
|
|
233
|
-
// 先检查是否是"查看所有接口"的变体表达
|
|
234
|
-
const listAllPatterns = [
|
|
235
|
-
/(?:我想|我要|帮我).*查看.*所有接口/i,
|
|
236
|
-
/(?:我想|我要|帮我).*列出.*所有接口/i,
|
|
237
|
-
/(?:我想|我要|帮我).*显示.*所有接口/i,
|
|
238
|
-
/(?:我想|我要|帮我).*所有接口.*信息/i,
|
|
239
|
-
];
|
|
240
|
-
if (listAllPatterns.some((pattern) => pattern.test(prompt))) {
|
|
241
|
-
// 识别为列出所有接口
|
|
242
|
-
return handleListProjectInterfaces({
|
|
243
|
-
projectName: lastProject.projectName,
|
|
244
|
-
projectId: lastProject.projectId,
|
|
245
|
-
}, { projectRoot, configManager, mcpBridge, contextStore });
|
|
246
|
-
}
|
|
247
|
-
// 尝试作为接口查询处理
|
|
248
|
-
return handleQueryInterfaces({
|
|
249
|
-
projectName: lastProject.projectName,
|
|
250
|
-
projectId: lastProject.projectId,
|
|
251
|
-
keyword: prompt,
|
|
252
|
-
}, { projectRoot, configManager, mcpBridge, contextStore });
|
|
253
|
-
}
|
|
254
|
-
// 3. 没有匹配到预置意图,返回结构化提示让 agent 自行调用工具
|
|
255
|
-
// 分析用户请求,提供针对性的工具调用建议
|
|
256
|
-
const promptLower = prompt.toLowerCase();
|
|
257
|
-
let toolSuggestions = '';
|
|
258
|
-
// 分析用户意图,提供针对性的建议
|
|
259
|
-
if (promptLower.includes('生成') ||
|
|
260
|
-
promptLower.includes('类型') ||
|
|
261
|
-
promptLower.includes('mock')) {
|
|
262
|
-
// 用户想要生成代码
|
|
263
|
-
toolSuggestions =
|
|
264
|
-
`**检测到您想要生成代码,建议操作流程:**\n` +
|
|
265
|
-
`1. 如果请求中包含接口路径(如 /api/xxx),请先调用 \`query_interfaces\` 工具搜索接口\n` +
|
|
266
|
-
` - 参数:keyword: "${prompt.match(/\/?api\/[^\s"']+/i)?.[0] || '从请求中提取的路径'}"\n` +
|
|
267
|
-
`2. 从搜索结果中获取 interfaceId,然后调用 \`generate_artifacts\` 工具生成类型\n` +
|
|
268
|
-
` - 参数:interfaceIds: ["从查询结果中获取"], artifactType: "ts_types"\n` +
|
|
269
|
-
`3. 或者,如果用户提供了完整的 Apifox 接口 URL,可以直接调用 \`parse_and_add_project\` 然后 \`get_interface_detail\`\n\n`;
|
|
270
|
-
}
|
|
271
|
-
else if (promptLower.includes('查询') ||
|
|
272
|
-
promptLower.includes('搜索') ||
|
|
273
|
-
promptLower.includes('找')) {
|
|
274
|
-
// 用户想要查询接口
|
|
275
|
-
toolSuggestions =
|
|
276
|
-
`**检测到您想要查询接口,建议操作:**\n` +
|
|
277
|
-
`1. 调用 \`query_interfaces\` 工具搜索接口\n` +
|
|
278
|
-
` - 参数:keyword: "${extractSearchKeyword(prompt)}"\n` +
|
|
279
|
-
`2. 如果找到接口,可以进一步调用 \`get_interface_detail\` 查看详情\n\n`;
|
|
280
|
-
}
|
|
281
|
-
else if (promptLower.includes('详情') || promptLower.includes('具体')) {
|
|
282
|
-
// 用户想要查看详情
|
|
283
|
-
toolSuggestions =
|
|
284
|
-
`**检测到您想要查看接口详情,建议操作:**\n` +
|
|
285
|
-
`1. 如果知道接口 ID,直接调用 \`get_interface_detail\`\n` +
|
|
286
|
-
`2. 如果不知道接口 ID,先调用 \`query_interfaces\` 搜索,然后调用 \`get_interface_detail\`\n\n`;
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
// 通用建议
|
|
290
|
-
toolSuggestions =
|
|
291
|
-
`**可用工具:**\n` +
|
|
292
|
-
`- \`query_interfaces\` - 查询接口(支持关键词、路径搜索)\n` +
|
|
293
|
-
`- \`get_interface_detail\` - 获取接口详情(需要 projectName 和 interfaceId)\n` +
|
|
294
|
-
`- \`generate_artifacts\` - 生成接口类型/Mock/封装(需要 interfaceIds)\n` +
|
|
295
|
-
`- \`list_projects\` - 列出所有项目\n` +
|
|
296
|
-
`- \`parse_and_add_project\` - 添加项目(需要 Apifox 分享链接)\n\n`;
|
|
297
|
-
}
|
|
298
|
-
return buildTextResponse(`**用户请求:** ${args.prompt}\n\n` +
|
|
299
|
-
toolSuggestions +
|
|
300
|
-
`**上下文信息:**\n` +
|
|
301
|
-
(lastProject
|
|
302
|
-
? `- 当前项目:${lastProject.projectName || lastProject.projectId}\n`
|
|
303
|
-
: `- 无项目上下文,建议先调用 \`list_projects\` 或 \`parse_and_add_project\`\n`) +
|
|
304
|
-
`\n请根据用户意图和上下文,选择合适的工具进行处理。如果无法确定,可以尝试先调用 \`query_interfaces\` 搜索相关接口。`);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
//# sourceMappingURL=assistant.js.map
|