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,573 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent 类
|
|
3
|
+
* 负责对话和推理
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { EventEmitter } = require('../utils/event-emitter')
|
|
7
|
+
const { AgentChatHandler } = require('./agent-chat')
|
|
8
|
+
const os = require('os')
|
|
9
|
+
|
|
10
|
+
class Agent extends EventEmitter {
|
|
11
|
+
/**
|
|
12
|
+
* @param {Framework} framework - 框架实例
|
|
13
|
+
* @param {Object} config - 配置
|
|
14
|
+
* @param {string} [config.name] - Agent 名称
|
|
15
|
+
* @param {string} [config.systemPrompt] - 系统提示
|
|
16
|
+
* @param {string} [config.sharedPrompt] - 共享提示模板,支持 {{VAR}} 占位符
|
|
17
|
+
* @param {Object} [config.metadata] - 元数据,注入到 sharedPrompt
|
|
18
|
+
* @param {boolean} [config.enableToolRouting=true] - 是否启用工具路由
|
|
19
|
+
*/
|
|
20
|
+
constructor(framework, config = {}) {
|
|
21
|
+
super()
|
|
22
|
+
|
|
23
|
+
this.framework = framework
|
|
24
|
+
this.config = config
|
|
25
|
+
|
|
26
|
+
this.name = config.name || 'Agent'
|
|
27
|
+
this.model = config.model || 'deepseek-chat'
|
|
28
|
+
this.apiKey = config.apiKey
|
|
29
|
+
this.baseURL = config.baseURL
|
|
30
|
+
this.provider = config.provider || 'deepseek'
|
|
31
|
+
this.providerOptions = config.providerOptions || {}
|
|
32
|
+
|
|
33
|
+
// 原始 system prompt
|
|
34
|
+
this._originalPrompt = config.systemPrompt || 'You are a helpful assistant.'
|
|
35
|
+
|
|
36
|
+
// 共享提示模板
|
|
37
|
+
this._sharedPrompt = config.sharedPrompt || ''
|
|
38
|
+
|
|
39
|
+
// 元数据
|
|
40
|
+
const metadata = config.metadata || {}
|
|
41
|
+
this._metadata = new Map(Object.entries(metadata))
|
|
42
|
+
|
|
43
|
+
this._chatHandler = null
|
|
44
|
+
this._tools = new Map()
|
|
45
|
+
this._status = 'idle'
|
|
46
|
+
|
|
47
|
+
// 子Agent管理
|
|
48
|
+
this._subAgents = new Map()
|
|
49
|
+
|
|
50
|
+
// 处理后的 system prompt (带上下文)
|
|
51
|
+
this.systemPrompt = this._buildSystemPrompt()
|
|
52
|
+
|
|
53
|
+
// 初始化聊天处理器
|
|
54
|
+
this._initChatHandler()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 获取元数据值
|
|
59
|
+
*/
|
|
60
|
+
_getMetadataValue(key) {
|
|
61
|
+
// 优先从 metadata 获取
|
|
62
|
+
if (this._metadata.has(key)) {
|
|
63
|
+
return this._metadata.get(key)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 内置变量
|
|
67
|
+
switch (key) {
|
|
68
|
+
case 'WORK_DIR':
|
|
69
|
+
case 'CWD':
|
|
70
|
+
return process.cwd()
|
|
71
|
+
case 'HOME_DIR':
|
|
72
|
+
return os.homedir()
|
|
73
|
+
case 'HOST_NAME':
|
|
74
|
+
return os.hostname()
|
|
75
|
+
case 'PLATFORM':
|
|
76
|
+
return process.platform
|
|
77
|
+
case 'TIME':
|
|
78
|
+
return new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })
|
|
79
|
+
case 'DATE':
|
|
80
|
+
return new Date().toISOString().split('T')[0]
|
|
81
|
+
default:
|
|
82
|
+
return `{{${key}}}`
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 替换 sharedPrompt 中的占位符
|
|
88
|
+
*/
|
|
89
|
+
_replacePlaceholders(template) {
|
|
90
|
+
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
|
|
91
|
+
return this._getMetadataValue(key)
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 构建工具描述
|
|
97
|
+
*/
|
|
98
|
+
_buildToolsDescription() {
|
|
99
|
+
if (this._tools.size === 0) {
|
|
100
|
+
return ''
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let desc = '【可用工具】\n'
|
|
104
|
+
for (const [name, tool] of this._tools) {
|
|
105
|
+
desc += `- ${name}: ${tool.description || '无描述'}\n`
|
|
106
|
+
}
|
|
107
|
+
return desc.trim()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 构建技能描述
|
|
112
|
+
*/
|
|
113
|
+
_buildSkillsDescription() {
|
|
114
|
+
const skillManager = this.framework.pluginManager.get('skill-manager')
|
|
115
|
+
if (!skillManager) {
|
|
116
|
+
return ''
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const skills = skillManager.getAllSkills()
|
|
120
|
+
if (!skills || skills.length === 0) {
|
|
121
|
+
return ''
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let desc = '【可用技能】\n'
|
|
125
|
+
for (const skill of skills) {
|
|
126
|
+
const name = skill.metadata?.name || skill.name || 'unknown'
|
|
127
|
+
const descText = skill.metadata?.description || ''
|
|
128
|
+
desc += `- ${name}: ${descText}\n`
|
|
129
|
+
}
|
|
130
|
+
desc += '\n重要:当需要开发插件、执行专业任务时,必须先使用 loadSkill 工具加载对应技能,获取专业指导。'
|
|
131
|
+
return desc.trim()
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 构建系统能力描述
|
|
136
|
+
*/
|
|
137
|
+
_buildCapabilitiesDescription() {
|
|
138
|
+
const plugins = this.framework.pluginManager.getAll()
|
|
139
|
+
if (!plugins || plugins.length === 0) {
|
|
140
|
+
return ''
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// 过滤出有描述的关键插件(排除内部插件)
|
|
144
|
+
const keyPlugins = plugins.filter(p => {
|
|
145
|
+
const name = p.name
|
|
146
|
+
// 排除默认配置插件和内部插件
|
|
147
|
+
return name !== 'defaults' && name !== 'agent'
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
if (keyPlugins.length === 0) {
|
|
151
|
+
return ''
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let desc = '【系统能力】\n'
|
|
155
|
+
for (const plugin of keyPlugins) {
|
|
156
|
+
const name = plugin.instance?.name || plugin.name || 'unknown'
|
|
157
|
+
const description = plugin.instance?.description || '无描述'
|
|
158
|
+
desc += `- ${name}: ${description}\n`
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return desc.trim()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 构建子Agent描述
|
|
166
|
+
*/
|
|
167
|
+
_buildSubAgentsDescription() {
|
|
168
|
+
if (this._subAgents.size === 0) {
|
|
169
|
+
return ''
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let desc = '【子 Agent 分配规则 - 必须遵守】\n'
|
|
173
|
+
desc += '1. 每个子Agent有固定的专业领域,必须委托给对应的专家:\n'
|
|
174
|
+
for (const [name, { role, goal }] of this._subAgents) {
|
|
175
|
+
desc += ` - ${name}: ${role || goal || '子代理'}\n`
|
|
176
|
+
}
|
|
177
|
+
desc += '2. 你需要对任务进行拆分,传递给对应的子Agent执行。\n'
|
|
178
|
+
desc += '3. 多个不同类型的任务必须分别委托给不同的子Agent,每个子Agent只处理自己专业领域的任务。\n'
|
|
179
|
+
desc += '\n【可委托的子 Agent】\n'
|
|
180
|
+
for (const [name, { role, goal }] of this._subAgents) {
|
|
181
|
+
desc += ` - ${name}: ${role || goal || '子代理'}\n`
|
|
182
|
+
}
|
|
183
|
+
desc += '\n使用相应子Agent名称的工具将任务委托给相应子代理。'
|
|
184
|
+
|
|
185
|
+
return desc.trim()
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* 构建系统提示(带上下文)
|
|
190
|
+
*/
|
|
191
|
+
_buildSystemPrompt() {
|
|
192
|
+
const parts = []
|
|
193
|
+
|
|
194
|
+
// 1. 原始 system prompt
|
|
195
|
+
parts.push(this._originalPrompt)
|
|
196
|
+
|
|
197
|
+
// 2. 共享提示模板(带占位符替换)
|
|
198
|
+
if (this._sharedPrompt) {
|
|
199
|
+
const replaced = this._replacePlaceholders(this._sharedPrompt)
|
|
200
|
+
parts.push(replaced)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// 3. 元数据
|
|
204
|
+
if (this._metadata.size > 0) {
|
|
205
|
+
const metaParts = ['【元数据】']
|
|
206
|
+
for (const [key, value] of this._metadata) {
|
|
207
|
+
if (typeof value === 'object') {
|
|
208
|
+
metaParts.push(`- ${key}: ${JSON.stringify(value)}`)
|
|
209
|
+
} else {
|
|
210
|
+
metaParts.push(`- ${key}: ${value}`)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
parts.push(metaParts.join('\n'))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// 4. 工具列表
|
|
217
|
+
const toolsDesc = this._buildToolsDescription()
|
|
218
|
+
if (toolsDesc) {
|
|
219
|
+
parts.push(toolsDesc)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// 5. 技能列表
|
|
223
|
+
const skillsDesc = this._buildSkillsDescription()
|
|
224
|
+
if (skillsDesc) {
|
|
225
|
+
parts.push(skillsDesc)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 6. 子Agent列表
|
|
229
|
+
const subAgentsDesc = this._buildSubAgentsDescription()
|
|
230
|
+
if (subAgentsDesc) {
|
|
231
|
+
parts.push(subAgentsDesc)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 7. 系统能力
|
|
235
|
+
const capabilitiesDesc = this._buildCapabilitiesDescription()
|
|
236
|
+
if (capabilitiesDesc) {
|
|
237
|
+
parts.push(capabilitiesDesc)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return parts.join('\n\n')
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* 刷新上下文
|
|
245
|
+
*/
|
|
246
|
+
_refreshContext() {
|
|
247
|
+
this.systemPrompt = this._buildSystemPrompt()
|
|
248
|
+
if (this._chatHandler) {
|
|
249
|
+
this._chatHandler.setSystemPrompt(this.systemPrompt)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* 初始化聊天处理器
|
|
255
|
+
* @private
|
|
256
|
+
*/
|
|
257
|
+
_initChatHandler() {
|
|
258
|
+
let aiClient = null
|
|
259
|
+
const aiPlugin = this.framework.pluginManager.get('ai')
|
|
260
|
+
if (aiPlugin) {
|
|
261
|
+
aiClient = aiPlugin.getAIClient()
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
this._chatHandler = new AgentChatHandler(this, {
|
|
265
|
+
model: this.model,
|
|
266
|
+
provider: this.provider,
|
|
267
|
+
apiKey: this.apiKey,
|
|
268
|
+
baseURL: this.baseURL,
|
|
269
|
+
providerOptions: this.providerOptions
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
if (aiClient) {
|
|
273
|
+
this._chatHandler.setAIClient(aiClient)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// 转发事件
|
|
277
|
+
this._chatHandler.on('message', (msg) => this.emit('message', msg))
|
|
278
|
+
this._chatHandler.on('chunk', (chunk) => this.emit('chunk', chunk))
|
|
279
|
+
this._chatHandler.on('tool-call', (tool) => this.emit('tool-call', tool))
|
|
280
|
+
this._chatHandler.on('tool-result', (result) => this.emit('tool-result', result))
|
|
281
|
+
this._chatHandler.on('error', (err) => this.emit('error', err))
|
|
282
|
+
|
|
283
|
+
this._syncTools()
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* 设置系统提示
|
|
288
|
+
*/
|
|
289
|
+
setSystemPrompt(prompt) {
|
|
290
|
+
this._originalPrompt = prompt
|
|
291
|
+
this.systemPrompt = this._buildSystemPrompt()
|
|
292
|
+
if (this._chatHandler) {
|
|
293
|
+
this._chatHandler.setSystemPrompt(this.systemPrompt)
|
|
294
|
+
}
|
|
295
|
+
return this
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* 注册工具到 Agent
|
|
300
|
+
*/
|
|
301
|
+
registerTool(tool) {
|
|
302
|
+
this._tools.set(tool.name, tool)
|
|
303
|
+
if (this._chatHandler) {
|
|
304
|
+
this._chatHandler.registerTool(tool)
|
|
305
|
+
}
|
|
306
|
+
this._refreshContext()
|
|
307
|
+
return this
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* 获取已注册工具
|
|
312
|
+
*/
|
|
313
|
+
getTools() {
|
|
314
|
+
return Array.from(this._tools.values())
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* 同步框架中的工具到 Agent
|
|
319
|
+
* @private
|
|
320
|
+
*/
|
|
321
|
+
_syncTools() {
|
|
322
|
+
if (this.framework.toolRegistry.size() > 0) {
|
|
323
|
+
for (const tool of this.framework.getTools()) {
|
|
324
|
+
if (!this._tools.has(tool.name)) {
|
|
325
|
+
this.registerTool(tool)
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* 注册子Agent
|
|
333
|
+
* @param {string} name - 子Agent名称
|
|
334
|
+
* @param {Agent} agent - 子Agent实例
|
|
335
|
+
* @param {string} role - 角色描述
|
|
336
|
+
* @param {string} goal - 目标描述
|
|
337
|
+
*/
|
|
338
|
+
registerSubAgent(name, agent, role, goal) {
|
|
339
|
+
this._subAgents.set(name, { agent, role, goal })
|
|
340
|
+
this._refreshContext()
|
|
341
|
+
return this
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* 注销子Agent
|
|
346
|
+
*/
|
|
347
|
+
unregisterSubAgent(name) {
|
|
348
|
+
this._subAgents.delete(name)
|
|
349
|
+
this._refreshContext()
|
|
350
|
+
return this
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* 获取所有子Agent
|
|
355
|
+
*/
|
|
356
|
+
getSubAgents() {
|
|
357
|
+
return this._subAgents
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* 获取待处理的调度通知并清除(下次不再重复显示)
|
|
362
|
+
*/
|
|
363
|
+
_getAndClearSchedulerNotifications() {
|
|
364
|
+
try {
|
|
365
|
+
const scheduler = this.framework.pluginManager.get('scheduler')
|
|
366
|
+
if (scheduler && scheduler.instance && scheduler.instance.getPendingNotifications) {
|
|
367
|
+
const results = scheduler.instance.getPendingNotifications()
|
|
368
|
+
if (results.length > 0) {
|
|
369
|
+
const notifications = results.slice(-5).reverse() // 最多5条,最新的在前
|
|
370
|
+
// 清除已发送的通知
|
|
371
|
+
if (scheduler.instance.clearDeliveredNotifications) {
|
|
372
|
+
scheduler.instance.clearDeliveredNotifications(notifications.length)
|
|
373
|
+
}
|
|
374
|
+
return notifications
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
} catch (err) {
|
|
378
|
+
// 忽略错误,避免影响主流程
|
|
379
|
+
}
|
|
380
|
+
return []
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* 获取待处理的思考结果并清除
|
|
385
|
+
*/
|
|
386
|
+
_getAndClearThinkNotifications() {
|
|
387
|
+
try {
|
|
388
|
+
const think = this.framework.pluginManager.get('think')
|
|
389
|
+
if (think && think.instance && think.instance.getPendingThoughts) {
|
|
390
|
+
const thoughts = think.instance.getPendingThoughts()
|
|
391
|
+
if (thoughts.length > 0) {
|
|
392
|
+
return thoughts.slice(-5).reverse() // 最多5条,最新的在前
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
} catch (err) {
|
|
396
|
+
// 忽略错误,避免影响主流程
|
|
397
|
+
}
|
|
398
|
+
return []
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* 获取所有待处理的系统通知(调度 + 思考)
|
|
403
|
+
*/
|
|
404
|
+
_getAllPendingNotifications() {
|
|
405
|
+
const notifications = []
|
|
406
|
+
|
|
407
|
+
// 调度通知
|
|
408
|
+
const schedulerNotifs = this._getAndClearSchedulerNotifications()
|
|
409
|
+
for (const n of schedulerNotifs) {
|
|
410
|
+
notifications.push(`【定时任务通知】\n任务: ${n.taskName || n.taskId}\n执行时间: ${n.executedAt}\n结果: ${n.result || n.action || '执行完成'}`)
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// 思考通知
|
|
414
|
+
const thinkNotifs = this._getAndClearThinkNotifications()
|
|
415
|
+
for (const t of thinkNotifs) {
|
|
416
|
+
notifications.push(`【主动思考】\n模式: ${t.mode}\n主题: ${t.topic}\n结果: ${t.result || '思考完成'}`)
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return notifications
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* 发送消息
|
|
424
|
+
*/
|
|
425
|
+
async chat(message, options = {}) {
|
|
426
|
+
if (this._status === 'busy') {
|
|
427
|
+
throw new Error('Agent is busy')
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (this._status === 'error') {
|
|
431
|
+
this._status = 'idle'
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
this._status = 'busy'
|
|
435
|
+
this.emit('status', { status: 'busy' })
|
|
436
|
+
|
|
437
|
+
try {
|
|
438
|
+
// 检查是否有待处理的系统通知(调度 + 思考)
|
|
439
|
+
const notifications = this._getAllPendingNotifications()
|
|
440
|
+
let enhancedMessage = message
|
|
441
|
+
if (notifications.length > 0) {
|
|
442
|
+
enhancedMessage = `【系统通知】\n${notifications.join('\n\n')}\n\n---\n用户消息: ${message}`
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
this._syncTools()
|
|
446
|
+
|
|
447
|
+
const result = await this._chatHandler.chat(enhancedMessage, options)
|
|
448
|
+
this._status = 'idle'
|
|
449
|
+
this.emit('status', { status: 'idle' })
|
|
450
|
+
return result
|
|
451
|
+
} catch (err) {
|
|
452
|
+
this._status = 'error'
|
|
453
|
+
this.emit('status', { status: 'error', error: err.message })
|
|
454
|
+
throw err
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* 发送消息(流式)
|
|
460
|
+
*/
|
|
461
|
+
async *chatStream(message, options = {}) {
|
|
462
|
+
if (this._status === 'busy') {
|
|
463
|
+
throw new Error('Agent is busy')
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// 允许从 error 状态重试
|
|
467
|
+
if (this._status === 'error') {
|
|
468
|
+
this._status = 'idle'
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
this._status = 'busy'
|
|
472
|
+
this.emit('status', { status: 'busy' })
|
|
473
|
+
|
|
474
|
+
try {
|
|
475
|
+
// 检查是否有待处理的系统通知(调度 + 思考)
|
|
476
|
+
const notifications = this._getAllPendingNotifications()
|
|
477
|
+
let enhancedMessage = message
|
|
478
|
+
if (notifications.length > 0) {
|
|
479
|
+
enhancedMessage = `【系统通知】\n${notifications.join('\n\n')}\n\n---\n用户消息: ${message}`
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
this._syncTools()
|
|
483
|
+
|
|
484
|
+
yield* this._chatHandler.chatStream(enhancedMessage, options)
|
|
485
|
+
this._status = 'idle'
|
|
486
|
+
this.emit('status', { status: 'idle' })
|
|
487
|
+
} catch (err) {
|
|
488
|
+
this._status = 'error'
|
|
489
|
+
this.emit('status', { status: 'error', error: err.message })
|
|
490
|
+
throw err
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* 设置元数据
|
|
496
|
+
*/
|
|
497
|
+
setMetadata(keyOrObj, value) {
|
|
498
|
+
if (typeof keyOrObj === 'string') {
|
|
499
|
+
this._metadata.set(keyOrObj, value)
|
|
500
|
+
} else if (keyOrObj && typeof keyOrObj === 'object') {
|
|
501
|
+
for (const [key, val] of Object.entries(keyOrObj)) {
|
|
502
|
+
this._metadata.set(key, val)
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
this._refreshContext()
|
|
506
|
+
return this
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* 获取元数据
|
|
511
|
+
*/
|
|
512
|
+
getMetadata(key) {
|
|
513
|
+
return this._metadata.get(key)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* 删除元数据
|
|
518
|
+
*/
|
|
519
|
+
deleteMetadata(key) {
|
|
520
|
+
this._metadata.delete(key)
|
|
521
|
+
this._refreshContext()
|
|
522
|
+
return this
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* 清空元数据
|
|
527
|
+
*/
|
|
528
|
+
clearMetadata() {
|
|
529
|
+
this._metadata.clear()
|
|
530
|
+
this._refreshContext()
|
|
531
|
+
return this
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* 清空对话历史
|
|
536
|
+
*/
|
|
537
|
+
clearHistory() {
|
|
538
|
+
if (this._chatHandler) {
|
|
539
|
+
this._chatHandler.clearHistory()
|
|
540
|
+
}
|
|
541
|
+
return this
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* 获取状态
|
|
546
|
+
*/
|
|
547
|
+
getStatus() {
|
|
548
|
+
return this._status
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* 重置状态(从卡住状态恢复)
|
|
553
|
+
*/
|
|
554
|
+
resetStatus() {
|
|
555
|
+
this._status = 'idle'
|
|
556
|
+
this.emit('status', { status: 'idle' })
|
|
557
|
+
return this
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* 销毁 Agent
|
|
562
|
+
*/
|
|
563
|
+
destroy() {
|
|
564
|
+
if (this._chatHandler) {
|
|
565
|
+
this._chatHandler.destroy()
|
|
566
|
+
}
|
|
567
|
+
this._tools.clear()
|
|
568
|
+
this.removeAllListeners()
|
|
569
|
+
this.emit('destroyed')
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
module.exports = { Agent }
|