foliko 1.0.0
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 +30 -0
- package/22.txt +10 -0
- package/README.md +218 -0
- package/SPEC.md +452 -0
- package/cli/bin/foliko.js +12 -0
- package/cli/src/commands/chat.js +75 -0
- package/cli/src/index.js +64 -0
- package/cli/src/ui/chat-ui.js +272 -0
- package/cli/src/utils/ansi.js +40 -0
- package/cli/src/utils/markdown.js +296 -0
- package/docs/quick-reference.md +131 -0
- package/docs/user-manual.md +1205 -0
- package/examples/basic.js +110 -0
- package/examples/bootstrap.js +93 -0
- package/examples/mcp-example.js +53 -0
- package/examples/skill-example.js +49 -0
- package/examples/workflow.js +158 -0
- package/package.json +36 -0
- package/plugins/ai-plugin.js +89 -0
- package/plugins/audit-plugin.js +187 -0
- package/plugins/default-plugins.js +412 -0
- package/plugins/file-system-plugin.js +344 -0
- package/plugins/install-plugin.js +93 -0
- package/plugins/python-executor-plugin.js +331 -0
- package/plugins/rules-plugin.js +292 -0
- package/plugins/scheduler-plugin.js +426 -0
- package/plugins/session-plugin.js +343 -0
- package/plugins/shell-executor-plugin.js +196 -0
- package/plugins/storage-plugin.js +237 -0
- package/plugins/subagent-plugin.js +395 -0
- package/plugins/think-plugin.js +329 -0
- package/plugins/tools-plugin.js +114 -0
- package/skills/mcp-usage/SKILL.md +198 -0
- package/skills/vb-agent-dev/AGENTS.md +162 -0
- package/skills/vb-agent-dev/SKILL.md +370 -0
- package/src/capabilities/index.js +11 -0
- package/src/capabilities/skill-manager.js +319 -0
- package/src/capabilities/workflow-engine.js +401 -0
- package/src/core/agent-chat.js +311 -0
- package/src/core/agent.js +573 -0
- package/src/core/framework.js +255 -0
- package/src/core/index.js +19 -0
- package/src/core/plugin-base.js +205 -0
- package/src/core/plugin-manager.js +392 -0
- package/src/core/provider.js +108 -0
- package/src/core/tool-registry.js +134 -0
- package/src/core/tool-router.js +216 -0
- package/src/executors/executor-base.js +58 -0
- package/src/executors/mcp-executor.js +728 -0
- package/src/index.js +37 -0
- package/src/utils/event-emitter.js +97 -0
- package/test-chat.js +129 -0
- package/test-mcp.js +79 -0
- package/test-reload.js +61 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage 存储插件
|
|
3
|
+
* 提供数据持久化存储,支持 JSON 文件存储
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Plugin } = require('../src/core/plugin-base')
|
|
7
|
+
const { z } = require('zod')
|
|
8
|
+
const fs = require('fs')
|
|
9
|
+
const path = require('path')
|
|
10
|
+
|
|
11
|
+
class StoragePlugin extends Plugin {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
super()
|
|
14
|
+
this.name = 'storage'
|
|
15
|
+
this.version = '1.0.0'
|
|
16
|
+
this.description = '数据持久化存储插件,支持键值对存储'
|
|
17
|
+
this.priority = 3
|
|
18
|
+
|
|
19
|
+
this.config = {
|
|
20
|
+
type: config.type || 'json', // json 或 memory
|
|
21
|
+
path: config.path || '.agent/data',
|
|
22
|
+
namespace: config.namespace || 'default'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
this._framework = null
|
|
26
|
+
this._store = new Map()
|
|
27
|
+
this._filePath = null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
install(framework) {
|
|
31
|
+
this._framework = framework
|
|
32
|
+
return this
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
start(framework) {
|
|
36
|
+
// 初始化存储
|
|
37
|
+
if (this.config.type === 'json') {
|
|
38
|
+
this._initJsonStore()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 注册存储工具
|
|
42
|
+
framework.registerTool({
|
|
43
|
+
name: 'storage_set',
|
|
44
|
+
description: '存储数据到键值存储',
|
|
45
|
+
inputSchema: z.object({
|
|
46
|
+
key: z.string().describe('存储键名'),
|
|
47
|
+
value: z.any().describe('存储值'),
|
|
48
|
+
namespace: z.string().optional().describe('命名空间,默认使用全局命名空间')
|
|
49
|
+
}),
|
|
50
|
+
execute: async (args) => {
|
|
51
|
+
try {
|
|
52
|
+
const ns = args.namespace || this.config.namespace
|
|
53
|
+
const fullKey = `${ns}:${args.key}`
|
|
54
|
+
this._store.set(fullKey, {
|
|
55
|
+
value: args.value,
|
|
56
|
+
updatedAt: new Date()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
if (this.config.type === 'json') {
|
|
60
|
+
await this._persistToFile()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { success: true, key: args.key, namespace: ns }
|
|
64
|
+
} catch (err) {
|
|
65
|
+
return { success: false, error: err.message }
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
framework.registerTool({
|
|
71
|
+
name: 'storage_get',
|
|
72
|
+
description: '从键值存储获取数据',
|
|
73
|
+
inputSchema: z.object({
|
|
74
|
+
key: z.string().describe('存储键名'),
|
|
75
|
+
namespace: z.string().optional().describe('命名空间')
|
|
76
|
+
}),
|
|
77
|
+
execute: async (args) => {
|
|
78
|
+
const ns = args.namespace || this.config.namespace
|
|
79
|
+
const fullKey = `${ns}:${args.key}`
|
|
80
|
+
const entry = this._store.get(fullKey)
|
|
81
|
+
|
|
82
|
+
if (!entry) {
|
|
83
|
+
return { success: false, error: 'Key not found', key: args.key }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
success: true,
|
|
88
|
+
key: args.key,
|
|
89
|
+
namespace: ns,
|
|
90
|
+
value: entry.value,
|
|
91
|
+
updatedAt: entry.updatedAt
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
framework.registerTool({
|
|
97
|
+
name: 'storage_delete',
|
|
98
|
+
description: '删除存储的数据',
|
|
99
|
+
inputSchema: z.object({
|
|
100
|
+
key: z.string().describe('存储键名'),
|
|
101
|
+
namespace: z.string().optional().describe('命名空间')
|
|
102
|
+
}),
|
|
103
|
+
execute: async (args) => {
|
|
104
|
+
const ns = args.namespace || this.config.namespace
|
|
105
|
+
const fullKey = `${ns}:${args.key}`
|
|
106
|
+
const existed = this._store.has(fullKey)
|
|
107
|
+
this._store.delete(fullKey)
|
|
108
|
+
|
|
109
|
+
if (this.config.type === 'json') {
|
|
110
|
+
await this._persistToFile()
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return { success: true, deleted: existed, key: args.key }
|
|
114
|
+
}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
framework.registerTool({
|
|
118
|
+
name: 'storage_list',
|
|
119
|
+
description: '列出命名空间下的所有键',
|
|
120
|
+
inputSchema: z.object({
|
|
121
|
+
namespace: z.string().optional().describe('命名空间,默认全局')
|
|
122
|
+
}),
|
|
123
|
+
execute: async (args) => {
|
|
124
|
+
const ns = args.namespace || this.config.namespace
|
|
125
|
+
const prefix = `${ns}:`
|
|
126
|
+
const keys = []
|
|
127
|
+
|
|
128
|
+
for (const key of this._store.keys()) {
|
|
129
|
+
if (key.startsWith(prefix)) {
|
|
130
|
+
keys.push(key.substring(prefix.length))
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
success: true,
|
|
136
|
+
namespace: ns,
|
|
137
|
+
keys,
|
|
138
|
+
count: keys.length
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
framework.registerTool({
|
|
144
|
+
name: 'storage_clear',
|
|
145
|
+
description: '清空命名空间下的所有数据',
|
|
146
|
+
inputSchema: z.object({
|
|
147
|
+
namespace: z.string().optional().describe('命名空间,默认全局')
|
|
148
|
+
}),
|
|
149
|
+
execute: async (args) => {
|
|
150
|
+
const ns = args.namespace || this.config.namespace
|
|
151
|
+
const prefix = `${ns}:`
|
|
152
|
+
let count = 0
|
|
153
|
+
|
|
154
|
+
for (const key of this._store.keys()) {
|
|
155
|
+
if (key.startsWith(prefix)) {
|
|
156
|
+
this._store.delete(key)
|
|
157
|
+
count++
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (this.config.type === 'json') {
|
|
162
|
+
await this._persistToFile()
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return { success: true, namespace: ns, cleared: count }
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
return this
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* 初始化 JSON 文件存储
|
|
174
|
+
*/
|
|
175
|
+
_initJsonStore() {
|
|
176
|
+
this._filePath = path.resolve(process.cwd(), this.config.path, `${this.config.namespace}.json`)
|
|
177
|
+
|
|
178
|
+
// 确保目录存在
|
|
179
|
+
const dir = path.dirname(this._filePath)
|
|
180
|
+
if (!fs.existsSync(dir)) {
|
|
181
|
+
fs.mkdirSync(dir, { recursive: true })
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 加载已有数据
|
|
185
|
+
if (fs.existsSync(this._filePath)) {
|
|
186
|
+
try {
|
|
187
|
+
const content = fs.readFileSync(this._filePath, 'utf-8')
|
|
188
|
+
const data = JSON.parse(content)
|
|
189
|
+
|
|
190
|
+
for (const [key, entry] of Object.entries(data)) {
|
|
191
|
+
this._store.set(key, entry)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.log(`[Storage] Loaded ${this._store.size} entries from ${this._filePath}`)
|
|
195
|
+
} catch (err) {
|
|
196
|
+
console.warn(`[Storage] Failed to load storage file: ${err.message}`)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 持久化到文件
|
|
203
|
+
*/
|
|
204
|
+
async _persistToFile() {
|
|
205
|
+
if (!this._filePath) return
|
|
206
|
+
|
|
207
|
+
try {
|
|
208
|
+
const data = Object.fromEntries(this._store)
|
|
209
|
+
fs.writeFileSync(this._filePath, JSON.stringify(data, null, 2), 'utf-8')
|
|
210
|
+
} catch (err) {
|
|
211
|
+
console.error(`[Storage] Failed to persist: ${err.message}`)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* 获取存储实例(供其他插件使用)
|
|
217
|
+
*/
|
|
218
|
+
getStore() {
|
|
219
|
+
return this._store
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
reload(framework) {
|
|
223
|
+
this._framework = framework
|
|
224
|
+
this._store.clear()
|
|
225
|
+
|
|
226
|
+
if (this.config.type === 'json') {
|
|
227
|
+
this._initJsonStore()
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
uninstall(framework) {
|
|
232
|
+
this._store.clear()
|
|
233
|
+
this._framework = null
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
module.exports = { StoragePlugin }
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SubAgent 子Agent插件
|
|
3
|
+
* 创建具有独立工具集的子Agent,用于分工处理不同领域的任务
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Plugin } = require('../src/core/plugin-base')
|
|
7
|
+
const { z } = require('zod')
|
|
8
|
+
const { Agent } = require('../src/core/agent')
|
|
9
|
+
|
|
10
|
+
class SubAgentPlugin extends Plugin {
|
|
11
|
+
constructor(config = {}) {
|
|
12
|
+
super()
|
|
13
|
+
this.name = config.name
|
|
14
|
+
this.version = '1.0.0'
|
|
15
|
+
this.description = config.description || `子Agent: ${config.name}`
|
|
16
|
+
this.priority = 10
|
|
17
|
+
|
|
18
|
+
// 子Agent配置
|
|
19
|
+
// tools: { toolName: toolFn } 自定义工具(只属于此子Agent)
|
|
20
|
+
// parentTools: ['read_file'] 从父Agent继承的工具名称列表
|
|
21
|
+
this.config = {
|
|
22
|
+
name: config.name, // 子Agent名称
|
|
23
|
+
role: config.role || config.name, // 角色描述
|
|
24
|
+
description: config.description || '', // 供主Agent智能选择
|
|
25
|
+
tools: config.tools || {}, // 自定义工具 { name: toolDef }
|
|
26
|
+
parentTools: config.parentTools || [], // 从父Agent继承的工具名称列表
|
|
27
|
+
llmConfig: config.llmConfig || null // 独立LLM配置
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this._framework = null
|
|
31
|
+
this._agent = null
|
|
32
|
+
this._parentAgent = null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
install(framework) {
|
|
36
|
+
this._framework = framework
|
|
37
|
+
return this
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
start(framework) {
|
|
41
|
+
// 创建子Agent
|
|
42
|
+
this._createSubAgent()
|
|
43
|
+
|
|
44
|
+
// 注册委托工具到主Agent(通过framework获取父agent)
|
|
45
|
+
this._registerDelegateTool()
|
|
46
|
+
|
|
47
|
+
return this
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 创建子Agent
|
|
52
|
+
*/
|
|
53
|
+
_createSubAgent() {
|
|
54
|
+
// 获取父Agent(主Agent)
|
|
55
|
+
const parentAgent = this._getParentAgent()
|
|
56
|
+
if (!parentAgent) {
|
|
57
|
+
console.warn(`[SubAgent:${this.config.name}] Parent agent not found`)
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// 获取从父Agent继承的工具
|
|
62
|
+
const parentTools = this._getParentTools(parentAgent)
|
|
63
|
+
|
|
64
|
+
// 确定LLM配置
|
|
65
|
+
const aiPlugin = this._framework.pluginManager.get('ai')
|
|
66
|
+
const llmConfig = this.config.llmConfig || (aiPlugin ? aiPlugin.getConfig() : {})
|
|
67
|
+
|
|
68
|
+
// 创建子Agent
|
|
69
|
+
this._agent = new Agent(this._framework, {
|
|
70
|
+
name: this.config.name,
|
|
71
|
+
systemPrompt: this._buildSystemPrompt(),
|
|
72
|
+
model: llmConfig.model,
|
|
73
|
+
provider: llmConfig.provider,
|
|
74
|
+
apiKey: llmConfig.apiKey,
|
|
75
|
+
baseURL: llmConfig.baseURL
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// 注册从父Agent继承的工具
|
|
79
|
+
for (const tool of parentTools) {
|
|
80
|
+
this._agent.registerTool(tool)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 注册自定义工具(只属于此子Agent,不污染全局)
|
|
84
|
+
// tools 格式: { toolName: toolDef }
|
|
85
|
+
if (this.config.tools && typeof this.config.tools === 'object') {
|
|
86
|
+
for (const [toolName, toolDef] of Object.entries(this.config.tools)) {
|
|
87
|
+
const tool = typeof toolDef === 'function' ? toolDef() : toolDef
|
|
88
|
+
if (typeof tool === 'object' && tool.name) {
|
|
89
|
+
this._agent.registerTool(tool)
|
|
90
|
+
} else {
|
|
91
|
+
// 假设是简化的工具定义,需要补充 name
|
|
92
|
+
this._agent.registerTool({ name: toolName, ...tool })
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 保存父Agent引用
|
|
98
|
+
this._parentAgent = parentAgent
|
|
99
|
+
|
|
100
|
+
// 注册子Agent到父Agent
|
|
101
|
+
parentAgent.registerSubAgent(this.config.name, this._agent, this.config.role, this.config.description)
|
|
102
|
+
|
|
103
|
+
// 监听子Agent的chunk事件并转发给父Agent
|
|
104
|
+
this._agent.on('chunk', (chunk) => {
|
|
105
|
+
chunk.fromSubAgent = this.config.name
|
|
106
|
+
parentAgent.emit('chunk', chunk)
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
const parentToolNames = parentTools.map(t => t.name)
|
|
110
|
+
const customToolNames = Object.keys(this.config.tools || {})
|
|
111
|
+
console.log(`[SubAgent:${this.config.name}] Created with ${parentToolNames.length} parent tools + ${customToolNames.length} custom tools`)
|
|
112
|
+
if (parentToolNames.length > 0) {
|
|
113
|
+
console.log(` Parent tools: ${parentToolNames.join(', ')}`)
|
|
114
|
+
}
|
|
115
|
+
if (customToolNames.length > 0) {
|
|
116
|
+
console.log(` Custom tools: ${customToolNames.join(', ')}`)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 获取父Agent
|
|
122
|
+
*/
|
|
123
|
+
_getParentAgent() {
|
|
124
|
+
// 优先使用外部传入的获取器
|
|
125
|
+
if (this.config._parentAgentGetter) {
|
|
126
|
+
return this.config._parentAgentGetter()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 尝试从framework获取主agent
|
|
130
|
+
// 在vb-agent中,主agent通常是通过framework.createAgent创建的
|
|
131
|
+
if (this._framework._mainAgent) {
|
|
132
|
+
return this._framework._mainAgent
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// 查找最后一个创建的agent作为父agent
|
|
136
|
+
const agents = this._framework._agents || []
|
|
137
|
+
if (agents.length > 0) {
|
|
138
|
+
return agents[agents.length - 1]
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return null
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* 获取从父Agent继承的工具
|
|
146
|
+
*/
|
|
147
|
+
_getParentTools(parentAgent) {
|
|
148
|
+
const allTools = parentAgent.getTools ? parentAgent.getTools() : []
|
|
149
|
+
const toolMap = new Map(allTools.map(t => [t.name, t]))
|
|
150
|
+
|
|
151
|
+
// 如果没有指定 parentTools,返回全部
|
|
152
|
+
if (!this.config.parentTools || this.config.parentTools.length === 0) {
|
|
153
|
+
return allTools
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// 过滤指定工具
|
|
157
|
+
const filtered = []
|
|
158
|
+
for (const toolName of this.config.parentTools) {
|
|
159
|
+
const tool = toolMap.get(toolName)
|
|
160
|
+
if (tool) {
|
|
161
|
+
filtered.push(tool)
|
|
162
|
+
} else {
|
|
163
|
+
console.warn(`[SubAgent:${this.config.name}] Parent tool not found: ${toolName}`)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return filtered
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 构建系统提示
|
|
172
|
+
*/
|
|
173
|
+
_buildSystemPrompt() {
|
|
174
|
+
return `你是 ${this.config.role}。
|
|
175
|
+
|
|
176
|
+
角色描述:${this.config.description || '一个专业的子Agent'}
|
|
177
|
+
|
|
178
|
+
当你被调用时,你应该:
|
|
179
|
+
1. 仔细理解任务要求
|
|
180
|
+
2. 使用你的工具集完成任务
|
|
181
|
+
3. 返回完整的操作结果
|
|
182
|
+
|
|
183
|
+
重要:返回结果要简洁明确,只包含最终结果,不需要解释过程。`
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 注册委托工具到父Agent
|
|
188
|
+
*/
|
|
189
|
+
_registerDelegateTool() {
|
|
190
|
+
const parentAgent = this._getParentAgent()
|
|
191
|
+
if (!parentAgent) return
|
|
192
|
+
|
|
193
|
+
const agentName = this.config.name
|
|
194
|
+
const role = this.config.role
|
|
195
|
+
|
|
196
|
+
// 注册工具到父Agent
|
|
197
|
+
parentAgent.registerTool({
|
|
198
|
+
name: agentName,
|
|
199
|
+
description: `${role}:当需要${role}时,调用此工具执行任务。如:编译代码、运行测试、代码重构等。`,
|
|
200
|
+
inputSchema: z.object({
|
|
201
|
+
task: z.string().describe('给子Agent的具体任务描述')
|
|
202
|
+
}),
|
|
203
|
+
execute: async (args, framework) => {
|
|
204
|
+
if (!this._agent) {
|
|
205
|
+
return { error: `SubAgent ${agentName} not initialized` }
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 发射子Agent开始处理事件
|
|
209
|
+
parentAgent.emit('subagent:chat:start', {
|
|
210
|
+
parentAgent,
|
|
211
|
+
subAgent: this._agent,
|
|
212
|
+
subAgentName: agentName,
|
|
213
|
+
task: args.task
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
const result = await this._agent.chat(args.task)
|
|
218
|
+
// 发射子Agent完成处理事件
|
|
219
|
+
parentAgent.emit('subagent:chat:end', {
|
|
220
|
+
parentAgent,
|
|
221
|
+
subAgent: this._agent,
|
|
222
|
+
subAgentName: agentName,
|
|
223
|
+
result
|
|
224
|
+
})
|
|
225
|
+
return {
|
|
226
|
+
agent: agentName,
|
|
227
|
+
result: result.message || result.error || result,
|
|
228
|
+
success: result.success !== false
|
|
229
|
+
}
|
|
230
|
+
} catch (err) {
|
|
231
|
+
// 发射子Agent错误事件
|
|
232
|
+
parentAgent.emit('subagent:error', {
|
|
233
|
+
parentAgent,
|
|
234
|
+
subAgent: this._agent,
|
|
235
|
+
subAgentName: agentName,
|
|
236
|
+
error: err.message
|
|
237
|
+
})
|
|
238
|
+
return {
|
|
239
|
+
agent: agentName,
|
|
240
|
+
error: err.message,
|
|
241
|
+
success: false
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
console.log(`[SubAgent:${this.config.name}] Delegate tool registered on parent agent`)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* 获取子Agent实例
|
|
252
|
+
*/
|
|
253
|
+
getAgent() {
|
|
254
|
+
return this._agent
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* 调用子Agent处理任务
|
|
259
|
+
*/
|
|
260
|
+
async chat(task) {
|
|
261
|
+
if (!this._agent) {
|
|
262
|
+
throw new Error(`SubAgent ${this.config.name} not initialized`)
|
|
263
|
+
}
|
|
264
|
+
return this._agent.chat(task)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
reload(framework) {
|
|
268
|
+
this._framework = framework
|
|
269
|
+
this._createSubAgent()
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
uninstall(framework) {
|
|
273
|
+
if (this._parentAgent) {
|
|
274
|
+
this._parentAgent.unregisterSubAgent(this.config.name)
|
|
275
|
+
}
|
|
276
|
+
if (this._agent) {
|
|
277
|
+
this._agent.destroy()
|
|
278
|
+
this._agent = null
|
|
279
|
+
}
|
|
280
|
+
this._parentAgent = null
|
|
281
|
+
this._framework = null
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* SubAgentManager - 管理多个子Agent
|
|
287
|
+
*/
|
|
288
|
+
class SubAgentManagerPlugin extends Plugin {
|
|
289
|
+
constructor(config = {}) {
|
|
290
|
+
super()
|
|
291
|
+
this.name = 'subagent-manager'
|
|
292
|
+
this.version = '1.0.0'
|
|
293
|
+
this.description = '子Agent管理器,统一管理多个子Agent'
|
|
294
|
+
this.priority = 10
|
|
295
|
+
|
|
296
|
+
this.config = {
|
|
297
|
+
agents: config.agents || [] // 子Agent配置列表
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
this._framework = null
|
|
301
|
+
this._subAgents = new Map()
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
install(framework) {
|
|
305
|
+
this._framework = framework
|
|
306
|
+
return this
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
start(framework) {
|
|
310
|
+
// 创建所有配置的子Agent
|
|
311
|
+
for (const agentConfig of this.config.agents) {
|
|
312
|
+
const plugin = new SubAgentPlugin(agentConfig)
|
|
313
|
+
plugin.install(framework)
|
|
314
|
+
plugin.start(framework)
|
|
315
|
+
this._subAgents.set(agentConfig.name, plugin)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// 注册管理工具
|
|
319
|
+
framework.registerTool({
|
|
320
|
+
name: 'subagent_list',
|
|
321
|
+
description: '列出所有子Agent',
|
|
322
|
+
inputSchema: z.object({}),
|
|
323
|
+
execute: async () => {
|
|
324
|
+
const agents = Array.from(this._subAgents.values()).map(p => ({
|
|
325
|
+
name: p.config.name,
|
|
326
|
+
role: p.config.role,
|
|
327
|
+
description: p.config.description,
|
|
328
|
+
toolCount: p._agent ? p._agent.getTools().length : 0
|
|
329
|
+
}))
|
|
330
|
+
return { success: true, agents }
|
|
331
|
+
}
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
framework.registerTool({
|
|
335
|
+
name: 'subagent_call',
|
|
336
|
+
description: '调用指定的子Agent处理任务',
|
|
337
|
+
inputSchema: z.object({
|
|
338
|
+
agentName: z.string().describe('子Agent名称'),
|
|
339
|
+
task: z.string().describe('任务描述')
|
|
340
|
+
}),
|
|
341
|
+
execute: async (args) => {
|
|
342
|
+
const plugin = this._subAgents.get(args.agentName)
|
|
343
|
+
if (!plugin) {
|
|
344
|
+
return { success: false, error: `SubAgent ${args.agentName} not found` }
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
try {
|
|
348
|
+
const result = await plugin.chat(args.task)
|
|
349
|
+
return {
|
|
350
|
+
success: true,
|
|
351
|
+
agent: args.agentName,
|
|
352
|
+
result: result.message || result,
|
|
353
|
+
success: result.success !== false
|
|
354
|
+
}
|
|
355
|
+
} catch (err) {
|
|
356
|
+
return { success: false, error: err.message }
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
return this
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* 获取子Agent
|
|
366
|
+
*/
|
|
367
|
+
getSubAgent(name) {
|
|
368
|
+
const plugin = this._subAgents.get(name)
|
|
369
|
+
return plugin ? plugin.getAgent() : null
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
reload(framework) {
|
|
373
|
+
// 销毁旧的子Agent
|
|
374
|
+
for (const plugin of this._subAgents.values()) {
|
|
375
|
+
plugin.uninstall(framework)
|
|
376
|
+
}
|
|
377
|
+
this._subAgents.clear()
|
|
378
|
+
|
|
379
|
+
// 重新创建
|
|
380
|
+
this.start(framework)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
uninstall(framework) {
|
|
384
|
+
for (const plugin of this._subAgents.values()) {
|
|
385
|
+
plugin.uninstall(framework)
|
|
386
|
+
}
|
|
387
|
+
this._subAgents.clear()
|
|
388
|
+
this._framework = null
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
module.exports = {
|
|
393
|
+
SubAgentPlugin,
|
|
394
|
+
SubAgentManagerPlugin
|
|
395
|
+
}
|