test-registry.js
4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#!/usr/bin/env node
/**
* 测试 AgentRegistry + AgentBus — 完整的多 Agent 协作流程
*
* 模拟场景:
* 1. 创建 Master + CEO + 编剧部 三个 Agent
* 2. CEO 给编剧部分派任务 (消息通讯)
* 3. 编剧部汇报结果 (消息回流)
* 4. 查看组织架构树
* 5. 修改编剧部的 agent.md (热更新)
* 6. 销毁编剧部 (递归删除)
*
* 用法: node packages/agent-core/test-registry.js
*/
import { AgentBus } from './AgentBus.js';
import { AgentRegistry } from './AgentRegistry.js';
import { rm } from 'node:fs/promises';
const TEST_DIR = './data/agents-test';
async function main() {
console.log('═══════════════════════════════════════');
console.log(' LemonBoss Registry + Bus 集成测试');
console.log('═══════════════════════════════════════\n');
// 初始化 (不用 SQLite, 纯内存)
const bus = new AgentBus();
const registry = new AgentRegistry({ agentsDir: TEST_DIR, bus });
// 监控消息流
const messageLog = [];
bus.on('message', (msg) => {
messageLog.push(msg);
console.log(` 📨 [${msg.method}] ${msg.from} → ${msg.to}`);
});
// ── Step 1: 创建三个 Agent ──
console.log('1️⃣ 创建组织架构\n');
const master = await registry.create({
id: 'master-001',
type: 'master',
name: 'Lemon Master',
});
console.log(` ✅ Master : ${master.id}`);
const ceo = await registry.create({
id: 'cxo-ceo-001',
type: 'cxo',
name: 'Lemon CEO',
parentId: 'master-001',
});
console.log(` ✅ CEO : ${ceo.id}`);
const dramatist = await registry.create({
id: 'role-dramatist-001',
type: 'role',
name: '编剧部',
parentId: 'cxo-ceo-001',
});
console.log(` ✅ 编剧部 : ${dramatist.id}\n`);
// ── Step 2: 查看所有 Agent ──
console.log('2️⃣ 查看所有 Agent\n');
const allAgents = registry.list();
for (const a of allAgents) {
console.log(` ${a.type.padEnd(7)} | ${a.id.padEnd(25)} | ${a.status}`);
}
console.log();
// ── Step 3: 查看组织架构树 ──
console.log('3️⃣ 组织架构树\n');
const tree = registry.getOrgTree();
printTree(tree, ' ');
console.log();
// ── Step 4: CEO 给编剧部分派任务 ──
console.log('4️⃣ CEO → 编剧部: 分派任务\n');
const task = bus.assignTask('cxo-ceo-001', 'role-dramatist-001', {
description: '创作一个都市爱情互动短剧剧本',
deadline: '2026-03-25',
priority: 'high',
});
console.log(` 任务ID: ${task.id}\n`);
// ── Step 5: 编剧部汇报结果 ──
console.log('5️⃣ 编剧部 → CEO: 汇报结果\n');
bus.reportResult('role-dramatist-001', 'cxo-ceo-001', {
status: 'done',
deliverable: '剧本已完成, 共 5 集, 含 3 个互动分支',
}, task.id);
console.log();
// ── Step 6: 修改编剧部的 agent.md ──
console.log('6️⃣ 热更新编剧部的 agent.md\n');
await registry.updateBootstrap('role-dramatist-001', 'agent.md', `# 编剧部
## 身份
你是 Lemon Drama 的编剧部主管, 负责所有短剧的剧本创作。
## 职责
- 根据选题方向创作互动短剧剧本
- 每个剧本至少包含 3 个互动分支点
- 管理下属 Skill Agent (对白生成、场景设计)
## Never Rules
- 不要抄袭已有作品
- 不要在剧本中包含敏感内容
## 可用工具
- skill.create: 创建 Skill Agent
- skill.redefine: 调整 Skill 定义
- skill.destroy: 销毁 Skill Agent
`);
console.log(' ✅ agent.md 已更新并热加载\n');
// ── Step 7: 消息统计 ──
console.log('7️⃣ 消息统计\n');
console.log(` 总消息数: ${messageLog.length}`);
console.log(` 消息类型: ${[...new Set(messageLog.map(m => m.method))].join(', ')}\n`);
// ── Step 8: 销毁编剧部 ──
console.log('8️⃣ 销毁编剧部\n');
await registry.destroy('role-dramatist-001');
console.log(` ✅ 编剧部已销毁`);
console.log(` 剩余 Agent 数: ${registry.list().length}\n`);
// 清理
await registry.destroy('cxo-ceo-001');
await registry.destroy('master-001');
const { rm: rmDir } = await import('node:fs/promises');
await rmDir(TEST_DIR, { recursive: true, force: true });
console.log('🗑️ 测试数据已清理');
console.log('\n✅ 全部测试通过!');
}
function printTree(node, indent) {
if (!node) return;
const name = node.name || node.id || 'root';
const type = node.type || '';
console.log(`${indent}${type ? `[${type}]` : ''} ${name}`);
if (node.children) {
for (const child of node.children) {
printTree(child, indent + ' ');
}
}
}
main().catch(console.error);