foliko 1.0.75 → 1.0.76
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/.claude/settings.local.json +159 -157
- package/cli/bin/foliko.js +12 -12
- package/cli/src/commands/chat.js +143 -143
- package/cli/src/commands/list.js +93 -93
- package/cli/src/index.js +75 -75
- package/cli/src/ui/chat-ui.js +201 -201
- package/cli/src/utils/ansi.js +40 -40
- package/cli/src/utils/markdown.js +292 -292
- package/examples/ambient-example.js +194 -194
- package/examples/basic.js +115 -115
- package/examples/bootstrap.js +121 -121
- package/examples/mcp-example.js +56 -56
- package/examples/skill-example.js +49 -49
- package/examples/test-chat.js +137 -137
- package/examples/test-mcp.js +85 -85
- package/examples/test-reload.js +59 -59
- package/examples/test-telegram.js +50 -50
- package/examples/test-tg-bot.js +45 -45
- package/examples/test-tg-simple.js +47 -47
- package/examples/test-tg.js +62 -62
- package/examples/test-think.js +43 -43
- package/examples/test-web-plugin.js +103 -103
- package/examples/test-weixin-feishu.js +103 -103
- package/examples/workflow.js +158 -158
- package/package.json +1 -1
- package/plugins/ai-plugin.js +102 -102
- package/plugins/ambient-agent/EventWatcher.js +113 -113
- package/plugins/ambient-agent/ExplorerLoop.js +640 -640
- package/plugins/ambient-agent/GoalManager.js +197 -197
- package/plugins/ambient-agent/Reflector.js +95 -95
- package/plugins/ambient-agent/StateStore.js +90 -90
- package/plugins/ambient-agent/constants.js +101 -101
- package/plugins/ambient-agent/index.js +579 -579
- package/plugins/audit-plugin.js +187 -187
- package/plugins/default-plugins.js +662 -662
- package/plugins/email/constants.js +64 -64
- package/plugins/email/handlers.js +461 -461
- package/plugins/email/index.js +278 -278
- package/plugins/email/monitor.js +269 -269
- package/plugins/email/parser.js +138 -138
- package/plugins/email/reply.js +151 -151
- package/plugins/email/utils.js +124 -124
- package/plugins/feishu-plugin.js +481 -481
- package/plugins/file-system-plugin.js +826 -826
- package/plugins/install-plugin.js +199 -199
- package/plugins/python-executor-plugin.js +367 -367
- package/plugins/python-plugin-loader.js +481 -481
- package/plugins/rules-plugin.js +294 -294
- package/plugins/scheduler-plugin.js +691 -691
- package/plugins/session-plugin.js +369 -369
- package/plugins/shell-executor-plugin.js +197 -197
- package/plugins/storage-plugin.js +240 -240
- package/plugins/subagent-plugin.js +845 -845
- package/plugins/telegram-plugin.js +482 -482
- package/plugins/think-plugin.js +345 -345
- package/plugins/tools-plugin.js +196 -196
- package/plugins/web-plugin.js +606 -606
- package/plugins/weixin-plugin.js +545 -545
- package/src/capabilities/index.js +11 -11
- package/src/capabilities/skill-manager.js +609 -609
- package/src/capabilities/workflow-engine.js +1109 -1109
- package/src/core/agent-chat.js +882 -882
- package/src/core/agent.js +892 -892
- package/src/core/framework.js +465 -465
- package/src/core/index.js +19 -19
- package/src/core/plugin-base.js +219 -219
- package/src/core/plugin-manager.js +863 -863
- package/src/core/provider.js +114 -114
- package/src/core/sub-agent-config.js +264 -264
- package/src/core/system-prompt-builder.js +120 -120
- package/src/core/tool-registry.js +517 -517
- package/src/core/tool-router.js +297 -297
- package/src/executors/executor-base.js +58 -58
- package/src/executors/mcp-executor.js +741 -741
- package/src/index.js +25 -25
- package/src/utils/circuit-breaker.js +301 -301
- package/src/utils/error-boundary.js +363 -363
- package/src/utils/error.js +374 -374
- package/src/utils/event-emitter.js +97 -97
- package/src/utils/id.js +133 -133
- package/src/utils/index.js +217 -217
- package/src/utils/logger.js +181 -181
- package/src/utils/plugin-helpers.js +90 -90
- package/src/utils/retry.js +122 -122
- package/src/utils/sandbox.js +292 -292
- package/test/tool-registry-validation.test.js +218 -218
- package/website/script.js +136 -136
- package/foliko-1.0.75.tgz +0 -0
package/src/core/framework.js
CHANGED
|
@@ -1,465 +1,465 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Framework 核心容器
|
|
3
|
-
* 管理所有子系统,提供统一入口
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const { AsyncLocalStorage } = require('async_hooks');
|
|
8
|
-
const { EventEmitter } = require('../utils/event-emitter');
|
|
9
|
-
const { PluginManager } = require('./plugin-manager');
|
|
10
|
-
const { ToolRegistry } = require('./tool-registry');
|
|
11
|
-
const { Agent } = require('./agent');
|
|
12
|
-
const { SubAgentConfigManager } = require('./sub-agent-config');
|
|
13
|
-
|
|
14
|
-
// 添加框架目录的 node_modules 到全局搜索路径
|
|
15
|
-
// 让项目插件能 require 框架内置的包(如 zod)
|
|
16
|
-
const frameworkNodeModules = path.join(__dirname, '..', '..', 'node_modules');
|
|
17
|
-
if (!module.paths.includes(frameworkNodeModules)) {
|
|
18
|
-
module.paths.unshift(frameworkNodeModules);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// AsyncLocalStorage 实现真正的上下文隔离(支持并行处理)
|
|
22
|
-
const asyncLocalStorage = new AsyncLocalStorage();
|
|
23
|
-
|
|
24
|
-
class Framework extends EventEmitter {
|
|
25
|
-
/**
|
|
26
|
-
* @param {Object} config - 配置
|
|
27
|
-
* @param {boolean} [config.debug=false] - 调试模式
|
|
28
|
-
*/
|
|
29
|
-
constructor(config = {}) {
|
|
30
|
-
super();
|
|
31
|
-
|
|
32
|
-
this._debug = config.debug || false;
|
|
33
|
-
this._ready = false;
|
|
34
|
-
this._readyPromise = null;
|
|
35
|
-
this._resolveReady = null;
|
|
36
|
-
|
|
37
|
-
// 初始化子系统
|
|
38
|
-
this.toolRegistry = new ToolRegistry();
|
|
39
|
-
this.pluginManager = new PluginManager(this);
|
|
40
|
-
|
|
41
|
-
// Agent 管理
|
|
42
|
-
this._agents = []; // 所有创建的 agent
|
|
43
|
-
this._mainAgent = null; // 主 agent
|
|
44
|
-
|
|
45
|
-
// 子代理配置管理器
|
|
46
|
-
this._subAgentConfigManager = null;
|
|
47
|
-
|
|
48
|
-
// 执行上下文(工具调用时可用)
|
|
49
|
-
this._executionContext = null;
|
|
50
|
-
|
|
51
|
-
// 事件转发
|
|
52
|
-
this.toolRegistry.on('tool:registered', (tool) => {
|
|
53
|
-
this.emit('tool:registered', tool);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
this._registerBuiltinTools();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* 从 AI 插件合并配置到目标配置对象
|
|
61
|
-
* @param {Object} target - 目标配置对象
|
|
62
|
-
* @private
|
|
63
|
-
*/
|
|
64
|
-
_mergeAIConfig(target) {
|
|
65
|
-
if (target.apiKey) return target; // 已有 apiKey 不需要合并
|
|
66
|
-
|
|
67
|
-
const aiPlugin = this.pluginManager.get('ai');
|
|
68
|
-
if (!aiPlugin) return target;
|
|
69
|
-
|
|
70
|
-
const defaults = {
|
|
71
|
-
apiKey: aiPlugin.config.apiKey,
|
|
72
|
-
provider: aiPlugin.config.provider,
|
|
73
|
-
model: aiPlugin.config.model,
|
|
74
|
-
baseURL: aiPlugin.config.baseURL,
|
|
75
|
-
providerOptions: aiPlugin.config.providerOptions || {},
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
...target,
|
|
80
|
-
apiKey: target.apiKey || defaults.apiKey,
|
|
81
|
-
provider: target.provider || defaults.provider,
|
|
82
|
-
model: target.model || defaults.model,
|
|
83
|
-
baseURL: target.baseURL || defaults.baseURL,
|
|
84
|
-
providerOptions: target.providerOptions || defaults.providerOptions,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* 注册插件(不加载)
|
|
90
|
-
* @param {Plugin|Object} plugin - 插件
|
|
91
|
-
*/
|
|
92
|
-
registerPlugin(plugin) {
|
|
93
|
-
this.pluginManager.register(plugin);
|
|
94
|
-
return this;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* 加载并启动插件)
|
|
99
|
-
* @param {Plugin|Object} plugin - 插件
|
|
100
|
-
*/
|
|
101
|
-
async loadPlugin(plugin) {
|
|
102
|
-
await this.pluginManager.load(plugin);
|
|
103
|
-
return this;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* 卸载插件
|
|
108
|
-
* @param {string} name - 插件名称
|
|
109
|
-
*/
|
|
110
|
-
async unloadPlugin(name) {
|
|
111
|
-
await this.pluginManager.unload(name);
|
|
112
|
-
return this;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* 重载单个插件
|
|
117
|
-
* @param {string} name - 插件名称
|
|
118
|
-
*/
|
|
119
|
-
async reloadPlugin(name) {
|
|
120
|
-
await this.pluginManager.reload(name);
|
|
121
|
-
return this;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* 重载所有插件)
|
|
126
|
-
*/
|
|
127
|
-
async reloadAllPlugins() {
|
|
128
|
-
await this.pluginManager.reloadAll();
|
|
129
|
-
return this;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* 启用插件
|
|
134
|
-
* @param {string} name - 插件名称
|
|
135
|
-
*/
|
|
136
|
-
async enablePlugin(name) {
|
|
137
|
-
await this.pluginManager.enable(name);
|
|
138
|
-
return this;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* 禁用插件
|
|
143
|
-
* @param {string} name - 插件名称
|
|
144
|
-
*/
|
|
145
|
-
async disablePlugin(name) {
|
|
146
|
-
await this.pluginManager.disable(name);
|
|
147
|
-
return this;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* 更新插件配置
|
|
152
|
-
* @param {string} name - 插件名称
|
|
153
|
-
* @param {Object} config - 新配置
|
|
154
|
-
*/
|
|
155
|
-
updatePluginConfig(name, config) {
|
|
156
|
-
return this.pluginManager.updatePluginConfig(name, config);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* 注册工具
|
|
161
|
-
* @param {Object} tool - 工具定义
|
|
162
|
-
*/
|
|
163
|
-
registerTool(tool) {
|
|
164
|
-
this.toolRegistry.register(tool);
|
|
165
|
-
return this;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* 获取所有工具)
|
|
170
|
-
* @returns {Array<Object>}
|
|
171
|
-
*/
|
|
172
|
-
getTools() {
|
|
173
|
-
return this.toolRegistry.getAll();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// ============================================================================
|
|
177
|
-
// 事件描述注册(供 Ambient Agent 使用)
|
|
178
|
-
// ============================================================================
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* 注册事件描述
|
|
182
|
-
* @param {string} eventType - 事件类型,如 'tool:result'
|
|
183
|
-
* @param {string} description - 事件描述
|
|
184
|
-
* @param {Object} schema - 事件参数 Schema(可选)
|
|
185
|
-
*/
|
|
186
|
-
registerEventDescription(eventType, description, schema = null) {
|
|
187
|
-
this.pluginManager.registerEventDescription(eventType, description, schema);
|
|
188
|
-
return this;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* 获取所有已注册的事件描述
|
|
193
|
-
* @returns {Map<string, Object>} 事件描述 Map
|
|
194
|
-
*/
|
|
195
|
-
getEventDescriptions() {
|
|
196
|
-
return this.pluginManager.getEventDescriptions();
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* 获取单个事件描述
|
|
201
|
-
* @param {string} eventType - 事件类型
|
|
202
|
-
* @returns {Object|null} 事件描述
|
|
203
|
-
*/
|
|
204
|
-
getEventDescription(eventType) {
|
|
205
|
-
return this.pluginManager.getEventDescription(eventType);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* 执行工具
|
|
210
|
-
* @param {string} name - 工具名称
|
|
211
|
-
* @param {Object} args - 参数
|
|
212
|
-
*/
|
|
213
|
-
async executeTool(name, args) {
|
|
214
|
-
return this.toolRegistry.execute(name, args, this);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* 在上下文中执行函数(支持并行处理,自动隔离 session)
|
|
219
|
-
* @param {Object} context - 执行上下文 { sessionId, ... }
|
|
220
|
-
* @param {Function} fn - 要执行的异步函数
|
|
221
|
-
* @returns {Promise}
|
|
222
|
-
*/
|
|
223
|
-
runWithContext(context, fn) {
|
|
224
|
-
return asyncLocalStorage.run(context, fn);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* 获取当前执行上下文(在 runWithContext 内部调用)
|
|
229
|
-
* @returns {Object|null}
|
|
230
|
-
*/
|
|
231
|
-
getExecutionContext() {
|
|
232
|
-
return asyncLocalStorage.getStore() || null;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* @deprecated 使用 runWithContext 代替
|
|
237
|
-
*/
|
|
238
|
-
setExecutionContext() {}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* @deprecated 使用 runWithContext 代替
|
|
242
|
-
*/
|
|
243
|
-
clearExecutionContext() {}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* 创建 Agent
|
|
247
|
-
* @param {Object} config - Agent 配置
|
|
248
|
-
*/
|
|
249
|
-
createAgent(config) {
|
|
250
|
-
// 合并 AI 插件配置
|
|
251
|
-
config = this._mergeAIConfig(config);
|
|
252
|
-
|
|
253
|
-
const agent = new Agent(this, config);
|
|
254
|
-
|
|
255
|
-
// 跟踪 agent
|
|
256
|
-
this._agents.push(agent);
|
|
257
|
-
if (!this._mainAgent) {
|
|
258
|
-
this._mainAgent = agent;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
this.emit('agent:created', agent);
|
|
262
|
-
return agent;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* 为指定 session 创建独立 Agent 实例
|
|
267
|
-
* @param {string} sessionId - session ID
|
|
268
|
-
* @param {Object} config - Agent 配置
|
|
269
|
-
*/
|
|
270
|
-
createSessionAgent(sessionId, config = {}) {
|
|
271
|
-
const agentConfig = {
|
|
272
|
-
name: `session_${sessionId}`,
|
|
273
|
-
...config,
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
// 合并 AI 插件配置
|
|
277
|
-
const merged = this._mergeAIConfig(agentConfig);
|
|
278
|
-
|
|
279
|
-
const agent = new Agent(this, merged);
|
|
280
|
-
this._agents.push(agent);
|
|
281
|
-
|
|
282
|
-
// 如果提供了 systemPrompt,需要替换 AgentChatHandler
|
|
283
|
-
if (merged.systemPrompt) {
|
|
284
|
-
agent.setSystemPrompt(merged.systemPrompt);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
this.emit('agent:created', agent);
|
|
288
|
-
return agent;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* 创建子Agent(具有独立工具集的轻量级Agent)
|
|
293
|
-
* @param {Object} config - 子Agent配置
|
|
294
|
-
* @param {string} config.name - 子Agent名称
|
|
295
|
-
* @param {string} config.role - 角色描述(用于智能选择)
|
|
296
|
-
* @param {string} [config.description] - 供主Agent理解的描述)
|
|
297
|
-
* @param {Object} [config.tools] - 自定义工具 { name: toolDef }
|
|
298
|
-
* @param {string[]} [config.parentTools] - 从父Agent继承的工具名称列表)
|
|
299
|
-
* @param {Object} [config.llmConfig] - 独立LLM配置
|
|
300
|
-
* @returns {Agent} 创建的子Agent
|
|
301
|
-
*/
|
|
302
|
-
createSubAgent(config) {
|
|
303
|
-
const {
|
|
304
|
-
name,
|
|
305
|
-
role,
|
|
306
|
-
description = '',
|
|
307
|
-
tools = {},
|
|
308
|
-
parentTools, // 如果不传,默认继承主agent所有工具
|
|
309
|
-
llmConfig = null,
|
|
310
|
-
} = config;
|
|
311
|
-
|
|
312
|
-
// 构建子Agent配置
|
|
313
|
-
const agentConfig = {
|
|
314
|
-
name: `subagent_${name}`,
|
|
315
|
-
role: role,
|
|
316
|
-
systemPrompt: role, // 使用 role 作为 systemPrompt
|
|
317
|
-
...(llmConfig || {}), // 如果提供了独立LLM配置,合并
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
// 合并 AI 插件配置
|
|
321
|
-
const merged = this._mergeAIConfig(agentConfig);
|
|
322
|
-
|
|
323
|
-
// 创建 Agent
|
|
324
|
-
const agent = new Agent(this, merged);
|
|
325
|
-
|
|
326
|
-
// 注册自定义工具
|
|
327
|
-
for (const [toolName, toolDef] of Object.entries(tools)) {
|
|
328
|
-
if (toolDef && typeof toolDef === 'object') {
|
|
329
|
-
agent.registerTool({
|
|
330
|
-
name: toolName,
|
|
331
|
-
description: toolDef.description || '',
|
|
332
|
-
inputSchema: toolDef.inputSchema,
|
|
333
|
-
execute: toolDef.execute,
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// 从父Agent继承工具
|
|
339
|
-
if (this._mainAgent) {
|
|
340
|
-
const parentToolsDefs = this._mainAgent.getTools();
|
|
341
|
-
if (parentTools === undefined) {
|
|
342
|
-
// 如果没有指定 parentTools,默认继承所有工具
|
|
343
|
-
for (const toolDef of parentToolsDefs) {
|
|
344
|
-
agent.registerTool(toolDef);
|
|
345
|
-
}
|
|
346
|
-
} else if (Array.isArray(parentTools) && parentTools.length > 0) {
|
|
347
|
-
// 指定了要继承的工具列表
|
|
348
|
-
for (const toolName of parentTools) {
|
|
349
|
-
const toolDef = parentToolsDefs.find((t) => t.name === toolName);
|
|
350
|
-
if (toolDef) {
|
|
351
|
-
agent.registerTool(toolDef);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
this._agents.push(agent);
|
|
358
|
-
this.emit('agent:created', agent);
|
|
359
|
-
return agent;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
/**
|
|
363
|
-
* 获取 AI 插件
|
|
364
|
-
* @returns {Object|undefined}
|
|
365
|
-
*/
|
|
366
|
-
getAIPlugin() {
|
|
367
|
-
return this.pluginManager.get('ai');
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Bootstrap - 使用默认配置启动框架
|
|
372
|
-
* 自动加载 .agent/ 目录下的配置和所有默认插件)
|
|
373
|
-
* @param {Object} config - 配置
|
|
374
|
-
* @param {string} [config.agentDir='.agent'] - Agent 配置目录
|
|
375
|
-
* @param {Object} [config.aiConfig] - AI 配置(可选,覆盖文件配置)
|
|
376
|
-
* @returns {Promise<Framework>}
|
|
377
|
-
*/
|
|
378
|
-
async bootstrap(config = {}) {
|
|
379
|
-
const {
|
|
380
|
-
bootstrapDefaults,
|
|
381
|
-
DefaultPlugins,
|
|
382
|
-
loadAgentConfig,
|
|
383
|
-
} = require('../../plugins/default-plugins');
|
|
384
|
-
|
|
385
|
-
// 先加载默认插件配置
|
|
386
|
-
const defaultsPlugin = new DefaultPlugins({
|
|
387
|
-
agentDir: config.agentDir || '.agent',
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
await this.loadPlugin(defaultsPlugin);
|
|
391
|
-
|
|
392
|
-
// 获取配置
|
|
393
|
-
const agentConfig = defaultsPlugin.getConfig();
|
|
394
|
-
|
|
395
|
-
// 如果提供了 AI 配置,覆盖文件配置
|
|
396
|
-
if (config.aiConfig) {
|
|
397
|
-
agentConfig.ai = { ...agentConfig.ai, ...config.aiConfig };
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
// 加载所有默认插件(传入已加载的配置避免重复加载)
|
|
401
|
-
await bootstrapDefaults(this, { _config: agentConfig, _skipConfigLoad: true });
|
|
402
|
-
|
|
403
|
-
this._setReady();
|
|
404
|
-
return this;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* 等待框架就绪
|
|
409
|
-
*/
|
|
410
|
-
async ready() {
|
|
411
|
-
if (this._ready) {
|
|
412
|
-
return this;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
if (!this._readyPromise) {
|
|
416
|
-
this._readyPromise = new Promise((resolve) => {
|
|
417
|
-
this._resolveReady = resolve;
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
await this._readyPromise;
|
|
422
|
-
return this;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* 标记框架就绪
|
|
427
|
-
* @private
|
|
428
|
-
*/
|
|
429
|
-
_setReady() {
|
|
430
|
-
this._ready = true;
|
|
431
|
-
if (this._resolveReady) {
|
|
432
|
-
this._resolveReady(this);
|
|
433
|
-
}
|
|
434
|
-
this.emit('framework:ready', this);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* 注册内置工具
|
|
439
|
-
* @private
|
|
440
|
-
*/
|
|
441
|
-
_registerBuiltinTools() {
|
|
442
|
-
// 内置工具会在 Agent 创建时添加)
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* 销毁框架)
|
|
447
|
-
*/
|
|
448
|
-
async destroy() {
|
|
449
|
-
// 卸载所有插件)
|
|
450
|
-
const plugins = this.pluginManager.getAll();
|
|
451
|
-
for (const { name } of plugins) {
|
|
452
|
-
await this.pluginManager.unload(name);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// 清空工具
|
|
456
|
-
this.toolRegistry.clear();
|
|
457
|
-
|
|
458
|
-
// 清空事件
|
|
459
|
-
this.removeAllListeners();
|
|
460
|
-
|
|
461
|
-
this.emit('framework:destroyed');
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
module.exports = { Framework };
|
|
1
|
+
/**
|
|
2
|
+
* Framework 核心容器
|
|
3
|
+
* 管理所有子系统,提供统一入口
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { AsyncLocalStorage } = require('async_hooks');
|
|
8
|
+
const { EventEmitter } = require('../utils/event-emitter');
|
|
9
|
+
const { PluginManager } = require('./plugin-manager');
|
|
10
|
+
const { ToolRegistry } = require('./tool-registry');
|
|
11
|
+
const { Agent } = require('./agent');
|
|
12
|
+
const { SubAgentConfigManager } = require('./sub-agent-config');
|
|
13
|
+
|
|
14
|
+
// 添加框架目录的 node_modules 到全局搜索路径
|
|
15
|
+
// 让项目插件能 require 框架内置的包(如 zod)
|
|
16
|
+
const frameworkNodeModules = path.join(__dirname, '..', '..', 'node_modules');
|
|
17
|
+
if (!module.paths.includes(frameworkNodeModules)) {
|
|
18
|
+
module.paths.unshift(frameworkNodeModules);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// AsyncLocalStorage 实现真正的上下文隔离(支持并行处理)
|
|
22
|
+
const asyncLocalStorage = new AsyncLocalStorage();
|
|
23
|
+
|
|
24
|
+
class Framework extends EventEmitter {
|
|
25
|
+
/**
|
|
26
|
+
* @param {Object} config - 配置
|
|
27
|
+
* @param {boolean} [config.debug=false] - 调试模式
|
|
28
|
+
*/
|
|
29
|
+
constructor(config = {}) {
|
|
30
|
+
super();
|
|
31
|
+
|
|
32
|
+
this._debug = config.debug || false;
|
|
33
|
+
this._ready = false;
|
|
34
|
+
this._readyPromise = null;
|
|
35
|
+
this._resolveReady = null;
|
|
36
|
+
|
|
37
|
+
// 初始化子系统
|
|
38
|
+
this.toolRegistry = new ToolRegistry();
|
|
39
|
+
this.pluginManager = new PluginManager(this);
|
|
40
|
+
|
|
41
|
+
// Agent 管理
|
|
42
|
+
this._agents = []; // 所有创建的 agent
|
|
43
|
+
this._mainAgent = null; // 主 agent
|
|
44
|
+
|
|
45
|
+
// 子代理配置管理器
|
|
46
|
+
this._subAgentConfigManager = null;
|
|
47
|
+
|
|
48
|
+
// 执行上下文(工具调用时可用)
|
|
49
|
+
this._executionContext = null;
|
|
50
|
+
|
|
51
|
+
// 事件转发
|
|
52
|
+
this.toolRegistry.on('tool:registered', (tool) => {
|
|
53
|
+
this.emit('tool:registered', tool);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
this._registerBuiltinTools();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 从 AI 插件合并配置到目标配置对象
|
|
61
|
+
* @param {Object} target - 目标配置对象
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
64
|
+
_mergeAIConfig(target) {
|
|
65
|
+
if (target.apiKey) return target; // 已有 apiKey 不需要合并
|
|
66
|
+
|
|
67
|
+
const aiPlugin = this.pluginManager.get('ai');
|
|
68
|
+
if (!aiPlugin) return target;
|
|
69
|
+
|
|
70
|
+
const defaults = {
|
|
71
|
+
apiKey: aiPlugin.config.apiKey,
|
|
72
|
+
provider: aiPlugin.config.provider,
|
|
73
|
+
model: aiPlugin.config.model,
|
|
74
|
+
baseURL: aiPlugin.config.baseURL,
|
|
75
|
+
providerOptions: aiPlugin.config.providerOptions || {},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
...target,
|
|
80
|
+
apiKey: target.apiKey || defaults.apiKey,
|
|
81
|
+
provider: target.provider || defaults.provider,
|
|
82
|
+
model: target.model || defaults.model,
|
|
83
|
+
baseURL: target.baseURL || defaults.baseURL,
|
|
84
|
+
providerOptions: target.providerOptions || defaults.providerOptions,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 注册插件(不加载)
|
|
90
|
+
* @param {Plugin|Object} plugin - 插件
|
|
91
|
+
*/
|
|
92
|
+
registerPlugin(plugin) {
|
|
93
|
+
this.pluginManager.register(plugin);
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 加载并启动插件)
|
|
99
|
+
* @param {Plugin|Object} plugin - 插件
|
|
100
|
+
*/
|
|
101
|
+
async loadPlugin(plugin) {
|
|
102
|
+
await this.pluginManager.load(plugin);
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* 卸载插件
|
|
108
|
+
* @param {string} name - 插件名称
|
|
109
|
+
*/
|
|
110
|
+
async unloadPlugin(name) {
|
|
111
|
+
await this.pluginManager.unload(name);
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 重载单个插件
|
|
117
|
+
* @param {string} name - 插件名称
|
|
118
|
+
*/
|
|
119
|
+
async reloadPlugin(name) {
|
|
120
|
+
await this.pluginManager.reload(name);
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 重载所有插件)
|
|
126
|
+
*/
|
|
127
|
+
async reloadAllPlugins() {
|
|
128
|
+
await this.pluginManager.reloadAll();
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 启用插件
|
|
134
|
+
* @param {string} name - 插件名称
|
|
135
|
+
*/
|
|
136
|
+
async enablePlugin(name) {
|
|
137
|
+
await this.pluginManager.enable(name);
|
|
138
|
+
return this;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* 禁用插件
|
|
143
|
+
* @param {string} name - 插件名称
|
|
144
|
+
*/
|
|
145
|
+
async disablePlugin(name) {
|
|
146
|
+
await this.pluginManager.disable(name);
|
|
147
|
+
return this;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* 更新插件配置
|
|
152
|
+
* @param {string} name - 插件名称
|
|
153
|
+
* @param {Object} config - 新配置
|
|
154
|
+
*/
|
|
155
|
+
updatePluginConfig(name, config) {
|
|
156
|
+
return this.pluginManager.updatePluginConfig(name, config);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 注册工具
|
|
161
|
+
* @param {Object} tool - 工具定义
|
|
162
|
+
*/
|
|
163
|
+
registerTool(tool) {
|
|
164
|
+
this.toolRegistry.register(tool);
|
|
165
|
+
return this;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* 获取所有工具)
|
|
170
|
+
* @returns {Array<Object>}
|
|
171
|
+
*/
|
|
172
|
+
getTools() {
|
|
173
|
+
return this.toolRegistry.getAll();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ============================================================================
|
|
177
|
+
// 事件描述注册(供 Ambient Agent 使用)
|
|
178
|
+
// ============================================================================
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 注册事件描述
|
|
182
|
+
* @param {string} eventType - 事件类型,如 'tool:result'
|
|
183
|
+
* @param {string} description - 事件描述
|
|
184
|
+
* @param {Object} schema - 事件参数 Schema(可选)
|
|
185
|
+
*/
|
|
186
|
+
registerEventDescription(eventType, description, schema = null) {
|
|
187
|
+
this.pluginManager.registerEventDescription(eventType, description, schema);
|
|
188
|
+
return this;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* 获取所有已注册的事件描述
|
|
193
|
+
* @returns {Map<string, Object>} 事件描述 Map
|
|
194
|
+
*/
|
|
195
|
+
getEventDescriptions() {
|
|
196
|
+
return this.pluginManager.getEventDescriptions();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 获取单个事件描述
|
|
201
|
+
* @param {string} eventType - 事件类型
|
|
202
|
+
* @returns {Object|null} 事件描述
|
|
203
|
+
*/
|
|
204
|
+
getEventDescription(eventType) {
|
|
205
|
+
return this.pluginManager.getEventDescription(eventType);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 执行工具
|
|
210
|
+
* @param {string} name - 工具名称
|
|
211
|
+
* @param {Object} args - 参数
|
|
212
|
+
*/
|
|
213
|
+
async executeTool(name, args) {
|
|
214
|
+
return this.toolRegistry.execute(name, args, this);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* 在上下文中执行函数(支持并行处理,自动隔离 session)
|
|
219
|
+
* @param {Object} context - 执行上下文 { sessionId, ... }
|
|
220
|
+
* @param {Function} fn - 要执行的异步函数
|
|
221
|
+
* @returns {Promise}
|
|
222
|
+
*/
|
|
223
|
+
runWithContext(context, fn) {
|
|
224
|
+
return asyncLocalStorage.run(context, fn);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* 获取当前执行上下文(在 runWithContext 内部调用)
|
|
229
|
+
* @returns {Object|null}
|
|
230
|
+
*/
|
|
231
|
+
getExecutionContext() {
|
|
232
|
+
return asyncLocalStorage.getStore() || null;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* @deprecated 使用 runWithContext 代替
|
|
237
|
+
*/
|
|
238
|
+
setExecutionContext() {}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* @deprecated 使用 runWithContext 代替
|
|
242
|
+
*/
|
|
243
|
+
clearExecutionContext() {}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* 创建 Agent
|
|
247
|
+
* @param {Object} config - Agent 配置
|
|
248
|
+
*/
|
|
249
|
+
createAgent(config) {
|
|
250
|
+
// 合并 AI 插件配置
|
|
251
|
+
config = this._mergeAIConfig(config);
|
|
252
|
+
|
|
253
|
+
const agent = new Agent(this, config);
|
|
254
|
+
|
|
255
|
+
// 跟踪 agent
|
|
256
|
+
this._agents.push(agent);
|
|
257
|
+
if (!this._mainAgent) {
|
|
258
|
+
this._mainAgent = agent;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
this.emit('agent:created', agent);
|
|
262
|
+
return agent;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* 为指定 session 创建独立 Agent 实例
|
|
267
|
+
* @param {string} sessionId - session ID
|
|
268
|
+
* @param {Object} config - Agent 配置
|
|
269
|
+
*/
|
|
270
|
+
createSessionAgent(sessionId, config = {}) {
|
|
271
|
+
const agentConfig = {
|
|
272
|
+
name: `session_${sessionId}`,
|
|
273
|
+
...config,
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
// 合并 AI 插件配置
|
|
277
|
+
const merged = this._mergeAIConfig(agentConfig);
|
|
278
|
+
|
|
279
|
+
const agent = new Agent(this, merged);
|
|
280
|
+
this._agents.push(agent);
|
|
281
|
+
|
|
282
|
+
// 如果提供了 systemPrompt,需要替换 AgentChatHandler
|
|
283
|
+
if (merged.systemPrompt) {
|
|
284
|
+
agent.setSystemPrompt(merged.systemPrompt);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
this.emit('agent:created', agent);
|
|
288
|
+
return agent;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* 创建子Agent(具有独立工具集的轻量级Agent)
|
|
293
|
+
* @param {Object} config - 子Agent配置
|
|
294
|
+
* @param {string} config.name - 子Agent名称
|
|
295
|
+
* @param {string} config.role - 角色描述(用于智能选择)
|
|
296
|
+
* @param {string} [config.description] - 供主Agent理解的描述)
|
|
297
|
+
* @param {Object} [config.tools] - 自定义工具 { name: toolDef }
|
|
298
|
+
* @param {string[]} [config.parentTools] - 从父Agent继承的工具名称列表)
|
|
299
|
+
* @param {Object} [config.llmConfig] - 独立LLM配置
|
|
300
|
+
* @returns {Agent} 创建的子Agent
|
|
301
|
+
*/
|
|
302
|
+
createSubAgent(config) {
|
|
303
|
+
const {
|
|
304
|
+
name,
|
|
305
|
+
role,
|
|
306
|
+
description = '',
|
|
307
|
+
tools = {},
|
|
308
|
+
parentTools, // 如果不传,默认继承主agent所有工具
|
|
309
|
+
llmConfig = null,
|
|
310
|
+
} = config;
|
|
311
|
+
|
|
312
|
+
// 构建子Agent配置
|
|
313
|
+
const agentConfig = {
|
|
314
|
+
name: `subagent_${name}`,
|
|
315
|
+
role: role,
|
|
316
|
+
systemPrompt: role, // 使用 role 作为 systemPrompt
|
|
317
|
+
...(llmConfig || {}), // 如果提供了独立LLM配置,合并
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
// 合并 AI 插件配置
|
|
321
|
+
const merged = this._mergeAIConfig(agentConfig);
|
|
322
|
+
|
|
323
|
+
// 创建 Agent
|
|
324
|
+
const agent = new Agent(this, merged);
|
|
325
|
+
|
|
326
|
+
// 注册自定义工具
|
|
327
|
+
for (const [toolName, toolDef] of Object.entries(tools)) {
|
|
328
|
+
if (toolDef && typeof toolDef === 'object') {
|
|
329
|
+
agent.registerTool({
|
|
330
|
+
name: toolName,
|
|
331
|
+
description: toolDef.description || '',
|
|
332
|
+
inputSchema: toolDef.inputSchema,
|
|
333
|
+
execute: toolDef.execute,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// 从父Agent继承工具
|
|
339
|
+
if (this._mainAgent) {
|
|
340
|
+
const parentToolsDefs = this._mainAgent.getTools();
|
|
341
|
+
if (parentTools === undefined) {
|
|
342
|
+
// 如果没有指定 parentTools,默认继承所有工具
|
|
343
|
+
for (const toolDef of parentToolsDefs) {
|
|
344
|
+
agent.registerTool(toolDef);
|
|
345
|
+
}
|
|
346
|
+
} else if (Array.isArray(parentTools) && parentTools.length > 0) {
|
|
347
|
+
// 指定了要继承的工具列表
|
|
348
|
+
for (const toolName of parentTools) {
|
|
349
|
+
const toolDef = parentToolsDefs.find((t) => t.name === toolName);
|
|
350
|
+
if (toolDef) {
|
|
351
|
+
agent.registerTool(toolDef);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
this._agents.push(agent);
|
|
358
|
+
this.emit('agent:created', agent);
|
|
359
|
+
return agent;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* 获取 AI 插件
|
|
364
|
+
* @returns {Object|undefined}
|
|
365
|
+
*/
|
|
366
|
+
getAIPlugin() {
|
|
367
|
+
return this.pluginManager.get('ai');
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Bootstrap - 使用默认配置启动框架
|
|
372
|
+
* 自动加载 .agent/ 目录下的配置和所有默认插件)
|
|
373
|
+
* @param {Object} config - 配置
|
|
374
|
+
* @param {string} [config.agentDir='.agent'] - Agent 配置目录
|
|
375
|
+
* @param {Object} [config.aiConfig] - AI 配置(可选,覆盖文件配置)
|
|
376
|
+
* @returns {Promise<Framework>}
|
|
377
|
+
*/
|
|
378
|
+
async bootstrap(config = {}) {
|
|
379
|
+
const {
|
|
380
|
+
bootstrapDefaults,
|
|
381
|
+
DefaultPlugins,
|
|
382
|
+
loadAgentConfig,
|
|
383
|
+
} = require('../../plugins/default-plugins');
|
|
384
|
+
|
|
385
|
+
// 先加载默认插件配置
|
|
386
|
+
const defaultsPlugin = new DefaultPlugins({
|
|
387
|
+
agentDir: config.agentDir || '.agent',
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
await this.loadPlugin(defaultsPlugin);
|
|
391
|
+
|
|
392
|
+
// 获取配置
|
|
393
|
+
const agentConfig = defaultsPlugin.getConfig();
|
|
394
|
+
|
|
395
|
+
// 如果提供了 AI 配置,覆盖文件配置
|
|
396
|
+
if (config.aiConfig) {
|
|
397
|
+
agentConfig.ai = { ...agentConfig.ai, ...config.aiConfig };
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// 加载所有默认插件(传入已加载的配置避免重复加载)
|
|
401
|
+
await bootstrapDefaults(this, { _config: agentConfig, _skipConfigLoad: true });
|
|
402
|
+
|
|
403
|
+
this._setReady();
|
|
404
|
+
return this;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* 等待框架就绪
|
|
409
|
+
*/
|
|
410
|
+
async ready() {
|
|
411
|
+
if (this._ready) {
|
|
412
|
+
return this;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (!this._readyPromise) {
|
|
416
|
+
this._readyPromise = new Promise((resolve) => {
|
|
417
|
+
this._resolveReady = resolve;
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
await this._readyPromise;
|
|
422
|
+
return this;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* 标记框架就绪
|
|
427
|
+
* @private
|
|
428
|
+
*/
|
|
429
|
+
_setReady() {
|
|
430
|
+
this._ready = true;
|
|
431
|
+
if (this._resolveReady) {
|
|
432
|
+
this._resolveReady(this);
|
|
433
|
+
}
|
|
434
|
+
this.emit('framework:ready', this);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* 注册内置工具
|
|
439
|
+
* @private
|
|
440
|
+
*/
|
|
441
|
+
_registerBuiltinTools() {
|
|
442
|
+
// 内置工具会在 Agent 创建时添加)
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* 销毁框架)
|
|
447
|
+
*/
|
|
448
|
+
async destroy() {
|
|
449
|
+
// 卸载所有插件)
|
|
450
|
+
const plugins = this.pluginManager.getAll();
|
|
451
|
+
for (const { name } of plugins) {
|
|
452
|
+
await this.pluginManager.unload(name);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// 清空工具
|
|
456
|
+
this.toolRegistry.clear();
|
|
457
|
+
|
|
458
|
+
// 清空事件
|
|
459
|
+
this.removeAllListeners();
|
|
460
|
+
|
|
461
|
+
this.emit('framework:destroyed');
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
module.exports = { Framework };
|