@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.
Files changed (114) hide show
  1. package/package.json +31 -24
  2. package/packages/resources/tools/agent-browser/README.md +640 -0
  3. package/packages/resources/tools/agent-browser/agent-browser.tool.js +1389 -0
  4. package/packages/resources/tools/thinking/README.md +324 -0
  5. package/packages/resources/tools/thinking/thinking.tool.js +911 -0
  6. package/packages/server/README.md +3 -4
  7. package/packages/server/api/admin.routes.js +668 -664
  8. package/packages/server/api/open.routes.js +68 -67
  9. package/packages/server/api/surge.routes.js +5 -6
  10. package/packages/server/api/tool.routes.js +70 -71
  11. package/packages/server/app.js +70 -73
  12. package/packages/server/configs/authors.json +40 -0
  13. package/packages/server/configs/models/built-in/bigmodel.yaml +6 -6
  14. package/packages/server/configs/models/providers.yaml +4 -4
  15. package/packages/server/configs/templates/built-in/general-iteration.yaml +1 -1
  16. package/packages/server/configs/templates/built-in/general-optimize.yaml +1 -1
  17. package/packages/server/configs/templates/built-in/output-format-optimize.yaml +1 -1
  18. package/packages/server/index.js +3 -9
  19. package/packages/server/mcp/heartbeat-patch.js +1 -3
  20. package/packages/server/mcp/mcp.server.js +64 -134
  21. package/packages/server/mcp/prompt.handler.js +101 -95
  22. package/packages/server/middlewares/auth.middleware.js +31 -31
  23. package/packages/server/server.js +60 -45
  24. package/packages/server/services/TerminalService.js +156 -70
  25. package/packages/server/services/WebSocketService.js +35 -34
  26. package/packages/server/services/author-config.service.js +199 -0
  27. package/packages/server/services/manager.js +66 -60
  28. package/packages/server/services/model.service.js +5 -9
  29. package/packages/server/services/optimization.service.js +25 -22
  30. package/packages/server/services/template.service.js +3 -8
  31. package/packages/server/toolm/author-sync.service.js +97 -0
  32. package/packages/server/toolm/index.js +1 -2
  33. package/packages/server/toolm/package-installer.service.js +47 -50
  34. package/packages/server/toolm/tool-context.service.js +64 -62
  35. package/packages/server/toolm/tool-dependency.service.js +28 -30
  36. package/packages/server/toolm/tool-description-generator-optimized.service.js +55 -55
  37. package/packages/server/toolm/tool-description-generator.service.js +20 -23
  38. package/packages/server/toolm/tool-environment.service.js +45 -44
  39. package/packages/server/toolm/tool-execution.service.js +49 -48
  40. package/packages/server/toolm/tool-loader.service.js +13 -18
  41. package/packages/server/toolm/tool-logger.service.js +33 -39
  42. package/packages/server/toolm/tool-manager.handler.js +17 -15
  43. package/packages/server/toolm/tool-manual-generator.service.js +107 -87
  44. package/packages/server/toolm/tool-mode-handlers.service.js +52 -59
  45. package/packages/server/toolm/tool-storage.service.js +11 -12
  46. package/packages/server/toolm/tool-sync.service.js +36 -39
  47. package/packages/server/toolm/tool-utils.js +0 -1
  48. package/packages/server/toolm/tool-yaml-parser.service.js +12 -11
  49. package/packages/server/toolm/validate-system.js +56 -84
  50. package/packages/server/utils/config.js +97 -12
  51. package/packages/server/utils/logger.js +1 -1
  52. package/packages/server/utils/port-checker.js +8 -8
  53. package/packages/server/utils/util.js +470 -467
  54. package/packages/resources/tools/cognitive-thinking/README.md +0 -284
  55. package/packages/resources/tools/cognitive-thinking/cognitive-thinking.tool.js +0 -837
  56. package/packages/server/mcp/sequential-thinking.handler.js +0 -318
  57. package/packages/server/mcp/think-plan.handler.js +0 -274
  58. package/packages/server/mcp/thinking-toolkit.handler.js +0 -380
  59. package/packages/web/0.d1c5a72339dfc32ad86a.js +0 -1
  60. package/packages/web/112.8807b976372b2b0541a8.js +0 -1
  61. package/packages/web/130.584c7e365da413f5d9be.js +0 -1
  62. package/packages/web/142.72c985bc29720f975cca.js +0 -1
  63. package/packages/web/165.a05fc53bf84d18db36b8.js +0 -2
  64. package/packages/web/165.a05fc53bf84d18db36b8.js.LICENSE.txt +0 -9
  65. package/packages/web/203.724ab9f717b80554c397.js +0 -1
  66. package/packages/web/241.bf941d4f02866795f64a.js +0 -1
  67. package/packages/web/249.54cfb224af63f5f5ec55.js +0 -1
  68. package/packages/web/291.6df35042f8f296fca7cd.js +0 -1
  69. package/packages/web/319.2fab900a31b29873f666.js +0 -1
  70. package/packages/web/32.c78d866281995ec33a7b.js +0 -1
  71. package/packages/web/325.9ca297d0f73f38468ce9.js +0 -1
  72. package/packages/web/366.2f9b48fdbf8eee039e57.js +0 -1
  73. package/packages/web/378.6be08c612cd5a3ef97dc.js +0 -1
  74. package/packages/web/393.7a2f817515c5e90623d7.js +0 -1
  75. package/packages/web/412.062df5f732d5ba203415.js +0 -1
  76. package/packages/web/426.08656fef4918b3fb19ad.js +0 -1
  77. package/packages/web/465.2be8018327130a3bd798.js +0 -1
  78. package/packages/web/48.8ca96fc93667a715e67a.js +0 -1
  79. package/packages/web/480.44c1f1a2927486ac3d4f.js +0 -1
  80. package/packages/web/489.e041a8d0db15dc96d607.js +0 -1
  81. package/packages/web/490.9ffb26c907de020d671b.js +0 -1
  82. package/packages/web/492.58781369e348d91fc06a.js +0 -1
  83. package/packages/web/495.ed63e99791a87167c6b3.js +0 -1
  84. package/packages/web/510.4cc07ab7d30d5c1cd17f.js +0 -1
  85. package/packages/web/543.3af155ed4fa237664308.js +0 -1
  86. package/packages/web/567.f04ab60f8e2c2fb0745a.js +0 -1
  87. package/packages/web/592.f3ad085fa9c1849daa06.js +0 -1
  88. package/packages/web/616.b03fb801b3433b17750f.js +0 -1
  89. package/packages/web/617.d88def54921d2c4dc44c.js +0 -1
  90. package/packages/web/641.d30787d674f548928261.js +0 -1
  91. package/packages/web/672.5269c8399fa42a5af95d.js +0 -1
  92. package/packages/web/731.97cab92b71811c502bda.js +0 -1
  93. package/packages/web/746.3947c6f0235407e420fb.js +0 -1
  94. package/packages/web/756.a53233b3f3913900d5ac.js +0 -1
  95. package/packages/web/77.68801af593a28a631fbf.js +0 -1
  96. package/packages/web/802.53b2bff3cf2a69f7b80c.js +0 -1
  97. package/packages/web/815.b6dfab82265f56c7e046.js +0 -1
  98. package/packages/web/821.f5a13e5c735aac244eb9.js +0 -1
  99. package/packages/web/846.b9bf97d5f559270675ce.js +0 -1
  100. package/packages/web/869.7c10403f500e6201407f.js +0 -1
  101. package/packages/web/885.135050364f99e6924fb5.js +0 -1
  102. package/packages/web/901.fd5aeb9df630609a2b43.js +0 -1
  103. package/packages/web/928.f67e590de3caa4daa3ae.js +0 -1
  104. package/packages/web/955.d833403521ba4dd567ee.js +0 -1
  105. package/packages/web/981.a45cb745cf424044c8c8.js +0 -1
  106. package/packages/web/992.645320b60c74c8787482.js +0 -1
  107. package/packages/web/996.ed9a963dc9e7439eca9a.js +0 -1
  108. package/packages/web/css/codemirror-theme_xq-light.css +0 -43
  109. package/packages/web/css/codemirror.css +0 -344
  110. package/packages/web/css/main.196f434e6a88cd448158.css +0 -7278
  111. package/packages/web/css/terminal-fix.css +0 -571
  112. package/packages/web/index.html +0 -3
  113. package/packages/web/main.dceff50c7307dda04873.js +0 -2
  114. package/packages/web/main.dceff50c7307dda04873.js.LICENSE.txt +0 -3
