@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,6 +1,6 @@
1
1
  /**
2
2
  * 工具描述生成服务(优化版)
3
- *
3
+ *
4
4
  * 从AI模型理解和使用工具的角度优化:
5
5
  * 1. 提高信息密度,减少冗余
6
6
  * 2. 增强语义匹配能力(利用tags、category)
@@ -19,7 +19,7 @@ import { logger } from '../utils/logger.js';
19
19
  */
20
20
  function groupToolsByCategory(tools) {
21
21
  const grouped = {};
22
-
22
+
23
23
  for (const tool of tools) {
24
24
  const category = tool.metadata.category || 'other';
25
25
  if (!grouped[category]) {
@@ -27,14 +27,14 @@ function groupToolsByCategory(tools) {
27
27
  }
28
28
  grouped[category].push(tool);
29
29
  }
30
-
30
+
31
31
  // 按category名称排序
32
32
  const sortedCategories = Object.keys(grouped).sort();
33
33
  const result = {};
34
34
  for (const cat of sortedCategories) {
35
35
  result[cat] = grouped[cat].sort((a, b) => a.name.localeCompare(b.name));
36
36
  }
37
-
37
+
38
38
  return result;
39
39
  }
40
40
 
@@ -45,14 +45,14 @@ function groupToolsByCategory(tools) {
45
45
  */
46
46
  function generateUsageScenarios(tools) {
47
47
  const scenarios = [];
48
-
48
+
49
49
  for (const tool of tools) {
50
50
  const { name, metadata } = tool;
51
51
  const toolId = `tool://${name}`;
52
-
52
+
53
53
  // 策略1:优先使用scenarios,合并前2个场景(如果存在)
54
54
  let scenarioText = '';
55
-
55
+
56
56
  if (metadata.scenarios && metadata.scenarios.length > 0) {
57
57
  // 合并前2个场景,用"或"连接,提供更丰富的语义信息
58
58
  if (metadata.scenarios.length >= 2) {
@@ -62,26 +62,28 @@ function generateUsageScenarios(tools) {
62
62
  }
63
63
  } else if (metadata.description) {
64
64
  // 策略2:从description中提取核心语义(前80字符,更完整)
65
- scenarioText = metadata.description.length > 80
66
- ? metadata.description.substring(0, 80) + '...'
67
- : metadata.description;
65
+ scenarioText =
66
+ metadata.description.length > 80 ? `${metadata.description.substring(0, 80)}...` : metadata.description;
68
67
  } else {
69
68
  // 策略3:使用工具名称和category
70
69
  const category = metadata.category ? `(${metadata.category}类)` : '';
71
70
  scenarioText = `需要使用 ${name} 功能${category}`;
72
71
  }
73
-
72
+
74
73
  // 添加tags作为语义增强(如果存在)
75
74
  let tagsHint = '';
76
75
  if (metadata.tags && metadata.tags.length > 0) {
77
76
  // 只显示前3个最相关的tags
78
- const keyTags = metadata.tags.slice(0, 3).map(t => `#${t}`).join(' ');
77
+ const keyTags = metadata.tags
78
+ .slice(0, 3)
79
+ .map(t => `#${t}`)
80
+ .join(' ');
79
81
  tagsHint = ` ${keyTags}`;
80
82
  }
81
-
83
+
82
84
  scenarios.push(`- IF ${scenarioText}${tagsHint} → 使用 ${toolId}`);
83
85
  }
84
-
86
+
85
87
  return scenarios.join('\n');
86
88
  }
87
89
 
@@ -92,26 +94,26 @@ function generateUsageScenarios(tools) {
92
94
  */
93
95
  function generateCategorizedToolList(groupedTools) {
94
96
  const sections = [];
95
-
97
+
96
98
  const categoryNames = {
97
- 'system': '系统工具',
98
- 'utility': '实用工具',
99
- 'ai': 'AI工具',
100
- 'browser': '浏览器工具',
101
- 'other': '其他工具'
99
+ system: '系统工具',
100
+ utility: '实用工具',
101
+ ai: 'AI工具',
102
+ browser: '浏览器工具',
103
+ other: '其他工具'
102
104
  };
103
-
105
+
104
106
  for (const [category, tools] of Object.entries(groupedTools)) {
105
107
  const categoryName = categoryNames[category] || category;
106
108
  const toolItems = [];
107
-
109
+
108
110
  for (const tool of tools) {
109
111
  const { name, metadata } = tool;
110
112
  const toolId = `tool://${name}`;
111
-
113
+
112
114
  // 生成工具描述(优化截断逻辑)
113
115
  let description = metadata.description || `${name} 工具`;
114
-
116
+
115
117
  // 智能截断:尝试在句号、逗号处截断,保持语义完整
116
118
  if (description.length > 120) {
117
119
  const truncated = description.substring(0, 120);
@@ -124,22 +126,22 @@ function generateCategorizedToolList(groupedTools) {
124
126
  if (lastPunctuation > 80) {
125
127
  description = truncated.substring(0, lastPunctuation + 1);
126
128
  } else {
127
- description = truncated + '...';
129
+ description = `${truncated}...`;
128
130
  }
129
131
  }
130
-
132
+
131
133
  // 添加tags(如果存在)
132
134
  let tagsDisplay = '';
133
135
  if (metadata.tags && metadata.tags.length > 0) {
134
136
  tagsDisplay = ` [${metadata.tags.slice(0, 3).join(', ')}]`;
135
137
  }
136
-
138
+
137
139
  toolItems.push(` - **${toolId}** - ${description}${tagsDisplay}`);
138
140
  }
139
-
141
+
140
142
  sections.push(`### ${categoryName}\n${toolItems.join('\n')}`);
141
143
  }
142
-
144
+
143
145
  return sections.join('\n\n');
144
146
  }
145
147
 
@@ -152,55 +154,55 @@ function generateToolComparison(tools) {
152
154
  // 识别相似工具(基于category和tags)
153
155
  const similarGroups = [];
154
156
  const processed = new Set();
155
-
157
+
156
158
  for (let i = 0; i < tools.length; i++) {
157
159
  if (processed.has(i)) continue;
158
-
160
+
159
161
  const tool1 = tools[i];
160
162
  const group = [tool1];
161
163
  processed.add(i);
162
-
164
+
163
165
  // 查找相似工具(相同category或tags重叠)
164
166
  for (let j = i + 1; j < tools.length; j++) {
165
167
  if (processed.has(j)) continue;
166
-
168
+
167
169
  const tool2 = tools[j];
168
-
170
+
169
171
  // 判断相似度:相同category或tags有重叠
170
172
  const sameCategory = tool1.metadata.category === tool2.metadata.category;
171
- const tagsOverlap = tool1.metadata.tags && tool2.metadata.tags &&
173
+ const tagsOverlap =
174
+ tool1.metadata.tags &&
175
+ tool2.metadata.tags &&
172
176
  tool1.metadata.tags.some(tag => tool2.metadata.tags.includes(tag));
173
-
177
+
174
178
  if (sameCategory && tagsOverlap) {
175
179
  group.push(tool2);
176
180
  processed.add(j);
177
181
  }
178
182
  }
179
-
183
+
180
184
  if (group.length > 1) {
181
185
  similarGroups.push(group);
182
186
  }
183
187
  }
184
-
188
+
185
189
  if (similarGroups.length === 0) {
186
190
  return '';
187
191
  }
188
-
192
+
189
193
  const comparisons = [];
190
194
  for (const group of similarGroups) {
191
195
  const toolNames = group.map(t => `tool://${t.name}`).join('、');
192
196
  const differences = [];
193
-
197
+
194
198
  for (const tool of group) {
195
- const keyFeature = tool.metadata.description?.split(',')[0] ||
196
- tool.metadata.scenarios?.[0] ||
197
- tool.name;
199
+ const keyFeature = tool.metadata.description?.split(',')[0] || tool.metadata.scenarios?.[0] || tool.name;
198
200
  differences.push(`- **${tool.name}**:${keyFeature}`);
199
201
  }
200
-
202
+
201
203
  comparisons.push(`**相似工具对比**(${toolNames}):\n${differences.join('\n')}`);
202
204
  }
203
-
205
+
204
206
  return comparisons.join('\n\n');
205
207
  }
206
208
 
@@ -215,30 +217,30 @@ export function generateToolmDescription() {
215
217
  logger.warn('工具加载器尚未初始化,使用默认描述');
216
218
  return getDefaultDescription();
217
219
  }
218
-
220
+
219
221
  // 获取所有工具
220
222
  const tools = toolLoaderService.getAllTools();
221
-
223
+
222
224
  if (tools.length === 0) {
223
225
  logger.warn('未发现任何工具,使用默认描述');
224
226
  return getDefaultDescription();
225
227
  }
226
-
228
+
227
229
  // 按名称排序(用于IF-THEN规则)
228
230
  tools.sort((a, b) => a.name.localeCompare(b.name));
229
-
231
+
230
232
  // 按分类组织工具
231
233
  const groupedTools = groupToolsByCategory(tools);
232
-
234
+
233
235
  // 生成使用场景规则
234
236
  const usageScenarios = generateUsageScenarios(tools);
235
-
237
+
236
238
  // 生成分类工具列表
237
239
  const categorizedToolList = generateCategorizedToolList(groupedTools);
238
-
240
+
239
241
  // 生成工具对比信息
240
242
  const toolComparison = generateToolComparison(tools);
241
-
243
+
242
244
  // 组装完整的描述(优化结构,减少冗余)
243
245
  const description = `🛠️ ToolM 是 Prompt Manager 新一代工具系统运行时,提供统一的工具管理和执行能力。
244
246
 
@@ -309,7 +311,6 @@ ${categorizedToolList}
309
311
 
310
312
  logger.debug('工具描述生成成功(优化版)', { toolCount: tools.length });
311
313
  return description;
312
-
313
314
  } catch (error) {
314
315
  logger.error('生成工具描述失败,使用默认描述', { error: error.message });
315
316
  return getDefaultDescription();
@@ -375,4 +376,3 @@ parameters:
375
376
  - 不要忘记 "tool://" 前缀
376
377
  - 不要跳过手册,首次使用必须先看 manual`;
377
378
  }
378
-
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * 工具描述生成服务
3
- *
3
+ *
4
4
  * 职责:
5
5
  * 1. 从工具加载服务获取所有工具的元数据
6
6
  * 2. 动态生成 toolm 工具的 description
@@ -17,31 +17,30 @@ import { logger } from '../utils/logger.js';
17
17
  */
18
18
  function generateUsageScenarios(tools) {
19
19
  const scenarios = [];
20
-
20
+
21
21
  for (const tool of tools) {
22
22
  const { name, metadata } = tool;
23
23
  const toolId = `tool://${name}`;
24
-
24
+
25
25
  // 从 metadata 中提取使用场景描述
26
26
  // 优先使用 scenarios 字段的第一个场景,如果没有则从 description 提取关键词
27
27
  let scenarioText = '';
28
-
28
+
29
29
  if (metadata.scenarios && metadata.scenarios.length > 0) {
30
30
  // 使用第一个场景作为主要描述
31
31
  scenarioText = metadata.scenarios[0];
32
32
  } else if (metadata.description) {
33
33
  // 从描述中提取核心功能关键词(前60个字符)
34
- scenarioText = metadata.description.length > 60
35
- ? metadata.description.substring(0, 60) + '...'
36
- : metadata.description;
34
+ scenarioText =
35
+ metadata.description.length > 60 ? `${metadata.description.substring(0, 60)}...` : metadata.description;
37
36
  } else {
38
37
  // 使用工具名称
39
38
  scenarioText = `需要使用 ${name} 功能`;
40
39
  }
41
-
40
+
42
41
  scenarios.push(`- IF ${scenarioText} → 使用 ${toolId}`);
43
42
  }
44
-
43
+
45
44
  return scenarios.join('\n');
46
45
  }
47
46
 
@@ -52,22 +51,22 @@ function generateUsageScenarios(tools) {
52
51
  */
53
52
  function generateToolList(tools) {
54
53
  const toolItems = [];
55
-
54
+
56
55
  for (const tool of tools) {
57
56
  const { name, metadata } = tool;
58
57
  const toolId = `tool://${name}`;
59
-
58
+
60
59
  // 生成工具描述
61
60
  let description = metadata.description || `${name} 工具`;
62
-
61
+
63
62
  // 如果描述太长,截取前100个字符
64
63
  if (description.length > 100) {
65
- description = description.substring(0, 100) + '...';
64
+ description = `${description.substring(0, 100)}...`;
66
65
  }
67
-
66
+
68
67
  toolItems.push(`- **${toolId}** - ${description}`);
69
68
  }
70
-
69
+
71
70
  return toolItems.join('\n');
72
71
  }
73
72
 
@@ -82,24 +81,24 @@ export function generateToolmDescription() {
82
81
  logger.warn('工具加载器尚未初始化,使用默认描述');
83
82
  return getDefaultDescription();
84
83
  }
85
-
84
+
86
85
  // 获取所有工具
87
86
  const tools = toolLoaderService.getAllTools();
88
-
87
+
89
88
  if (tools.length === 0) {
90
89
  logger.warn('未发现任何工具,使用默认描述');
91
90
  return getDefaultDescription();
92
91
  }
93
-
92
+
94
93
  // 按名称排序
95
94
  tools.sort((a, b) => a.name.localeCompare(b.name));
96
-
95
+
97
96
  // 生成使用场景规则
98
97
  const usageScenarios = generateUsageScenarios(tools);
99
-
98
+
100
99
  // 生成工具列表
101
100
  const toolList = generateToolList(tools);
102
-
101
+
103
102
  // 组装完整的描述
104
103
  const description = `ToolM 是 Prompt Manager 新一代工具系统运行时,提供统一的工具管理和执行能力。
105
104
 
@@ -240,7 +239,6 @@ mode: manual\`
240
239
 
241
240
  logger.debug('工具描述生成成功', { toolCount: tools.length });
242
241
  return description;
243
-
244
242
  } catch (error) {
245
243
  logger.error('生成工具描述失败,使用默认描述', { error: error.message });
246
244
  return getDefaultDescription();
@@ -309,4 +307,3 @@ yaml 参数必须是完整的 YAML 文档:
309
307
  - 不要忘记 "tool://" 前缀(不是 "tool: filesystem")
310
308
  - 不要跳过手册,首次使用必须先看 manual`;
311
309
  }
312
-
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * 工具环境变量管理服务
3
- *
3
+ *
4
4
  * 职责:
5
5
  * 1. 管理工具的环境变量配置(.env 文件)
6
6
  * 2. 加载环境变量到工具执行环境
@@ -9,9 +9,9 @@
9
9
 
10
10
  import fs from 'fs-extra';
11
11
  import path from 'path';
12
- import os from 'os';
13
12
  import { logger } from '../utils/logger.js';
14
13
  import { pathExists } from './tool-utils.js';
14
+ import { config } from '../utils/config.js';
15
15
 
16
16
  /**
17
17
  * 加载工具环境变量
@@ -19,52 +19,50 @@ import { pathExists } from './tool-utils.js';
19
19
  * @returns {object} 环境变量对象
20
20
  */
21
21
  export async function loadToolEnvironment(toolName) {
22
- const toolDir = path.join(os.homedir(), '.prompt-manager', 'toolbox', toolName);
22
+ const toolDir = config.getToolDir(toolName);
23
23
  const envFilePath = path.join(toolDir, '.env');
24
-
24
+
25
25
  // 检查 .env 文件是否存在
26
- if (!await pathExists(envFilePath)) {
26
+ if (!(await pathExists(envFilePath))) {
27
27
  logger.debug(`工具 ${toolName} 的 .env 文件不存在`);
28
28
  return {};
29
29
  }
30
-
30
+
31
31
  try {
32
32
  // 读取 .env 文件内容
33
33
  const envContent = await fs.readFile(envFilePath, 'utf-8');
34
-
34
+
35
35
  // 解析 .env 文件内容
36
36
  const envVars = {};
37
37
  const lines = envContent.split('\n');
38
-
38
+
39
39
  for (const line of lines) {
40
40
  // 跳过注释和空行
41
41
  const trimmedLine = line.trim();
42
42
  if (!trimmedLine || trimmedLine.startsWith('#')) {
43
43
  continue;
44
44
  }
45
-
45
+
46
46
  // 解析键值对
47
47
  const equalIndex = trimmedLine.indexOf('=');
48
48
  if (equalIndex === -1) {
49
49
  continue;
50
50
  }
51
-
51
+
52
52
  const key = trimmedLine.substring(0, equalIndex).trim();
53
53
  let value = trimmedLine.substring(equalIndex + 1).trim();
54
-
54
+
55
55
  // 处理带引号的值
56
- if ((value.startsWith('"') && value.endsWith('"')) ||
57
- (value.startsWith("'") && value.endsWith("'"))) {
56
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
58
57
  value = value.substring(1, value.length - 1);
59
58
  }
60
-
59
+
61
60
  // 处理转义字符
62
61
  value = value.replace(/\\n/g, '\n').replace(/\\t/g, '\t');
63
-
62
+
64
63
  // 尝试解析JSON(如果是JSON数组或对象)
65
64
  try {
66
- if ((value.startsWith('[') && value.endsWith(']')) ||
67
- (value.startsWith('{') && value.endsWith('}'))) {
65
+ if ((value.startsWith('[') && value.endsWith(']')) || (value.startsWith('{') && value.endsWith('}'))) {
68
66
  const parsed = JSON.parse(value);
69
67
  envVars[key] = parsed;
70
68
  } else {
@@ -75,13 +73,12 @@ export async function loadToolEnvironment(toolName) {
75
73
  envVars[key] = value;
76
74
  }
77
75
  }
78
-
79
- logger.debug(`工具 ${toolName} 环境变量加载成功`, {
80
- count: Object.keys(envVars).length
76
+
77
+ logger.debug(`工具 ${toolName} 环境变量加载成功`, {
78
+ count: Object.keys(envVars).length
81
79
  });
82
-
80
+
83
81
  return envVars;
84
-
85
82
  } catch (error) {
86
83
  logger.error(`加载工具 ${toolName} 的环境变量失败`, { error: error.message });
87
84
  return {};
@@ -94,20 +91,20 @@ export async function loadToolEnvironment(toolName) {
94
91
  * @param {object} envVars - 环境变量对象
95
92
  */
96
93
  export async function saveToolEnvironment(toolName, envVars) {
97
- const toolDir = path.join(os.homedir(), '.prompt-manager', 'toolbox', toolName);
94
+ const toolDir = config.getToolDir(toolName);
98
95
  await fs.ensureDir(toolDir);
99
-
96
+
100
97
  const envFilePath = path.join(toolDir, '.env');
101
-
98
+
102
99
  // 读取现有配置(如果存在)
103
100
  const existingVars = await loadToolEnvironment(toolName);
104
-
101
+
105
102
  // 合并配置
106
103
  const mergedVars = {
107
104
  ...existingVars,
108
105
  ...envVars
109
106
  };
110
-
107
+
111
108
  // 生成 .env 文件内容
112
109
  let envContent = `# Tool Environment Variables
113
110
  # Tool: ${toolName}
@@ -115,11 +112,11 @@ export async function saveToolEnvironment(toolName, envVars) {
115
112
  # Last modified: ${new Date().toISOString()}
116
113
 
117
114
  `;
118
-
115
+
119
116
  // 写入环境变量
120
117
  for (const [key, value] of Object.entries(mergedVars)) {
121
118
  let escapedValue;
122
-
119
+
123
120
  // 如果值是对象或数组,转换为JSON字符串
124
121
  if (typeof value === 'object' && value !== null) {
125
122
  escapedValue = JSON.stringify(value);
@@ -131,20 +128,25 @@ export async function saveToolEnvironment(toolName, envVars) {
131
128
  .replace(/\n/g, '\\n')
132
129
  .replace(/\t/g, '\\t');
133
130
  }
134
-
131
+
135
132
  // 如果值包含空格、等号或特殊字符,用引号包裹
136
- if (escapedValue.includes(' ') || escapedValue.includes('=') || escapedValue.includes('[') || escapedValue.includes('{')) {
133
+ if (
134
+ escapedValue.includes(' ') ||
135
+ escapedValue.includes('=') ||
136
+ escapedValue.includes('[') ||
137
+ escapedValue.includes('{')
138
+ ) {
137
139
  escapedValue = `"${escapedValue}"`;
138
140
  }
139
-
141
+
140
142
  envContent += `${key}=${escapedValue}\n`;
141
143
  }
142
-
144
+
143
145
  // 写入文件
144
146
  await fs.writeFile(envFilePath, envContent, 'utf-8');
145
-
146
- logger.info(`工具 ${toolName} 环境变量配置已保存`, {
147
- count: Object.keys(mergedVars).length
147
+
148
+ logger.info(`工具 ${toolName} 环境变量配置已保存`, {
149
+ count: Object.keys(mergedVars).length
148
150
  });
149
151
  }
150
152
 
@@ -155,23 +157,23 @@ export async function saveToolEnvironment(toolName, envVars) {
155
157
  * @returns {object} 配置信息对象
156
158
  */
157
159
  export async function getToolEnvironmentInfo(toolName, schema) {
158
- const toolDir = path.join(os.homedir(), '.prompt-manager', 'toolbox', toolName);
160
+ const toolDir = config.getToolDir(toolName);
159
161
  const envFilePath = path.join(toolDir, '.env');
160
-
162
+
161
163
  // 加载当前配置
162
164
  const currentVars = await loadToolEnvironment(toolName);
163
-
165
+
164
166
  // 获取环境变量定义
165
167
  const envProps = schema?.environment?.properties || {};
166
-
168
+
167
169
  // 构建配置信息
168
170
  const configured = [];
169
171
  const unconfigured = [];
170
-
172
+
171
173
  for (const [key, def] of Object.entries(envProps)) {
172
174
  const value = currentVars[key];
173
175
  const defaultValue = def.default;
174
-
176
+
175
177
  if (value !== undefined) {
176
178
  configured.push({
177
179
  key,
@@ -188,7 +190,7 @@ export async function getToolEnvironmentInfo(toolName, schema) {
188
190
  });
189
191
  }
190
192
  }
191
-
193
+
192
194
  return {
193
195
  toolName,
194
196
  envFilePath,
@@ -197,4 +199,3 @@ export async function getToolEnvironmentInfo(toolName, schema) {
197
199
  hasConfig: await pathExists(envFilePath)
198
200
  };
199
201
  }
200
-