@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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@becrafter/prompt-desktop",
3
- "version": "0.1.15",
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.15",
9
+ "version": "0.1.17",
10
10
  "dependencies": {
11
11
  "@becrafter/prompt-manager-core": "file:../../packages/server",
12
12
  "@modelcontextprotocol/sdk": "^1.20.2",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@becrafter/prompt-desktop",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Menu bar desktop wrapper for @becrafter/prompt-manager",
5
5
  "author": "BeCrafter",
6
6
  "homepage": "https://github.com/BeCrafter/prompt-manager",
package/env.example CHANGED
@@ -7,7 +7,7 @@ PROMPTS_DIR=$HOME/.prompt-manager/prompts
7
7
 
8
8
  # MCP服务器配置
9
9
  MCP_SERVER_NAME=prompt-manager
10
- MCP_SERVER_VERSION=0.1.15
10
+ MCP_SERVER_VERSION=0.1.17
11
11
 
12
12
  # 日志级别 (error, warn, info, debug)
13
13
  LOG_LEVEL=info
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@becrafter/prompt-manager",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "Remote MCP Server for managing prompts",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -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) : 'packages/web';
108
- const indexPath = path.posix.join(relativePathInAsar, 'admin.html');
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
- // 优先查找 index.html,如果不存在则使用 admin.html
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
- const args = this.getShellArgs(resolvedShell);
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
- try {
270
- return pty.default.spawn(resolvedShell, args, {
271
- name: 'xterm-color',
272
- cols: options.size.cols,
273
- rows: options.size.rows,
274
- cwd: cwd,
275
- env: env
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
- // macOS 上优先使用用户的 SHELL 环境变量
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.15';
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'; // 默认启用递归扫描