@becrafter/prompt-manager 0.1.21 → 0.1.31
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 +23 -23
- package/packages/resources/tools/agent-browser/README.md +640 -0
- package/packages/resources/tools/agent-browser/agent-browser.tool.js +1388 -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 +98 -13
- 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
|
@@ -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 =
|
|
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
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 (
|
|
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 =
|
|
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
|
-
|