@becrafter/prompt-manager 0.1.22 → 0.2.2
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/package.json +31 -24
- package/packages/resources/tools/agent-browser/README.md +640 -0
- package/packages/resources/tools/agent-browser/agent-browser.tool.js +1389 -0
- package/packages/resources/tools/thinking/README.md +324 -0
- package/packages/resources/tools/thinking/thinking.tool.js +911 -0
- package/packages/server/README.md +3 -4
- package/packages/server/api/admin.routes.js +668 -664
- package/packages/server/api/open.routes.js +68 -67
- package/packages/server/api/surge.routes.js +5 -6
- package/packages/server/api/tool.routes.js +70 -71
- package/packages/server/app.js +70 -73
- package/packages/server/configs/authors.json +40 -0
- package/packages/server/configs/models/built-in/bigmodel.yaml +6 -6
- package/packages/server/configs/models/providers.yaml +4 -4
- package/packages/server/configs/templates/built-in/general-iteration.yaml +1 -1
- package/packages/server/configs/templates/built-in/general-optimize.yaml +1 -1
- package/packages/server/configs/templates/built-in/output-format-optimize.yaml +1 -1
- package/packages/server/index.js +3 -9
- package/packages/server/mcp/heartbeat-patch.js +1 -3
- package/packages/server/mcp/mcp.server.js +64 -134
- package/packages/server/mcp/prompt.handler.js +101 -95
- package/packages/server/middlewares/auth.middleware.js +31 -31
- package/packages/server/server.js +60 -45
- package/packages/server/services/TerminalService.js +156 -70
- package/packages/server/services/WebSocketService.js +35 -34
- package/packages/server/services/author-config.service.js +199 -0
- package/packages/server/services/manager.js +66 -60
- package/packages/server/services/model.service.js +5 -9
- package/packages/server/services/optimization.service.js +25 -22
- package/packages/server/services/template.service.js +3 -8
- package/packages/server/toolm/author-sync.service.js +97 -0
- package/packages/server/toolm/index.js +1 -2
- package/packages/server/toolm/package-installer.service.js +47 -50
- package/packages/server/toolm/tool-context.service.js +64 -62
- package/packages/server/toolm/tool-dependency.service.js +28 -30
- package/packages/server/toolm/tool-description-generator-optimized.service.js +55 -55
- package/packages/server/toolm/tool-description-generator.service.js +20 -23
- package/packages/server/toolm/tool-environment.service.js +45 -44
- package/packages/server/toolm/tool-execution.service.js +49 -48
- package/packages/server/toolm/tool-loader.service.js +13 -18
- package/packages/server/toolm/tool-logger.service.js +33 -39
- package/packages/server/toolm/tool-manager.handler.js +17 -15
- package/packages/server/toolm/tool-manual-generator.service.js +107 -87
- package/packages/server/toolm/tool-mode-handlers.service.js +52 -59
- package/packages/server/toolm/tool-storage.service.js +11 -12
- package/packages/server/toolm/tool-sync.service.js +36 -39
- package/packages/server/toolm/tool-utils.js +0 -1
- package/packages/server/toolm/tool-yaml-parser.service.js +12 -11
- package/packages/server/toolm/validate-system.js +56 -84
- package/packages/server/utils/config.js +97 -12
- package/packages/server/utils/logger.js +1 -1
- package/packages/server/utils/port-checker.js +8 -8
- package/packages/server/utils/util.js +470 -467
- package/packages/resources/tools/cognitive-thinking/README.md +0 -284
- package/packages/resources/tools/cognitive-thinking/cognitive-thinking.tool.js +0 -837
- package/packages/server/mcp/sequential-thinking.handler.js +0 -318
- package/packages/server/mcp/think-plan.handler.js +0 -274
- package/packages/server/mcp/thinking-toolkit.handler.js +0 -380
- package/packages/web/0.d1c5a72339dfc32ad86a.js +0 -1
- package/packages/web/112.8807b976372b2b0541a8.js +0 -1
- package/packages/web/130.584c7e365da413f5d9be.js +0 -1
- package/packages/web/142.72c985bc29720f975cca.js +0 -1
- package/packages/web/165.a05fc53bf84d18db36b8.js +0 -2
- package/packages/web/165.a05fc53bf84d18db36b8.js.LICENSE.txt +0 -9
- package/packages/web/203.724ab9f717b80554c397.js +0 -1
- package/packages/web/241.bf941d4f02866795f64a.js +0 -1
- package/packages/web/249.54cfb224af63f5f5ec55.js +0 -1
- package/packages/web/291.6df35042f8f296fca7cd.js +0 -1
- package/packages/web/319.2fab900a31b29873f666.js +0 -1
- package/packages/web/32.c78d866281995ec33a7b.js +0 -1
- package/packages/web/325.9ca297d0f73f38468ce9.js +0 -1
- package/packages/web/366.2f9b48fdbf8eee039e57.js +0 -1
- package/packages/web/378.6be08c612cd5a3ef97dc.js +0 -1
- package/packages/web/393.7a2f817515c5e90623d7.js +0 -1
- package/packages/web/412.062df5f732d5ba203415.js +0 -1
- package/packages/web/426.08656fef4918b3fb19ad.js +0 -1
- package/packages/web/465.2be8018327130a3bd798.js +0 -1
- package/packages/web/48.8ca96fc93667a715e67a.js +0 -1
- package/packages/web/480.44c1f1a2927486ac3d4f.js +0 -1
- package/packages/web/489.e041a8d0db15dc96d607.js +0 -1
- package/packages/web/490.9ffb26c907de020d671b.js +0 -1
- package/packages/web/492.58781369e348d91fc06a.js +0 -1
- package/packages/web/495.ed63e99791a87167c6b3.js +0 -1
- package/packages/web/510.4cc07ab7d30d5c1cd17f.js +0 -1
- package/packages/web/543.3af155ed4fa237664308.js +0 -1
- package/packages/web/567.f04ab60f8e2c2fb0745a.js +0 -1
- package/packages/web/592.f3ad085fa9c1849daa06.js +0 -1
- package/packages/web/616.b03fb801b3433b17750f.js +0 -1
- package/packages/web/617.d88def54921d2c4dc44c.js +0 -1
- package/packages/web/641.d30787d674f548928261.js +0 -1
- package/packages/web/672.5269c8399fa42a5af95d.js +0 -1
- package/packages/web/731.97cab92b71811c502bda.js +0 -1
- package/packages/web/746.3947c6f0235407e420fb.js +0 -1
- package/packages/web/756.a53233b3f3913900d5ac.js +0 -1
- package/packages/web/77.68801af593a28a631fbf.js +0 -1
- package/packages/web/802.53b2bff3cf2a69f7b80c.js +0 -1
- package/packages/web/815.b6dfab82265f56c7e046.js +0 -1
- package/packages/web/821.f5a13e5c735aac244eb9.js +0 -1
- package/packages/web/846.b9bf97d5f559270675ce.js +0 -1
- package/packages/web/869.7c10403f500e6201407f.js +0 -1
- package/packages/web/885.135050364f99e6924fb5.js +0 -1
- package/packages/web/901.fd5aeb9df630609a2b43.js +0 -1
- package/packages/web/928.f67e590de3caa4daa3ae.js +0 -1
- package/packages/web/955.d833403521ba4dd567ee.js +0 -1
- package/packages/web/981.a45cb745cf424044c8c8.js +0 -1
- package/packages/web/992.645320b60c74c8787482.js +0 -1
- package/packages/web/996.ed9a963dc9e7439eca9a.js +0 -1
- package/packages/web/css/codemirror-theme_xq-light.css +0 -43
- package/packages/web/css/codemirror.css +0 -344
- package/packages/web/css/main.196f434e6a88cd448158.css +0 -7278
- package/packages/web/css/terminal-fix.css +0 -571
- package/packages/web/index.html +0 -3
- package/packages/web/main.dceff50c7307dda04873.js +0 -2
- package/packages/web/main.dceff50c7307dda04873.js.LICENSE.txt +0 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 工具执行服务
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* 职责:
|
|
5
5
|
* 1. 处理工具执行模式
|
|
6
6
|
* 2. 创建执行上下文
|
|
@@ -21,7 +21,7 @@ import { generateHelpInfo } from './tool-manual-generator.service.js';
|
|
|
21
21
|
*/
|
|
22
22
|
export async function executeTool(toolName, parameters) {
|
|
23
23
|
logger.info(`执行工具: ${toolName}`, { parameters });
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
try {
|
|
26
26
|
const tool = toolLoaderService.getTool(toolName);
|
|
27
27
|
const toolModule = tool.module;
|
|
@@ -31,9 +31,9 @@ export async function executeTool(toolName, parameters) {
|
|
|
31
31
|
|
|
32
32
|
// 2. 创建工具执行上下文
|
|
33
33
|
const toolContext = await createToolContext(toolName, toolModule);
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
// 3. 记录执行开始
|
|
36
|
-
toolContext.api.logger.info('执行开始', {
|
|
36
|
+
toolContext.api.logger.info('执行开始', {
|
|
37
37
|
tool: toolName,
|
|
38
38
|
parameters: Object.keys(parameters)
|
|
39
39
|
});
|
|
@@ -42,35 +42,33 @@ export async function executeTool(toolName, parameters) {
|
|
|
42
42
|
let result;
|
|
43
43
|
try {
|
|
44
44
|
result = await toolContext.execute(parameters);
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
// 5. 记录执行完成
|
|
47
|
-
toolContext.api.logger.info('执行完成', {
|
|
47
|
+
toolContext.api.logger.info('执行完成', {
|
|
48
48
|
tool: toolName,
|
|
49
49
|
success: true
|
|
50
50
|
});
|
|
51
|
-
|
|
52
51
|
} catch (error) {
|
|
53
52
|
// 记录执行错误
|
|
54
|
-
toolContext.api.logger.error('执行失败', {
|
|
53
|
+
toolContext.api.logger.error('执行失败', {
|
|
55
54
|
tool: toolName,
|
|
56
55
|
error: error.message,
|
|
57
56
|
stack: error.stack
|
|
58
57
|
});
|
|
59
58
|
throw error;
|
|
60
59
|
}
|
|
61
|
-
|
|
60
|
+
|
|
62
61
|
logger.info(`工具执行成功: ${toolName}`);
|
|
63
|
-
|
|
62
|
+
|
|
64
63
|
// 6. 格式化并返回结果
|
|
65
64
|
const content = formatToolResult(result, toolName);
|
|
66
65
|
return { content };
|
|
67
|
-
|
|
68
66
|
} catch (error) {
|
|
69
67
|
logger.error(`工具执行失败: ${toolName}`, { error: error.message });
|
|
70
|
-
|
|
68
|
+
|
|
71
69
|
const tool = toolLoaderService.getTool(toolName);
|
|
72
70
|
const helpInfo = generateErrorHelpInfo(toolName, error, tool, parameters);
|
|
73
|
-
|
|
71
|
+
|
|
74
72
|
return createTextResponse(helpInfo);
|
|
75
73
|
}
|
|
76
74
|
}
|
|
@@ -82,40 +80,40 @@ export async function executeTool(toolName, parameters) {
|
|
|
82
80
|
/**
|
|
83
81
|
* 格式化工具执行结果
|
|
84
82
|
* 根据结果类型自动识别并转换为 MCP 格式的内容
|
|
85
|
-
*
|
|
83
|
+
*
|
|
86
84
|
* @param {any} result - 工具执行结果
|
|
87
85
|
* @param {string} toolName - 工具名称
|
|
88
86
|
* @returns {Array} MCP 格式的内容数组
|
|
89
87
|
*/
|
|
90
88
|
function formatToolResult(result, toolName) {
|
|
91
89
|
const content = [];
|
|
92
|
-
|
|
90
|
+
|
|
93
91
|
// 尝试提取图片数据
|
|
94
92
|
const imageContent = extractImageContent(result);
|
|
95
93
|
if (imageContent.length > 0) {
|
|
96
94
|
content.push(...imageContent);
|
|
97
|
-
|
|
95
|
+
|
|
98
96
|
// 对于截图操作,只返回图片
|
|
99
97
|
if (result?.method === 'takeScreenshot') {
|
|
100
98
|
logger.info('截图成功,返回图片数据');
|
|
101
99
|
return content;
|
|
102
100
|
}
|
|
103
|
-
|
|
101
|
+
|
|
104
102
|
// 其他操作有图片时,添加文本信息
|
|
105
103
|
if (result?.text) {
|
|
106
104
|
content.push(createTextContent(result.text));
|
|
107
105
|
} else if (result?.method) {
|
|
108
106
|
content.push(createTextContent(`操作成功:${result.method}`));
|
|
109
107
|
}
|
|
110
|
-
|
|
108
|
+
|
|
111
109
|
return content;
|
|
112
110
|
}
|
|
113
|
-
|
|
111
|
+
|
|
114
112
|
// 处理 file-reader 工具的其他格式(二进制、媒体元信息等)
|
|
115
113
|
if (result?.format && result?.content) {
|
|
116
114
|
return [createJsonTextContent(result, toolName)];
|
|
117
115
|
}
|
|
118
|
-
|
|
116
|
+
|
|
119
117
|
// 默认情况:返回 JSON 格式
|
|
120
118
|
return [createJsonTextContent(result, toolName)];
|
|
121
119
|
}
|
|
@@ -126,17 +124,17 @@ function formatToolResult(result, toolName) {
|
|
|
126
124
|
* 1. chrome-devtools: result.images 数组
|
|
127
125
|
* 2. filesystem: result.base64 + result.mimeType (图片类型)
|
|
128
126
|
* 3. file-reader: result.format === 'image' + result.content.base64
|
|
129
|
-
*
|
|
127
|
+
*
|
|
130
128
|
* @param {any} result - 工具执行结果
|
|
131
129
|
* @returns {Array} 图片内容数组
|
|
132
130
|
*/
|
|
133
131
|
function extractImageContent(result) {
|
|
134
132
|
const images = [];
|
|
135
|
-
|
|
133
|
+
|
|
136
134
|
if (!result) {
|
|
137
135
|
return images;
|
|
138
136
|
}
|
|
139
|
-
|
|
137
|
+
|
|
140
138
|
// 情况1: chrome-devtools 工具返回的图片数组
|
|
141
139
|
if (Array.isArray(result.images) && result.images.length > 0) {
|
|
142
140
|
for (const image of result.images) {
|
|
@@ -146,18 +144,18 @@ function extractImageContent(result) {
|
|
|
146
144
|
}
|
|
147
145
|
return images;
|
|
148
146
|
}
|
|
149
|
-
|
|
147
|
+
|
|
150
148
|
// 情况2: filesystem 工具的 read_media_file 返回的 base64 + mimeType
|
|
151
149
|
if (result.base64 && result.mimeType && result.mimeType.startsWith('image/')) {
|
|
152
150
|
images.push(createImageContent(result.base64, result.mimeType));
|
|
153
151
|
logger.info('读取图片文件成功,返回图片数据');
|
|
154
152
|
return images;
|
|
155
153
|
}
|
|
156
|
-
|
|
154
|
+
|
|
157
155
|
// 情况3: file-reader 工具返回的图片格式
|
|
158
156
|
if (result.format === 'image' && result.content?.base64 && result.content?.mimeType) {
|
|
159
157
|
images.push(createImageContent(result.content.base64, result.content.mimeType));
|
|
160
|
-
|
|
158
|
+
|
|
161
159
|
// 如果有描述信息,也一并返回
|
|
162
160
|
if (result.content.description) {
|
|
163
161
|
images.push(createTextContent(result.content.description));
|
|
@@ -165,59 +163,63 @@ function extractImageContent(result) {
|
|
|
165
163
|
logger.info('读取图片文件成功,返回图片数据');
|
|
166
164
|
return images;
|
|
167
165
|
}
|
|
168
|
-
|
|
166
|
+
|
|
169
167
|
return images;
|
|
170
168
|
}
|
|
171
169
|
|
|
172
170
|
/**
|
|
173
171
|
* 创建图片类型的内容
|
|
174
|
-
*
|
|
172
|
+
*
|
|
175
173
|
* @param {string} data - base64 编码的图片数据
|
|
176
174
|
* @param {string} mimeType - 图片 MIME 类型
|
|
177
175
|
* @returns {object} MCP 图片内容对象
|
|
178
176
|
*/
|
|
179
177
|
function createImageContent(data, mimeType) {
|
|
180
178
|
return {
|
|
181
|
-
type:
|
|
182
|
-
data
|
|
183
|
-
mimeType
|
|
179
|
+
type: 'image',
|
|
180
|
+
data,
|
|
181
|
+
mimeType
|
|
184
182
|
};
|
|
185
183
|
}
|
|
186
184
|
|
|
187
185
|
/**
|
|
188
186
|
* 创建文本类型的内容
|
|
189
|
-
*
|
|
187
|
+
*
|
|
190
188
|
* @param {string} text - 文本内容
|
|
191
189
|
* @returns {object} MCP 文本内容对象
|
|
192
190
|
*/
|
|
193
191
|
function createTextContent(text) {
|
|
194
192
|
return {
|
|
195
|
-
type:
|
|
196
|
-
text
|
|
193
|
+
type: 'text',
|
|
194
|
+
text
|
|
197
195
|
};
|
|
198
196
|
}
|
|
199
197
|
|
|
200
198
|
/**
|
|
201
199
|
* 创建 JSON 格式的文本内容
|
|
202
|
-
*
|
|
200
|
+
*
|
|
203
201
|
* @param {any} result - 工具执行结果
|
|
204
202
|
* @param {string} toolName - 工具名称
|
|
205
203
|
* @returns {object} MCP 文本内容对象
|
|
206
204
|
*/
|
|
207
205
|
function createJsonTextContent(result, toolName) {
|
|
208
206
|
return createTextContent(
|
|
209
|
-
JSON.stringify(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
207
|
+
JSON.stringify(
|
|
208
|
+
{
|
|
209
|
+
success: true,
|
|
210
|
+
tool: toolName,
|
|
211
|
+
mode: 'execute',
|
|
212
|
+
result
|
|
213
|
+
},
|
|
214
|
+
null,
|
|
215
|
+
2
|
|
216
|
+
)
|
|
215
217
|
);
|
|
216
218
|
}
|
|
217
219
|
|
|
218
220
|
/**
|
|
219
221
|
* 创建文本类型的响应
|
|
220
|
-
*
|
|
222
|
+
*
|
|
221
223
|
* @param {string} text - 文本内容
|
|
222
224
|
* @returns {object} MCP 格式的响应对象
|
|
223
225
|
*/
|
|
@@ -229,7 +231,7 @@ function createTextResponse(text) {
|
|
|
229
231
|
|
|
230
232
|
/**
|
|
231
233
|
* 生成错误帮助信息
|
|
232
|
-
*
|
|
234
|
+
*
|
|
233
235
|
* @param {string} toolName - 工具名称
|
|
234
236
|
* @param {Error} error - 错误对象
|
|
235
237
|
* @param {object} tool - 工具对象
|
|
@@ -241,7 +243,7 @@ function generateErrorHelpInfo(toolName, error, tool, parameters) {
|
|
|
241
243
|
if (isValidationErrorType(error.message)) {
|
|
242
244
|
return generateHelpInfo(toolName, error, tool, parameters);
|
|
243
245
|
}
|
|
244
|
-
|
|
246
|
+
|
|
245
247
|
// 检查是否是业务错误
|
|
246
248
|
const businessErrors = tool?.businessErrors || [];
|
|
247
249
|
for (const businessError of businessErrors) {
|
|
@@ -249,14 +251,14 @@ function generateErrorHelpInfo(toolName, error, tool, parameters) {
|
|
|
249
251
|
return generateHelpInfo(toolName, error, tool, parameters, businessError);
|
|
250
252
|
}
|
|
251
253
|
}
|
|
252
|
-
|
|
254
|
+
|
|
253
255
|
// 其他错误也返回帮助信息
|
|
254
256
|
return generateHelpInfo(toolName, error, tool, parameters);
|
|
255
257
|
}
|
|
256
258
|
|
|
257
259
|
/**
|
|
258
260
|
* 判断是否是参数验证错误
|
|
259
|
-
*
|
|
261
|
+
*
|
|
260
262
|
* @param {string} errorMessage - 错误消息
|
|
261
263
|
* @returns {boolean} 是否是参数验证错误
|
|
262
264
|
*/
|
|
@@ -271,7 +273,6 @@ function isValidationErrorType(errorMessage) {
|
|
|
271
273
|
/参数.*类型错误/i,
|
|
272
274
|
/参数.*格式错误/i
|
|
273
275
|
];
|
|
274
|
-
|
|
276
|
+
|
|
275
277
|
return validationPatterns.some(pattern => pattern.test(errorMessage));
|
|
276
278
|
}
|
|
277
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 工具加载服务
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* 职责:
|
|
5
5
|
* 1. 扫描并加载 ~/.prompt-manager/tools 和 packages/resources/tools 目录下的所有工具
|
|
6
6
|
* 2. 验证工具是否符合标准接口规范
|
|
@@ -11,26 +11,22 @@
|
|
|
11
11
|
|
|
12
12
|
import fs from 'fs-extra';
|
|
13
13
|
import path from 'path';
|
|
14
|
-
import os from 'os';
|
|
15
|
-
import { fileURLToPath } from 'url';
|
|
16
14
|
import { logger } from '../utils/logger.js';
|
|
17
15
|
import { pathExists } from './tool-utils.js';
|
|
18
16
|
import { generateManual as generateManualFromService } from './tool-manual-generator.service.js';
|
|
19
|
-
|
|
20
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
21
|
-
const __dirname = path.dirname(__filename);
|
|
17
|
+
import { config } from '../utils/config.js';
|
|
22
18
|
|
|
23
19
|
class ToolLoaderService {
|
|
24
20
|
constructor() {
|
|
25
21
|
// 工具缓存:toolName -> toolModule
|
|
26
22
|
this.toolCache = new Map();
|
|
27
|
-
|
|
23
|
+
|
|
28
24
|
// 工具目录列表(所有工具都在沙箱环境中)
|
|
29
25
|
this.toolDirectories = [
|
|
30
26
|
// 沙箱工具目录(系统工具和用户工具都在这里)
|
|
31
|
-
|
|
27
|
+
config.getToolboxDir()
|
|
32
28
|
];
|
|
33
|
-
|
|
29
|
+
|
|
34
30
|
// 已初始化标志
|
|
35
31
|
this.initialized = false;
|
|
36
32
|
}
|
|
@@ -45,14 +41,14 @@ class ToolLoaderService {
|
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
logger.info('初始化工具加载器...');
|
|
48
|
-
|
|
44
|
+
|
|
49
45
|
// 确保工具箱目录存在
|
|
50
|
-
const toolboxDir =
|
|
46
|
+
const toolboxDir = config.getToolboxDir();
|
|
51
47
|
await fs.ensureDir(toolboxDir);
|
|
52
|
-
|
|
48
|
+
|
|
53
49
|
// 扫描并加载所有工具
|
|
54
50
|
await this.scanAndLoadTools();
|
|
55
|
-
|
|
51
|
+
|
|
56
52
|
this.initialized = true;
|
|
57
53
|
logger.info(`工具加载器初始化完成,共加载 ${this.toolCache.size} 个工具`);
|
|
58
54
|
}
|
|
@@ -62,14 +58,14 @@ class ToolLoaderService {
|
|
|
62
58
|
*/
|
|
63
59
|
async scanAndLoadTools() {
|
|
64
60
|
for (const toolsDir of this.toolDirectories) {
|
|
65
|
-
if (!await pathExists(toolsDir)) {
|
|
61
|
+
if (!(await pathExists(toolsDir))) {
|
|
66
62
|
logger.debug(`工具目录不存在,跳过: ${toolsDir}`);
|
|
67
63
|
continue;
|
|
68
64
|
}
|
|
69
65
|
|
|
70
66
|
try {
|
|
71
67
|
const entries = await fs.readdir(toolsDir, { withFileTypes: true });
|
|
72
|
-
|
|
68
|
+
|
|
73
69
|
for (const entry of entries) {
|
|
74
70
|
if (!entry.isDirectory()) {
|
|
75
71
|
continue;
|
|
@@ -78,7 +74,7 @@ class ToolLoaderService {
|
|
|
78
74
|
const toolName = entry.name;
|
|
79
75
|
const toolDir = path.join(toolsDir, toolName);
|
|
80
76
|
const toolFile = path.join(toolDir, `${toolName}.tool.js`);
|
|
81
|
-
|
|
77
|
+
|
|
82
78
|
if (await pathExists(toolFile)) {
|
|
83
79
|
try {
|
|
84
80
|
await this.loadTool(toolName, toolFile);
|
|
@@ -129,7 +125,7 @@ class ToolLoaderService {
|
|
|
129
125
|
validateToolInterface(toolName, tool) {
|
|
130
126
|
// 必需的方法
|
|
131
127
|
const requiredMethods = ['execute'];
|
|
132
|
-
|
|
128
|
+
|
|
133
129
|
// 推荐的方法
|
|
134
130
|
const recommendedMethods = ['getMetadata', 'getSchema', 'getDependencies', 'getBusinessErrors'];
|
|
135
131
|
|
|
@@ -216,4 +212,3 @@ class ToolLoaderService {
|
|
|
216
212
|
|
|
217
213
|
// 导出单例实例
|
|
218
214
|
export const toolLoaderService = new ToolLoaderService();
|
|
219
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 工具日志记录服务
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* 职责:
|
|
5
5
|
* 1. 为每个工具提供独立的日志记录器
|
|
6
6
|
* 2. 日志自动写入到工具的 run.log 文件
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
|
|
11
11
|
import fs from 'fs-extra';
|
|
12
12
|
import path from 'path';
|
|
13
|
-
import os from 'os';
|
|
14
13
|
import { logger } from '../utils/logger.js';
|
|
15
14
|
import { pathExists } from './tool-utils.js';
|
|
15
|
+
import { config } from '../utils/config.js';
|
|
16
16
|
|
|
17
17
|
// 日志队列,用于批量写入
|
|
18
18
|
const logQueues = new Map();
|
|
@@ -38,27 +38,25 @@ export function getLogger(toolName) {
|
|
|
38
38
|
if (!logQueues.has(toolName)) {
|
|
39
39
|
logQueues.set(toolName, []);
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
const logQueue = logQueues.get(toolName);
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
return {
|
|
45
45
|
info: (message, meta) => log(toolName, 'INFO', message, meta),
|
|
46
46
|
warn: (message, meta) => log(toolName, 'WARN', message, meta),
|
|
47
47
|
error: (message, meta) => log(toolName, 'ERROR', message, meta),
|
|
48
48
|
debug: (message, meta) => log(toolName, 'DEBUG', message, meta)
|
|
49
49
|
};
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
function log(toolName, level, message, meta = {}) {
|
|
52
52
|
const timestamp = new Date().toISOString();
|
|
53
|
-
const metaStr = meta && Object.keys(meta).length > 0
|
|
54
|
-
|
|
55
|
-
: '';
|
|
56
|
-
|
|
53
|
+
const metaStr = meta && Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : '';
|
|
54
|
+
|
|
57
55
|
const logEntry = `[${timestamp}] [${level}] ${message}${metaStr}\n`;
|
|
58
|
-
|
|
56
|
+
|
|
59
57
|
// 添加到队列
|
|
60
58
|
logQueue.push(logEntry);
|
|
61
|
-
|
|
59
|
+
|
|
62
60
|
// 如果队列达到一定大小,立即刷新
|
|
63
61
|
if (logQueue.length >= 10) {
|
|
64
62
|
flushLogQueue(toolName).catch(error => {
|
|
@@ -84,38 +82,35 @@ async function flushLogQueue(toolName) {
|
|
|
84
82
|
if (!logQueue || logQueue.length === 0) {
|
|
85
83
|
return;
|
|
86
84
|
}
|
|
87
|
-
|
|
88
|
-
const toolDir =
|
|
85
|
+
|
|
86
|
+
const toolDir = config.getToolDir(toolName);
|
|
89
87
|
const logFilePath = path.join(toolDir, 'run.log');
|
|
90
|
-
|
|
88
|
+
|
|
91
89
|
try {
|
|
92
90
|
// 确保目录存在
|
|
93
91
|
await fs.ensureDir(toolDir);
|
|
94
|
-
|
|
92
|
+
|
|
95
93
|
// 读取现有日志(如果存在)
|
|
96
94
|
let existingLogs = '';
|
|
97
95
|
if (await pathExists(logFilePath)) {
|
|
98
96
|
existingLogs = await fs.readFile(logFilePath, 'utf-8');
|
|
99
97
|
}
|
|
100
|
-
|
|
98
|
+
|
|
101
99
|
// 清理过期日志
|
|
102
100
|
const cleanedLogs = cleanOldLogs(existingLogs);
|
|
103
|
-
|
|
101
|
+
|
|
104
102
|
// 合并新日志
|
|
105
103
|
const newLogs = logQueue.join('');
|
|
106
104
|
const allLogs = cleanedLogs + newLogs;
|
|
107
|
-
|
|
105
|
+
|
|
108
106
|
// 检查日志文件大小
|
|
109
|
-
const logsToWrite = allLogs.length > MAX_LOG_SIZE
|
|
110
|
-
|
|
111
|
-
: allLogs;
|
|
112
|
-
|
|
107
|
+
const logsToWrite = allLogs.length > MAX_LOG_SIZE ? keepRecentLogs(allLogs) : allLogs;
|
|
108
|
+
|
|
113
109
|
// 写入日志文件
|
|
114
110
|
await fs.writeFile(logFilePath, logsToWrite, 'utf-8');
|
|
115
|
-
|
|
111
|
+
|
|
116
112
|
// 清空队列
|
|
117
113
|
logQueue.length = 0;
|
|
118
|
-
|
|
119
114
|
} catch (error) {
|
|
120
115
|
logger.error(`写入工具日志失败: ${toolName}`, { error: error.message });
|
|
121
116
|
}
|
|
@@ -130,15 +125,15 @@ function cleanOldLogs(logs) {
|
|
|
130
125
|
const lines = logs.split('\n');
|
|
131
126
|
const now = Date.now();
|
|
132
127
|
const retentionMs = LOG_RETENTION_HOURS * 60 * 60 * 1000;
|
|
133
|
-
|
|
128
|
+
|
|
134
129
|
const validLines = [];
|
|
135
|
-
|
|
130
|
+
|
|
136
131
|
for (const line of lines) {
|
|
137
132
|
if (!line.trim()) {
|
|
138
133
|
validLines.push(line);
|
|
139
134
|
continue;
|
|
140
135
|
}
|
|
141
|
-
|
|
136
|
+
|
|
142
137
|
// 提取时间戳
|
|
143
138
|
const timestampMatch = line.match(/^\[([^\]]+)\]/);
|
|
144
139
|
if (timestampMatch) {
|
|
@@ -156,7 +151,7 @@ function cleanOldLogs(logs) {
|
|
|
156
151
|
validLines.push(line);
|
|
157
152
|
}
|
|
158
153
|
}
|
|
159
|
-
|
|
154
|
+
|
|
160
155
|
return validLines.join('\n');
|
|
161
156
|
}
|
|
162
157
|
|
|
@@ -168,7 +163,7 @@ function cleanOldLogs(logs) {
|
|
|
168
163
|
function keepRecentLogs(logs) {
|
|
169
164
|
const lines = logs.split('\n');
|
|
170
165
|
const recentLines = lines.slice(-MAX_LOG_LINES);
|
|
171
|
-
return recentLines.join('\n')
|
|
166
|
+
return `${recentLines.join('\n')}\n`;
|
|
172
167
|
}
|
|
173
168
|
|
|
174
169
|
/**
|
|
@@ -176,27 +171,27 @@ function keepRecentLogs(logs) {
|
|
|
176
171
|
*/
|
|
177
172
|
export function startLogCleanupTask() {
|
|
178
173
|
setInterval(async () => {
|
|
179
|
-
const toolboxDir =
|
|
180
|
-
|
|
181
|
-
if (!await pathExists(toolboxDir)) {
|
|
174
|
+
const toolboxDir = config.getToolboxDir();
|
|
175
|
+
|
|
176
|
+
if (!(await pathExists(toolboxDir))) {
|
|
182
177
|
return;
|
|
183
178
|
}
|
|
184
|
-
|
|
179
|
+
|
|
185
180
|
try {
|
|
186
181
|
const entries = await fs.readdir(toolboxDir, { withFileTypes: true });
|
|
187
|
-
|
|
182
|
+
|
|
188
183
|
for (const entry of entries) {
|
|
189
184
|
if (!entry.isDirectory()) {
|
|
190
185
|
continue;
|
|
191
186
|
}
|
|
192
|
-
|
|
187
|
+
|
|
193
188
|
const toolName = entry.name;
|
|
194
189
|
const logFilePath = path.join(toolboxDir, toolName, 'run.log');
|
|
195
|
-
|
|
190
|
+
|
|
196
191
|
if (await pathExists(logFilePath)) {
|
|
197
192
|
const logs = await fs.readFile(logFilePath, 'utf-8');
|
|
198
193
|
const cleanedLogs = cleanOldLogs(logs);
|
|
199
|
-
|
|
194
|
+
|
|
200
195
|
if (cleanedLogs.length < logs.length) {
|
|
201
196
|
await fs.writeFile(logFilePath, cleanedLogs, 'utf-8');
|
|
202
197
|
logger.debug(`清理工具日志: ${toolName}`);
|
|
@@ -207,7 +202,7 @@ export function startLogCleanupTask() {
|
|
|
207
202
|
logger.error('定期清理日志失败', { error: error.message });
|
|
208
203
|
}
|
|
209
204
|
}, CLEANUP_INTERVAL);
|
|
210
|
-
|
|
205
|
+
|
|
211
206
|
logger.info('工具日志清理任务已启动');
|
|
212
207
|
}
|
|
213
208
|
|
|
@@ -220,4 +215,3 @@ export async function flushAllLogQueues() {
|
|
|
220
215
|
await flushLogQueue(toolName);
|
|
221
216
|
}
|
|
222
217
|
}
|
|
223
|
-
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 统一工具管理处理器
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* 职责:
|
|
5
5
|
* 1. 实现 mcp__promptmanager__toolm 工具的处理逻辑
|
|
6
6
|
* 2. 路由到不同的模式处理器
|
|
7
7
|
* 3. 统一错误处理
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { logger } from '../utils/logger.js';
|
|
11
10
|
import { toolLoaderService } from './tool-loader.service.js';
|
|
12
11
|
import { parseToolYaml } from './tool-yaml-parser.service.js';
|
|
13
|
-
import {
|
|
14
|
-
handleManualMode,
|
|
15
|
-
handleExecuteMode,
|
|
16
|
-
handleConfigureMode,
|
|
17
|
-
handleLogMode
|
|
12
|
+
import {
|
|
13
|
+
handleManualMode,
|
|
14
|
+
handleExecuteMode,
|
|
15
|
+
handleConfigureMode,
|
|
16
|
+
handleLogMode
|
|
18
17
|
} from './tool-mode-handlers.service.js';
|
|
19
18
|
|
|
20
19
|
/**
|
|
@@ -24,7 +23,8 @@ import {
|
|
|
24
23
|
*/
|
|
25
24
|
export async function handleToolM(args) {
|
|
26
25
|
const { yaml: yamlInput } = args;
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
/* eslint-disable no-useless-catch */
|
|
28
28
|
try {
|
|
29
29
|
// 初始化工具加载器(如果尚未初始化)
|
|
30
30
|
if (!toolLoaderService.initialized) {
|
|
@@ -33,10 +33,13 @@ export async function handleToolM(args) {
|
|
|
33
33
|
|
|
34
34
|
// 解析 YAML 配置
|
|
35
35
|
const { toolName, mode, parameters } = parseToolYaml(yamlInput);
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
// 检查工具是否存在
|
|
38
38
|
if (!toolLoaderService.hasTool(toolName)) {
|
|
39
|
-
const availableTools = toolLoaderService
|
|
39
|
+
const availableTools = toolLoaderService
|
|
40
|
+
.getAllTools()
|
|
41
|
+
.map(t => t.name)
|
|
42
|
+
.join(', ');
|
|
40
43
|
throw new Error(`工具 '${toolName}' 不存在\n可用工具: ${availableTools}`);
|
|
41
44
|
}
|
|
42
45
|
|
|
@@ -44,20 +47,19 @@ export async function handleToolM(args) {
|
|
|
44
47
|
switch (mode) {
|
|
45
48
|
case 'manual':
|
|
46
49
|
return handleManualMode(toolName);
|
|
47
|
-
|
|
50
|
+
|
|
48
51
|
case 'execute':
|
|
49
52
|
return await handleExecuteMode(toolName, parameters);
|
|
50
|
-
|
|
53
|
+
|
|
51
54
|
case 'configure':
|
|
52
55
|
return await handleConfigureMode(toolName, parameters);
|
|
53
|
-
|
|
56
|
+
|
|
54
57
|
case 'log':
|
|
55
58
|
return await handleLogMode(toolName, parameters);
|
|
56
|
-
|
|
59
|
+
|
|
57
60
|
default:
|
|
58
61
|
throw new Error(`不支持的模式: ${mode}\n支持的模式: manual, execute, configure, log`);
|
|
59
62
|
}
|
|
60
|
-
|
|
61
63
|
} catch (error) {
|
|
62
64
|
// 错误已经在 parseToolYaml 中处理,直接抛出
|
|
63
65
|
throw error;
|