@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
package/packages/server/app.js
CHANGED
|
@@ -30,18 +30,18 @@ function serveAsarStatic(root) {
|
|
|
30
30
|
try {
|
|
31
31
|
// 动态导入 asar 模块(在 ES 模块环境中)
|
|
32
32
|
const { default: asar } = await import('@electron/asar');
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
// 从 root 中提取 asar 文件路径和相对路径
|
|
35
35
|
const asarPathMatch = root.match(/^(.*?\.asar)(\/.*)?$/);
|
|
36
36
|
const asarFilePath = asarPathMatch ? asarPathMatch[1] : root.replace(/\/.*$/, '.asar');
|
|
37
37
|
const relativePathInAsar = asarPathMatch && asarPathMatch[2] ? asarPathMatch[2].substring(1) : 'web';
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
const filePath = path.posix.join(relativePathInAsar, req.path).replace(/^\//, '');
|
|
40
40
|
const stat = asar.statFile(asarFilePath, filePath);
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
if (stat) {
|
|
43
43
|
const fileContent = asar.extractFile(asarFilePath, filePath);
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
// 设置适当的 Content-Type
|
|
46
46
|
const ext = path.extname(filePath).toLowerCase();
|
|
47
47
|
const mimeTypes = {
|
|
@@ -55,11 +55,11 @@ function serveAsarStatic(root) {
|
|
|
55
55
|
'.svg': 'image/svg+xml',
|
|
56
56
|
'.ico': 'image/x-icon'
|
|
57
57
|
};
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
if (mimeTypes[ext]) {
|
|
60
60
|
res.setHeader('Content-Type', mimeTypes[ext]);
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
res.send(fileContent);
|
|
64
64
|
} else {
|
|
65
65
|
next();
|
|
@@ -80,7 +80,6 @@ app.use(cors());
|
|
|
80
80
|
app.use(express.json({ limit: '8mb' }));
|
|
81
81
|
app.use(express.urlencoded({ extended: true }));
|
|
82
82
|
|
|
83
|
-
|
|
84
83
|
// 为管理员界面提供静态文件服务 - 根路径
|
|
85
84
|
// 检查是否需要使用 ASAR 处理(需要验证 .asar 文件实际上存在)
|
|
86
85
|
const isAsarPath = adminUiRoot.includes('.asar') && fs.existsSync(adminUiRoot.replace(/\/.*$/, '.asar'));
|
|
@@ -100,13 +99,13 @@ async function sendIndexHtml(req, res) {
|
|
|
100
99
|
try {
|
|
101
100
|
// 动态导入 asar 模块(在 ES 模块环境中)
|
|
102
101
|
const { default: asar } = await import('@electron/asar');
|
|
103
|
-
|
|
102
|
+
|
|
104
103
|
// 从 adminUiRoot 中提取 asar 文件路径和相对路径
|
|
105
104
|
const asarPathMatch = adminUiRoot.match(/^(.*?\.asar)(\/.*)?$/);
|
|
106
105
|
const asarFilePath = asarPathMatch ? asarPathMatch[1] : adminUiRoot.replace(/\/.*$/, '.asar');
|
|
107
106
|
const relativePathInAsar = asarPathMatch && asarPathMatch[2] ? asarPathMatch[2].substring(1) : 'web';
|
|
108
107
|
const indexPath = path.posix.join(relativePathInAsar, 'index.html');
|
|
109
|
-
|
|
108
|
+
|
|
110
109
|
// 检查文件是否存在
|
|
111
110
|
const stat = asar.statFile(asarFilePath, indexPath);
|
|
112
111
|
if (stat) {
|
|
@@ -129,13 +128,12 @@ async function sendIndexHtml(req, res) {
|
|
|
129
128
|
app.get(config.adminPath, sendIndexHtml);
|
|
130
129
|
|
|
131
130
|
// 为管理员界面提供根路径访问(当用户访问 /admin/ 时显示 index.html)
|
|
132
|
-
app.get(config.adminPath
|
|
133
|
-
|
|
131
|
+
app.get(`${config.adminPath}/`, sendIndexHtml);
|
|
134
132
|
|
|
135
133
|
// 健康检查端点
|
|
136
134
|
app.get('/health', (req, res) => {
|
|
137
|
-
res.status(200).json({
|
|
138
|
-
status: 'ok',
|
|
135
|
+
res.status(200).json({
|
|
136
|
+
status: 'ok',
|
|
139
137
|
timestamp: new Date().toISOString(),
|
|
140
138
|
uptime: process.uptime(),
|
|
141
139
|
port: config.getPort(),
|
|
@@ -155,7 +153,6 @@ app.use('/surge', surgeRouter);
|
|
|
155
153
|
// 注册工具API
|
|
156
154
|
app.use('/tool', toolRouter);
|
|
157
155
|
|
|
158
|
-
|
|
159
156
|
const transports = {};
|
|
160
157
|
const mcpServers = {}; // 存储每个会话的MCP服务器实例
|
|
161
158
|
const eventStores = {}; // 存储每个会话的事件存储,以支持会话恢复
|
|
@@ -198,7 +195,7 @@ function attachTransportLifecycle(transport) {
|
|
|
198
195
|
scheduleSessionCleanup(sid);
|
|
199
196
|
};
|
|
200
197
|
|
|
201
|
-
transport.onerror =
|
|
198
|
+
transport.onerror = error => {
|
|
202
199
|
console.error('MCP Transport error:', error);
|
|
203
200
|
};
|
|
204
201
|
}
|
|
@@ -208,7 +205,7 @@ app.all('/mcp', (req, res) => {
|
|
|
208
205
|
try {
|
|
209
206
|
let transport;
|
|
210
207
|
const sessionId = req.headers['mcp-session-id'] || '';
|
|
211
|
-
|
|
208
|
+
|
|
212
209
|
if (sessionId && transports[sessionId]) {
|
|
213
210
|
const existingTransport = transports[sessionId];
|
|
214
211
|
// Check if the transport is of the correct type
|
|
@@ -218,12 +215,12 @@ app.all('/mcp', (req, res) => {
|
|
|
218
215
|
} else {
|
|
219
216
|
// Transport exists but is not a StreamableHTTPServerTransport (could be SSEServerTransport)
|
|
220
217
|
res.status(400).json({
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
218
|
+
jsonrpc: '2.0',
|
|
219
|
+
error: {
|
|
220
|
+
code: -32000,
|
|
221
|
+
message: 'Bad Request: Session exists but uses a different transport protocol'
|
|
222
|
+
},
|
|
223
|
+
id: null
|
|
227
224
|
});
|
|
228
225
|
return;
|
|
229
226
|
}
|
|
@@ -231,51 +228,51 @@ app.all('/mcp', (req, res) => {
|
|
|
231
228
|
// 断线后尝试恢复会话:为已有会话重新创建 transport
|
|
232
229
|
const eventStore = eventStores[sessionId];
|
|
233
230
|
transport = new StreamableHTTPServerTransport({
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
231
|
+
sessionIdGenerator: () => sessionId,
|
|
232
|
+
eventStore,
|
|
233
|
+
onsessioninitialized: async () => {
|
|
234
|
+
// 已有会话,不需要重新初始化
|
|
235
|
+
transports[sessionId] = transport;
|
|
236
|
+
// 重新连接已有的 MCP server
|
|
237
|
+
try {
|
|
238
|
+
const server = mcpServers[sessionId];
|
|
239
|
+
server.connect(transport);
|
|
240
|
+
console.log(`MCP server reconnected for session ${sessionId}`);
|
|
241
|
+
} catch (error) {
|
|
242
|
+
console.error('会话恢复失败:', error);
|
|
247
243
|
}
|
|
244
|
+
}
|
|
248
245
|
});
|
|
249
246
|
// 确保立即记录 transport
|
|
250
247
|
transports[sessionId] = transport;
|
|
251
248
|
attachTransportLifecycle(transport);
|
|
252
249
|
// 若存在延迟清理计时器,先取消
|
|
253
250
|
if (sessionCleanupTimers[sessionId]) {
|
|
254
|
-
|
|
255
|
-
|
|
251
|
+
clearTimeout(sessionCleanupTimers[sessionId]);
|
|
252
|
+
delete sessionCleanupTimers[sessionId];
|
|
256
253
|
}
|
|
257
254
|
} else if (!sessionId && req.method === 'POST' && isInitializeRequest(req.body)) {
|
|
258
255
|
const eventStore = new InMemoryEventStore();
|
|
259
256
|
|
|
260
257
|
transport = new StreamableHTTPServerTransport({
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
258
|
+
sessionIdGenerator: () => randomUUID(),
|
|
259
|
+
eventStore, // Enable resumability
|
|
260
|
+
onsessioninitialized: async sessionId => {
|
|
261
|
+
// Store the transport by session ID when session is initialized
|
|
262
|
+
console.log(`StreamableHTTP session initialized with ID: ${sessionId}`);
|
|
263
|
+
transports[sessionId] = transport;
|
|
264
|
+
eventStores[sessionId] = eventStore;
|
|
265
|
+
|
|
266
|
+
try {
|
|
267
|
+
// 为新会话创建MCP服务器实例(同步等待完成)
|
|
268
|
+
const server = await getMcpServer();
|
|
269
|
+
mcpServers[sessionId] = server;
|
|
270
|
+
server.connect(transport);
|
|
271
|
+
console.log(`MCP server connected for session ${sessionId}`);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
console.error('创建MCP服务器失败:', error);
|
|
278
274
|
}
|
|
275
|
+
}
|
|
279
276
|
});
|
|
280
277
|
|
|
281
278
|
// 统一注册关闭/错误处理(含延迟清理)
|
|
@@ -283,40 +280,40 @@ app.all('/mcp', (req, res) => {
|
|
|
283
280
|
} else {
|
|
284
281
|
// Invalid request - no session ID or not initialization request
|
|
285
282
|
res.status(400).json({
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
283
|
+
jsonrpc: '2.0',
|
|
284
|
+
error: {
|
|
285
|
+
code: -32000,
|
|
286
|
+
message: 'Bad Request: No valid session ID provided'
|
|
287
|
+
},
|
|
288
|
+
id: null
|
|
292
289
|
});
|
|
293
290
|
return;
|
|
294
291
|
}
|
|
295
|
-
|
|
292
|
+
|
|
296
293
|
// Handle the request with the transport
|
|
297
294
|
transport.handleRequest(req, res, req.body);
|
|
298
295
|
} catch (error) {
|
|
299
|
-
logger.error(
|
|
296
|
+
logger.error(`Error handling MCP request: ${error.message}`);
|
|
300
297
|
return res.status(500).json({
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
298
|
+
jsonrpc: '2.0',
|
|
299
|
+
error: {
|
|
300
|
+
code: -32603,
|
|
301
|
+
message: 'Internal server error'
|
|
302
|
+
},
|
|
303
|
+
id: null
|
|
307
304
|
});
|
|
308
305
|
}
|
|
309
306
|
});
|
|
310
307
|
|
|
311
308
|
// 错误处理中间件
|
|
312
|
-
app.use((err, req, res,
|
|
309
|
+
app.use((err, req, res, _next) => {
|
|
313
310
|
console.error(`[服务器错误]: ${err.message}`);
|
|
314
|
-
res.status(500).send('Internal Server Error')
|
|
311
|
+
res.status(500).send('Internal Server Error');
|
|
315
312
|
});
|
|
316
313
|
|
|
317
314
|
// 404处理
|
|
318
315
|
app.use((req, res) => {
|
|
319
|
-
res.status(404).send('Not Found')
|
|
316
|
+
res.status(404).send('Not Found');
|
|
320
317
|
});
|
|
321
318
|
|
|
322
319
|
// 导出清理函数
|
|
@@ -333,8 +330,8 @@ export function cleanupMcpSessions() {
|
|
|
333
330
|
}
|
|
334
331
|
delete transports[sessionId];
|
|
335
332
|
}
|
|
336
|
-
|
|
333
|
+
|
|
337
334
|
// 注意:mcpServers 对象在 app.js 中不可访问,需要在 server.js 中处理
|
|
338
335
|
}
|
|
339
336
|
|
|
340
|
-
export default app;
|
|
337
|
+
export default app;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"last_updated": "2026-01-11",
|
|
4
|
+
|
|
5
|
+
"authors": {
|
|
6
|
+
"becrafter": {
|
|
7
|
+
"name": "BeCrafter",
|
|
8
|
+
"github": "https://github.com/BeCrafter",
|
|
9
|
+
"homepage": "https://github.com/BeCrafter",
|
|
10
|
+
"bio": "让AI提示词管理变得简单而强大",
|
|
11
|
+
"featured": true,
|
|
12
|
+
"sort_order": 1,
|
|
13
|
+
"aliases": ["默认", "空", "Prompt Manager", "prompt-manager", "system", "promptmanager"]
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
"luban": {
|
|
17
|
+
"name": "鲁班",
|
|
18
|
+
"github": "https://github.com/Deepractice",
|
|
19
|
+
"homepage": "https://github.com/Deepractice",
|
|
20
|
+
"bio": "Prompt Manager 工具开发大师 | AI Agent 工具集创造者",
|
|
21
|
+
"featured": true,
|
|
22
|
+
"sort_order": 2
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
"nuwa": {
|
|
26
|
+
"name": "女娲",
|
|
27
|
+
"github": "https://github.com/Deepractice",
|
|
28
|
+
"homepage": "https://github.com/Deepractice",
|
|
29
|
+
"bio": "AI角色创造专家 | Prompt Manager 角色系统设计者",
|
|
30
|
+
"featured": true,
|
|
31
|
+
"sort_order": 3
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
"settings": {
|
|
36
|
+
"default_author": "becrafter",
|
|
37
|
+
"cache_avatar_hours": 24,
|
|
38
|
+
"default_avatar_emoji": "👤"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
name:
|
|
2
|
-
provider:
|
|
3
|
-
model:
|
|
4
|
-
apiEndpoint:
|
|
5
|
-
apiKey:
|
|
6
|
-
enabled: true
|
|
1
|
+
name: 'BigModel'
|
|
2
|
+
provider: 'BigModel'
|
|
3
|
+
model: 'glm-4.5-air'
|
|
4
|
+
apiEndpoint: 'https://open.bigmodel.cn/api/paas/v4/chat/completions'
|
|
5
|
+
apiKey: 'ba6397b3478a47c79938c98b822a3ced.fGPlm03ACPDDsbmL'
|
|
6
|
+
enabled: true
|
package/packages/server/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Prompt Manager Core Library
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* This is the main entry point for the Prompt Manager core library.
|
|
5
5
|
* It exports the main server functionality and utility functions.
|
|
6
6
|
*/
|
|
@@ -21,13 +21,7 @@ export { promptManager } from './services/manager.js';
|
|
|
21
21
|
|
|
22
22
|
// Export MCP functionality
|
|
23
23
|
export { getMcpServer } from './mcp/mcp.server.js';
|
|
24
|
-
export {
|
|
25
|
-
handleGetPrompt,
|
|
26
|
-
handleSearchPrompts,
|
|
27
|
-
handleReloadPrompts
|
|
28
|
-
} from './mcp/prompt.handler.js';
|
|
29
|
-
export { handleSequentialThinking } from './mcp/sequential-thinking.handler.js';
|
|
30
|
-
export { handleThinkPlan } from './mcp/think-plan.handler.js';
|
|
24
|
+
export { handleGetPrompt, handleSearchPrompts, handleReloadPrompts } from './mcp/prompt.handler.js';
|
|
31
25
|
export { handleToolM } from './toolm/index.js';
|
|
32
26
|
|
|
33
27
|
// Export API routes
|
|
@@ -36,4 +30,4 @@ export { openRouter } from './api/open.routes.js';
|
|
|
36
30
|
export { surgeRouter } from './api/surge.routes.js';
|
|
37
31
|
|
|
38
32
|
// Export middlewares
|
|
39
|
-
export { adminAuthMiddleware } from './middlewares/auth.middleware.js';
|
|
33
|
+
export { adminAuthMiddleware } from './middlewares/auth.middleware.js';
|
|
@@ -44,7 +44,7 @@ export function patchStreamableHTTPHeartbeat() {
|
|
|
44
44
|
|
|
45
45
|
const proto = StreamableHTTPServerTransport.prototype;
|
|
46
46
|
|
|
47
|
-
const wrap =
|
|
47
|
+
const wrap = original => {
|
|
48
48
|
return async function wrapped(...args) {
|
|
49
49
|
const res = args[1];
|
|
50
50
|
try {
|
|
@@ -69,5 +69,3 @@ export function patchStreamableHTTPHeartbeat() {
|
|
|
69
69
|
proto.handlePostRequest = wrap(proto.handlePostRequest);
|
|
70
70
|
proto.replayEvents = wrap(proto.replayEvents);
|
|
71
71
|
}
|
|
72
|
-
|
|
73
|
-
|
|
@@ -1,149 +1,79 @@
|
|
|
1
1
|
import { config } from '../utils/config.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
|
-
import {
|
|
5
|
-
handleGetPrompt,
|
|
6
|
-
handleSearchPrompts,
|
|
7
|
-
handleReloadPrompts,
|
|
8
|
-
handlePrompts
|
|
9
|
-
} from './prompt.handler.js';
|
|
4
|
+
import { handlePrompts } from './prompt.handler.js';
|
|
10
5
|
import { handleToolM } from '../toolm/index.js';
|
|
11
|
-
import { handleThinkingToolkit, THINKING_SCENARIOS } from './thinking-toolkit.handler.js';
|
|
12
|
-
// import { generateToolmDescription } from '../toolm/tool-description-generator.service.js';
|
|
13
6
|
import { generateToolmDescription } from '../toolm/tool-description-generator-optimized.service.js';
|
|
14
7
|
import { toolLoaderService } from '../toolm/tool-loader.service.js';
|
|
15
8
|
|
|
16
|
-
const sequentialThinkingPayloadSchema = z.object({
|
|
17
|
-
thought: z.string().describe('当前思考内容,是顺序思考步骤的主体'),
|
|
18
|
-
nextThoughtNeeded: z.boolean().optional().describe('是否继续向下一个思考步骤推进'),
|
|
19
|
-
thoughtNumber: z.number().int().min(1).optional().describe('显式指定此次思考的编号'),
|
|
20
|
-
totalThoughts: z.number().int().min(1).optional().describe('预计需要的总思考步数'),
|
|
21
|
-
isRevision: z.boolean().optional().describe('该思考是否用于修订之前的结果'),
|
|
22
|
-
revisesThought: z.number().int().min(1).optional().describe('若为修订,指向被修订的思考编号'),
|
|
23
|
-
branchFromThought: z.number().int().min(1).optional().describe('创建分支时,来源的思考编号'),
|
|
24
|
-
branchId: z.string().optional().describe('为新的思考分支设置的标识'),
|
|
25
|
-
needsMoreThoughts: z.boolean().optional().describe('终点后发现仍需更多思考时标记为 true')
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const thinkPlanPayloadSchema = z.object({
|
|
29
|
-
thought: z.string().describe('对当前任务的分析、假设或洞见'),
|
|
30
|
-
plan: z.string().describe('将任务拆分为可执行步骤的计划文本'),
|
|
31
|
-
action: z.string().describe('下一步需要执行的具体行动'),
|
|
32
|
-
thoughtNumber: z.string().describe('思考步骤编号,用于追踪整个规划过程'),
|
|
33
|
-
sessionId: z.string().optional().describe('可选的会话标识,区分并行任务')
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const metaSchema = z.object({
|
|
37
|
-
scenario: z.string().describe('思考场景:exploratory(顺序思考)或 execution(思考规划)').optional(),
|
|
38
|
-
progressToken: z.any().optional()
|
|
39
|
-
}).catchall(z.any());
|
|
40
|
-
|
|
41
|
-
const thinkingToolkitPayloadSchema = z.object({
|
|
42
|
-
thought: z.string().optional().describe('思考内容(两种场景都依赖)'),
|
|
43
|
-
thoughtNumber: z.union([z.string(), z.number()]).optional().describe('思考编号;execution 场景必填,可使用字符串或数字'),
|
|
44
|
-
plan: z.string().optional().describe('execution 场景:将任务拆分成可执行步骤'),
|
|
45
|
-
action: z.string().optional().describe('execution 场景:下一步可验证的行动'),
|
|
46
|
-
sessionId: z.string().optional().describe('execution 场景:可选会话标识'),
|
|
47
|
-
nextThoughtNeeded: z.boolean().optional().describe('exploratory 场景:是否继续下一步'),
|
|
48
|
-
totalThoughts: z.number().int().min(1).optional().describe('exploratory 场景:预计总步数'),
|
|
49
|
-
isRevision: z.boolean().optional().describe('exploratory 场景:是否为修订'),
|
|
50
|
-
revisesThought: z.number().int().min(1).optional().describe('exploratory 场景:被修订的编号'),
|
|
51
|
-
branchFromThought: z.number().int().min(1).optional().describe('exploratory 场景:分支起点编号'),
|
|
52
|
-
branchId: z.string().optional().describe('exploratory 场景:分支 ID'),
|
|
53
|
-
needsMoreThoughts: z.boolean().optional().describe('exploratory 场景:终点后仍需继续时标记')
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const thinkingToolkitInputSchema = {
|
|
57
|
-
scenario: z.enum(
|
|
58
|
-
[THINKING_SCENARIOS.EXPLORATORY, THINKING_SCENARIOS.EXECUTION],
|
|
59
|
-
{
|
|
60
|
-
description: '思考场景:exploratory(顺序思考)或 execution(思考规划)'
|
|
61
|
-
}
|
|
62
|
-
).optional(),
|
|
63
|
-
payload: thinkingToolkitPayloadSchema.optional().describe('根据场景填写对应字段;缺省或 null 时仅返回说明'),
|
|
64
|
-
_meta: metaSchema.optional()
|
|
65
|
-
};
|
|
66
|
-
|
|
67
9
|
class Server {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
10
|
+
constructor() {
|
|
11
|
+
this.server = new McpServer(
|
|
12
|
+
{
|
|
13
|
+
name: 'Prompt Management Server',
|
|
14
|
+
version: config.getServerVersion()
|
|
15
|
+
},
|
|
16
|
+
{ capabilities: { logging: {} } }
|
|
17
|
+
);
|
|
18
|
+
}
|
|
77
19
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
20
|
+
registerTools(tools) {
|
|
21
|
+
for (const tool of tools) {
|
|
22
|
+
this.server.registerTool(
|
|
23
|
+
tool.name,
|
|
24
|
+
{
|
|
25
|
+
description: tool.description,
|
|
26
|
+
inputSchema: tool.inputSchema
|
|
27
|
+
},
|
|
28
|
+
tool.handler
|
|
29
|
+
);
|
|
88
30
|
}
|
|
31
|
+
}
|
|
89
32
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
33
|
+
getServer() {
|
|
34
|
+
return this.server;
|
|
35
|
+
}
|
|
93
36
|
}
|
|
94
37
|
|
|
95
38
|
export const getMcpServer = async () => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
39
|
+
const mcpServer = new Server();
|
|
40
|
+
|
|
41
|
+
// 确保工具加载器已初始化(用于生成动态描述)
|
|
42
|
+
if (!toolLoaderService.initialized) {
|
|
43
|
+
try {
|
|
44
|
+
await toolLoaderService.initialize();
|
|
45
|
+
} catch (error) {
|
|
46
|
+
// 如果初始化失败,继续使用默认描述
|
|
47
|
+
console.warn('工具加载器初始化失败,使用默认描述:', error.message);
|
|
106
48
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
// }
|
|
139
|
-
// {
|
|
140
|
-
// name: 'reload_prompts',
|
|
141
|
-
// description: 'Force a reload of all preset prompts to overwrite the cache.',
|
|
142
|
-
// inputSchema: {},
|
|
143
|
-
// handler: async (args) => {
|
|
144
|
-
// return handleReloadPrompts(args);
|
|
145
|
-
// }
|
|
146
|
-
// }
|
|
147
|
-
]);
|
|
148
|
-
return mcpServer.getServer();
|
|
149
|
-
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 动态生成 toolm 工具的描述
|
|
52
|
+
const toolmDescription = generateToolmDescription();
|
|
53
|
+
|
|
54
|
+
mcpServer.registerTools([
|
|
55
|
+
{
|
|
56
|
+
name: 'prompts',
|
|
57
|
+
description:
|
|
58
|
+
'🤖 **提示词助手** - 你的AI提示词管家\n\n【规范名称】promptmanager_prompts\n【调用说明】在提示词中使用 promptmanager_prompts,实际调用时自动映射到 mcp__[server]__action\n\n我可以帮你找到并使用各种专业的提示词,让AI变得更聪明、更专业。\n\n## 我能做什么\n- 🔍 **找提示词** - 告诉我你想要什么功能,我帮你搜索匹配的提示词\n- 📋 **用提示词** - 帮你加载并应用专业的提示词到对话中\n- 📚 **逛提示词库** - 带你浏览所有可用的提示词,了解有什么可以用的\n\n## 在对话中怎么和我说\n\n**想找提示词时可以说:**\n- "帮我找找代码审查相关的提示词"\n- "有什么标题生成的提示词可以用吗?"\n- "我想看看所有可用的提示词"\n\n**想用某个提示词时可以说:**\n- "用代码审查的提示词帮我看看这段代码"\n- "加载标题生成器,我要写文章标题"\n- "用文档生成提示词帮我写API文档"\n\n## 实际使用示例\n\n```json\n// 对话中的自然表达:\n// "我想找个代码审查的提示词"\n{"action": "search", "query": "代码审查"}\n\n// "帮我用标题生成器"\n{"action": "get", "query": "examples-prompts-generator-gen_title"}\n\n// "看看有什么提示词可以用"\n{"action": "search"}\n```\n\n**提示:** 先搜索找到合适的提示词ID,然后用"get"加载它,就能直接在对话中使用啦!',
|
|
59
|
+
inputSchema: {
|
|
60
|
+
action: z.enum(['search', 'get']).describe('操作类型:search(搜索提示词) 或 get(获取提示词详情)'),
|
|
61
|
+
query: z.string().optional().describe('搜索关键词(用于search) 或 提示词ID/名称(用于get)')
|
|
62
|
+
},
|
|
63
|
+
handler: async args => {
|
|
64
|
+
return handlePrompts(args);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'toolm',
|
|
69
|
+
description: toolmDescription,
|
|
70
|
+
inputSchema: {
|
|
71
|
+
yaml: z.string().describe('YAML 格式的工具调用配置')
|
|
72
|
+
},
|
|
73
|
+
handler: async args => {
|
|
74
|
+
return handleToolM(args);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
]);
|
|
78
|
+
return mcpServer.getServer();
|
|
79
|
+
};
|