@becrafter/prompt-manager 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/desktop/package-lock.json +2 -2
- package/app/desktop/package.json +1 -1
- package/env.example +1 -1
- package/package.json +1 -1
- package/packages/server/app.js +3 -13
- package/packages/server/package.json +2 -0
- package/packages/server/services/TerminalService.js +11 -84
- package/packages/server/utils/config.js +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@becrafter/prompt-desktop",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@becrafter/prompt-desktop",
|
|
9
|
-
"version": "0.1.
|
|
9
|
+
"version": "0.1.17",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@becrafter/prompt-manager-core": "file:../../packages/server",
|
|
12
12
|
"@modelcontextprotocol/sdk": "^1.20.2",
|
package/app/desktop/package.json
CHANGED
package/env.example
CHANGED
package/package.json
CHANGED
package/packages/server/app.js
CHANGED
|
@@ -104,8 +104,8 @@ async function sendIndexHtml(req, res) {
|
|
|
104
104
|
// 从 adminUiRoot 中提取 asar 文件路径和相对路径
|
|
105
105
|
const asarPathMatch = adminUiRoot.match(/^(.*?\.asar)(\/.*)?$/);
|
|
106
106
|
const asarFilePath = asarPathMatch ? asarPathMatch[1] : adminUiRoot.replace(/\/.*$/, '.asar');
|
|
107
|
-
const relativePathInAsar = asarPathMatch && asarPathMatch[2] ? asarPathMatch[2].substring(1) : '
|
|
108
|
-
const indexPath = path.posix.join(relativePathInAsar, '
|
|
107
|
+
const relativePathInAsar = asarPathMatch && asarPathMatch[2] ? asarPathMatch[2].substring(1) : 'web';
|
|
108
|
+
const indexPath = path.posix.join(relativePathInAsar, 'index.html');
|
|
109
109
|
|
|
110
110
|
// 检查文件是否存在
|
|
111
111
|
const stat = asar.statFile(asarFilePath, indexPath);
|
|
@@ -121,17 +121,7 @@ async function sendIndexHtml(req, res) {
|
|
|
121
121
|
res.status(500).send('Internal Server Error');
|
|
122
122
|
}
|
|
123
123
|
} else {
|
|
124
|
-
|
|
125
|
-
const indexPath = path.join(adminUiRoot, 'index.html');
|
|
126
|
-
const adminPath = path.join(adminUiRoot, 'admin.html');
|
|
127
|
-
|
|
128
|
-
if (fs.existsSync(indexPath)) {
|
|
129
|
-
res.sendFile(indexPath);
|
|
130
|
-
} else if (fs.existsSync(adminPath)) {
|
|
131
|
-
res.sendFile(adminPath);
|
|
132
|
-
} else {
|
|
133
|
-
res.status(404).send('Admin UI not found');
|
|
134
|
-
}
|
|
124
|
+
res.sendFile(path.join(adminUiRoot, 'index.html'));
|
|
135
125
|
}
|
|
136
126
|
}
|
|
137
127
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"dev": "node --watch ./server.js",
|
|
11
11
|
"dev:clean": "node ./dev-server.js",
|
|
12
12
|
"fix:pty": "npm rebuild node-pty",
|
|
13
|
+
"postinstall": "npm run fix:pty",
|
|
13
14
|
"start": "node ./server.js",
|
|
14
15
|
"example": "node --experimental-specifier-resolution=node ./example.js",
|
|
15
16
|
"test": "vitest run tests/unit",
|
|
@@ -52,6 +53,7 @@
|
|
|
52
53
|
"http-proxy-middleware": "^3.0.5",
|
|
53
54
|
"js-yaml": "^4.1.0",
|
|
54
55
|
"multer": "^2.0.2",
|
|
56
|
+
"node-pty": "^1.0.0",
|
|
55
57
|
"ws": "^8.18.0",
|
|
56
58
|
"yaml": "^2.4.1",
|
|
57
59
|
"zod": "^3.23.8"
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
import { spawn } from 'child_process';
|
|
9
9
|
import { randomUUID } from 'crypto';
|
|
10
|
-
import fs from 'fs';
|
|
11
10
|
import { logger } from '../utils/logger.js';
|
|
12
11
|
import path from 'path';
|
|
13
12
|
import os from 'os';
|
|
@@ -250,37 +249,20 @@ export class TerminalService {
|
|
|
250
249
|
* 创建PTY进程
|
|
251
250
|
*/
|
|
252
251
|
async createPtyProcess(options) {
|
|
252
|
+
const shell = options.shell || this.getDefaultShellForPlatform();
|
|
253
|
+
const args = this.getShellArgs(shell);
|
|
253
254
|
const cwd = options.workingDirectory || os.homedir();
|
|
254
255
|
const env = { ...process.env, ...options.environment };
|
|
255
|
-
const shells = this.getShellCandidates(options.shell);
|
|
256
|
-
let lastError = null;
|
|
257
|
-
|
|
258
|
-
for (const candidate of shells) {
|
|
259
|
-
if (!candidate) continue;
|
|
260
|
-
const resolvedShell = this.resolveShellPath(candidate);
|
|
261
|
-
if (!resolvedShell) {
|
|
262
|
-
logger.debug(`Shell not found on system: ${candidate}`);
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
256
|
|
|
266
|
-
|
|
267
|
-
logger.debug(`Creating PTY with shell: ${resolvedShell}, args: ${args.join(' ')}, cwd: ${cwd}`);
|
|
257
|
+
logger.debug(`Creating PTY with shell: ${shell}, args: ${args.join(' ')}, cwd: ${cwd}`);
|
|
268
258
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
});
|
|
277
|
-
} catch (error) {
|
|
278
|
-
lastError = error;
|
|
279
|
-
logger.warn(`Failed to spawn shell ${resolvedShell}: ${error.message}`);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
throw lastError || new Error('Unable to create PTY session: no suitable shell found');
|
|
259
|
+
return pty.default.spawn(shell, args, {
|
|
260
|
+
name: 'xterm-color',
|
|
261
|
+
cols: options.size.cols,
|
|
262
|
+
rows: options.size.rows,
|
|
263
|
+
cwd: cwd,
|
|
264
|
+
env: env
|
|
265
|
+
});
|
|
284
266
|
}
|
|
285
267
|
|
|
286
268
|
/**
|
|
@@ -291,8 +273,7 @@ export class TerminalService {
|
|
|
291
273
|
case 'win32':
|
|
292
274
|
return process.env.COMSPEC || 'cmd.exe';
|
|
293
275
|
case 'darwin':
|
|
294
|
-
|
|
295
|
-
return process.env.SHELL || '/bin/zsh' || '/bin/bash';
|
|
276
|
+
return process.env.SHELL || '/bin/bash';
|
|
296
277
|
case 'linux':
|
|
297
278
|
return process.env.SHELL || '/bin/bash';
|
|
298
279
|
default:
|
|
@@ -310,63 +291,9 @@ export class TerminalService {
|
|
|
310
291
|
}
|
|
311
292
|
return ['/c'];
|
|
312
293
|
}
|
|
313
|
-
|
|
314
|
-
// 某些精简 shell(如 /bin/sh)不支持 -l
|
|
315
|
-
if (shell.endsWith('/sh')) {
|
|
316
|
-
return ['-i'];
|
|
317
|
-
}
|
|
318
|
-
|
|
319
294
|
return ['-l'];
|
|
320
295
|
}
|
|
321
296
|
|
|
322
|
-
/**
|
|
323
|
-
* 获取 shell 候选列表(按优先级)
|
|
324
|
-
*/
|
|
325
|
-
getShellCandidates(preferredShell) {
|
|
326
|
-
const candidates = [];
|
|
327
|
-
|
|
328
|
-
if (preferredShell) candidates.push(preferredShell);
|
|
329
|
-
if (process.env.SHELL) candidates.push(process.env.SHELL);
|
|
330
|
-
|
|
331
|
-
if (process.platform === 'darwin') {
|
|
332
|
-
candidates.push('/bin/zsh', '/bin/bash', '/bin/sh');
|
|
333
|
-
} else if (process.platform === 'linux') {
|
|
334
|
-
candidates.push('/bin/bash', '/bin/sh');
|
|
335
|
-
} else if (process.platform === 'win32') {
|
|
336
|
-
candidates.push(process.env.COMSPEC || 'cmd.exe');
|
|
337
|
-
} else {
|
|
338
|
-
candidates.push('/bin/sh');
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
return [...new Set(candidates)];
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
/**
|
|
345
|
-
* 确保 shell 路径在当前系统存在
|
|
346
|
-
*/
|
|
347
|
-
resolveShellPath(shellPath) {
|
|
348
|
-
// 绝对路径直接检查
|
|
349
|
-
if (shellPath.startsWith('/')) {
|
|
350
|
-
return fs.existsSync(shellPath) ? shellPath : null;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// Windows 可执行文件
|
|
354
|
-
if (process.platform === 'win32') {
|
|
355
|
-
return shellPath;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// 如果是相对路径,尝试在常见目录查找
|
|
359
|
-
const searchPaths = ['/bin', '/usr/bin', '/usr/local/bin'];
|
|
360
|
-
for (const base of searchPaths) {
|
|
361
|
-
const fullPath = path.join(base, shellPath);
|
|
362
|
-
if (fs.existsSync(fullPath)) {
|
|
363
|
-
return fullPath;
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
return null;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
297
|
/**
|
|
371
298
|
* 获取会话
|
|
372
299
|
*/
|
|
@@ -121,7 +121,7 @@ export class Config {
|
|
|
121
121
|
|
|
122
122
|
// 其他配置
|
|
123
123
|
this.serverName = process.env.MCP_SERVER_NAME || 'prompt-manager';
|
|
124
|
-
this.serverVersion = process.env.MCP_SERVER_VERSION || '0.1.
|
|
124
|
+
this.serverVersion = process.env.MCP_SERVER_VERSION || '0.1.17';
|
|
125
125
|
this.logLevel = process.env.LOG_LEVEL || 'info';
|
|
126
126
|
this.maxPrompts = parseInt(process.env.MAX_PROMPTS) || 1000;
|
|
127
127
|
this.recursiveScan = process.env.RECURSIVE_SCAN !== 'false'; // 默认启用递归扫描
|