mta-mcp 3.0.0 → 3.1.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/agents/flutter.agent.md +17 -0
- package/agents/vue3.agent.md +17 -0
- package/bin/mta.cjs +98 -0
- package/dist/index.js +1668 -760
- package/dist/index.js.map +1 -1
- package/dist/skills/filesystem.d.ts +96 -0
- package/dist/skills/filesystem.js +269 -0
- package/dist/skills/filesystem.js.map +1 -0
- package/dist/skills/http.d.ts +73 -0
- package/dist/skills/http.js +234 -0
- package/dist/skills/http.js.map +1 -0
- package/dist/skills/index.d.ts +79 -0
- package/dist/skills/index.js +206 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/memory.d.ts +73 -0
- package/dist/skills/memory.js +223 -0
- package/dist/skills/memory.js.map +1 -0
- package/dist/skills/thinking.d.ts +48 -0
- package/dist/skills/thinking.js +199 -0
- package/dist/skills/thinking.js.map +1 -0
- package/dist/skills/versionChecker.d.ts +30 -0
- package/dist/skills/versionChecker.js +225 -0
- package/dist/skills/versionChecker.js.map +1 -0
- package/package.json +7 -2
- package/skills.json +68 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem Skill - 高级文件操作
|
|
3
|
+
* 提供批量处理和模式匹配能力
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 使用 glob 模式查找文件
|
|
7
|
+
*/
|
|
8
|
+
declare function globFiles(pattern: string, options?: {
|
|
9
|
+
cwd?: string;
|
|
10
|
+
ignore?: string[];
|
|
11
|
+
}): Promise<string[]>;
|
|
12
|
+
/**
|
|
13
|
+
* 批量重命名文件
|
|
14
|
+
*/
|
|
15
|
+
declare function batchRename(files: string[], pattern: string, replacement: string, options?: {
|
|
16
|
+
cwd?: string;
|
|
17
|
+
dryRun?: boolean;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
success: number;
|
|
20
|
+
failed: number;
|
|
21
|
+
changes: Array<{
|
|
22
|
+
from: string;
|
|
23
|
+
to: string;
|
|
24
|
+
}>;
|
|
25
|
+
}>;
|
|
26
|
+
/**
|
|
27
|
+
* 处理 glob_files 工具调用
|
|
28
|
+
*/
|
|
29
|
+
declare function handleGlobFiles(args: any): Promise<any>;
|
|
30
|
+
/**
|
|
31
|
+
* 处理 batch_rename 工具调用
|
|
32
|
+
*/
|
|
33
|
+
declare function handleBatchRename(args: any): Promise<any>;
|
|
34
|
+
declare const FILESYSTEM_TOOLS: ({
|
|
35
|
+
name: string;
|
|
36
|
+
description: string;
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: string;
|
|
39
|
+
properties: {
|
|
40
|
+
pattern: {
|
|
41
|
+
type: string;
|
|
42
|
+
description: string;
|
|
43
|
+
};
|
|
44
|
+
cwd: {
|
|
45
|
+
type: string;
|
|
46
|
+
description: string;
|
|
47
|
+
};
|
|
48
|
+
ignore: {
|
|
49
|
+
type: string;
|
|
50
|
+
items: {
|
|
51
|
+
type: string;
|
|
52
|
+
};
|
|
53
|
+
description: string;
|
|
54
|
+
};
|
|
55
|
+
files?: undefined;
|
|
56
|
+
replacement?: undefined;
|
|
57
|
+
dryRun?: undefined;
|
|
58
|
+
};
|
|
59
|
+
required: string[];
|
|
60
|
+
};
|
|
61
|
+
} | {
|
|
62
|
+
name: string;
|
|
63
|
+
description: string;
|
|
64
|
+
inputSchema: {
|
|
65
|
+
type: string;
|
|
66
|
+
properties: {
|
|
67
|
+
files: {
|
|
68
|
+
type: string;
|
|
69
|
+
items: {
|
|
70
|
+
type: string;
|
|
71
|
+
};
|
|
72
|
+
description: string;
|
|
73
|
+
};
|
|
74
|
+
pattern: {
|
|
75
|
+
type: string;
|
|
76
|
+
description: string;
|
|
77
|
+
};
|
|
78
|
+
replacement: {
|
|
79
|
+
type: string;
|
|
80
|
+
description: string;
|
|
81
|
+
};
|
|
82
|
+
cwd: {
|
|
83
|
+
type: string;
|
|
84
|
+
description: string;
|
|
85
|
+
};
|
|
86
|
+
dryRun: {
|
|
87
|
+
type: string;
|
|
88
|
+
description: string;
|
|
89
|
+
};
|
|
90
|
+
ignore?: undefined;
|
|
91
|
+
};
|
|
92
|
+
required: string[];
|
|
93
|
+
};
|
|
94
|
+
})[];
|
|
95
|
+
|
|
96
|
+
export { FILESYSTEM_TOOLS, batchRename, globFiles, handleBatchRename, handleGlobFiles };
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// src/skills/filesystem.ts
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import { glob } from "fast-glob";
|
|
5
|
+
|
|
6
|
+
// src/core/logger.ts
|
|
7
|
+
var LOG_LEVEL_NAMES = {
|
|
8
|
+
[0 /* DEBUG */]: "DEBUG",
|
|
9
|
+
[1 /* INFO */]: "INFO",
|
|
10
|
+
[2 /* WARN */]: "WARN",
|
|
11
|
+
[3 /* ERROR */]: "ERROR",
|
|
12
|
+
[4 /* SILENT */]: "SILENT"
|
|
13
|
+
};
|
|
14
|
+
var globalConfig = {
|
|
15
|
+
level: process.env.DEBUG ? 0 /* DEBUG */ : 1 /* INFO */,
|
|
16
|
+
timestamp: false,
|
|
17
|
+
prefix: "[MCP]"
|
|
18
|
+
};
|
|
19
|
+
var Logger = class _Logger {
|
|
20
|
+
constructor(name, config) {
|
|
21
|
+
this.name = name || "";
|
|
22
|
+
this.config = { ...globalConfig, ...config };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* 格式化日志消息
|
|
26
|
+
*/
|
|
27
|
+
format(level, message, ...args) {
|
|
28
|
+
const parts = [];
|
|
29
|
+
if (this.config.timestamp) {
|
|
30
|
+
parts.push((/* @__PURE__ */ new Date()).toISOString());
|
|
31
|
+
}
|
|
32
|
+
parts.push(this.config.prefix);
|
|
33
|
+
if (this.name) {
|
|
34
|
+
parts.push(`[${this.name}]`);
|
|
35
|
+
}
|
|
36
|
+
parts.push(`[${LOG_LEVEL_NAMES[level]}]`);
|
|
37
|
+
parts.push(message);
|
|
38
|
+
if (args.length > 0) {
|
|
39
|
+
const formatted = args.map((arg) => {
|
|
40
|
+
if (typeof arg === "object") {
|
|
41
|
+
try {
|
|
42
|
+
return JSON.stringify(arg, null, 2);
|
|
43
|
+
} catch {
|
|
44
|
+
return String(arg);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return String(arg);
|
|
48
|
+
});
|
|
49
|
+
parts.push(...formatted);
|
|
50
|
+
}
|
|
51
|
+
return parts.join(" ");
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 检查日志级别是否应该输出
|
|
55
|
+
*/
|
|
56
|
+
shouldLog(level) {
|
|
57
|
+
return level >= this.config.level;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 调试日志
|
|
61
|
+
*/
|
|
62
|
+
debug(message, ...args) {
|
|
63
|
+
if (this.shouldLog(0 /* DEBUG */)) {
|
|
64
|
+
console.error(this.format(0 /* DEBUG */, message, ...args));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 信息日志
|
|
69
|
+
*/
|
|
70
|
+
info(message, ...args) {
|
|
71
|
+
if (this.shouldLog(1 /* INFO */)) {
|
|
72
|
+
console.error(this.format(1 /* INFO */, message, ...args));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 简化的 log 方法(等同于 info)
|
|
77
|
+
*/
|
|
78
|
+
log(message, ...args) {
|
|
79
|
+
this.info(message, ...args);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 警告日志
|
|
83
|
+
*/
|
|
84
|
+
warn(message, ...args) {
|
|
85
|
+
if (this.shouldLog(2 /* WARN */)) {
|
|
86
|
+
console.error(this.format(2 /* WARN */, message, ...args));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* 错误日志
|
|
91
|
+
*/
|
|
92
|
+
error(message, ...args) {
|
|
93
|
+
if (this.shouldLog(3 /* ERROR */)) {
|
|
94
|
+
console.error(this.format(3 /* ERROR */, message, ...args));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 创建子 Logger
|
|
99
|
+
*/
|
|
100
|
+
child(name) {
|
|
101
|
+
const childName = this.name ? `${this.name}:${name}` : name;
|
|
102
|
+
return new _Logger(childName, this.config);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
var logger = new Logger();
|
|
106
|
+
function createLogger(name) {
|
|
107
|
+
return new Logger(name);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/core/autoConfig.ts
|
|
111
|
+
var CACHE_DURATION = 5 * 60 * 1e3;
|
|
112
|
+
|
|
113
|
+
// src/skills/filesystem.ts
|
|
114
|
+
var logger2 = createLogger("Skills:Filesystem");
|
|
115
|
+
async function globFiles(pattern, options) {
|
|
116
|
+
try {
|
|
117
|
+
const files = await glob(pattern, {
|
|
118
|
+
cwd: (options == null ? void 0 : options.cwd) || process.cwd(),
|
|
119
|
+
ignore: (options == null ? void 0 : options.ignore) || ["**/node_modules/**", "**/.git/**"],
|
|
120
|
+
absolute: false
|
|
121
|
+
});
|
|
122
|
+
logger2.info(`glob \u67E5\u627E: ${pattern}, \u627E\u5230 ${files.length} \u4E2A\u6587\u4EF6`);
|
|
123
|
+
return files;
|
|
124
|
+
} catch (error) {
|
|
125
|
+
logger2.error(`glob \u67E5\u627E\u5931\u8D25: ${error}`);
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async function batchRename(files, pattern, replacement, options) {
|
|
130
|
+
const cwd = (options == null ? void 0 : options.cwd) || process.cwd();
|
|
131
|
+
const dryRun = (options == null ? void 0 : options.dryRun) || false;
|
|
132
|
+
const changes = [];
|
|
133
|
+
let success = 0;
|
|
134
|
+
let failed = 0;
|
|
135
|
+
const regex = new RegExp(pattern);
|
|
136
|
+
for (const file of files) {
|
|
137
|
+
const basename2 = path.basename(file);
|
|
138
|
+
const dirname2 = path.dirname(file);
|
|
139
|
+
if (!regex.test(basename2)) {
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
const newBasename = basename2.replace(regex, replacement);
|
|
143
|
+
if (newBasename === basename2) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const fromPath = path.join(cwd, file);
|
|
147
|
+
const toPath = path.join(cwd, dirname2, newBasename);
|
|
148
|
+
changes.push({
|
|
149
|
+
from: file,
|
|
150
|
+
to: path.join(dirname2, newBasename)
|
|
151
|
+
});
|
|
152
|
+
if (!dryRun) {
|
|
153
|
+
try {
|
|
154
|
+
fs.renameSync(fromPath, toPath);
|
|
155
|
+
success++;
|
|
156
|
+
logger2.info(`\u91CD\u547D\u540D: ${file} -> ${newBasename}`);
|
|
157
|
+
} catch (error) {
|
|
158
|
+
failed++;
|
|
159
|
+
logger2.error(`\u91CD\u547D\u540D\u5931\u8D25: ${file} - ${error}`);
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
success++;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return { success, failed, changes };
|
|
166
|
+
}
|
|
167
|
+
async function handleGlobFiles(args) {
|
|
168
|
+
const { pattern, cwd, ignore } = args;
|
|
169
|
+
if (!pattern) {
|
|
170
|
+
return {
|
|
171
|
+
error: "\u7F3A\u5C11\u5FC5\u9700\u53C2\u6570: pattern"
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
const files = await globFiles(pattern, { cwd, ignore });
|
|
176
|
+
return {
|
|
177
|
+
count: files.length,
|
|
178
|
+
files
|
|
179
|
+
};
|
|
180
|
+
} catch (error) {
|
|
181
|
+
return {
|
|
182
|
+
error: error.message
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async function handleBatchRename(args) {
|
|
187
|
+
const { files, pattern, replacement, cwd, dryRun } = args;
|
|
188
|
+
if (!files || !pattern || !replacement) {
|
|
189
|
+
return {
|
|
190
|
+
error: "\u7F3A\u5C11\u5FC5\u9700\u53C2\u6570: files, pattern, replacement"
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
try {
|
|
194
|
+
const result = await batchRename(files, pattern, replacement, { cwd, dryRun });
|
|
195
|
+
return {
|
|
196
|
+
...result,
|
|
197
|
+
dryRun: dryRun || false,
|
|
198
|
+
message: dryRun ? "\u6A21\u62DF\u8FD0\u884C\uFF0C\u672A\u5B9E\u9645\u6267\u884C\u91CD\u547D\u540D" : `\u6210\u529F\u91CD\u547D\u540D ${result.success} \u4E2A\u6587\u4EF6`
|
|
199
|
+
};
|
|
200
|
+
} catch (error) {
|
|
201
|
+
return {
|
|
202
|
+
error: error.message
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
var FILESYSTEM_TOOLS = [
|
|
207
|
+
{
|
|
208
|
+
name: "glob_files",
|
|
209
|
+
description: "\u4F7F\u7528 glob \u6A21\u5F0F\u67E5\u627E\u6587\u4EF6\uFF0C\u652F\u6301\u901A\u914D\u7B26\uFF08\u5982 **/*.ts\uFF09",
|
|
210
|
+
inputSchema: {
|
|
211
|
+
type: "object",
|
|
212
|
+
properties: {
|
|
213
|
+
pattern: {
|
|
214
|
+
type: "string",
|
|
215
|
+
description: "glob \u6A21\u5F0F\uFF08\u5982 src/**/*.ts\uFF09"
|
|
216
|
+
},
|
|
217
|
+
cwd: {
|
|
218
|
+
type: "string",
|
|
219
|
+
description: "\u5DE5\u4F5C\u76EE\u5F55\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4E3A\u5F53\u524D\u76EE\u5F55\uFF09"
|
|
220
|
+
},
|
|
221
|
+
ignore: {
|
|
222
|
+
type: "array",
|
|
223
|
+
items: { type: "string" },
|
|
224
|
+
description: "\u5FFD\u7565\u7684\u6A21\u5F0F\u5217\u8868\uFF08\u53EF\u9009\uFF09"
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
required: ["pattern"]
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
name: "batch_rename",
|
|
232
|
+
description: "\u6279\u91CF\u91CD\u547D\u540D\u6587\u4EF6\uFF0C\u4F7F\u7528\u6B63\u5219\u8868\u8FBE\u5F0F\u66FF\u6362",
|
|
233
|
+
inputSchema: {
|
|
234
|
+
type: "object",
|
|
235
|
+
properties: {
|
|
236
|
+
files: {
|
|
237
|
+
type: "array",
|
|
238
|
+
items: { type: "string" },
|
|
239
|
+
description: "\u8981\u91CD\u547D\u540D\u7684\u6587\u4EF6\u5217\u8868"
|
|
240
|
+
},
|
|
241
|
+
pattern: {
|
|
242
|
+
type: "string",
|
|
243
|
+
description: "\u6B63\u5219\u8868\u8FBE\u5F0F\u6A21\u5F0F\uFF08\u7528\u4E8E\u5339\u914D\u6587\u4EF6\u540D\uFF09"
|
|
244
|
+
},
|
|
245
|
+
replacement: {
|
|
246
|
+
type: "string",
|
|
247
|
+
description: "\u66FF\u6362\u5B57\u7B26\u4E32\uFF08\u652F\u6301 $1, $2 \u7B49\u6355\u83B7\u7EC4\uFF09"
|
|
248
|
+
},
|
|
249
|
+
cwd: {
|
|
250
|
+
type: "string",
|
|
251
|
+
description: "\u5DE5\u4F5C\u76EE\u5F55\uFF08\u53EF\u9009\uFF09"
|
|
252
|
+
},
|
|
253
|
+
dryRun: {
|
|
254
|
+
type: "boolean",
|
|
255
|
+
description: "\u6A21\u62DF\u8FD0\u884C\uFF0C\u4E0D\u5B9E\u9645\u6267\u884C\uFF08\u53EF\u9009\uFF09"
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
required: ["files", "pattern", "replacement"]
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
];
|
|
262
|
+
export {
|
|
263
|
+
FILESYSTEM_TOOLS,
|
|
264
|
+
batchRename,
|
|
265
|
+
globFiles,
|
|
266
|
+
handleBatchRename,
|
|
267
|
+
handleGlobFiles
|
|
268
|
+
};
|
|
269
|
+
//# sourceMappingURL=filesystem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/skills/filesystem.ts","../../src/core/logger.ts","../../src/core/autoConfig.ts"],"sourcesContent":["/**\n * Filesystem Skill - 高级文件操作\n * 提供批量处理和模式匹配能力\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { glob } from 'fast-glob';\nimport { createLogger } from '../core/index.js';\n\nconst logger = createLogger('Skills:Filesystem');\n\n/**\n * 使用 glob 模式查找文件\n */\nexport async function globFiles(pattern: string, options?: { cwd?: string; ignore?: string[] }): Promise<string[]> {\n try {\n const files = await glob(pattern, {\n cwd: options?.cwd || process.cwd(),\n ignore: options?.ignore || ['**/node_modules/**', '**/.git/**'],\n absolute: false\n });\n \n logger.info(`glob 查找: ${pattern}, 找到 ${files.length} 个文件`);\n return files;\n } catch (error) {\n logger.error(`glob 查找失败: ${error}`);\n throw error;\n }\n}\n\n/**\n * 批量重命名文件\n */\nexport async function batchRename(\n files: string[],\n pattern: string,\n replacement: string,\n options?: { cwd?: string; dryRun?: boolean }\n): Promise<{ success: number; failed: number; changes: Array<{ from: string; to: string }> }> {\n const cwd = options?.cwd || process.cwd();\n const dryRun = options?.dryRun || false;\n const changes: Array<{ from: string; to: string }> = [];\n let success = 0;\n let failed = 0;\n \n const regex = new RegExp(pattern);\n \n for (const file of files) {\n const basename = path.basename(file);\n const dirname = path.dirname(file);\n \n if (!regex.test(basename)) {\n continue;\n }\n \n const newBasename = basename.replace(regex, replacement);\n if (newBasename === basename) {\n continue;\n }\n \n const fromPath = path.join(cwd, file);\n const toPath = path.join(cwd, dirname, newBasename);\n \n changes.push({\n from: file,\n to: path.join(dirname, newBasename)\n });\n \n if (!dryRun) {\n try {\n fs.renameSync(fromPath, toPath);\n success++;\n logger.info(`重命名: ${file} -> ${newBasename}`);\n } catch (error) {\n failed++;\n logger.error(`重命名失败: ${file} - ${error}`);\n }\n } else {\n success++;\n }\n }\n \n return { success, failed, changes };\n}\n\n/**\n * 处理 glob_files 工具调用\n */\nexport async function handleGlobFiles(args: any): Promise<any> {\n const { pattern, cwd, ignore } = args;\n \n if (!pattern) {\n return {\n error: '缺少必需参数: pattern'\n };\n }\n \n try {\n const files = await globFiles(pattern, { cwd, ignore });\n \n return {\n count: files.length,\n files\n };\n } catch (error: any) {\n return {\n error: error.message\n };\n }\n}\n\n/**\n * 处理 batch_rename 工具调用\n */\nexport async function handleBatchRename(args: any): Promise<any> {\n const { files, pattern, replacement, cwd, dryRun } = args;\n \n if (!files || !pattern || !replacement) {\n return {\n error: '缺少必需参数: files, pattern, replacement'\n };\n }\n \n try {\n const result = await batchRename(files, pattern, replacement, { cwd, dryRun });\n \n return {\n ...result,\n dryRun: dryRun || false,\n message: dryRun \n ? '模拟运行,未实际执行重命名' \n : `成功重命名 ${result.success} 个文件`\n };\n } catch (error: any) {\n return {\n error: error.message\n };\n }\n}\n\n// 导出工具定义\nexport const FILESYSTEM_TOOLS = [\n {\n name: 'glob_files',\n description: '使用 glob 模式查找文件,支持通配符(如 **/*.ts)',\n inputSchema: {\n type: 'object',\n properties: {\n pattern: {\n type: 'string',\n description: 'glob 模式(如 src/**/*.ts)'\n },\n cwd: {\n type: 'string',\n description: '工作目录(可选,默认为当前目录)'\n },\n ignore: {\n type: 'array',\n items: { type: 'string' },\n description: '忽略的模式列表(可选)'\n }\n },\n required: ['pattern']\n }\n },\n {\n name: 'batch_rename',\n description: '批量重命名文件,使用正则表达式替换',\n inputSchema: {\n type: 'object',\n properties: {\n files: {\n type: 'array',\n items: { type: 'string' },\n description: '要重命名的文件列表'\n },\n pattern: {\n type: 'string',\n description: '正则表达式模式(用于匹配文件名)'\n },\n replacement: {\n type: 'string',\n description: '替换字符串(支持 $1, $2 等捕获组)'\n },\n cwd: {\n type: 'string',\n description: '工作目录(可选)'\n },\n dryRun: {\n type: 'boolean',\n description: '模拟运行,不实际执行(可选)'\n }\n },\n required: ['files', 'pattern', 'replacement']\n }\n }\n];\n","/**\n * MCP 日志模块\n * \n * 统一的日志接口,支持不同级别和格式化输出\n * MCP 服务器通过 stderr 输出日志,避免污染 stdout\n * \n * @module core/logger\n */\n\n/**\n * 日志级别\n */\nexport enum LogLevel {\n DEBUG = 0,\n INFO = 1,\n WARN = 2,\n ERROR = 3,\n SILENT = 4\n}\n\n/**\n * 日志级别名称\n */\nconst LOG_LEVEL_NAMES: Record<LogLevel, string> = {\n [LogLevel.DEBUG]: 'DEBUG',\n [LogLevel.INFO]: 'INFO',\n [LogLevel.WARN]: 'WARN',\n [LogLevel.ERROR]: 'ERROR',\n [LogLevel.SILENT]: 'SILENT'\n};\n\n/**\n * 日志配置\n */\ninterface LoggerConfig {\n /** 最小日志级别 */\n level: LogLevel;\n /** 是否显示时间戳 */\n timestamp: boolean;\n /** 前缀 */\n prefix: string;\n}\n\n/**\n * 全局日志配置\n */\nlet globalConfig: LoggerConfig = {\n level: process.env.DEBUG ? LogLevel.DEBUG : LogLevel.INFO,\n timestamp: false,\n prefix: '[MCP]'\n};\n\n/**\n * Logger 类\n */\nexport class Logger {\n private readonly name: string;\n private readonly config: LoggerConfig;\n \n constructor(name?: string, config?: Partial<LoggerConfig>) {\n this.name = name || '';\n this.config = { ...globalConfig, ...config };\n }\n \n /**\n * 格式化日志消息\n */\n private format(level: LogLevel, message: string, ...args: unknown[]): string {\n const parts: string[] = [];\n \n if (this.config.timestamp) {\n parts.push(new Date().toISOString());\n }\n \n parts.push(this.config.prefix);\n \n if (this.name) {\n parts.push(`[${this.name}]`);\n }\n \n parts.push(`[${LOG_LEVEL_NAMES[level]}]`);\n parts.push(message);\n \n // 处理额外参数\n if (args.length > 0) {\n const formatted = args.map(arg => {\n if (typeof arg === 'object') {\n try {\n return JSON.stringify(arg, null, 2);\n } catch {\n return String(arg);\n }\n }\n return String(arg);\n });\n parts.push(...formatted);\n }\n \n return parts.join(' ');\n }\n \n /**\n * 检查日志级别是否应该输出\n */\n private shouldLog(level: LogLevel): boolean {\n return level >= this.config.level;\n }\n \n /**\n * 调试日志\n */\n debug(message: string, ...args: unknown[]): void {\n if (this.shouldLog(LogLevel.DEBUG)) {\n console.error(this.format(LogLevel.DEBUG, message, ...args));\n }\n }\n \n /**\n * 信息日志\n */\n info(message: string, ...args: unknown[]): void {\n if (this.shouldLog(LogLevel.INFO)) {\n console.error(this.format(LogLevel.INFO, message, ...args));\n }\n }\n \n /**\n * 简化的 log 方法(等同于 info)\n */\n log(message: string, ...args: unknown[]): void {\n this.info(message, ...args);\n }\n \n /**\n * 警告日志\n */\n warn(message: string, ...args: unknown[]): void {\n if (this.shouldLog(LogLevel.WARN)) {\n console.error(this.format(LogLevel.WARN, message, ...args));\n }\n }\n \n /**\n * 错误日志\n */\n error(message: string, ...args: unknown[]): void {\n if (this.shouldLog(LogLevel.ERROR)) {\n console.error(this.format(LogLevel.ERROR, message, ...args));\n }\n }\n \n /**\n * 创建子 Logger\n */\n child(name: string): Logger {\n const childName = this.name ? `${this.name}:${name}` : name;\n return new Logger(childName, this.config);\n }\n}\n\n/**\n * 配置全局日志\n */\nexport function configureLogger(config: Partial<LoggerConfig>): void {\n globalConfig = { ...globalConfig, ...config };\n}\n\n/**\n * 设置日志级别\n */\nexport function setLogLevel(level: LogLevel): void {\n globalConfig.level = level;\n}\n\n/**\n * 默认 Logger 实例\n */\nexport const logger = new Logger();\n\n/**\n * 创建带名称的 Logger\n */\nexport function createLogger(name: string): Logger {\n return new Logger(name);\n}\n\n/**\n * 工具函数:计时日志\n */\nexport function createTimer(logger: Logger, operation: string): () => void {\n const start = Date.now();\n logger.debug(`开始: ${operation}`);\n \n return () => {\n const duration = Date.now() - start;\n logger.debug(`完成: ${operation} (${duration}ms)`);\n };\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\n\n/**\n * 自动配置检测与修复\n * 当 AI 调用任何工具时,自动检测并修复配置问题\n */\n\nexport interface ConfigCheckResult {\n needsSetup: boolean;\n wasFixed: boolean;\n workspacePath: string;\n message?: string;\n}\n\n// 已检测过的工作区缓存(避免重复检测)\nconst checkedWorkspaces = new Map<string, { configured: boolean; timestamp: number }>();\nconst CACHE_DURATION = 5 * 60 * 1000; // 5 分钟缓存\n\n/**\n * 检测并自动修复工作区配置\n * 使用缓存避免重复检测,只在首次或缓存过期时执行\n * @param workspacePath 工作区路径\n * @returns 配置检测结果\n */\nexport function ensureWorkspaceConfig(workspacePath: string): ConfigCheckResult {\n const result: ConfigCheckResult = {\n needsSetup: false,\n wasFixed: false,\n workspacePath\n };\n \n if (!workspacePath || !fs.existsSync(workspacePath)) {\n return result;\n }\n \n // 检查缓存\n const cached = checkedWorkspaces.get(workspacePath);\n const now = Date.now();\n \n if (cached && cached.configured && (now - cached.timestamp) < CACHE_DURATION) {\n // 缓存有效且已配置,直接返回\n return result;\n }\n \n const vscodeDir = path.join(workspacePath, '.vscode');\n const mcpJsonPath = path.join(vscodeDir, 'mcp.json');\n const settingsPath = path.join(vscodeDir, 'settings.json');\n \n // 快速检查是否已配置(只读取文件,不修改)\n let hasMtaConfig = false;\n if (fs.existsSync(mcpJsonPath)) {\n try {\n const config = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf-8'));\n hasMtaConfig = !!(config.servers?.mta || config.mcpServers?.mta);\n } catch {\n // 配置文件损坏\n }\n }\n \n if (hasMtaConfig) {\n // 已配置,更新缓存并返回\n checkedWorkspaces.set(workspacePath, { configured: true, timestamp: now });\n return result;\n }\n \n // 需要配置,自动修复\n result.needsSetup = true;\n \n try {\n // 创建 .vscode 目录\n if (!fs.existsSync(vscodeDir)) {\n fs.mkdirSync(vscodeDir, { recursive: true });\n }\n \n // 创建或更新 mcp.json\n let mcpConfig: any = { servers: {} };\n if (fs.existsSync(mcpJsonPath)) {\n try {\n mcpConfig = JSON.parse(fs.readFileSync(mcpJsonPath, 'utf-8'));\n if (!mcpConfig.servers) {\n mcpConfig.servers = {};\n }\n } catch {\n mcpConfig = { servers: {} };\n }\n }\n \n mcpConfig.servers.mta = {\n command: 'npx',\n args: ['-y', 'mta-mcp'],\n env: {}\n };\n \n fs.writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));\n \n // 更新 settings.json 启用 MCP\n let settings: any = {};\n if (fs.existsSync(settingsPath)) {\n try {\n settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));\n } catch {\n settings = {};\n }\n }\n \n if (!settings['github.copilot.chat.mcp.enabled']) {\n settings['github.copilot.chat.mcp.enabled'] = true;\n fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));\n }\n \n result.wasFixed = true;\n result.message = `✅ 已自动为 ${path.basename(workspacePath)} 配置 MTA MCP。请重新加载 VS Code 窗口使配置生效。`;\n \n // 更新缓存\n checkedWorkspaces.set(workspacePath, { configured: true, timestamp: now });\n \n } catch (error) {\n result.message = `⚠️ 自动配置失败: ${error instanceof Error ? error.message : String(error)}`;\n }\n \n return result;\n}\n\n/**\n * 包装工具响应,添加自动配置信息\n */\nexport function wrapResponseWithConfigInfo(\n response: any,\n configResult: ConfigCheckResult\n): any {\n if (!configResult.wasFixed) {\n return response;\n }\n \n // 在响应中添加配置修复信息\n if (typeof response === 'object' && response !== null) {\n return {\n ...response,\n _autoConfig: {\n wasFixed: true,\n message: configResult.message,\n action: '请运行命令: Cmd+Shift+P → \"重新加载窗口\" 使配置生效'\n }\n };\n }\n \n return response;\n}\n"],"mappings":"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","names":["logger","basename","dirname"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP 请求技能
|
|
3
|
+
*
|
|
4
|
+
* 提供 HTTP 请求能力,可以发送 GET/POST 等请求
|
|
5
|
+
* 使用 axios 实现,不依赖外部 MCP 服务器
|
|
6
|
+
*/
|
|
7
|
+
interface HttpRequestArgs {
|
|
8
|
+
url: string;
|
|
9
|
+
method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
|
|
10
|
+
headers?: Record<string, string>;
|
|
11
|
+
body?: any;
|
|
12
|
+
timeout?: number;
|
|
13
|
+
}
|
|
14
|
+
interface HttpResponse {
|
|
15
|
+
status: number;
|
|
16
|
+
statusText: string;
|
|
17
|
+
headers: Record<string, string>;
|
|
18
|
+
data: any;
|
|
19
|
+
timing: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 发送 HTTP 请求
|
|
23
|
+
*/
|
|
24
|
+
declare function httpRequest(args: HttpRequestArgs): Promise<HttpResponse>;
|
|
25
|
+
/**
|
|
26
|
+
* 工具定义(供 MCP 注册)
|
|
27
|
+
*/
|
|
28
|
+
declare const httpRequestToolDefinition: {
|
|
29
|
+
name: string;
|
|
30
|
+
description: string;
|
|
31
|
+
inputSchema: {
|
|
32
|
+
type: "object";
|
|
33
|
+
properties: {
|
|
34
|
+
url: {
|
|
35
|
+
type: string;
|
|
36
|
+
description: string;
|
|
37
|
+
};
|
|
38
|
+
method: {
|
|
39
|
+
type: string;
|
|
40
|
+
enum: string[];
|
|
41
|
+
default: string;
|
|
42
|
+
description: string;
|
|
43
|
+
};
|
|
44
|
+
headers: {
|
|
45
|
+
type: string;
|
|
46
|
+
additionalProperties: {
|
|
47
|
+
type: string;
|
|
48
|
+
};
|
|
49
|
+
description: string;
|
|
50
|
+
};
|
|
51
|
+
body: {
|
|
52
|
+
description: string;
|
|
53
|
+
};
|
|
54
|
+
timeout: {
|
|
55
|
+
type: string;
|
|
56
|
+
default: number;
|
|
57
|
+
description: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
required: string[];
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* 处理 http_request 工具调用
|
|
65
|
+
*/
|
|
66
|
+
declare function handleHttpRequest(args: any): Promise<{
|
|
67
|
+
content: Array<{
|
|
68
|
+
type: string;
|
|
69
|
+
text: string;
|
|
70
|
+
}>;
|
|
71
|
+
}>;
|
|
72
|
+
|
|
73
|
+
export { type HttpRequestArgs, type HttpResponse, handleHttpRequest, httpRequest, httpRequestToolDefinition };
|