foliko 1.1.4 → 1.1.6
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/.agent/agents/code-assistant.json +4 -1
- package/.agent/agents/file-assistant.json +4 -1
- package/.agent/agents/orchestrator-demo.md +53 -0
- package/.agent/agents/orchestrator.json +7 -0
- package/.agent/data/plugins-state.json +4 -0
- package/.agent/mcp_config.json +6 -0
- package/.agent/memory/feedback/mnrsiuoc-e1ru74.md +9 -0
- package/.agent/memory/feedback/mnrt2mmz-98az6n.md +9 -0
- package/.agent/memory/feedback/mnrtqrhm-kxsicz.md +9 -0
- package/.agent/memory/feedback/mnrts8vg-i0ngzp.md +15 -0
- package/.agent/memory/feedback/mnrtt7jt-c0trb2.md +9 -0
- package/.agent/memory/feedback/mnruc2f0-5s52la.md +16 -0
- package/.agent/memory/feedback/mnrumbmx-63sa0v.md +9 -0
- package/.agent/memory/project/mnrp7p5n-8enm2a.md +31 -0
- package/.agent/memory/project/mnrp9ifb-yynks0.md +40 -0
- package/.agent/memory/project/mnrpb3b8-f617s4.md +25 -0
- package/.agent/memory/project/mnrrmqgg-focprv.md +9 -0
- package/.agent/memory/project/mnrtykbh-6atsor.md +9 -0
- package/.agent/memory/project/mnru9jiu-kgau16.md +35 -0
- package/.agent/memory/reference/mnrnvpwo-rcqv9m.md +52 -0
- package/.agent/memory/reference/mnrovxvz-zy9xqm.md +25 -0
- package/.agent/memory/reference/mnroxabj-1b3930.md +68 -0
- package/.agent/memory/reference/mnrpjtlp-mnb9od.md +35 -0
- package/.agent/memory/reference/mnrps1x3-6b8xfm.md +28 -0
- package/.agent/memory/reference/mnrpt9ov-15er5w.md +22 -0
- package/.agent/memory/reference/mnrq82dn-y9tv9e.md +50 -0
- package/.agent/memory/reference/mnrqnr5v-v75drf.md +34 -0
- package/.agent/memory/reference/mnrrfzys-urudaf.md +31 -0
- package/.agent/memory/reference/mnrrocha-t0027n.md +21 -0
- package/.agent/memory/reference/mnrukklc-bxndsb.md +35 -0
- package/.agent/memory/user/mnrt39t8-8eosy0.md +9 -0
- package/.agent/plugins/marknative/fonts.zip +0 -0
- package/.agent/sessions/cli_default.json +4493 -1183
- package/.agent/test-agent.js +35 -0
- package/cli/src/commands/chat.js +69 -1
- package/cli/src/index.js +11 -2
- package/foliko-cloud-rising.png +0 -0
- package/foliko-dawn-of-ai.png +0 -0
- package/foliko-mindful-observation.png +0 -0
- package/foliko-stellar-dreams.png +0 -0
- package/foliko-zen-jing.png +0 -0
- package/foliko-zen-kong.png +0 -0
- package/foliko-zen-wu.png +0 -0
- package/package.json +2 -2
- package/plugins/coordinator-plugin.js +282 -0
- package/plugins/default-plugins.js +1 -1
- package/plugins/extension-executor-plugin.js +27 -1
- package/plugins/memory-plugin.js +228 -57
- package/src/core/agent-chat.js +206 -115
- package/src/core/agent.js +258 -71
- package/src/core/coordinator-manager.js +341 -0
- package/src/core/framework.js +50 -0
- package/src/core/plugin-base.js +30 -17
- package/src/core/sub-agent-config.js +8 -1
- package/src/core/worker-agent.js +176 -0
- package/src/executors/mcp-executor.js +4 -4
- package/zen_karesansui.png +0 -0
- package/.agent/plugins/marknative/update-readme.js +0 -134
- package/output/emoji-segoe-test-v2.png +0 -0
- package/output/emoji-segoe-test.png +0 -0
- package/output/emoji-test.png +0 -0
- package/output/emoji-windows-test.png +0 -0
- package/output/foliko-emoji-poster.png +0 -0
- package/output/foliko-muji-poster-final.png +0 -0
- package/output/foliko-muji-poster-v2.png +0 -0
- package/output/foliko-muji-poster.png +0 -0
- package/output/foliko-share.png +0 -0
- package/output/progress-circle-test.png +0 -0
- package/output/vb-agent-poster.png +0 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
const agentsDir = path.join(".", "agents");
|
|
5
|
+
const files = fs.readdirSync(agentsDir);
|
|
6
|
+
console.log("子Agent文件:", files);
|
|
7
|
+
|
|
8
|
+
const { SubAgentConfigManager } = require("../src/core/sub-agent-config.js");
|
|
9
|
+
const configManager = new SubAgentConfigManager(agentsDir);
|
|
10
|
+
|
|
11
|
+
// 需要调用 loadAll() 来加载配置
|
|
12
|
+
configManager.loadAll();
|
|
13
|
+
|
|
14
|
+
const configs = configManager.getAll();
|
|
15
|
+
console.log("\n加载的子Agent配置:", configs.map(c => c.getName()));
|
|
16
|
+
|
|
17
|
+
// 测试 getAllConfigs
|
|
18
|
+
const configs2 = configManager.getAllConfigs();
|
|
19
|
+
console.log("getAllConfigs():", configs2.size, "个");
|
|
20
|
+
configs2.forEach((config, name) => {
|
|
21
|
+
console.log(` - ${name}: valid=${config.isValid()}`);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// 测试 orchestrator-demo
|
|
25
|
+
const demoConfig = configManager.get("orchestrator-demo");
|
|
26
|
+
if (demoConfig) {
|
|
27
|
+
console.log("\norchestrator-demo 配置:");
|
|
28
|
+
console.log(" 名称:", demoConfig.getName());
|
|
29
|
+
console.log(" 描述:", demoConfig.getDescription());
|
|
30
|
+
console.log(" 技能:", demoConfig.getSkills());
|
|
31
|
+
console.log(" 工具:", demoConfig.getTools());
|
|
32
|
+
console.log(" 模型:", demoConfig.getModel());
|
|
33
|
+
} else {
|
|
34
|
+
console.log("\n未找到 orchestrator-demo 配置");
|
|
35
|
+
}
|
package/cli/src/commands/chat.js
CHANGED
|
@@ -63,7 +63,12 @@ function parseArgs(args) {
|
|
|
63
63
|
|
|
64
64
|
for (let i = 0; i < args.length; i++) {
|
|
65
65
|
const arg = args[i];
|
|
66
|
-
if (arg === '--
|
|
66
|
+
if (arg === '-c' || arg === '--continue' || arg === '--continuous') {
|
|
67
|
+
// 持续测试模式:传入 'sessionId:command1|command2|command3'
|
|
68
|
+
// 或 command1|command2|command3 (使用默认 sessionId)
|
|
69
|
+
options.continuous = true;
|
|
70
|
+
options.commandSequence = args[++i] || '';
|
|
71
|
+
} else if (arg === '--model' && args[i + 1]) {
|
|
67
72
|
options.model = args[++i];
|
|
68
73
|
} else if (arg === '--provider' && args[i + 1]) {
|
|
69
74
|
options.provider = args[++i];
|
|
@@ -75,6 +80,10 @@ function parseArgs(args) {
|
|
|
75
80
|
options.stream = true;
|
|
76
81
|
} else if (arg === '--no-stream') {
|
|
77
82
|
options.stream = false;
|
|
83
|
+
} else if (arg === '--clear') {
|
|
84
|
+
options.clearSession = true;
|
|
85
|
+
} else if (arg === '--session' && args[i + 1]) {
|
|
86
|
+
options.sessionId = args[++i];
|
|
78
87
|
}
|
|
79
88
|
}
|
|
80
89
|
|
|
@@ -86,6 +95,59 @@ function parseArgs(args) {
|
|
|
86
95
|
return options;
|
|
87
96
|
}
|
|
88
97
|
|
|
98
|
+
/**
|
|
99
|
+
* 持续测试模式:自动发送多条消息进行测试
|
|
100
|
+
*/
|
|
101
|
+
async function runContinuousTest(agent, options) {
|
|
102
|
+
const sessionId = options.sessionId || 'cli_default';
|
|
103
|
+
const commands = options.commandSequence.split('|').filter((c) => c.trim());
|
|
104
|
+
|
|
105
|
+
if (commands.length === 0) {
|
|
106
|
+
console.log('错误:-c 参数需要提供命令序列,格式:command1|command2|command3');
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log('=== 持续测试模式 ===');
|
|
111
|
+
console.log(`Session: ${sessionId}`);
|
|
112
|
+
console.log(`命令数量: ${commands.length}`);
|
|
113
|
+
console.log('');
|
|
114
|
+
|
|
115
|
+
const runWithContext = agent.framework?.runWithContext.bind(agent.framework);
|
|
116
|
+
|
|
117
|
+
for (let i = 0; i < commands.length; i++) {
|
|
118
|
+
const cmd = commands[i];
|
|
119
|
+
console.log(`\n[${i + 1}/${commands.length}] >>> ${cmd}`);
|
|
120
|
+
console.log('-'.repeat(50));
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
let fullResponse = '';
|
|
124
|
+
await runWithContext({ sessionId }, async () => {
|
|
125
|
+
for await (const chunk of agent.chatStream(cmd, { sessionId })) {
|
|
126
|
+
if (chunk.type === 'text') {
|
|
127
|
+
fullResponse += chunk.text;
|
|
128
|
+
process.stdout.write(chunk.text);
|
|
129
|
+
} else if (chunk.type === 'tool-call') {
|
|
130
|
+
console.log(`\n[工具调用] ${chunk.toolName} ${JSON.stringify(chunk.input)}`);
|
|
131
|
+
} else if (chunk.type === 'error') {
|
|
132
|
+
console.error(`\n[错误] ${chunk.error}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
console.log('\n' + '-'.repeat(50));
|
|
137
|
+
console.log(`[完成] 回复长度: ${fullResponse.length}`);
|
|
138
|
+
} catch (err) {
|
|
139
|
+
console.error(`\n[执行错误] ${err.message}`);
|
|
140
|
+
// 继续执行下一条命令
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 命令间隔 1 秒
|
|
144
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
console.log('\n=== 测试完成 ===');
|
|
148
|
+
console.log(`共执行 ${commands.length} 条命令`);
|
|
149
|
+
}
|
|
150
|
+
|
|
89
151
|
/**
|
|
90
152
|
* Chat 命令入口
|
|
91
153
|
*/
|
|
@@ -127,6 +189,12 @@ async function chatCommand(args) {
|
|
|
127
189
|
- 禁止添加 -g 参数
|
|
128
190
|
- 例如:npx skills add xxx 应该执行为 npx skills add xxx -a openclaw -y`);
|
|
129
191
|
|
|
192
|
+
// 持续测试模式
|
|
193
|
+
if (options.continuous) {
|
|
194
|
+
await runContinuousTest(agent, options);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
130
198
|
// 初始化 UI
|
|
131
199
|
const ui = new ChatUI(agent, { stream: options.stream });
|
|
132
200
|
|
package/cli/src/index.js
CHANGED
|
@@ -12,12 +12,21 @@ const path = require('path');
|
|
|
12
12
|
*/
|
|
13
13
|
async function cli() {
|
|
14
14
|
const args = process.argv.slice(2);
|
|
15
|
-
|
|
15
|
+
let command = args[0] || 'chat';
|
|
16
16
|
const packageJsonPath = path.join(__dirname, '../../package.json');
|
|
17
17
|
|
|
18
|
+
// 如果第一个参数看起来像选项而不是命令,说明用户直接运行 "npm run chat -c ..."
|
|
19
|
+
// 把命令设为 'chat',所有参数都传给 chat 命令
|
|
20
|
+
if (command && command.startsWith('-')) {
|
|
21
|
+
command = 'chat';
|
|
22
|
+
}
|
|
23
|
+
|
|
18
24
|
switch (command) {
|
|
19
25
|
case 'chat':
|
|
20
|
-
|
|
26
|
+
// 如果第一个参数是选项(如 -c),args 已经是传给 chat 的参数
|
|
27
|
+
// 如果第一个参数是 'chat',需要 slice(1) 去掉 'chat'
|
|
28
|
+
const chatArgs = args[0] === 'chat' ? args.slice(1) : args;
|
|
29
|
+
await chatCommand(chatArgs);
|
|
21
30
|
break;
|
|
22
31
|
|
|
23
32
|
case 'list':
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "foliko",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "简约的插件化 Agent 框架",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"@ai-sdk/openai-compatible": "^2.0.35",
|
|
55
55
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
56
56
|
"@chnak/weixin-bot": "^1.2.7",
|
|
57
|
-
"@chnak/zod-to-markdown": "
|
|
57
|
+
"@chnak/zod-to-markdown": "1.0.3",
|
|
58
58
|
"@hono/node-server": "^1.19.11",
|
|
59
59
|
"@larksuiteoapi/node-sdk": "^1.59.0",
|
|
60
60
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordinator Plugin
|
|
3
|
+
* 提供Coordinator模式的工具集:
|
|
4
|
+
* - spawn_worker: 创建Worker
|
|
5
|
+
* - send_message_to_worker: 继续Worker
|
|
6
|
+
* - stop_worker: 停止Worker
|
|
7
|
+
* - list_workers: 列出Worker
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { Plugin } = require('../src/core/plugin-base');
|
|
11
|
+
const { z } = require('zod');
|
|
12
|
+
const { logger } = require('../src/utils/logger');
|
|
13
|
+
|
|
14
|
+
const log = logger.child('CoordinatorPlugin');
|
|
15
|
+
|
|
16
|
+
class CoordinatorPlugin extends Plugin {
|
|
17
|
+
constructor(config = {}) {
|
|
18
|
+
super();
|
|
19
|
+
this.name = 'coordinator';
|
|
20
|
+
this.version = '1.0.0';
|
|
21
|
+
this.description = 'Coordinator模式插件,支持多Worker协作';
|
|
22
|
+
this.priority = 50;
|
|
23
|
+
|
|
24
|
+
this._framework = null;
|
|
25
|
+
this._coordinatorAgent = null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
install(framework) {
|
|
29
|
+
this._framework = framework;
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
start(framework) {
|
|
34
|
+
this._framework = framework;
|
|
35
|
+
|
|
36
|
+
// 初始化CoordinatorManager(如果尚未初始化)
|
|
37
|
+
if (!framework._coordinatorManager) {
|
|
38
|
+
// framework.initCoordinatorManager 会创建并设置
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 获取主Agent作为默认的Coordinator
|
|
42
|
+
const mainAgent = framework._mainAgent;
|
|
43
|
+
if (mainAgent) {
|
|
44
|
+
// 初始化CoordinatorManager并传入coordinatorAgent
|
|
45
|
+
framework.initCoordinatorManager(mainAgent);
|
|
46
|
+
|
|
47
|
+
// 注册Coordinator工具到主Agent
|
|
48
|
+
this.registerTools(mainAgent);
|
|
49
|
+
|
|
50
|
+
// 注册系统提示词部分,让Agent知道如何使用Coordinator模式
|
|
51
|
+
this._registerCoordinatorPrompt(mainAgent);
|
|
52
|
+
|
|
53
|
+
// 监听Worker事件用于生成通知
|
|
54
|
+
this._setupWorkerEventListeners(framework);
|
|
55
|
+
|
|
56
|
+
log.debug(' Coordinator plugin initialized with main agent');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 注册Coordinator模式提示词到Agent
|
|
64
|
+
* @private
|
|
65
|
+
*/
|
|
66
|
+
_registerCoordinatorPrompt(agent) {
|
|
67
|
+
if (!agent || typeof agent.registerPromptPart !== 'function') {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
agent.registerPromptPart('coordinator-mode', 650, () => `
|
|
72
|
+
【并行任务处理 - Coordinator 模式】
|
|
73
|
+
当遇到可并行处理的任务时(如多主题搜索、多文件处理、多计算任务),使用以下工具:
|
|
74
|
+
|
|
75
|
+
- spawn_worker: 创建独立Worker并行执行任务
|
|
76
|
+
- send_message_to_worker: 向Worker发送消息继续执行
|
|
77
|
+
- stop_worker: 停止Worker
|
|
78
|
+
- list_workers: 查看所有Worker状态
|
|
79
|
+
- get_worker: 查看单个Worker详情
|
|
80
|
+
|
|
81
|
+
【使用场景】
|
|
82
|
+
- "帮我搜索X、Y、Z" → 使用 spawn_worker 并行执行
|
|
83
|
+
- "帮我同时处理这几个文件" → 使用 spawn_worker 并行执行
|
|
84
|
+
- 需要主动查询Worker结果时 → 使用 get_worker / list_workers
|
|
85
|
+
|
|
86
|
+
【重要】
|
|
87
|
+
- spawn_worker 创建后立即返回,Worker在后台执行
|
|
88
|
+
- 可同时创建多个Worker并行处理不同任务
|
|
89
|
+
- Worker完成后生成 <task-notification> JSON 通知
|
|
90
|
+
`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 设置Worker事件监听器
|
|
95
|
+
* @private
|
|
96
|
+
*/
|
|
97
|
+
_setupWorkerEventListeners(framework) {
|
|
98
|
+
const coordinatorManager = framework.getCoordinatorManager();
|
|
99
|
+
if (!coordinatorManager) return;
|
|
100
|
+
|
|
101
|
+
// 监听Worker完成事件
|
|
102
|
+
coordinatorManager.on('worker:completed', (data) => {
|
|
103
|
+
// 通知会被发送到Coordinator Agent的事件队列
|
|
104
|
+
framework.emit('coordinator:worker-completed', data);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// 监听Worker错误事件
|
|
108
|
+
coordinatorManager.on('worker:error', (data) => {
|
|
109
|
+
framework.emit('coordinator:worker-error', data);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// 监听Worker停止事件
|
|
113
|
+
coordinatorManager.on('worker:stopped', (data) => {
|
|
114
|
+
framework.emit('coordinator:worker-stopped', data);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 设置Coordinator Agent
|
|
120
|
+
* @param {Agent} agent - Coordinator Agent实例
|
|
121
|
+
*/
|
|
122
|
+
setCoordinatorAgent(agent) {
|
|
123
|
+
this._coordinatorAgent = agent;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 注册Coordinator工具到指定Agent
|
|
128
|
+
* @param {Agent} agent - Agent实例
|
|
129
|
+
*/
|
|
130
|
+
registerTools(agent) {
|
|
131
|
+
// spawn_worker - 创建Worker
|
|
132
|
+
agent.registerTool({
|
|
133
|
+
name: 'spawn_worker',
|
|
134
|
+
description: '创建一个独立的Worker Agent来执行任务。Worker会在后台异步执行,完成后通过事件通知。',
|
|
135
|
+
inputSchema: z.object({
|
|
136
|
+
worker_name: z.string().describe('Worker的唯一名称'),
|
|
137
|
+
task: z.string().describe('给Worker的初始任务描述'),
|
|
138
|
+
system_prompt: z.string().optional().describe('可选的系统提示词'),
|
|
139
|
+
tools: z.array(z.string()).optional().describe('Worker可用的工具名称列表'),
|
|
140
|
+
}),
|
|
141
|
+
execute: async (args, fw) => {
|
|
142
|
+
const coordinatorManager = fw.getCoordinatorManager();
|
|
143
|
+
if (!coordinatorManager) {
|
|
144
|
+
return { success: false, error: 'CoordinatorManager not initialized' };
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const result = await coordinatorManager.createWorker({
|
|
149
|
+
name: args.worker_name,
|
|
150
|
+
task: args.task,
|
|
151
|
+
systemPrompt: args.system_prompt,
|
|
152
|
+
tools: args.tools,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
return {
|
|
156
|
+
success: true,
|
|
157
|
+
workerId: result.workerId,
|
|
158
|
+
status: result.status,
|
|
159
|
+
message: `Worker '${args.worker_name}' created and running`,
|
|
160
|
+
};
|
|
161
|
+
} catch (err) {
|
|
162
|
+
return { success: false, error: err.message };
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// send_message_to_worker - 继续Worker
|
|
168
|
+
agent.registerTool({
|
|
169
|
+
name: 'send_message_to_worker',
|
|
170
|
+
description: '向指定的Worker发送消息,继续其执行',
|
|
171
|
+
inputSchema: z.object({
|
|
172
|
+
worker_name: z.string().describe('Worker名称'),
|
|
173
|
+
message: z.string().describe('要发送给Worker的消息'),
|
|
174
|
+
}),
|
|
175
|
+
execute: async (args, fw) => {
|
|
176
|
+
const coordinatorManager = fw.getCoordinatorManager();
|
|
177
|
+
if (!coordinatorManager) {
|
|
178
|
+
return { success: false, error: 'CoordinatorManager not initialized' };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
const result = await coordinatorManager.sendToWorker(args.worker_name, args.message);
|
|
183
|
+
return {
|
|
184
|
+
success: true,
|
|
185
|
+
workerName: args.worker_name,
|
|
186
|
+
result: result.message || result,
|
|
187
|
+
};
|
|
188
|
+
} catch (err) {
|
|
189
|
+
return { success: false, error: err.message };
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// stop_worker - 停止Worker
|
|
195
|
+
agent.registerTool({
|
|
196
|
+
name: 'stop_worker',
|
|
197
|
+
description: '停止指定的Worker',
|
|
198
|
+
inputSchema: z.object({
|
|
199
|
+
worker_name: z.string().describe('Worker名称'),
|
|
200
|
+
reason: z.string().optional().describe('停止原因'),
|
|
201
|
+
}),
|
|
202
|
+
execute: async (args, fw) => {
|
|
203
|
+
const coordinatorManager = fw.getCoordinatorManager();
|
|
204
|
+
if (!coordinatorManager) {
|
|
205
|
+
return { success: false, error: 'CoordinatorManager not initialized' };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
const result = coordinatorManager.stopWorker(args.worker_name, args.reason);
|
|
210
|
+
return {
|
|
211
|
+
success: true,
|
|
212
|
+
...result,
|
|
213
|
+
};
|
|
214
|
+
} catch (err) {
|
|
215
|
+
return { success: false, error: err.message };
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// list_workers - 列出Worker
|
|
221
|
+
agent.registerTool({
|
|
222
|
+
name: 'list_workers',
|
|
223
|
+
description: '列出所有活跃的Worker',
|
|
224
|
+
inputSchema: z.object({}),
|
|
225
|
+
execute: async (args, fw) => {
|
|
226
|
+
const coordinatorManager = fw.getCoordinatorManager();
|
|
227
|
+
if (!coordinatorManager) {
|
|
228
|
+
return { success: false, error: 'CoordinatorManager not initialized' };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const workers = coordinatorManager.listWorkers();
|
|
232
|
+
return {
|
|
233
|
+
success: true,
|
|
234
|
+
count: workers.length,
|
|
235
|
+
workers,
|
|
236
|
+
};
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// get_worker - 获取Worker详情
|
|
241
|
+
agent.registerTool({
|
|
242
|
+
name: 'get_worker',
|
|
243
|
+
description: '获取指定Worker的详细信息',
|
|
244
|
+
inputSchema: z.object({
|
|
245
|
+
worker_name: z.string().describe('Worker名称'),
|
|
246
|
+
}),
|
|
247
|
+
execute: async (args, fw) => {
|
|
248
|
+
const coordinatorManager = fw.getCoordinatorManager();
|
|
249
|
+
if (!coordinatorManager) {
|
|
250
|
+
return { success: false, error: 'CoordinatorManager not initialized' };
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const worker = coordinatorManager.getWorker(args.worker_name);
|
|
254
|
+
if (!worker) {
|
|
255
|
+
return { success: false, error: `Worker '${args.worker_name}' not found` };
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
success: true,
|
|
260
|
+
worker,
|
|
261
|
+
};
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
log.debug(' Coordinator tools registered');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
reload(framework) {
|
|
269
|
+
this._framework = framework;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
uninstall(framework) {
|
|
273
|
+
const coordinatorManager = framework.getCoordinatorManager();
|
|
274
|
+
if (coordinatorManager) {
|
|
275
|
+
coordinatorManager.destroy();
|
|
276
|
+
}
|
|
277
|
+
this._framework = null;
|
|
278
|
+
this._coordinatorAgent = null;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
module.exports = { CoordinatorPlugin };
|
|
@@ -232,7 +232,7 @@ async function bootstrapDefaults(framework, config = {}) {
|
|
|
232
232
|
'mcp-executor', 'extension-executor', 'shell-executor', 'python-executor', 'session', 'web',
|
|
233
233
|
'audit', 'rules', 'scheduler', 'file-system', 'think', 'ambient',
|
|
234
234
|
'python-plugin-loader', 'telegram', 'weixin', 'subagent-manager',
|
|
235
|
-
'memory'
|
|
235
|
+
'memory', 'coordinator'
|
|
236
236
|
])
|
|
237
237
|
|
|
238
238
|
// 辅助函数:检查插件是否应该加载
|
|
@@ -133,15 +133,29 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
133
133
|
}),
|
|
134
134
|
execute: async (args) => {
|
|
135
135
|
const { plugin, tool, args: toolArgs = {} } = args;
|
|
136
|
-
log.info(` ext_call: plugin=${plugin}, tool=${tool}`);
|
|
136
|
+
log.info(` ext_call: plugin=${plugin}, tool=${tool}, args=${JSON.stringify(toolArgs)}`);
|
|
137
137
|
|
|
138
138
|
const ext = this._extensions.get(plugin);
|
|
139
139
|
if (!ext) {
|
|
140
|
+
// 触发错误事件
|
|
141
|
+
framework.emit('tool:error', {
|
|
142
|
+
name: `${plugin}:${tool}`,
|
|
143
|
+
args: toolArgs,
|
|
144
|
+
error: `扩展插件 '${plugin}' 不存在`,
|
|
145
|
+
source: 'extension'
|
|
146
|
+
});
|
|
140
147
|
return { success: false, error: `扩展插件 '${plugin}' 不存在` };
|
|
141
148
|
}
|
|
142
149
|
|
|
143
150
|
const toolDef = ext.tools.find((t) => t.name === tool);
|
|
144
151
|
if (!toolDef) {
|
|
152
|
+
// 触发错误事件
|
|
153
|
+
framework.emit('tool:error', {
|
|
154
|
+
name: `${plugin}:${tool}`,
|
|
155
|
+
args: toolArgs,
|
|
156
|
+
error: `扩展工具 '${tool}' 不存在`,
|
|
157
|
+
source: 'extension'
|
|
158
|
+
});
|
|
145
159
|
return { success: false, error: `扩展工具 '${tool}' 不存在` };
|
|
146
160
|
}
|
|
147
161
|
|
|
@@ -161,6 +175,18 @@ class ExtensionExecutorPlugin extends Plugin {
|
|
|
161
175
|
// 统一 execute 签名为 (args, framework)
|
|
162
176
|
const result = await toolDef.execute(toolArgs, framework);
|
|
163
177
|
|
|
178
|
+
// 检查结果是否为错误
|
|
179
|
+
if (result && result.success === false && result.error) {
|
|
180
|
+
// 触发扩展工具错误事件
|
|
181
|
+
framework.emit('tool:error', {
|
|
182
|
+
name: `${plugin}:${tool}`,
|
|
183
|
+
args: toolArgs,
|
|
184
|
+
error: result.error,
|
|
185
|
+
source: 'extension'
|
|
186
|
+
});
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
|
|
164
190
|
// 触发扩展工具完成事件
|
|
165
191
|
framework.emit('tool:result', {
|
|
166
192
|
name: `${plugin}:${tool}`,
|