foliko 1.0.81 → 1.0.83

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 (88) hide show
  1. package/cli/bin/foliko.js +12 -12
  2. package/cli/src/commands/chat.js +143 -143
  3. package/cli/src/commands/list.js +93 -93
  4. package/cli/src/index.js +75 -75
  5. package/cli/src/ui/chat-ui.js +201 -201
  6. package/cli/src/utils/ansi.js +40 -40
  7. package/cli/src/utils/markdown.js +292 -292
  8. package/examples/ambient-example.js +194 -194
  9. package/examples/basic.js +115 -115
  10. package/examples/bootstrap.js +121 -121
  11. package/examples/mcp-example.js +56 -56
  12. package/examples/skill-example.js +49 -49
  13. package/examples/test-chat.js +137 -137
  14. package/examples/test-mcp.js +85 -85
  15. package/examples/test-reload.js +59 -59
  16. package/examples/test-telegram.js +50 -50
  17. package/examples/test-tg-bot.js +45 -45
  18. package/examples/test-tg-simple.js +47 -47
  19. package/examples/test-tg.js +62 -62
  20. package/examples/test-think.js +43 -43
  21. package/examples/test-web-plugin.js +103 -103
  22. package/examples/test-weixin-feishu.js +103 -103
  23. package/examples/workflow.js +158 -158
  24. package/package.json +83 -83
  25. package/plugins/ai-plugin.js +102 -102
  26. package/plugins/ambient-agent/EventWatcher.js +113 -113
  27. package/plugins/ambient-agent/ExplorerLoop.js +640 -640
  28. package/plugins/ambient-agent/GoalManager.js +197 -197
  29. package/plugins/ambient-agent/Reflector.js +95 -95
  30. package/plugins/ambient-agent/StateStore.js +90 -90
  31. package/plugins/ambient-agent/constants.js +101 -101
  32. package/plugins/ambient-agent/index.js +579 -579
  33. package/plugins/audit-plugin.js +187 -187
  34. package/plugins/default-plugins.js +548 -548
  35. package/plugins/email/constants.js +64 -64
  36. package/plugins/email/handlers.js +461 -461
  37. package/plugins/email/index.js +278 -278
  38. package/plugins/email/monitor.js +269 -269
  39. package/plugins/email/parser.js +138 -138
  40. package/plugins/email/reply.js +151 -151
  41. package/plugins/email/utils.js +124 -124
  42. package/plugins/extension-executor-plugin.js +326 -326
  43. package/plugins/feishu-plugin.js +481 -481
  44. package/plugins/file-system-plugin.js +920 -920
  45. package/plugins/gate-trading.js +747 -747
  46. package/plugins/install-plugin.js +199 -199
  47. package/plugins/python-executor-plugin.js +367 -367
  48. package/plugins/python-plugin-loader.js +651 -651
  49. package/plugins/rules-plugin.js +294 -294
  50. package/plugins/scheduler-plugin.js +691 -691
  51. package/plugins/session-plugin.js +494 -494
  52. package/plugins/shell-executor-plugin.js +197 -197
  53. package/plugins/storage-plugin.js +263 -263
  54. package/plugins/subagent-plugin.js +845 -845
  55. package/plugins/telegram-plugin.js +482 -482
  56. package/plugins/think-plugin.js +345 -345
  57. package/plugins/tools-plugin.js +196 -196
  58. package/plugins/web-plugin.js +637 -637
  59. package/plugins/weixin-plugin.js +545 -545
  60. package/src/capabilities/index.js +11 -11
  61. package/src/capabilities/skill-manager.js +609 -609
  62. package/src/capabilities/workflow-engine.js +1109 -1109
  63. package/src/core/agent-chat.js +1 -1
  64. package/src/core/agent.js +958 -958
  65. package/src/core/framework.js +465 -465
  66. package/src/core/index.js +19 -19
  67. package/src/core/plugin-base.js +262 -262
  68. package/src/core/plugin-manager.js +863 -863
  69. package/src/core/provider.js +114 -114
  70. package/src/core/sub-agent-config.js +264 -264
  71. package/src/core/system-prompt-builder.js +120 -120
  72. package/src/core/tool-registry.js +517 -517
  73. package/src/core/tool-router.js +297 -297
  74. package/src/executors/executor-base.js +58 -58
  75. package/src/executors/mcp-executor.js +845 -845
  76. package/src/index.js +25 -25
  77. package/src/utils/circuit-breaker.js +301 -301
  78. package/src/utils/error-boundary.js +363 -363
  79. package/src/utils/error.js +374 -374
  80. package/src/utils/event-emitter.js +97 -97
  81. package/src/utils/id.js +133 -133
  82. package/src/utils/index.js +217 -217
  83. package/src/utils/logger.js +181 -181
  84. package/src/utils/plugin-helpers.js +90 -90
  85. package/src/utils/retry.js +122 -122
  86. package/src/utils/sandbox.js +292 -292
  87. package/test/tool-registry-validation.test.js +218 -218
  88. package/website/script.js +136 -136