@@ -1,18 +1,18 @@
1
1
  /**
2
2
  * 工具执行上下文服务
3
- *
3
+ *
4
4
  * 职责:
5
5
  * 1. 创建工具执行上下文(包含 API、路径解析、模块导入等)
6
6
  * 2. 提供统一的工具执行环境
7
7
  */
8
8
 
9
9
  import path from 'path';
10
- import os from 'os';
11
10
  import { createRequire } from 'module';
12
11
  import { logger } from '../utils/logger.js';
13
12
  import { getLogger } from './tool-logger.service.js';
14
13
  import { getStorage } from './tool-storage.service.js';
15
14
  import { loadToolEnvironment, saveToolEnvironment } from './tool-environment.service.js';
15
+ import { config } from '../utils/config.js';
16
16
 
17
17
  /**
18
18
  * 创建工具执行上下文
@@ -21,23 +21,23 @@ import { loadToolEnvironment, saveToolEnvironment } from './tool-environment.ser
21
21
  * @returns {object} 工具执行上下文
22
22
  */
23
23
  export async function createToolContext(toolName, toolModule) {
24
- const toolDir = path.join(os.homedir(), '.prompt-manager', 'toolbox', toolName);
25
-
24
+ const toolDir = config.getToolDir(toolName);
25
+
26
26
  // 1. 加载工具环境变量
27
27
  const toolEnvVars = await loadToolEnvironment(toolName);
28
-
28
+
29
29
  // 2. 创建工具日志记录器
30
30
  const toolLogger = getLogger(toolName);
31
-
31
+
32
32
  // 3. 创建工具存储服务
33
33
  const toolStorage = getStorage(toolName);
34
-
34
+
35
35
  // 4. 创建 API 上下文
36
36
  const apiContext = {
37
37
  logger: toolLogger,
38
38
  storage: toolStorage,
39
39
  environment: {
40
- get: (key) => {
40
+ get: key => {
41
41
  // 优先从工具环境变量获取
42
42
  if (toolEnvVars[key] !== undefined) {
43
43
  return toolEnvVars[key];
@@ -56,7 +56,7 @@ export async function createToolContext(toolName, toolModule) {
56
56
  // 5. 创建工具专用的 require 函数
57
57
  const packageJsonPath = path.resolve(path.join(toolDir, 'package.json'));
58
58
  const toolRequire = createRequire(packageJsonPath);
59
-
59
+
60
60
  // 6. 创建工具执行上下文
61
61
  const toolContext = {
62
62
  api: apiContext,
@@ -65,28 +65,28 @@ export async function createToolContext(toolName, toolModule) {
65
65
  // 文件系统初始化状态(框架管理)
66
66
  _filesystemInitialized: false,
67
67
  _allowedDirectories: null,
68
-
68
+
69
69
  // 框架提供的文件系统基础能力
70
70
  getAllowedDirectories() {
71
71
  const { api } = this;
72
-
72
+
73
73
  // 默认值
74
- let allowedDirs = ['~/.prompt-manager'];
75
-
74
+ let allowedDirs = [config.getConfigHome()];
75
+
76
76
  if (api && api.environment) {
77
77
  try {
78
78
  let configStr = api.environment.get('ALLOWED_DIRECTORIES');
79
-
79
+
80
80
  // 如果直接获取失败,尝试使用工具特定的环境变量名
81
81
  if (!configStr) {
82
82
  const toolSpecificKey = `${toolName.toUpperCase().replace(/-/g, '_')}_ALLOWED_DIRECTORIES`;
83
83
  configStr = process.env[toolSpecificKey];
84
84
  }
85
-
85
+
86
86
  if (configStr) {
87
87
  // 处理转义字符(从 .env 文件解析时可能需要)
88
88
  configStr = configStr.replace(/\\"/g, '"').replace(/\\\\/g, '\\');
89
-
89
+
90
90
  // 首先尝试作为 JSON 字符串解析
91
91
  try {
92
92
  const parsed = JSON.parse(configStr);
@@ -96,7 +96,10 @@ export async function createToolContext(toolName, toolModule) {
96
96
  } catch (parseError) {
97
97
  // 如果不是 JSON,尝试作为逗号分隔的字符串
98
98
  if (typeof configStr === 'string' && configStr.includes(',')) {
99
- allowedDirs = configStr.split(',').map(s => s.trim()).filter(s => s);
99
+ allowedDirs = configStr
100
+ .split(',')
101
+ .map(s => s.trim())
102
+ .filter(s => s);
100
103
  } else if (configStr) {
101
104
  allowedDirs = [configStr];
102
105
  }
@@ -107,126 +110,126 @@ export async function createToolContext(toolName, toolModule) {
107
110
  api?.logger?.warn('Failed to parse ALLOWED_DIRECTORIES', { error: error.message });
108
111
  }
109
112
  }
110
-
113
+
111
114
  // 展开 ~ 到主目录并规范化路径
112
115
  return allowedDirs.map(dir => {
113
- const expanded = dir.replace(/^~/, os.homedir());
116
+ const expanded = dir.replace(/^~/, config.getConfigHome());
114
117
  return path.resolve(expanded);
115
118
  });
116
119
  },
117
-
120
+
118
121
  async initializeFilesystem() {
119
122
  if (!this._filesystemInitialized) {
120
123
  // 获取允许的目录列表
121
124
  const allowedDirectories = this.getAllowedDirectories();
122
125
  this._allowedDirectories = allowedDirectories;
123
126
  this._filesystemInitialized = true;
124
-
127
+
125
128
  // 记录日志
126
129
  const { api } = this;
127
- api?.logger?.info('Filesystem initialized', {
128
- allowedDirectories: this._allowedDirectories
130
+ api?.logger?.info('Filesystem initialized', {
131
+ allowedDirectories: this._allowedDirectories
129
132
  });
130
133
  }
131
134
  },
132
-
135
+
133
136
  resolvePromptManagerPath(inputPath) {
134
137
  const { api } = this;
135
-
138
+
136
139
  // 获取允许的目录列表
137
140
  const allowedDirs = this._allowedDirectories || this.getAllowedDirectories();
138
-
141
+
139
142
  if (!inputPath) {
140
143
  // 没有路径时返回第一个允许的目录
141
144
  return allowedDirs[0];
142
145
  }
143
-
146
+
144
147
  // 处理 ~ 开头的路径
145
- const expandedPath = inputPath.replace(/^~/, os.homedir());
146
-
148
+ const expandedPath = inputPath.replace(/^~/, config.getConfigHome());
149
+
147
150
  // 如果是绝对路径
148
151
  if (path.isAbsolute(expandedPath)) {
149
152
  const resolved = path.resolve(expandedPath);
150
153
  const normalizedResolved = path.normalize(resolved);
151
-
154
+
152
155
  // 检查路径是否在允许的目录范围内
153
156
  const isAllowed = allowedDirs.some(dir => {
154
157
  const normalizedDir = path.normalize(dir);
155
-
158
+
156
159
  // 完全匹配允许的目录
157
160
  if (normalizedResolved === normalizedDir) {
158
161
  return true;
159
162
  }
160
-
163
+
161
164
  // 检查是否是允许目录的子路径
162
165
  const relativePath = path.relative(normalizedDir, normalizedResolved);
163
-
166
+
164
167
  // 如果 relativePath 以 .. 开头,说明路径不在允许目录内
165
168
  if (relativePath.startsWith('..')) {
166
169
  return false;
167
170
  }
168
-
171
+
169
172
  // 如果 relativePath 为空,说明是完全匹配(已在上面检查)
170
173
  if (relativePath === '') {
171
174
  return false;
172
175
  }
173
-
176
+
174
177
  // 相对路径存在且不以 .. 开头,说明是允许目录的子路径
175
178
  return true;
176
179
  });
177
-
180
+
178
181
  if (!isAllowed) {
179
182
  const dirsStr = allowedDirs.join(', ');
180
183
  api?.logger?.warn('Path access denied', { path: resolved, allowedDirs });
181
184
  throw new Error(`路径越权: ${inputPath} 不在允许的目录范围内 [${dirsStr}]`);
182
185
  }
183
-
186
+
184
187
  return resolved;
185
188
  }
186
-
189
+
187
190
  // 相对路径,尝试在每个允许的目录中解析
188
191
  const baseDir = allowedDirs[0];
189
192
  const fullPath = path.join(baseDir, expandedPath);
190
193
  const resolved = path.resolve(fullPath);
191
194
  const normalizedResolved = path.normalize(resolved);
192
-
195
+
193
196
  // 安全检查:确保解析后的路径在允许的目录内或其子目录中
194
197
  const isAllowed = allowedDirs.some(dir => {
195
198
  const normalizedDir = path.normalize(dir);
196
-
199
+
197
200
  // 完全匹配允许的目录
198
201
  if (normalizedResolved === normalizedDir) {
199
202
  return true;
200
203
  }
201
-
204
+
202
205
  // 检查是否是允许目录的子路径
203
206
  const relativePath = path.relative(normalizedDir, normalizedResolved);
204
-
207
+
205
208
  // 如果 relativePath 以 .. 开头,说明路径不在允许目录内
206
209
  if (relativePath.startsWith('..')) {
207
210
  return false;
208
211
  }
209
-
212
+
210
213
  // 如果 relativePath 为空,说明是完全匹配(已在上面检查)
211
214
  if (relativePath === '') {
212
215
  return false;
213
216
  }
214
-
217
+
215
218
  // 相对路径存在且不以 .. 开头,说明是允许目录的子路径
216
219
  return true;
217
220
  });
218
-
221
+
219
222
  if (!isAllowed) {
220
223
  const dirsStr = allowedDirs.join(', ');
221
224
  api?.logger?.warn('Path resolution failed', { path: inputPath, resolved, allowedDirs });
222
225
  throw new Error(`路径越权: ${inputPath} 解析后超出允许的目录范围 [${dirsStr}]`);
223
226
  }
224
-
227
+
225
228
  return resolved;
226
229
  },
227
-
230
+
228
231
  // 提供工具专用的模块导入函数
229
- requireToolModule: (moduleName) => {
232
+ requireToolModule: moduleName => {
230
233
  try {
231
234
  // 首先尝试从工具的 node_modules 导入
232
235
  return toolRequire(moduleName);
@@ -239,42 +242,42 @@ export async function createToolContext(toolName, toolModule) {
239
242
  }
240
243
  }
241
244
  },
242
-
245
+
243
246
  // 提供工具专用的动态导入函数(支持 ES 模块和 CommonJS)
244
- importToolModule: async (moduleName) => {
247
+ importToolModule: async moduleName => {
245
248
  try {
246
249
  // 首先尝试使用 require 导入(适用于 CommonJS 模块,如 pdf-parse)
247
250
  const module = toolRequire(moduleName);
248
-
251
+
249
252
  logger.debug(`模块 ${moduleName} require 成功`, {
250
253
  type: typeof module,
251
254
  isFunction: typeof module === 'function',
252
255
  isObject: typeof module === 'object',
253
256
  keys: typeof module === 'object' ? Object.keys(module).slice(0, 10) : []
254
257
  });
255
-
258
+
256
259
  // pdf-parse 是 CommonJS 模块,直接导出函数
257
260
  // 如果 module 是函数,直接返回
258
261
  if (typeof module === 'function') {
259
262
  return { default: module };
260
263
  }
261
-
264
+
262
265
  // 如果是对象,检查是否有 default
263
266
  if (module && typeof module === 'object') {
264
267
  // 如果已经有 default,直接返回
265
268
  if (module.default) {
266
269
  return module;
267
270
  }
268
-
271
+
269
272
  // 检查是否有常见的导出名称(如 PDFParse)
270
273
  if (module.PDFParse && typeof module.PDFParse === 'function') {
271
274
  return { default: module.PDFParse };
272
275
  }
273
-
276
+
274
277
  // 否则包装为 { default: module }
275
278
  return { default: module, ...module };
276
279
  }
277
-
280
+
278
281
  return module;
279
282
  } catch (requireError) {
280
283
  logger.debug(`require 失败,尝试 import: ${moduleName}`, { error: requireError.message });
@@ -285,12 +288,12 @@ export async function createToolContext(toolName, toolModule) {
285
288
  return await import(modulePath);
286
289
  } catch (resolveError) {
287
290
  logger.debug(`resolve 失败,尝试特殊路径: ${moduleName}`, { error: resolveError.message });
288
-
291
+
289
292
  // 特殊处理:某些包的 main 字段指向错误的路径,需要尝试备用路径
290
293
  const fallbackPaths = {
291
294
  'chrome-devtools-mcp': 'chrome-devtools-mcp/build/src/index.js'
292
295
  };
293
-
296
+
294
297
  if (fallbackPaths[moduleName]) {
295
298
  try {
296
299
  const fallbackPath = toolRequire.resolve(fallbackPaths[moduleName]);
@@ -300,7 +303,7 @@ export async function createToolContext(toolName, toolModule) {
300
303
  logger.debug(`备用路径也失败: ${moduleName}`, { error: fallbackError.message });
301
304
  }
302
305
  }
303
-
306
+
304
307
  // 如果 resolve 失败,尝试直接导入(可能从系统 node_modules)
305
308
  try {
306
309
  logger.debug(`尝试直接导入模块: ${moduleName}`);
@@ -318,7 +321,7 @@ export async function createToolContext(toolName, toolModule) {
318
321
  }
319
322
  }
320
323
  };
321
-
324
+
322
325
  // 7. 将工具模块的所有方法复制到上下文中,并绑定this
323
326
  // 这样工具方法之间可以相互调用(如 execute 调用 this.initializeFilesystem)
324
327
  for (const [key, value] of Object.entries(toolModule)) {
@@ -328,7 +331,6 @@ export async function createToolContext(toolName, toolModule) {
328
331
  toolContext[key] = value;
329
332
  }
330
333
  }
331
-
334
+
332
335
  return toolContext;
333
336
  }
334
-
@@ -1,20 +1,20 @@
1
1
  /**
2
2
  * 工具依赖管理服务
3
- *
3
+ *
4
4
  * 职责:
5
5
  * 1. 检查工具依赖是否已安装
6
6
  * 2. 自动安装工具依赖(使用 @npmcli/arborist,不依赖系统 npm)
7
7
  * 3. 验证依赖版本匹配
8
- *
8
+ *
9
9
  * 使用 PackageInstaller 基于 @npmcli/arborist 实现,可在 Electron 环境中直接使用
10
10
  */
11
11
 
12
12
  import fs from 'fs-extra';
13
13
  import path from 'path';
14
- import os from 'os';
15
14
  import { logger } from '../utils/logger.js';
16
15
  import { pathExists } from './tool-utils.js';
17
16
  import PackageInstaller from './package-installer.service.js';
17
+ import { config } from '../utils/config.js';
18
18
 
19
19
  /**
20
20
  * 确保工具依赖已安装
@@ -22,34 +22,34 @@ import PackageInstaller from './package-installer.service.js';
22
22
  * @param {object} toolModule - 工具模块(可选,用于自动创建 package.json)
23
23
  */
24
24
  export async function ensureToolDependencies(toolName, toolModule = null) {
25
- const toolDir = path.join(os.homedir(), '.prompt-manager', 'toolbox', toolName);
25
+ const toolDir = config.getToolDir(toolName);
26
26
  const packageJsonPath = path.join(toolDir, 'package.json');
27
27
  const nodeModulesPath = path.join(toolDir, 'node_modules');
28
-
28
+
29
29
  // 检查 package.json 是否存在,如果不存在则自动创建
30
- if (!await pathExists(packageJsonPath)) {
30
+ if (!(await pathExists(packageJsonPath))) {
31
31
  logger.info(`工具 ${toolName} 缺少 package.json,正在自动创建...`);
32
32
  await createPackageJson(toolName, toolDir, toolModule);
33
33
  }
34
-
34
+
35
35
  const packageJson = await fs.readJson(packageJsonPath);
36
36
  const dependencies = packageJson.dependencies || {};
37
-
37
+
38
38
  // 如果没有依赖,直接返回
39
39
  if (Object.keys(dependencies).length === 0) {
40
40
  logger.debug(`工具 ${toolName} 无需依赖`);
41
41
  return;
42
42
  }
43
-
43
+
44
44
  // 检查 node_modules 是否存在,或者检查依赖是否需要更新
45
- const needsInstall = !await pathExists(nodeModulesPath) || await needsDependencyUpdate(toolDir, dependencies);
46
-
45
+ const needsInstall = !(await pathExists(nodeModulesPath)) || (await needsDependencyUpdate(toolDir, dependencies));
46
+
47
47
  if (needsInstall) {
48
48
  logger.info(`工具 ${toolName} 依赖需要安装或更新,开始安装...`);
49
49
  await installDependencies(toolDir, dependencies);
50
50
  return;
51
51
  }
52
-
52
+
53
53
  logger.debug(`工具 ${toolName} 依赖已存在且为最新`);
54
54
  }
55
55
 
@@ -62,7 +62,7 @@ export async function ensureToolDependencies(toolName, toolModule = null) {
62
62
  async function createPackageJson(toolName, toolDir, toolModule) {
63
63
  // 确保工具目录存在
64
64
  await fs.ensureDir(toolDir);
65
-
65
+
66
66
  // 获取工具依赖(如果工具模块提供了 getDependencies 方法)
67
67
  let dependencies = {};
68
68
  if (toolModule && typeof toolModule.getDependencies === 'function') {
@@ -72,7 +72,7 @@ async function createPackageJson(toolName, toolDir, toolModule) {
72
72
  logger.warn(`获取工具 ${toolName} 依赖失败:`, error.message);
73
73
  }
74
74
  }
75
-
75
+
76
76
  // 获取工具元数据(用于 package.json 的基本信息)
77
77
  let metadata = { name: toolName, version: '1.0.0' };
78
78
  if (toolModule && typeof toolModule.getMetadata === 'function') {
@@ -82,7 +82,7 @@ async function createPackageJson(toolName, toolDir, toolModule) {
82
82
  logger.warn(`获取工具 ${toolName} 元数据失败:`, error.message);
83
83
  }
84
84
  }
85
-
85
+
86
86
  // 创建 package.json
87
87
  const packageJson = {
88
88
  name: `@prompt-manager/tool-${toolName}`,
@@ -90,15 +90,15 @@ async function createPackageJson(toolName, toolDir, toolModule) {
90
90
  description: metadata.description || `Prompt Manager tool: ${toolName}`,
91
91
  main: `${toolName}.tool.js`,
92
92
  type: 'module',
93
- dependencies: dependencies
93
+ dependencies
94
94
  };
95
-
95
+
96
96
  // 写入 package.json
97
97
  const packageJsonPath = path.join(toolDir, 'package.json');
98
98
  await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
99
-
100
- logger.info(`已为工具 ${toolName} 创建 package.json`, {
101
- dependencies: Object.keys(dependencies).length
99
+
100
+ logger.info(`已为工具 ${toolName} 创建 package.json`, {
101
+ dependencies: Object.keys(dependencies).length
102
102
  });
103
103
  }
104
104
 
@@ -111,17 +111,17 @@ async function createPackageJson(toolName, toolDir, toolModule) {
111
111
  async function needsDependencyUpdate(toolDir, expectedDependencies) {
112
112
  try {
113
113
  // 检查每个依赖是否已安装且版本匹配
114
- for (const [packageName, expectedVersion] of Object.entries(expectedDependencies)) {
114
+ for (const [packageName] of Object.entries(expectedDependencies)) {
115
115
  const isInstalled = await PackageInstaller.isPackageInstalled(toolDir, packageName);
116
116
  if (!isInstalled) {
117
117
  logger.debug(`依赖 ${packageName} 未安装,需要更新`);
118
118
  return true;
119
119
  }
120
-
120
+
121
121
  // 可以进一步检查版本是否匹配(简化版本,暂时只检查是否存在)
122
122
  // 如果需要精确版本匹配,可以读取 package.json 并比较版本
123
123
  }
124
-
124
+
125
125
  return false;
126
126
  } catch (error) {
127
127
  logger.warn('检查依赖更新状态失败,将重新安装', { error: error.message });
@@ -136,27 +136,26 @@ async function needsDependencyUpdate(toolDir, expectedDependencies) {
136
136
  */
137
137
  async function installDependencies(toolDir, dependencies) {
138
138
  logger.info(`在目录 ${toolDir} 中安装依赖...`, { dependencies });
139
-
139
+
140
140
  try {
141
141
  // 使用 PackageInstaller 安装依赖
142
142
  // PackageInstaller 使用 @npmcli/arborist,不依赖系统 npm
143
143
  // 可在 Electron 环境中直接使用
144
144
  const result = await PackageInstaller.install({
145
145
  workingDir: toolDir,
146
- dependencies: dependencies,
146
+ dependencies,
147
147
  timeout: 300000 // 5分钟超时
148
148
  });
149
-
149
+
150
150
  logger.info('依赖安装成功', {
151
151
  elapsed: result.elapsed,
152
152
  installedCount: result.installedPackages.length,
153
153
  packages: result.installedPackages
154
154
  });
155
-
155
+
156
156
  return result;
157
-
158
157
  } catch (error) {
159
- logger.error('依赖安装失败', {
158
+ logger.error('依赖安装失败', {
160
159
  error: error.message,
161
160
  toolDir,
162
161
  dependencies,
@@ -165,4 +164,3 @@ async function installDependencies(toolDir, dependencies) {
165
164
  throw new Error(`依赖安装失败: ${error.message}`);
166
165
  }
167
166
  }
168
-