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
|
@@ -1,579 +1,579 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ambient Agent 插件
|
|
3
|
-
* 持续后台运行的智能代理,监控事件并主动执行操作
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const { Plugin } = require('../../src/core/plugin-base')
|
|
7
|
-
const { logger } = require('../../src/utils/logger')
|
|
8
|
-
const { z } = require('zod')
|
|
9
|
-
|
|
10
|
-
// 导入子模块
|
|
11
|
-
const { GoalState } = require('./constants')
|
|
12
|
-
const { StateStore } = require('./StateStore')
|
|
13
|
-
const { GoalManager } = require('./GoalManager')
|
|
14
|
-
const { EventWatcher } = require('./EventWatcher')
|
|
15
|
-
const { Reflector } = require('./Reflector')
|
|
16
|
-
const { ExplorerLoop } = require('./ExplorerLoop')
|
|
17
|
-
|
|
18
|
-
const log = logger.child('Ambient')
|
|
19
|
-
|
|
20
|
-
class AmbientAgentPlugin extends Plugin {
|
|
21
|
-
constructor(config = {}) {
|
|
22
|
-
super()
|
|
23
|
-
this.name = 'ambient'
|
|
24
|
-
this.version = '1.0.0'
|
|
25
|
-
this.description = `Ambient Agent - 持续后台运行的智能代理,用于主动监控事件并执行操作
|
|
26
|
-
|
|
27
|
-
## 支持的事件类型(创建目标时 conditions.events 必须使用这些确切的名称):
|
|
28
|
-
- email:received - 收到新邮件(参数:from, subject, text, messageId)
|
|
29
|
-
- tool:result - 工具执行完成(参数:name, args, result)
|
|
30
|
-
- scheduler:reminder - 定时提醒(参数:taskId, message, time)
|
|
31
|
-
- scheduler:task_completed - 任务完成(参数:taskId, result)
|
|
32
|
-
- scheduler:task_failed - 任务失败(参数:taskId, error)
|
|
33
|
-
- agent:message - 代理消息(参数:content, sessionId)
|
|
34
|
-
- think:thought_completed - 思考完成(参数:mode, topic, thought)
|
|
35
|
-
- webhook:received - Webhook接收(参数:headers, body, query, path)
|
|
36
|
-
|
|
37
|
-
## 在 action 参数中引用事件数据:
|
|
38
|
-
使用 \${event.xxx} 语法,例如:\${event.from}、\${event.subject}、\${event.text}`
|
|
39
|
-
this.priority = 18
|
|
40
|
-
this.system = true
|
|
41
|
-
|
|
42
|
-
this.config = {
|
|
43
|
-
enabled: config.enabled !== false,
|
|
44
|
-
tickInterval: config.tickInterval || 5000, // tick间隔(毫秒)
|
|
45
|
-
cooldownPeriod: config.cooldownPeriod || 3000, // 冷却时间(毫秒)
|
|
46
|
-
persistencePath: config.persistencePath || '.agent/data/ambient',
|
|
47
|
-
defaultGoals: config.defaultGoals || []
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
this._framework = null
|
|
51
|
-
this._stateStore = null
|
|
52
|
-
this._goalManager = null
|
|
53
|
-
this._eventWatcher = null
|
|
54
|
-
this._reflector = null
|
|
55
|
-
this._explorerLoop = null
|
|
56
|
-
this._memories = []
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// ============================================================================
|
|
60
|
-
// 生命周期
|
|
61
|
-
// ============================================================================
|
|
62
|
-
|
|
63
|
-
install(framework) {
|
|
64
|
-
this._framework = framework
|
|
65
|
-
this._stateStore = new StateStore(this.config.persistencePath)
|
|
66
|
-
this._goalManager = new GoalManager(this._stateStore)
|
|
67
|
-
this._reflector = new Reflector(this._goalManager)
|
|
68
|
-
|
|
69
|
-
// 加载持久化的记忆
|
|
70
|
-
this._memories = this._stateStore.loadMemories()
|
|
71
|
-
|
|
72
|
-
return this
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
start(framework) {
|
|
76
|
-
if (!this.config.enabled) {
|
|
77
|
-
log.info('插件已禁用,跳过启动')
|
|
78
|
-
return this
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// 如果没有现有目标,创建默认目标
|
|
82
|
-
if (this._goalManager.getAllGoals().length === 0 && this.config.defaultGoals.length > 0) {
|
|
83
|
-
for (const goalDef of this.config.defaultGoals) {
|
|
84
|
-
this._goalManager.createGoal(goalDef)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// 启动事件监听器
|
|
89
|
-
this._eventWatcher = new EventWatcher(this._goalManager, this._framework)
|
|
90
|
-
this._eventWatcher.start()
|
|
91
|
-
|
|
92
|
-
// 动态更新description显示支持的事件及参数
|
|
93
|
-
this._updateDescription()
|
|
94
|
-
|
|
95
|
-
// 启动探索循环
|
|
96
|
-
this._explorerLoop = new ExplorerLoop(this._goalManager, this._reflector, this._framework, {
|
|
97
|
-
tickInterval: this.config.tickInterval,
|
|
98
|
-
cooldownPeriod: this.config.cooldownPeriod
|
|
99
|
-
})
|
|
100
|
-
this._explorerLoop.start()
|
|
101
|
-
|
|
102
|
-
// 注册工具
|
|
103
|
-
this._registerTools(framework)
|
|
104
|
-
|
|
105
|
-
log.info('插件已启动')
|
|
106
|
-
return this
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
reload(framework) {
|
|
110
|
-
this._framework = framework
|
|
111
|
-
if (this._explorerLoop && this._explorerLoop.isRunning()) {
|
|
112
|
-
// 用新的框架引用重新启动
|
|
113
|
-
this._eventWatcher = new EventWatcher(this._goalManager, this._framework)
|
|
114
|
-
this._eventWatcher.start()
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
uninstall(framework) {
|
|
119
|
-
// 停止探索循环
|
|
120
|
-
if (this._explorerLoop) {
|
|
121
|
-
this._explorerLoop.stop()
|
|
122
|
-
this._explorerLoop = null
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// 停止事件监听器
|
|
126
|
-
if (this._eventWatcher) {
|
|
127
|
-
this._eventWatcher.stop()
|
|
128
|
-
this._eventWatcher = null
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// 清除引用
|
|
132
|
-
this._framework = null
|
|
133
|
-
this._goalManager = null
|
|
134
|
-
this._reflector = null
|
|
135
|
-
this._stateStore = null
|
|
136
|
-
this._memories = []
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// ============================================================================
|
|
140
|
-
// 描述更新
|
|
141
|
-
// ============================================================================
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* 动态更新插件描述,从 Framework 获取已注册的事件描述
|
|
145
|
-
*/
|
|
146
|
-
_updateDescription() {
|
|
147
|
-
if (!this._framework) return
|
|
148
|
-
|
|
149
|
-
// 从 Framework 获取所有已注册的事件描述
|
|
150
|
-
const eventDescriptions = this._framework.getEventDescriptions()
|
|
151
|
-
|
|
152
|
-
if (eventDescriptions.size === 0) {
|
|
153
|
-
// 如果没有动态注册的事件,使用默认事件列表
|
|
154
|
-
const defaultEvents = [
|
|
155
|
-
{ type: 'tool:result', desc: '工具执行结果 - name, args, result, error' },
|
|
156
|
-
{ type: 'scheduler:reminder', desc: '定时提醒 - taskId, message, time' },
|
|
157
|
-
{ type: 'scheduler:task_completed', desc: '任务完成 - taskId, result' },
|
|
158
|
-
{ type: 'scheduler:task_failed', desc: '任务失败 - taskId, error' },
|
|
159
|
-
{ type: 'agent:message', desc: '代理消息 - content, sessionId' },
|
|
160
|
-
{ type: 'think:thought_completed', desc: '思考完成 - mode, topic, thought, depth' },
|
|
161
|
-
{ type: 'email:received', desc: '收到邮件 - from, to, subject, text, messageId, timestamp' },
|
|
162
|
-
{ type: 'webhook:received', desc: 'Webhook接收 - webhook, data, headers, query, path, sessionId, response' }
|
|
163
|
-
]
|
|
164
|
-
|
|
165
|
-
const eventList = defaultEvents.map(e => ` - ${e.type} - ${e.desc}`).join('\n')
|
|
166
|
-
this.description = `Ambient Agent - 持续后台运行的智能代理,用于主动监控和执行操作
|
|
167
|
-
|
|
168
|
-
## 支持的事件类型(创建目标时 conditions.events 必须使用这些确切的名称):
|
|
169
|
-
${eventList}
|
|
170
|
-
|
|
171
|
-
## 在 action 参数中引用事件数据:
|
|
172
|
-
使用 \${event.xxx} 语法,例如:\${event.from}、\${event.subject}、\${event.text}`
|
|
173
|
-
return
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// 生成事件列表
|
|
177
|
-
const eventList = Array.from(eventDescriptions.entries())
|
|
178
|
-
.map(([type, info]) => {
|
|
179
|
-
const desc = info.params || info.description || ''
|
|
180
|
-
return ` - ${type} - ${desc}`
|
|
181
|
-
})
|
|
182
|
-
.join('\n')
|
|
183
|
-
|
|
184
|
-
this.description = `Ambient Agent - 持续后台运行的智能代理,用于主动监控和执行操作
|
|
185
|
-
|
|
186
|
-
## 支持的事件类型(创建目标时 conditions.events 必须使用这些确切的名称):
|
|
187
|
-
${eventList}
|
|
188
|
-
|
|
189
|
-
## 在 action 参数中引用事件数据:
|
|
190
|
-
使用 \${event.xxx} 语法,例如:\${event.from}、\${event.subject}、\${event.text}
|
|
191
|
-
|
|
192
|
-
---
|
|
193
|
-
💡 提示:事件描述由触发事件的插件动态注册。`
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// ============================================================================
|
|
197
|
-
// 工具注册
|
|
198
|
-
// ============================================================================
|
|
199
|
-
|
|
200
|
-
_registerTools(framework) {
|
|
201
|
-
// ambient_goals - 列出/创建/更新/删除目标
|
|
202
|
-
framework.registerTool({
|
|
203
|
-
name: 'ambient_goals',
|
|
204
|
-
description: '管理Ambient Agent目标 - 列出、创建、更新、删除、激活目标',
|
|
205
|
-
inputSchema: z.object({
|
|
206
|
-
action: z.enum(['list', 'create', 'update', 'delete', 'activate']).describe('执行的操作'),
|
|
207
|
-
goalId: z.string().optional().describe('目标ID(更新/删除/激活时必需)'),
|
|
208
|
-
title: z.string().optional().describe('目标标题(创建/更新时使用)'),
|
|
209
|
-
description: z.string().optional().describe('目标描述(创建/更新时使用)'),
|
|
210
|
-
priority: z.number().optional().describe('优先级1-10,数值越高越重要(创建/更新时使用)'),
|
|
211
|
-
actions: z.array(z.object({
|
|
212
|
-
id: z.string().optional().describe('操作标识符'),
|
|
213
|
-
type: z.enum(['tool', 'message', 'think']).describe('操作类型'),
|
|
214
|
-
name: z.string().optional().describe('工具名称(tool类型时使用)'),
|
|
215
|
-
args: z.record(z.any()).optional().describe('工具参数(tool类型时使用)'),
|
|
216
|
-
content: z.string().optional().describe('消息内容(message类型时使用)'),
|
|
217
|
-
topic: z.string().optional().describe('思考主题(think类型时使用)'),
|
|
218
|
-
mode: z.enum(['reflect', 'brainstorm', 'analyze', 'plan']).optional().describe('思考模式(think类型时使用)')
|
|
219
|
-
})).optional().describe('要执行的操作列表(创建/更新时使用)'),
|
|
220
|
-
conditions: z.object({
|
|
221
|
-
events: z.union([z.string(), z.array(z.string())]).optional().describe('要监听的事件类型'),
|
|
222
|
-
toolNames: z.union([z.string(), z.array(z.string())]).optional().describe('按工具名称过滤')
|
|
223
|
-
}).optional().describe('激活条件(创建/更新时使用)')
|
|
224
|
-
}),
|
|
225
|
-
execute: async (args) => {
|
|
226
|
-
return this._handleGoalsTool(args)
|
|
227
|
-
}
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
// ambient_status - 获取当前循环状态
|
|
231
|
-
framework.registerTool({
|
|
232
|
-
name: 'ambient_status',
|
|
233
|
-
description: '获取当前Ambient Agent状态 - 循环状态、进行中的目标、最近活动',
|
|
234
|
-
inputSchema: z.object({}),
|
|
235
|
-
execute: async () => {
|
|
236
|
-
return this._handleStatusTool()
|
|
237
|
-
}
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
// ambient_think - 触发主动LLM思考
|
|
241
|
-
framework.registerTool({
|
|
242
|
-
name: 'ambient_think',
|
|
243
|
-
description: '为某个目标触发主动LLM思考 - 模式:reflect(反思)、brainstorm(头脑风暴)、plan(计划)、analyze(分析)',
|
|
244
|
-
inputSchema: z.object({
|
|
245
|
-
goalId: z.string().optional().describe('要思考的目标ID'),
|
|
246
|
-
mode: z.enum(['reflect', 'brainstorm', 'plan', 'analyze']).describe('思考模式'),
|
|
247
|
-
topic: z.string().optional().describe('要思考的主题'),
|
|
248
|
-
depth: z.number().optional().describe('思考深度1-5')
|
|
249
|
-
}),
|
|
250
|
-
execute: async (args) => {
|
|
251
|
-
return this._handleThinkTool(args)
|
|
252
|
-
}
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
// ambient_remember - 存储/检索/搜索持久化记忆
|
|
256
|
-
framework.registerTool({
|
|
257
|
-
name: 'ambient_remember',
|
|
258
|
-
description: '为Ambient Agent存储或检索持久化记忆',
|
|
259
|
-
inputSchema: z.object({
|
|
260
|
-
action: z.enum(['store', 'retrieve', 'search']).describe('操作:store存储记忆、retrieve检索最近、search搜索'),
|
|
261
|
-
content: z.string().optional().describe('记忆内容(store时使用)'),
|
|
262
|
-
key: z.string().optional().describe('记忆键(store/retrieve时使用)'),
|
|
263
|
-
query: z.string().optional().describe('搜索查询(search时使用)'),
|
|
264
|
-
limit: z.number().optional().describe('最大结果数(retrieve/search时使用)')
|
|
265
|
-
}),
|
|
266
|
-
execute: async (args) => {
|
|
267
|
-
return this._handleRememberTool(args)
|
|
268
|
-
}
|
|
269
|
-
})
|
|
270
|
-
|
|
271
|
-
// ambient_control - 暂停/恢复/调整探索循环
|
|
272
|
-
framework.registerTool({
|
|
273
|
-
name: 'ambient_control',
|
|
274
|
-
description: '控制Ambient Agent探索循环 - 暂停、恢复或调整设置',
|
|
275
|
-
inputSchema: z.object({
|
|
276
|
-
action: z.enum(['pause', 'resume', 'status', 'adjust']).describe('控制操作'),
|
|
277
|
-
tickInterval: z.number().optional().describe('新的tick间隔毫秒数(adjust时使用)'),
|
|
278
|
-
cooldownPeriod: z.number().optional().describe('新的冷却时间毫秒数(adjust时使用)')
|
|
279
|
-
}),
|
|
280
|
-
execute: async (args) => {
|
|
281
|
-
return this._handleControlTool(args)
|
|
282
|
-
}
|
|
283
|
-
})
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// ============================================================================
|
|
287
|
-
// 工具处理器
|
|
288
|
-
// ============================================================================
|
|
289
|
-
|
|
290
|
-
_handleGoalsTool(args) {
|
|
291
|
-
const { action, goalId, title, description, priority, actions, conditions } = args
|
|
292
|
-
|
|
293
|
-
switch (action) {
|
|
294
|
-
case 'list': {
|
|
295
|
-
const allGoals = this._goalManager.getAllGoals()
|
|
296
|
-
return {
|
|
297
|
-
success: true,
|
|
298
|
-
goals: allGoals.map(g => ({
|
|
299
|
-
id: g.id,
|
|
300
|
-
title: g.title,
|
|
301
|
-
state: g.state,
|
|
302
|
-
priority: g.priority,
|
|
303
|
-
actionsCount: g.actions ? g.actions.length : 0,
|
|
304
|
-
attempts: g.attempts,
|
|
305
|
-
createdAt: g.createdAt,
|
|
306
|
-
activatedAt: g.activatedAt,
|
|
307
|
-
completedAt: g.completedAt,
|
|
308
|
-
failedAt: g.failedAt
|
|
309
|
-
})),
|
|
310
|
-
total: allGoals.length,
|
|
311
|
-
active: this._goalManager.getActiveGoals().length,
|
|
312
|
-
pending: this._goalManager.getPendingGoals().length
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
case 'create': {
|
|
317
|
-
if (!title) {
|
|
318
|
-
return { success: false, error: '创建目标需要提供标题' }
|
|
319
|
-
}
|
|
320
|
-
const goal = this._goalManager.createGoal({ title, description, priority, actions, conditions })
|
|
321
|
-
return { success: true, goal }
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
case 'update': {
|
|
325
|
-
if (!goalId) {
|
|
326
|
-
return { success: false, error: '更新目标需要提供目标ID' }
|
|
327
|
-
}
|
|
328
|
-
const updates = {}
|
|
329
|
-
if (title !== undefined) updates.title = title
|
|
330
|
-
if (description !== undefined) updates.description = description
|
|
331
|
-
if (priority !== undefined) updates.priority = priority
|
|
332
|
-
if (actions !== undefined) updates.actions = actions
|
|
333
|
-
if (conditions !== undefined) updates.conditions = conditions
|
|
334
|
-
const goal = this._goalManager.updateGoal(goalId, updates)
|
|
335
|
-
return goal ? { success: true, goal } : { success: false, error: '目标未找到' }
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
case 'delete': {
|
|
339
|
-
if (!goalId) {
|
|
340
|
-
return { success: false, error: '删除目标需要提供目标ID' }
|
|
341
|
-
}
|
|
342
|
-
const deleted = this._goalManager.deleteGoal(goalId)
|
|
343
|
-
return { success: deleted }
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
case 'activate': {
|
|
347
|
-
if (!goalId) {
|
|
348
|
-
return { success: false, error: '激活目标需要提供目标ID' }
|
|
349
|
-
}
|
|
350
|
-
const goal = this._goalManager.activateGoal(goalId)
|
|
351
|
-
return goal ? { success: true, goal } : { success: false, error: '目标未找到或不是待激活状态' }
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
default:
|
|
355
|
-
return { success: false, error: `未知操作: ${action}` }
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
_handleStatusTool() {
|
|
360
|
-
if (!this._explorerLoop) {
|
|
361
|
-
return { success: false, error: '探索循环未初始化' }
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const loopStatus = this._explorerLoop.getStatus()
|
|
365
|
-
const activeGoals = this._goalManager.getActiveGoals().map(g => ({
|
|
366
|
-
id: g.id,
|
|
367
|
-
title: g.title,
|
|
368
|
-
priority: g.priority,
|
|
369
|
-
attempts: g.attempts,
|
|
370
|
-
lastActionId: g.lastActionId
|
|
371
|
-
}))
|
|
372
|
-
const pendingGoals = this._goalManager.getPendingGoals().map(g => ({
|
|
373
|
-
id: g.id,
|
|
374
|
-
title: g.title,
|
|
375
|
-
priority: g.priority
|
|
376
|
-
}))
|
|
377
|
-
|
|
378
|
-
return {
|
|
379
|
-
success: true,
|
|
380
|
-
loop: {
|
|
381
|
-
running: loopStatus.running,
|
|
382
|
-
tickCount: loopStatus.tickCount,
|
|
383
|
-
lastTick: loopStatus.lastTick,
|
|
384
|
-
tickInterval: this.config.tickInterval,
|
|
385
|
-
cooldownPeriod: this.config.cooldownPeriod
|
|
386
|
-
},
|
|
387
|
-
activeGoals,
|
|
388
|
-
pendingGoals,
|
|
389
|
-
recentActivities: loopStatus.recentActivities
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
async _handleThinkTool(args) {
|
|
394
|
-
const { goalId, mode, topic, depth } = args
|
|
395
|
-
|
|
396
|
-
// 获取活跃代理
|
|
397
|
-
const agent = this._getActiveAgent()
|
|
398
|
-
if (!agent) {
|
|
399
|
-
return { success: false, error: '没有可用的活跃代理' }
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
// 构建思考提示
|
|
403
|
-
let prompt = ''
|
|
404
|
-
if (goalId) {
|
|
405
|
-
const goal = this._goalManager.getGoal(goalId)
|
|
406
|
-
if (goal) {
|
|
407
|
-
const { ThinkModePrompts } = require('./constants')
|
|
408
|
-
const modePrompts = ThinkModePrompts
|
|
409
|
-
const modePromptFn = modePrompts[mode]
|
|
410
|
-
prompt = modePromptFn ? modePromptFn(goal, topic) : modePrompts.reflect(goal, topic)
|
|
411
|
-
} else {
|
|
412
|
-
return { success: false, error: '目标未找到' }
|
|
413
|
-
}
|
|
414
|
-
} else {
|
|
415
|
-
const { FreeThinkPrompts } = require('./constants')
|
|
416
|
-
const modePrompts = FreeThinkPrompts
|
|
417
|
-
const modePromptFn = modePrompts[mode]
|
|
418
|
-
prompt = modePromptFn ? modePromptFn(topic) : modePrompts.reflect(topic)
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// 如果代理忙,等待其变为可用
|
|
422
|
-
let attempts = 0
|
|
423
|
-
const maxWaitAttempts = 10
|
|
424
|
-
const waitInterval = 500
|
|
425
|
-
|
|
426
|
-
while (agent._status === 'busy' && attempts < maxWaitAttempts) {
|
|
427
|
-
log.info('代理忙,等待中...')
|
|
428
|
-
await new Promise(resolve => setTimeout(resolve, waitInterval))
|
|
429
|
-
attempts++
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
if (agent._status === 'busy') {
|
|
433
|
-
return {
|
|
434
|
-
success: false,
|
|
435
|
-
error: '代理繁忙,无法及时变为可用。请稍后重试。',
|
|
436
|
-
queued: true
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// 通过代理执行思考
|
|
441
|
-
const thinkPlugin = this._framework.pluginManager.get('think')
|
|
442
|
-
if (thinkPlugin) {
|
|
443
|
-
const result = await thinkPlugin._triggerThinking({ topic: prompt, mode, depth: depth || 2 })
|
|
444
|
-
// 如果结果提示繁忙,返回更友好的消息
|
|
445
|
-
if (result && result.message && result.message.includes && result.message.includes('busy')) {
|
|
446
|
-
return {
|
|
447
|
-
success: true,
|
|
448
|
-
queued: true,
|
|
449
|
-
message: '思考请求已排队,将在代理空闲时处理。'
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
return result
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
// 备用:直接推送消息
|
|
456
|
-
return agent.pushMessage(prompt).then(result => ({
|
|
457
|
-
success: true,
|
|
458
|
-
result: typeof result === 'string' ? result : JSON.stringify(result)
|
|
459
|
-
})).catch(err => ({
|
|
460
|
-
success: false,
|
|
461
|
-
error: err.message
|
|
462
|
-
}))
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
_handleRememberTool(args) {
|
|
466
|
-
const { action, content, key, query, limit } = args
|
|
467
|
-
const maxResults = limit || 10
|
|
468
|
-
|
|
469
|
-
switch (action) {
|
|
470
|
-
case 'store': {
|
|
471
|
-
if (!content) {
|
|
472
|
-
return { success: false, error: '存储需要提供内容' }
|
|
473
|
-
}
|
|
474
|
-
const memoryKey = key || `memory_${Date.now()}`
|
|
475
|
-
const memory = {
|
|
476
|
-
key: memoryKey,
|
|
477
|
-
content,
|
|
478
|
-
timestamp: new Date()
|
|
479
|
-
}
|
|
480
|
-
this._memories.push(memory)
|
|
481
|
-
this._stateStore.saveMemories(this._memories)
|
|
482
|
-
return { success: true, memory }
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
case 'retrieve': {
|
|
486
|
-
const memories = this._memories.slice(-maxResults).reverse()
|
|
487
|
-
return {
|
|
488
|
-
success: true,
|
|
489
|
-
memories,
|
|
490
|
-
total: this._memories.length
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
case 'search': {
|
|
495
|
-
if (!query) {
|
|
496
|
-
return { success: false, error: '搜索需要提供查询词' }
|
|
497
|
-
}
|
|
498
|
-
const queryLower = query.toLowerCase()
|
|
499
|
-
const results = this._memories
|
|
500
|
-
.filter(m => m.content.toLowerCase().includes(queryLower))
|
|
501
|
-
.slice(-maxResults)
|
|
502
|
-
.reverse()
|
|
503
|
-
return {
|
|
504
|
-
success: true,
|
|
505
|
-
results,
|
|
506
|
-
total: results.length
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
default:
|
|
511
|
-
return { success: false, error: `未知操作: ${action}` }
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
_handleControlTool(args) {
|
|
516
|
-
const { action, tickInterval, cooldownPeriod } = args
|
|
517
|
-
|
|
518
|
-
switch (action) {
|
|
519
|
-
case 'pause': {
|
|
520
|
-
if (!this._explorerLoop) {
|
|
521
|
-
return { success: false, error: '探索循环未初始化' }
|
|
522
|
-
}
|
|
523
|
-
this._explorerLoop.pause()
|
|
524
|
-
return { success: true, message: '探索循环已暂停' }
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
case 'resume': {
|
|
528
|
-
if (!this._explorerLoop) {
|
|
529
|
-
return { success: false, error: '探索循环未初始化' }
|
|
530
|
-
}
|
|
531
|
-
this._explorerLoop.resume()
|
|
532
|
-
return { success: true, message: '探索循环已恢复' }
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
case 'status': {
|
|
536
|
-
if (!this._explorerLoop) {
|
|
537
|
-
return { success: false, error: '探索循环未初始化' }
|
|
538
|
-
}
|
|
539
|
-
const status = this._explorerLoop.getStatus()
|
|
540
|
-
return {
|
|
541
|
-
success: true,
|
|
542
|
-
running: status.running,
|
|
543
|
-
tickCount: status.tickCount,
|
|
544
|
-
lastTick: status.lastTick,
|
|
545
|
-
tickInterval: this.config.tickInterval,
|
|
546
|
-
cooldownPeriod: this.config.cooldownPeriod
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
case 'adjust': {
|
|
551
|
-
if (tickInterval) {
|
|
552
|
-
this.config.tickInterval = tickInterval
|
|
553
|
-
}
|
|
554
|
-
if (cooldownPeriod) {
|
|
555
|
-
this.config.cooldownPeriod = cooldownPeriod
|
|
556
|
-
}
|
|
557
|
-
return {
|
|
558
|
-
success: true,
|
|
559
|
-
message: '设置已调整',
|
|
560
|
-
tickInterval: this.config.tickInterval,
|
|
561
|
-
cooldownPeriod: this.config.cooldownPeriod
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
default:
|
|
566
|
-
return { success: false, error: `未知操作: ${action}` }
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
_getActiveAgent() {
|
|
571
|
-
if (this._framework._mainAgent) {
|
|
572
|
-
return this._framework._mainAgent
|
|
573
|
-
}
|
|
574
|
-
const agents = this._framework._agents || []
|
|
575
|
-
return agents.length > 0 ? agents[agents.length - 1] : null
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
module.exports = { AmbientAgentPlugin, GoalState }
|
|
1
|
+
/**
|
|
2
|
+
* Ambient Agent 插件
|
|
3
|
+
* 持续后台运行的智能代理,监控事件并主动执行操作
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { Plugin } = require('../../src/core/plugin-base')
|
|
7
|
+
const { logger } = require('../../src/utils/logger')
|
|
8
|
+
const { z } = require('zod')
|
|
9
|
+
|
|
10
|
+
// 导入子模块
|
|
11
|
+
const { GoalState } = require('./constants')
|
|
12
|
+
const { StateStore } = require('./StateStore')
|
|
13
|
+
const { GoalManager } = require('./GoalManager')
|
|
14
|
+
const { EventWatcher } = require('./EventWatcher')
|
|
15
|
+
const { Reflector } = require('./Reflector')
|
|
16
|
+
const { ExplorerLoop } = require('./ExplorerLoop')
|
|
17
|
+
|
|
18
|
+
const log = logger.child('Ambient')
|
|
19
|
+
|
|
20
|
+
class AmbientAgentPlugin extends Plugin {
|
|
21
|
+
constructor(config = {}) {
|
|
22
|
+
super()
|
|
23
|
+
this.name = 'ambient'
|
|
24
|
+
this.version = '1.0.0'
|
|
25
|
+
this.description = `Ambient Agent - 持续后台运行的智能代理,用于主动监控事件并执行操作
|
|
26
|
+
|
|
27
|
+
## 支持的事件类型(创建目标时 conditions.events 必须使用这些确切的名称):
|
|
28
|
+
- email:received - 收到新邮件(参数:from, subject, text, messageId)
|
|
29
|
+
- tool:result - 工具执行完成(参数:name, args, result)
|
|
30
|
+
- scheduler:reminder - 定时提醒(参数:taskId, message, time)
|
|
31
|
+
- scheduler:task_completed - 任务完成(参数:taskId, result)
|
|
32
|
+
- scheduler:task_failed - 任务失败(参数:taskId, error)
|
|
33
|
+
- agent:message - 代理消息(参数:content, sessionId)
|
|
34
|
+
- think:thought_completed - 思考完成(参数:mode, topic, thought)
|
|
35
|
+
- webhook:received - Webhook接收(参数:headers, body, query, path)
|
|
36
|
+
|
|
37
|
+
## 在 action 参数中引用事件数据:
|
|
38
|
+
使用 \${event.xxx} 语法,例如:\${event.from}、\${event.subject}、\${event.text}`
|
|
39
|
+
this.priority = 18
|
|
40
|
+
this.system = true
|
|
41
|
+
|
|
42
|
+
this.config = {
|
|
43
|
+
enabled: config.enabled !== false,
|
|
44
|
+
tickInterval: config.tickInterval || 5000, // tick间隔(毫秒)
|
|
45
|
+
cooldownPeriod: config.cooldownPeriod || 3000, // 冷却时间(毫秒)
|
|
46
|
+
persistencePath: config.persistencePath || '.agent/data/ambient',
|
|
47
|
+
defaultGoals: config.defaultGoals || []
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
this._framework = null
|
|
51
|
+
this._stateStore = null
|
|
52
|
+
this._goalManager = null
|
|
53
|
+
this._eventWatcher = null
|
|
54
|
+
this._reflector = null
|
|
55
|
+
this._explorerLoop = null
|
|
56
|
+
this._memories = []
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// 生命周期
|
|
61
|
+
// ============================================================================
|
|
62
|
+
|
|
63
|
+
install(framework) {
|
|
64
|
+
this._framework = framework
|
|
65
|
+
this._stateStore = new StateStore(this.config.persistencePath)
|
|
66
|
+
this._goalManager = new GoalManager(this._stateStore)
|
|
67
|
+
this._reflector = new Reflector(this._goalManager)
|
|
68
|
+
|
|
69
|
+
// 加载持久化的记忆
|
|
70
|
+
this._memories = this._stateStore.loadMemories()
|
|
71
|
+
|
|
72
|
+
return this
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
start(framework) {
|
|
76
|
+
if (!this.config.enabled) {
|
|
77
|
+
log.info('插件已禁用,跳过启动')
|
|
78
|
+
return this
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 如果没有现有目标,创建默认目标
|
|
82
|
+
if (this._goalManager.getAllGoals().length === 0 && this.config.defaultGoals.length > 0) {
|
|
83
|
+
for (const goalDef of this.config.defaultGoals) {
|
|
84
|
+
this._goalManager.createGoal(goalDef)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 启动事件监听器
|
|
89
|
+
this._eventWatcher = new EventWatcher(this._goalManager, this._framework)
|
|
90
|
+
this._eventWatcher.start()
|
|
91
|
+
|
|
92
|
+
// 动态更新description显示支持的事件及参数
|
|
93
|
+
this._updateDescription()
|
|
94
|
+
|
|
95
|
+
// 启动探索循环
|
|
96
|
+
this._explorerLoop = new ExplorerLoop(this._goalManager, this._reflector, this._framework, {
|
|
97
|
+
tickInterval: this.config.tickInterval,
|
|
98
|
+
cooldownPeriod: this.config.cooldownPeriod
|
|
99
|
+
})
|
|
100
|
+
this._explorerLoop.start()
|
|
101
|
+
|
|
102
|
+
// 注册工具
|
|
103
|
+
this._registerTools(framework)
|
|
104
|
+
|
|
105
|
+
log.info('插件已启动')
|
|
106
|
+
return this
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
reload(framework) {
|
|
110
|
+
this._framework = framework
|
|
111
|
+
if (this._explorerLoop && this._explorerLoop.isRunning()) {
|
|
112
|
+
// 用新的框架引用重新启动
|
|
113
|
+
this._eventWatcher = new EventWatcher(this._goalManager, this._framework)
|
|
114
|
+
this._eventWatcher.start()
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
uninstall(framework) {
|
|
119
|
+
// 停止探索循环
|
|
120
|
+
if (this._explorerLoop) {
|
|
121
|
+
this._explorerLoop.stop()
|
|
122
|
+
this._explorerLoop = null
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 停止事件监听器
|
|
126
|
+
if (this._eventWatcher) {
|
|
127
|
+
this._eventWatcher.stop()
|
|
128
|
+
this._eventWatcher = null
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// 清除引用
|
|
132
|
+
this._framework = null
|
|
133
|
+
this._goalManager = null
|
|
134
|
+
this._reflector = null
|
|
135
|
+
this._stateStore = null
|
|
136
|
+
this._memories = []
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// 描述更新
|
|
141
|
+
// ============================================================================
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 动态更新插件描述,从 Framework 获取已注册的事件描述
|
|
145
|
+
*/
|
|
146
|
+
_updateDescription() {
|
|
147
|
+
if (!this._framework) return
|
|
148
|
+
|
|
149
|
+
// 从 Framework 获取所有已注册的事件描述
|
|
150
|
+
const eventDescriptions = this._framework.getEventDescriptions()
|
|
151
|
+
|
|
152
|
+
if (eventDescriptions.size === 0) {
|
|
153
|
+
// 如果没有动态注册的事件,使用默认事件列表
|
|
154
|
+
const defaultEvents = [
|
|
155
|
+
{ type: 'tool:result', desc: '工具执行结果 - name, args, result, error' },
|
|
156
|
+
{ type: 'scheduler:reminder', desc: '定时提醒 - taskId, message, time' },
|
|
157
|
+
{ type: 'scheduler:task_completed', desc: '任务完成 - taskId, result' },
|
|
158
|
+
{ type: 'scheduler:task_failed', desc: '任务失败 - taskId, error' },
|
|
159
|
+
{ type: 'agent:message', desc: '代理消息 - content, sessionId' },
|
|
160
|
+
{ type: 'think:thought_completed', desc: '思考完成 - mode, topic, thought, depth' },
|
|
161
|
+
{ type: 'email:received', desc: '收到邮件 - from, to, subject, text, messageId, timestamp' },
|
|
162
|
+
{ type: 'webhook:received', desc: 'Webhook接收 - webhook, data, headers, query, path, sessionId, response' }
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
const eventList = defaultEvents.map(e => ` - ${e.type} - ${e.desc}`).join('\n')
|
|
166
|
+
this.description = `Ambient Agent - 持续后台运行的智能代理,用于主动监控和执行操作
|
|
167
|
+
|
|
168
|
+
## 支持的事件类型(创建目标时 conditions.events 必须使用这些确切的名称):
|
|
169
|
+
${eventList}
|
|
170
|
+
|
|
171
|
+
## 在 action 参数中引用事件数据:
|
|
172
|
+
使用 \${event.xxx} 语法,例如:\${event.from}、\${event.subject}、\${event.text}`
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 生成事件列表
|
|
177
|
+
const eventList = Array.from(eventDescriptions.entries())
|
|
178
|
+
.map(([type, info]) => {
|
|
179
|
+
const desc = info.params || info.description || ''
|
|
180
|
+
return ` - ${type} - ${desc}`
|
|
181
|
+
})
|
|
182
|
+
.join('\n')
|
|
183
|
+
|
|
184
|
+
this.description = `Ambient Agent - 持续后台运行的智能代理,用于主动监控和执行操作
|
|
185
|
+
|
|
186
|
+
## 支持的事件类型(创建目标时 conditions.events 必须使用这些确切的名称):
|
|
187
|
+
${eventList}
|
|
188
|
+
|
|
189
|
+
## 在 action 参数中引用事件数据:
|
|
190
|
+
使用 \${event.xxx} 语法,例如:\${event.from}、\${event.subject}、\${event.text}
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
💡 提示:事件描述由触发事件的插件动态注册。`
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ============================================================================
|
|
197
|
+
// 工具注册
|
|
198
|
+
// ============================================================================
|
|
199
|
+
|
|
200
|
+
_registerTools(framework) {
|
|
201
|
+
// ambient_goals - 列出/创建/更新/删除目标
|
|
202
|
+
framework.registerTool({
|
|
203
|
+
name: 'ambient_goals',
|
|
204
|
+
description: '管理Ambient Agent目标 - 列出、创建、更新、删除、激活目标',
|
|
205
|
+
inputSchema: z.object({
|
|
206
|
+
action: z.enum(['list', 'create', 'update', 'delete', 'activate']).describe('执行的操作'),
|
|
207
|
+
goalId: z.string().optional().describe('目标ID(更新/删除/激活时必需)'),
|
|
208
|
+
title: z.string().optional().describe('目标标题(创建/更新时使用)'),
|
|
209
|
+
description: z.string().optional().describe('目标描述(创建/更新时使用)'),
|
|
210
|
+
priority: z.number().optional().describe('优先级1-10,数值越高越重要(创建/更新时使用)'),
|
|
211
|
+
actions: z.array(z.object({
|
|
212
|
+
id: z.string().optional().describe('操作标识符'),
|
|
213
|
+
type: z.enum(['tool', 'message', 'think']).describe('操作类型'),
|
|
214
|
+
name: z.string().optional().describe('工具名称(tool类型时使用)'),
|
|
215
|
+
args: z.record(z.any()).optional().describe('工具参数(tool类型时使用)'),
|
|
216
|
+
content: z.string().optional().describe('消息内容(message类型时使用)'),
|
|
217
|
+
topic: z.string().optional().describe('思考主题(think类型时使用)'),
|
|
218
|
+
mode: z.enum(['reflect', 'brainstorm', 'analyze', 'plan']).optional().describe('思考模式(think类型时使用)')
|
|
219
|
+
})).optional().describe('要执行的操作列表(创建/更新时使用)'),
|
|
220
|
+
conditions: z.object({
|
|
221
|
+
events: z.union([z.string(), z.array(z.string())]).optional().describe('要监听的事件类型'),
|
|
222
|
+
toolNames: z.union([z.string(), z.array(z.string())]).optional().describe('按工具名称过滤')
|
|
223
|
+
}).optional().describe('激活条件(创建/更新时使用)')
|
|
224
|
+
}),
|
|
225
|
+
execute: async (args) => {
|
|
226
|
+
return this._handleGoalsTool(args)
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
// ambient_status - 获取当前循环状态
|
|
231
|
+
framework.registerTool({
|
|
232
|
+
name: 'ambient_status',
|
|
233
|
+
description: '获取当前Ambient Agent状态 - 循环状态、进行中的目标、最近活动',
|
|
234
|
+
inputSchema: z.object({}),
|
|
235
|
+
execute: async () => {
|
|
236
|
+
return this._handleStatusTool()
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
// ambient_think - 触发主动LLM思考
|
|
241
|
+
framework.registerTool({
|
|
242
|
+
name: 'ambient_think',
|
|
243
|
+
description: '为某个目标触发主动LLM思考 - 模式:reflect(反思)、brainstorm(头脑风暴)、plan(计划)、analyze(分析)',
|
|
244
|
+
inputSchema: z.object({
|
|
245
|
+
goalId: z.string().optional().describe('要思考的目标ID'),
|
|
246
|
+
mode: z.enum(['reflect', 'brainstorm', 'plan', 'analyze']).describe('思考模式'),
|
|
247
|
+
topic: z.string().optional().describe('要思考的主题'),
|
|
248
|
+
depth: z.number().optional().describe('思考深度1-5')
|
|
249
|
+
}),
|
|
250
|
+
execute: async (args) => {
|
|
251
|
+
return this._handleThinkTool(args)
|
|
252
|
+
}
|
|
253
|
+
})
|
|
254
|
+
|
|
255
|
+
// ambient_remember - 存储/检索/搜索持久化记忆
|
|
256
|
+
framework.registerTool({
|
|
257
|
+
name: 'ambient_remember',
|
|
258
|
+
description: '为Ambient Agent存储或检索持久化记忆',
|
|
259
|
+
inputSchema: z.object({
|
|
260
|
+
action: z.enum(['store', 'retrieve', 'search']).describe('操作:store存储记忆、retrieve检索最近、search搜索'),
|
|
261
|
+
content: z.string().optional().describe('记忆内容(store时使用)'),
|
|
262
|
+
key: z.string().optional().describe('记忆键(store/retrieve时使用)'),
|
|
263
|
+
query: z.string().optional().describe('搜索查询(search时使用)'),
|
|
264
|
+
limit: z.number().optional().describe('最大结果数(retrieve/search时使用)')
|
|
265
|
+
}),
|
|
266
|
+
execute: async (args) => {
|
|
267
|
+
return this._handleRememberTool(args)
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
// ambient_control - 暂停/恢复/调整探索循环
|
|
272
|
+
framework.registerTool({
|
|
273
|
+
name: 'ambient_control',
|
|
274
|
+
description: '控制Ambient Agent探索循环 - 暂停、恢复或调整设置',
|
|
275
|
+
inputSchema: z.object({
|
|
276
|
+
action: z.enum(['pause', 'resume', 'status', 'adjust']).describe('控制操作'),
|
|
277
|
+
tickInterval: z.number().optional().describe('新的tick间隔毫秒数(adjust时使用)'),
|
|
278
|
+
cooldownPeriod: z.number().optional().describe('新的冷却时间毫秒数(adjust时使用)')
|
|
279
|
+
}),
|
|
280
|
+
execute: async (args) => {
|
|
281
|
+
return this._handleControlTool(args)
|
|
282
|
+
}
|
|
283
|
+
})
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// ============================================================================
|
|
287
|
+
// 工具处理器
|
|
288
|
+
// ============================================================================
|
|
289
|
+
|
|
290
|
+
_handleGoalsTool(args) {
|
|
291
|
+
const { action, goalId, title, description, priority, actions, conditions } = args
|
|
292
|
+
|
|
293
|
+
switch (action) {
|
|
294
|
+
case 'list': {
|
|
295
|
+
const allGoals = this._goalManager.getAllGoals()
|
|
296
|
+
return {
|
|
297
|
+
success: true,
|
|
298
|
+
goals: allGoals.map(g => ({
|
|
299
|
+
id: g.id,
|
|
300
|
+
title: g.title,
|
|
301
|
+
state: g.state,
|
|
302
|
+
priority: g.priority,
|
|
303
|
+
actionsCount: g.actions ? g.actions.length : 0,
|
|
304
|
+
attempts: g.attempts,
|
|
305
|
+
createdAt: g.createdAt,
|
|
306
|
+
activatedAt: g.activatedAt,
|
|
307
|
+
completedAt: g.completedAt,
|
|
308
|
+
failedAt: g.failedAt
|
|
309
|
+
})),
|
|
310
|
+
total: allGoals.length,
|
|
311
|
+
active: this._goalManager.getActiveGoals().length,
|
|
312
|
+
pending: this._goalManager.getPendingGoals().length
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
case 'create': {
|
|
317
|
+
if (!title) {
|
|
318
|
+
return { success: false, error: '创建目标需要提供标题' }
|
|
319
|
+
}
|
|
320
|
+
const goal = this._goalManager.createGoal({ title, description, priority, actions, conditions })
|
|
321
|
+
return { success: true, goal }
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
case 'update': {
|
|
325
|
+
if (!goalId) {
|
|
326
|
+
return { success: false, error: '更新目标需要提供目标ID' }
|
|
327
|
+
}
|
|
328
|
+
const updates = {}
|
|
329
|
+
if (title !== undefined) updates.title = title
|
|
330
|
+
if (description !== undefined) updates.description = description
|
|
331
|
+
if (priority !== undefined) updates.priority = priority
|
|
332
|
+
if (actions !== undefined) updates.actions = actions
|
|
333
|
+
if (conditions !== undefined) updates.conditions = conditions
|
|
334
|
+
const goal = this._goalManager.updateGoal(goalId, updates)
|
|
335
|
+
return goal ? { success: true, goal } : { success: false, error: '目标未找到' }
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
case 'delete': {
|
|
339
|
+
if (!goalId) {
|
|
340
|
+
return { success: false, error: '删除目标需要提供目标ID' }
|
|
341
|
+
}
|
|
342
|
+
const deleted = this._goalManager.deleteGoal(goalId)
|
|
343
|
+
return { success: deleted }
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
case 'activate': {
|
|
347
|
+
if (!goalId) {
|
|
348
|
+
return { success: false, error: '激活目标需要提供目标ID' }
|
|
349
|
+
}
|
|
350
|
+
const goal = this._goalManager.activateGoal(goalId)
|
|
351
|
+
return goal ? { success: true, goal } : { success: false, error: '目标未找到或不是待激活状态' }
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
default:
|
|
355
|
+
return { success: false, error: `未知操作: ${action}` }
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
_handleStatusTool() {
|
|
360
|
+
if (!this._explorerLoop) {
|
|
361
|
+
return { success: false, error: '探索循环未初始化' }
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const loopStatus = this._explorerLoop.getStatus()
|
|
365
|
+
const activeGoals = this._goalManager.getActiveGoals().map(g => ({
|
|
366
|
+
id: g.id,
|
|
367
|
+
title: g.title,
|
|
368
|
+
priority: g.priority,
|
|
369
|
+
attempts: g.attempts,
|
|
370
|
+
lastActionId: g.lastActionId
|
|
371
|
+
}))
|
|
372
|
+
const pendingGoals = this._goalManager.getPendingGoals().map(g => ({
|
|
373
|
+
id: g.id,
|
|
374
|
+
title: g.title,
|
|
375
|
+
priority: g.priority
|
|
376
|
+
}))
|
|
377
|
+
|
|
378
|
+
return {
|
|
379
|
+
success: true,
|
|
380
|
+
loop: {
|
|
381
|
+
running: loopStatus.running,
|
|
382
|
+
tickCount: loopStatus.tickCount,
|
|
383
|
+
lastTick: loopStatus.lastTick,
|
|
384
|
+
tickInterval: this.config.tickInterval,
|
|
385
|
+
cooldownPeriod: this.config.cooldownPeriod
|
|
386
|
+
},
|
|
387
|
+
activeGoals,
|
|
388
|
+
pendingGoals,
|
|
389
|
+
recentActivities: loopStatus.recentActivities
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
async _handleThinkTool(args) {
|
|
394
|
+
const { goalId, mode, topic, depth } = args
|
|
395
|
+
|
|
396
|
+
// 获取活跃代理
|
|
397
|
+
const agent = this._getActiveAgent()
|
|
398
|
+
if (!agent) {
|
|
399
|
+
return { success: false, error: '没有可用的活跃代理' }
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// 构建思考提示
|
|
403
|
+
let prompt = ''
|
|
404
|
+
if (goalId) {
|
|
405
|
+
const goal = this._goalManager.getGoal(goalId)
|
|
406
|
+
if (goal) {
|
|
407
|
+
const { ThinkModePrompts } = require('./constants')
|
|
408
|
+
const modePrompts = ThinkModePrompts
|
|
409
|
+
const modePromptFn = modePrompts[mode]
|
|
410
|
+
prompt = modePromptFn ? modePromptFn(goal, topic) : modePrompts.reflect(goal, topic)
|
|
411
|
+
} else {
|
|
412
|
+
return { success: false, error: '目标未找到' }
|
|
413
|
+
}
|
|
414
|
+
} else {
|
|
415
|
+
const { FreeThinkPrompts } = require('./constants')
|
|
416
|
+
const modePrompts = FreeThinkPrompts
|
|
417
|
+
const modePromptFn = modePrompts[mode]
|
|
418
|
+
prompt = modePromptFn ? modePromptFn(topic) : modePrompts.reflect(topic)
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// 如果代理忙,等待其变为可用
|
|
422
|
+
let attempts = 0
|
|
423
|
+
const maxWaitAttempts = 10
|
|
424
|
+
const waitInterval = 500
|
|
425
|
+
|
|
426
|
+
while (agent._status === 'busy' && attempts < maxWaitAttempts) {
|
|
427
|
+
log.info('代理忙,等待中...')
|
|
428
|
+
await new Promise(resolve => setTimeout(resolve, waitInterval))
|
|
429
|
+
attempts++
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (agent._status === 'busy') {
|
|
433
|
+
return {
|
|
434
|
+
success: false,
|
|
435
|
+
error: '代理繁忙,无法及时变为可用。请稍后重试。',
|
|
436
|
+
queued: true
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// 通过代理执行思考
|
|
441
|
+
const thinkPlugin = this._framework.pluginManager.get('think')
|
|
442
|
+
if (thinkPlugin) {
|
|
443
|
+
const result = await thinkPlugin._triggerThinking({ topic: prompt, mode, depth: depth || 2 })
|
|
444
|
+
// 如果结果提示繁忙,返回更友好的消息
|
|
445
|
+
if (result && result.message && result.message.includes && result.message.includes('busy')) {
|
|
446
|
+
return {
|
|
447
|
+
success: true,
|
|
448
|
+
queued: true,
|
|
449
|
+
message: '思考请求已排队,将在代理空闲时处理。'
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return result
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// 备用:直接推送消息
|
|
456
|
+
return agent.pushMessage(prompt).then(result => ({
|
|
457
|
+
success: true,
|
|
458
|
+
result: typeof result === 'string' ? result : JSON.stringify(result)
|
|
459
|
+
})).catch(err => ({
|
|
460
|
+
success: false,
|
|
461
|
+
error: err.message
|
|
462
|
+
}))
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
_handleRememberTool(args) {
|
|
466
|
+
const { action, content, key, query, limit } = args
|
|
467
|
+
const maxResults = limit || 10
|
|
468
|
+
|
|
469
|
+
switch (action) {
|
|
470
|
+
case 'store': {
|
|
471
|
+
if (!content) {
|
|
472
|
+
return { success: false, error: '存储需要提供内容' }
|
|
473
|
+
}
|
|
474
|
+
const memoryKey = key || `memory_${Date.now()}`
|
|
475
|
+
const memory = {
|
|
476
|
+
key: memoryKey,
|
|
477
|
+
content,
|
|
478
|
+
timestamp: new Date()
|
|
479
|
+
}
|
|
480
|
+
this._memories.push(memory)
|
|
481
|
+
this._stateStore.saveMemories(this._memories)
|
|
482
|
+
return { success: true, memory }
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
case 'retrieve': {
|
|
486
|
+
const memories = this._memories.slice(-maxResults).reverse()
|
|
487
|
+
return {
|
|
488
|
+
success: true,
|
|
489
|
+
memories,
|
|
490
|
+
total: this._memories.length
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
case 'search': {
|
|
495
|
+
if (!query) {
|
|
496
|
+
return { success: false, error: '搜索需要提供查询词' }
|
|
497
|
+
}
|
|
498
|
+
const queryLower = query.toLowerCase()
|
|
499
|
+
const results = this._memories
|
|
500
|
+
.filter(m => m.content.toLowerCase().includes(queryLower))
|
|
501
|
+
.slice(-maxResults)
|
|
502
|
+
.reverse()
|
|
503
|
+
return {
|
|
504
|
+
success: true,
|
|
505
|
+
results,
|
|
506
|
+
total: results.length
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
default:
|
|
511
|
+
return { success: false, error: `未知操作: ${action}` }
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
_handleControlTool(args) {
|
|
516
|
+
const { action, tickInterval, cooldownPeriod } = args
|
|
517
|
+
|
|
518
|
+
switch (action) {
|
|
519
|
+
case 'pause': {
|
|
520
|
+
if (!this._explorerLoop) {
|
|
521
|
+
return { success: false, error: '探索循环未初始化' }
|
|
522
|
+
}
|
|
523
|
+
this._explorerLoop.pause()
|
|
524
|
+
return { success: true, message: '探索循环已暂停' }
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
case 'resume': {
|
|
528
|
+
if (!this._explorerLoop) {
|
|
529
|
+
return { success: false, error: '探索循环未初始化' }
|
|
530
|
+
}
|
|
531
|
+
this._explorerLoop.resume()
|
|
532
|
+
return { success: true, message: '探索循环已恢复' }
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
case 'status': {
|
|
536
|
+
if (!this._explorerLoop) {
|
|
537
|
+
return { success: false, error: '探索循环未初始化' }
|
|
538
|
+
}
|
|
539
|
+
const status = this._explorerLoop.getStatus()
|
|
540
|
+
return {
|
|
541
|
+
success: true,
|
|
542
|
+
running: status.running,
|
|
543
|
+
tickCount: status.tickCount,
|
|
544
|
+
lastTick: status.lastTick,
|
|
545
|
+
tickInterval: this.config.tickInterval,
|
|
546
|
+
cooldownPeriod: this.config.cooldownPeriod
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
case 'adjust': {
|
|
551
|
+
if (tickInterval) {
|
|
552
|
+
this.config.tickInterval = tickInterval
|
|
553
|
+
}
|
|
554
|
+
if (cooldownPeriod) {
|
|
555
|
+
this.config.cooldownPeriod = cooldownPeriod
|
|
556
|
+
}
|
|
557
|
+
return {
|
|
558
|
+
success: true,
|
|
559
|
+
message: '设置已调整',
|
|
560
|
+
tickInterval: this.config.tickInterval,
|
|
561
|
+
cooldownPeriod: this.config.cooldownPeriod
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
default:
|
|
566
|
+
return { success: false, error: `未知操作: ${action}` }
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
_getActiveAgent() {
|
|
571
|
+
if (this._framework._mainAgent) {
|
|
572
|
+
return this._framework._mainAgent
|
|
573
|
+
}
|
|
574
|
+
const agents = this._framework._agents || []
|
|
575
|
+
return agents.length > 0 ? agents[agents.length - 1] : null
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
module.exports = { AmbientAgentPlugin, GoalState }
|