@@ -1,326 +1,326 @@
1
- /**
2
- * ExtensionExecutorPlugin 扩展插件执行器
3
- * 统一管理扩展插件(如 gate-trading)的工具,通过 ext_call 调用
4
- */
5
-
6
- const { Plugin } = require('../src/core/plugin-base');
7
- const { logger } = require('../src/utils/logger');
8
- const { z } = require('zod');
9
- const { zodSchemaToMarkdown } = require('@chnak/zod-to-markdown');
10
-
11
- const log = logger.child('ExtensionExecutor');
12
-
13
- class ExtensionExecutorPlugin extends Plugin {
14
- constructor(config = {}) {
15
- super();
16
- this.name = 'extension-executor';
17
- this.version = '1.0.0';
18
- this.description = '扩展插件执行器 - 统一管理扩展工具';
19
- this.priority = 10;
20
- this.system = true;
21
-
22
- this._framework = null;
23
- this._extensions = new Map();
24
- }
25
-
26
- install(framework) {
27
- this._framework = framework;
28
-
29
- // 监听插件加载事件,自动扫描插件的 this.tools
30
- framework.on('plugin:loaded', (plugin) => {
31
- this._scanPluginTools(plugin);
32
- });
33
-
34
- return this;
35
- }
36
-
37
- /**
38
- * 扫描插件的 this.tools 并注册到扩展系统
39
- */
40
- _scanPluginTools(plugin) {
41
- if (!plugin || !plugin.tools || typeof plugin.tools !== 'object') {
42
- return;
43
- }
44
-
45
- const pluginName = plugin.name;
46
- if (!pluginName) return;
47
-
48
- // 获取插件信息
49
- const pluginInfo = {
50
- name: plugin.name,
51
- description: plugin.description || '',
52
- version: plugin.version || '1.0.0',
53
- };
54
-
55
- // 遍历插件的所有工具
56
- for (const [toolName, toolDef] of Object.entries(plugin.tools)) {
57
- if (!toolDef || typeof toolDef !== 'object') continue;
58
-
59
- this.registerTool(pluginName, pluginInfo, {
60
- name: toolName,
61
- description: toolDef.description || '',
62
- inputSchema: toolDef.inputSchema,
63
- execute: toolDef.execute,
64
- });
65
- }
66
-
67
- log.debug(` Scanned ${Object.keys(plugin.tools).length} tools from plugin '${pluginName}'`);
68
-
69
- // 刷新所有 Agent 的扩展提示词
70
- if (this._framework && this._framework._ready) {
71
- this._refreshAllAgentsExtPrompt(this._framework);
72
- }
73
- }
74
-
75
- async start(framework) {
76
- // 扫描所有已加载插件的 tools
77
- const plugins = framework.pluginManager.getAll();
78
- for (const { instance: plugin } of plugins) {
79
- this._scanPluginTools(plugin);
80
- }
81
-
82
- framework.registerTool({
83
- name: 'ext_call',
84
- description: '调用扩展插件的工具',
85
- inputSchema: z.object({
86
- plugin: z.string().describe('扩展插件名称'),
87
- tool: z.string().describe('工具名称'),
88
- args: z.record(z.any()).optional().describe('工具参数'),
89
- }),
90
- execute: async (args) => {
91
- const { plugin, tool, args: toolArgs = {} } = args;
92
- log.info(` ext_call: plugin=${plugin}, tool=${tool}`);
93
-
94
- const ext = this._extensions.get(plugin);
95
- if (!ext) {
96
- return { success: false, error: `扩展插件 '${plugin}' 不存在` };
97
- }
98
-
99
- const toolDef = ext.tools.find((t) => t.name === tool);
100
- if (!toolDef) {
101
- return { success: false, error: `扩展工具 '${tool}' 不存在` };
102
- }
103
-
104
- try {
105
- // 统一 execute 签名为 (args, framework)
106
- const result = await toolDef.execute(toolArgs, framework);
107
- return { success: true, result };
108
- } catch (err) {
109
- log.error(` Tool '${tool}' failed:`, err.message);
110
- return { success: false, error: err.message };
111
- }
112
- },
113
- });
114
-
115
- framework.registerTool({
116
- name: 'ext_list',
117
- description: '列出所有可用的扩展插件及其工具',
118
- inputSchema: z.object({}),
119
- execute: async () => {
120
- const extensions = [];
121
- for (const [name, ext] of this._extensions) {
122
- extensions.push({
123
- name,
124
- description: ext.description,
125
- version: ext.version,
126
- tools: ext.tools.map((t) => ({ name: t.name, description: t.description })),
127
- });
128
- }
129
- return { success: true, extensions };
130
- },
131
- });
132
-
133
- framework.registerTool({
134
- name: 'ext_schema',
135
- description: '查询扩展工具的调用参数结构',
136
- inputSchema: z.object({
137
- plugin: z.string().describe('扩展插件名称'),
138
- tool: z.string().describe('工具名称'),
139
- }),
140
- execute: async (args) => {
141
- const { plugin, tool } = args;
142
- const ext = this._extensions.get(plugin);
143
- if (!ext) {
144
- return { success: false, error: `扩展插件 '${plugin}' 不存在` };
145
- }
146
-
147
- const toolDef = ext.tools.find((t) => t.name === tool);
148
- if (!toolDef) {
149
- return { success: false, error: `扩展工具 '${tool}' 不存在` };
150
- }
151
-
152
- return {
153
- success: true,
154
- result: {
155
- plugin,
156
- tool,
157
- description: toolDef.description,
158
- inputSchema: toolDef.inputSchema,
159
- },
160
- };
161
- },
162
- });
163
-
164
- framework.on('agent:created', (agent) => {
165
- this._refreshAgentExtPrompt(agent);
166
- });
167
-
168
- if (framework._ready) {
169
- this._refreshAllAgentsExtPrompt(framework);
170
- } else {
171
- framework.once('framework:ready', () => {
172
- this._refreshAllAgentsExtPrompt(framework);
173
- });
174
- }
175
-
176
- return this;
177
- }
178
-
179
- registerTool(pluginName, pluginInfo, toolDef) {
180
- if (!this._extensions.has(pluginName)) {
181
- this._extensions.set(pluginName, {
182
- name: pluginInfo.name || pluginName,
183
- description: pluginInfo.description || '',
184
- version: pluginInfo.version || '1.0.0',
185
- tools: [],
186
- });
187
- }
188
-
189
- const ext = this._extensions.get(pluginName);
190
- if (!ext.tools.find((t) => t.name === toolDef.name)) {
191
- ext.tools.push({
192
- name: toolDef.name,
193
- description: toolDef.description || '',
194
- inputSchema: toolDef.inputSchema,
195
- execute: toolDef.execute,
196
- });
197
- }
198
-
199
- log.debug(` Registered tool '${toolDef.name}' for extension '${pluginName}'`);
200
-
201
- // 刷新所有 Agent 的扩展提示词
202
- if (this._framework && this._framework._ready) {
203
- this._refreshAllAgentsExtPrompt(this._framework);
204
- }
205
- }
206
-
207
- _refreshAllAgentsExtPrompt(framework) {
208
- const visited = new Set();
209
- const traverse = (agent) => {
210
- if (!agent || visited.has(agent)) return;
211
- visited.add(agent);
212
- this._refreshAgentExtPrompt(agent);
213
- const subAgents = agent.getSubAgents?.() || agent._subAgents || new Map();
214
- for (const [, subAgentInfo] of subAgents) {
215
- traverse(subAgentInfo.agent);
216
- }
217
- };
218
- for (const agent of framework._agents || []) {
219
- traverse(agent);
220
- }
221
- }
222
-
223
- _refreshAgentExtPrompt(agent) {
224
- const extDesc = this._buildExtensionsDescription();
225
- if (!extDesc) return;
226
-
227
- const existingPrompt = agent._originalPrompt || '';
228
-
229
- // 如果已有 [Extensions] 部分,替换它
230
- const extStartIdx = existingPrompt.indexOf('[Extensions]');
231
- if (extStartIdx !== -1) {
232
- const extEndMarker = '\n\n【';
233
- let extEndIdx = existingPrompt.indexOf(extEndMarker, extStartIdx);
234
- if (extEndIdx === -1) {
235
- // 尝试其他标记
236
- extEndIdx = existingPrompt.indexOf('\n\n---\n\n', extStartIdx);
237
- }
238
- if (extEndIdx === -1) {
239
- extEndIdx = existingPrompt.length;
240
- } else {
241
- extEndIdx += extEndMarker.length;
242
- }
243
- const newPrompt = existingPrompt.substring(0, extStartIdx) + extDesc + existingPrompt.substring(extEndIdx);
244
- agent.setSystemPrompt(newPrompt);
245
- } else {
246
- agent.setSystemPrompt(existingPrompt + '\n\n' + extDesc);
247
- }
248
- }
249
-
250
- _buildExtensionsDescription() {
251
- if (this._extensions.size === 0) {
252
- return '';
253
- }
254
-
255
- let desc = '[Extensions]\n\n';
256
- desc += '你可以通过 `ext_call` 工具调用以下扩展插件的功能。\n\n';
257
-
258
- for (const [name, ext] of this._extensions) {
259
- desc += `### ${ext.name || name}\n\n`;
260
- desc += `${ext.description || ''}\n\n`;
261
- for (const tool of ext.tools) {
262
- desc += `- **${tool.name}**: ${tool.description || '无描述'}\n`;
263
- // 添加参数描述
264
- if (tool.inputSchema) {
265
- try {
266
- if (typeof tool.inputSchema.toJSON === 'function') {
267
- desc += `**参数:**\n\n`;
268
- desc += zodSchemaToMarkdown(tool.inputSchema) + '\n\n';
269
- } else if (tool.inputSchema.properties) {
270
- // JSON Schema 格式
271
- desc += `**参数:**\n\n`;
272
- desc += this._schemaToMarkdown(tool.inputSchema) + '\n\n';
273
- }
274
- } catch (e) {
275
- // 忽略转换错误
276
- }
277
- }
278
- }
279
- desc += '\n';
280
- }
281
-
282
- desc += '**调用格式:**\n';
283
- desc += '```\next_call({ plugin: "插件名", tool: "工具名", args: {参数} })\n';
284
- desc += '```\n';
285
- return desc.trim();
286
- }
287
-
288
- /**
289
- * 将 JSON Schema 转换为 Markdown
290
- */
291
- _schemaToMarkdown(schema) {
292
- if (!schema || !schema.properties) return '';
293
-
294
- const props = schema.properties || {};
295
- const required = schema.required || [];
296
- let md = '';
297
-
298
- for (const [key, prop] of Object.entries(props)) {
299
- const isRequired = required.includes(key);
300
- const type = prop.type || 'any';
301
- const descText = prop.description || '';
302
- md += `- \`${key}\`${isRequired ? ' (必填)' : ''}: ${type} ${descText}\n`;
303
- }
304
- return md;
305
- }
306
-
307
- getExtensions() {
308
- return Array.from(this._extensions.entries()).map(([name, ext]) => ({
309
- name,
310
- description: ext.description,
311
- version: ext.version,
312
- tools: ext.tools,
313
- }));
314
- }
315
-
316
- reload(framework) {
317
- this._framework = framework;
318
- }
319
-
320
- async uninstall(framework) {
321
- this._extensions.clear();
322
- this._framework = null;
323
- }
324
- }
325
-
326
- module.exports = ExtensionExecutorPlugin
1
+ /**
2
+ * ExtensionExecutorPlugin 扩展插件执行器
3
+ * 统一管理扩展插件(如 gate-trading)的工具,通过 ext_call 调用
4
+ */
5
+
6
+ const { Plugin } = require('../src/core/plugin-base');
7
+ const { logger } = require('../src/utils/logger');
8
+ const { z } = require('zod');
9
+ const { zodSchemaToMarkdown } = require('@chnak/zod-to-markdown');
10
+
11
+ const log = logger.child('ExtensionExecutor');
12
+
13
+ class ExtensionExecutorPlugin extends Plugin {
14
+ constructor(config = {}) {
15
+ super();
16
+ this.name = 'extension-executor';
17
+ this.version = '1.0.0';
18
+ this.description = '扩展插件执行器 - 统一管理扩展工具';
19
+ this.priority = 10;
20
+ this.system = true;
21
+
22
+ this._framework = null;
23
+ this._extensions = new Map();
24
+ }
25
+
26
+ install(framework) {
27
+ this._framework = framework;
28
+
29
+ // 监听插件加载事件,自动扫描插件的 this.tools
30
+ framework.on('plugin:loaded', (plugin) => {
31
+ this._scanPluginTools(plugin);
32
+ });
33
+
34
+ return this;
35
+ }
36
+
37
+ /**
38
+ * 扫描插件的 this.tools 并注册到扩展系统
39
+ */
40
+ _scanPluginTools(plugin) {
41
+ if (!plugin || !plugin.tools || typeof plugin.tools !== 'object') {
42
+ return;
43
+ }
44
+
45
+ const pluginName = plugin.name;
46
+ if (!pluginName) return;
47
+
48
+ // 获取插件信息
49
+ const pluginInfo = {
50
+ name: plugin.name,
51
+ description: plugin.description || '',
52
+ version: plugin.version || '1.0.0',
53
+ };
54
+
55
+ // 遍历插件的所有工具
56
+ for (const [toolName, toolDef] of Object.entries(plugin.tools)) {
57
+ if (!toolDef || typeof toolDef !== 'object') continue;
58
+
59
+ this.registerTool(pluginName, pluginInfo, {
60
+ name: toolName,
61
+ description: toolDef.description || '',
62
+ inputSchema: toolDef.inputSchema,
63
+ execute: toolDef.execute,
64
+ });
65
+ }
66
+
67
+ log.debug(` Scanned ${Object.keys(plugin.tools).length} tools from plugin '${pluginName}'`);
68
+
69
+ // 刷新所有 Agent 的扩展提示词
70
+ if (this._framework && this._framework._ready) {
71
+ this._refreshAllAgentsExtPrompt(this._framework);
72
+ }
73
+ }
74
+
75
+ async start(framework) {
76
+ // 扫描所有已加载插件的 tools
77
+ const plugins = framework.pluginManager.getAll();
78
+ for (const { instance: plugin } of plugins) {
79
+ this._scanPluginTools(plugin);
80
+ }
81
+
82
+ framework.registerTool({
83
+ name: 'ext_call',
84
+ description: '调用扩展插件的工具',
85
+ inputSchema: z.object({
86
+ plugin: z.string().describe('扩展插件名称'),
87
+ tool: z.string().describe('工具名称'),
88
+ args: z.record(z.any()).optional().describe('工具参数'),
89
+ }),
90
+ execute: async (args) => {
91
+ const { plugin, tool, args: toolArgs = {} } = args;
92
+ log.info(` ext_call: plugin=${plugin}, tool=${tool}`);
93
+
94
+ const ext = this._extensions.get(plugin);
95
+ if (!ext) {
96
+ return { success: false, error: `扩展插件 '${plugin}' 不存在` };
97
+ }
98
+
99
+ const toolDef = ext.tools.find((t) => t.name === tool);
100
+ if (!toolDef) {
101
+ return { success: false, error: `扩展工具 '${tool}' 不存在` };
102
+ }
103
+
104
+ try {
105
+ // 统一 execute 签名为 (args, framework)
106
+ const result = await toolDef.execute(toolArgs, framework);
107
+ return { success: true, result };
108
+ } catch (err) {
109
+ log.error(` Tool '${tool}' failed:`, err.message);
110
+ return { success: false, error: err.message };
111
+ }
112
+ },
113
+ });
114
+
115
+ framework.registerTool({
116
+ name: 'ext_list',
117
+ description: '列出所有可用的扩展插件及其工具',
118
+ inputSchema: z.object({}),
119
+ execute: async () => {
120
+ const extensions = [];
121
+ for (const [name, ext] of this._extensions) {
122
+ extensions.push({
123
+ name,
124
+ description: ext.description,
125
+ version: ext.version,
126
+ tools: ext.tools.map((t) => ({ name: t.name, description: t.description })),
127
+ });
128
+ }
129
+ return { success: true, extensions };
130
+ },
131
+ });
132
+
133
+ framework.registerTool({
134
+ name: 'ext_schema',
135
+ description: '查询扩展工具的调用参数结构',
136
+ inputSchema: z.object({
137
+ plugin: z.string().describe('扩展插件名称'),
138
+ tool: z.string().describe('工具名称'),
139
+ }),
140
+ execute: async (args) => {
141
+ const { plugin, tool } = args;
142
+ const ext = this._extensions.get(plugin);
143
+ if (!ext) {
144
+ return { success: false, error: `扩展插件 '${plugin}' 不存在` };
145
+ }
146
+
147
+ const toolDef = ext.tools.find((t) => t.name === tool);
148
+ if (!toolDef) {
149
+ return { success: false, error: `扩展工具 '${tool}' 不存在` };
150
+ }
151
+
152
+ return {
153
+ success: true,
154
+ result: {
155
+ plugin,
156
+ tool,
157
+ description: toolDef.description,
158
+ inputSchema: toolDef.inputSchema,
159
+ },
160
+ };
161
+ },
162
+ });
163
+
164
+ framework.on('agent:created', (agent) => {
165
+ this._refreshAgentExtPrompt(agent);
166
+ });
167
+
168
+ if (framework._ready) {
169
+ this._refreshAllAgentsExtPrompt(framework);
170
+ } else {
171
+ framework.once('framework:ready', () => {
172
+ this._refreshAllAgentsExtPrompt(framework);
173
+ });
174
+ }
175
+
176
+ return this;
177
+ }
178
+
179
+ registerTool(pluginName, pluginInfo, toolDef) {
180
+ if (!this._extensions.has(pluginName)) {
181
+ this._extensions.set(pluginName, {
182
+ name: pluginInfo.name || pluginName,
183
+ description: pluginInfo.description || '',
184
+ version: pluginInfo.version || '1.0.0',
185
+ tools: [],
186
+ });
187
+ }
188
+
189
+ const ext = this._extensions.get(pluginName);
190
+ if (!ext.tools.find((t) => t.name === toolDef.name)) {
191
+ ext.tools.push({
192
+ name: toolDef.name,
193
+ description: toolDef.description || '',
194
+ inputSchema: toolDef.inputSchema,
195
+ execute: toolDef.execute,
196
+ });
197
+ }
198
+
199
+ log.debug(` Registered tool '${toolDef.name}' for extension '${pluginName}'`);
200
+
201
+ // 刷新所有 Agent 的扩展提示词
202
+ if (this._framework && this._framework._ready) {
203
+ this._refreshAllAgentsExtPrompt(this._framework);
204
+ }
205
+ }
206
+
207
+ _refreshAllAgentsExtPrompt(framework) {
208
+ const visited = new Set();
209
+ const traverse = (agent) => {
210
+ if (!agent || visited.has(agent)) return;
211
+ visited.add(agent);
212
+ this._refreshAgentExtPrompt(agent);
213
+ const subAgents = agent.getSubAgents?.() || agent._subAgents || new Map();
214
+ for (const [, subAgentInfo] of subAgents) {
215
+ traverse(subAgentInfo.agent);
216
+ }
217
+ };
218
+ for (const agent of framework._agents || []) {
219
+ traverse(agent);
220
+ }
221
+ }
222
+
223
+ _refreshAgentExtPrompt(agent) {
224
+ const extDesc = this._buildExtensionsDescription();
225
+ if (!extDesc) return;
226
+
227
+ const existingPrompt = agent._originalPrompt || '';
228
+
229
+ // 如果已有 [Extensions] 部分,替换它
230
+ const extStartIdx = existingPrompt.indexOf('[Extensions]');
231
+ if (extStartIdx !== -1) {
232
+ const extEndMarker = '\n\n【';
233
+ let extEndIdx = existingPrompt.indexOf(extEndMarker, extStartIdx);
234
+ if (extEndIdx === -1) {
235
+ // 尝试其他标记
236
+ extEndIdx = existingPrompt.indexOf('\n\n---\n\n', extStartIdx);
237
+ }
238
+ if (extEndIdx === -1) {
239
+ extEndIdx = existingPrompt.length;
240
+ } else {
241
+ extEndIdx += extEndMarker.length;
242
+ }
243
+ const newPrompt = existingPrompt.substring(0, extStartIdx) + extDesc + existingPrompt.substring(extEndIdx);
244
+ agent.setSystemPrompt(newPrompt);
245
+ } else {
246
+ agent.setSystemPrompt(existingPrompt + '\n\n' + extDesc);
247
+ }
248
+ }
249
+
250
+ _buildExtensionsDescription() {
251
+ if (this._extensions.size === 0) {
252
+ return '';
253
+ }
254
+
255
+ let desc = '[Extensions]\n\n';
256
+ desc += '你可以通过 `ext_call` 工具调用以下扩展插件的功能。\n\n';
257
+
258
+ for (const [name, ext] of this._extensions) {
259
+ desc += `### ${ext.name || name}\n\n`;
260
+ desc += `${ext.description || ''}\n\n`;
261
+ for (const tool of ext.tools) {
262
+ desc += `- **${tool.name}**: ${tool.description || '无描述'}\n`;
263
+ // 添加参数描述
264
+ if (tool.inputSchema) {
265
+ try {
266
+ if (typeof tool.inputSchema.toJSON === 'function') {
267
+ desc += `**参数:**\n\n`;
268
+ desc += zodSchemaToMarkdown(tool.inputSchema) + '\n\n';
269
+ } else if (tool.inputSchema.properties) {
270
+ // JSON Schema 格式
271
+ desc += `**参数:**\n\n`;
272
+ desc += this._schemaToMarkdown(tool.inputSchema) + '\n\n';
273
+ }
274
+ } catch (e) {
275
+ // 忽略转换错误
276
+ }
277
+ }
278
+ }
279
+ desc += '\n';
280
+ }
281
+
282
+ desc += '**调用格式:**\n';
283
+ desc += '```\next_call({ plugin: "插件名", tool: "工具名", args: {参数} })\n';
284
+ desc += '```\n';
285
+ return desc.trim();
286
+ }
287
+
288
+ /**
289
+ * 将 JSON Schema 转换为 Markdown
290
+ */
291
+ _schemaToMarkdown(schema) {
292
+ if (!schema || !schema.properties) return '';
293
+
294
+ const props = schema.properties || {};
295
+ const required = schema.required || [];
296
+ let md = '';
297
+
298
+ for (const [key, prop] of Object.entries(props)) {
299
+ const isRequired = required.includes(key);
300
+ const type = prop.type || 'any';
301
+ const descText = prop.description || '';
302
+ md += `- \`${key}\`${isRequired ? ' (必填)' : ''}: ${type} ${descText}\n`;
303
+ }
304
+ return md;
305
+ }
306
+
307
+ getExtensions() {
308
+ return Array.from(this._extensions.entries()).map(([name, ext]) => ({
309
+ name,
310
+ description: ext.description,
311
+ version: ext.version,
312
+ tools: ext.tools,
313
+ }));
314
+ }
315
+
316
+ reload(framework) {
317
+ this._framework = framework;
318
+ }
319
+
320
+ async uninstall(framework) {
321
+ this._extensions.clear();
322
+ this._framework = null;
323
+ }
324
+ }
325
+
326
+ module.exports = ExtensionExecutorPlugin