foliko 1.0.65 → 1.0.67
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 +145 -142
- package/package.json +1 -1
- package/plugins/ambient-agent-plugin.js +158 -46
- package/plugins/email.js +36 -4
- package/skills/ambient-agent/SKILL.md +234 -0
- package/skills/workflow-guide/SKILL.md +74 -14
- package/src/capabilities/workflow-engine.js +388 -181
- package/src/core/agent-chat.js +26 -4
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ambient-agent
|
|
3
|
+
description: Ambient Agent - 持续后台运行的智能代理,用于主动监控事件和执行操作
|
|
4
|
+
allowed-tools: ambient_goals,ambient_status,ambient_think,ambient_remember,ambient_control
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Ambient Agent
|
|
8
|
+
|
|
9
|
+
Ambient Agent 是一个持续后台运行的智能代理,监控事件并主动执行操作。
|
|
10
|
+
|
|
11
|
+
## 核心概念
|
|
12
|
+
|
|
13
|
+
### Goal(目标)
|
|
14
|
+
目标是对话式 LLM 派发的任务,包含:
|
|
15
|
+
- `title` - 目标标题
|
|
16
|
+
- `description` - 目标描述
|
|
17
|
+
- `priority` - 优先级 1-10
|
|
18
|
+
- `actions` - 要执行的操作列表
|
|
19
|
+
- `conditions` - 激活条件(如监听特定事件)
|
|
20
|
+
- `state` - 状态:`pending` | `active` | `completed` | `failed`
|
|
21
|
+
|
|
22
|
+
### Action(操作)
|
|
23
|
+
操作是目标的最小执行单元,有三种类型:
|
|
24
|
+
|
|
25
|
+
| 类型 | 说明 | 参数 |
|
|
26
|
+
|------|------|------|
|
|
27
|
+
| `tool` | 调用工具 | `name` 工具名, `args` 参数 |
|
|
28
|
+
| `message` | 发送消息 | `content` 消息内容 |
|
|
29
|
+
| `think` | 触发思考 | `topic` 主题, `mode` 模式, `depth` 深度 |
|
|
30
|
+
|
|
31
|
+
### Event(事件)
|
|
32
|
+
目标可以监听框架事件:
|
|
33
|
+
- `tool:result` - 工具执行结果
|
|
34
|
+
- `scheduler:reminder` - 定时提醒
|
|
35
|
+
- `agent:message` - 代理消息
|
|
36
|
+
- `email:received` - 收到邮件
|
|
37
|
+
- `webhook:received` - Webhook 接收
|
|
38
|
+
|
|
39
|
+
## 工具
|
|
40
|
+
|
|
41
|
+
### ambient_goals - 目标管理
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
// 列出所有目标
|
|
45
|
+
await ambient_goals({ action: 'list' })
|
|
46
|
+
|
|
47
|
+
// 创建目标
|
|
48
|
+
await ambient_goals({
|
|
49
|
+
action: 'create',
|
|
50
|
+
title: '监控邮件',
|
|
51
|
+
description: '定期检查新邮件',
|
|
52
|
+
priority: 8,
|
|
53
|
+
actions: [
|
|
54
|
+
{ id: 'check-email', type: 'tool', name: 'email_list', args: { box: 'INBOX' } }
|
|
55
|
+
],
|
|
56
|
+
conditions: {
|
|
57
|
+
events: ['email:received']
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
// 更新目标
|
|
62
|
+
await ambient_goals({
|
|
63
|
+
action: 'update',
|
|
64
|
+
goalId: 'xxx-xxx',
|
|
65
|
+
title: '新标题',
|
|
66
|
+
actions: [...] // 新操作列表
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
// 删除目标
|
|
70
|
+
await ambient_goals({ action: 'delete', goalId: 'xxx-xxx' })
|
|
71
|
+
|
|
72
|
+
// 激活目标
|
|
73
|
+
await ambient_goals({ action: 'activate', goalId: 'xxx-xxx' })
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### ambient_status - 获取状态
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
await ambient_status({})
|
|
80
|
+
// 返回: { running, tickCount, activeGoals, pendingGoals, recentActivities }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### ambient_think - 触发思考
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
await ambient_think({
|
|
87
|
+
goalId: 'xxx-xxx', // 可选,关联目标
|
|
88
|
+
mode: 'reflect', // reflect | brainstorm | plan | analyze
|
|
89
|
+
topic: '反思主题', // 可选
|
|
90
|
+
depth: 2 // 可选,1-5
|
|
91
|
+
})
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### ambient_remember - 记忆管理
|
|
95
|
+
|
|
96
|
+
```javascript
|
|
97
|
+
// 存储记忆
|
|
98
|
+
await ambient_remember({
|
|
99
|
+
action: 'store',
|
|
100
|
+
key: 'user-preference',
|
|
101
|
+
content: '用户喜欢在早上收到摘要'
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
// 检索最近记忆
|
|
105
|
+
await ambient_remember({
|
|
106
|
+
action: 'retrieve',
|
|
107
|
+
limit: 10
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// 搜索记忆
|
|
111
|
+
await ambient_remember({
|
|
112
|
+
action: 'search',
|
|
113
|
+
query: '邮件'
|
|
114
|
+
})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### ambient_control - 控制循环
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
// 暂停
|
|
121
|
+
await ambient_control({ action: 'pause' })
|
|
122
|
+
|
|
123
|
+
// 恢复
|
|
124
|
+
await ambient_control({ action: 'resume' })
|
|
125
|
+
|
|
126
|
+
// 调整参数
|
|
127
|
+
await ambient_control({
|
|
128
|
+
action: 'adjust',
|
|
129
|
+
tickInterval: 10000, // 新 tick 间隔(毫秒)
|
|
130
|
+
cooldownPeriod: 5000 // 新冷却时间(毫秒)
|
|
131
|
+
})
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## action 与 step 的关系
|
|
135
|
+
|
|
136
|
+
Ambient Agent 的 action 与 Workflow Engine 的 step 共用 `StepExecutor` 执行:
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
action.type → step.type
|
|
140
|
+
───────────────────────
|
|
141
|
+
tool → tool
|
|
142
|
+
message → message
|
|
143
|
+
think → think
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
这意味着:
|
|
147
|
+
- 变量引用语法一致:`{{variableName}}`
|
|
148
|
+
- sessionId 传递机制一致
|
|
149
|
+
- 错误处理方式一致
|
|
150
|
+
|
|
151
|
+
## action 执行上下文
|
|
152
|
+
|
|
153
|
+
当 action 执行时,可用的上下文:
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
// context.variables 中可用
|
|
157
|
+
context.variables._event // 触发的事件数据(如果有)
|
|
158
|
+
context.variables._action // 当前执行的 action 对象
|
|
159
|
+
context.variables.loopIndex // 循环索引(如果被 loop 执行)
|
|
160
|
+
|
|
161
|
+
// context.input 中可用
|
|
162
|
+
context.input // 工作流/目标输入参数
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## 创建目标的最佳实践
|
|
166
|
+
|
|
167
|
+
1. **明确目标标题** - 让用户清楚知道目标意图
|
|
168
|
+
2. **设置合适优先级** - 高优先级目标会被优先处理
|
|
169
|
+
3. **操作要原子化** - 每个 action 只做一件事
|
|
170
|
+
4. **设置冷却时间** - 避免同一目标过度频繁执行
|
|
171
|
+
5. **检查循环** - 同一 action 连续失败 3 次会判定为循环
|
|
172
|
+
|
|
173
|
+
## 示例:创建邮件自动回复目标
|
|
174
|
+
|
|
175
|
+
**重要**:`email:received` 事件的 `email` 对象包含:
|
|
176
|
+
- `email.from` - 发件人地址
|
|
177
|
+
- `email.to` - 收件人地址
|
|
178
|
+
- `email.subject` - 邮件主题
|
|
179
|
+
- `email.body` - 邮件正文
|
|
180
|
+
|
|
181
|
+
使用 `{{}}` 语法从事件中提取参数:
|
|
182
|
+
|
|
183
|
+
```javascript
|
|
184
|
+
await ambient_goals({
|
|
185
|
+
action: 'create',
|
|
186
|
+
title: '邮件自动回复',
|
|
187
|
+
description: '收到邮件后自动回复发件人',
|
|
188
|
+
priority: 8,
|
|
189
|
+
actions: [
|
|
190
|
+
{
|
|
191
|
+
id: 'auto-reply',
|
|
192
|
+
type: 'tool',
|
|
193
|
+
name: 'email_auto_reply',
|
|
194
|
+
args: {
|
|
195
|
+
to: '{{_event.email.from}}',
|
|
196
|
+
subject: '{{_event.email.subject}}',
|
|
197
|
+
body: '{{_event.email.body}}'
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
],
|
|
201
|
+
conditions: {
|
|
202
|
+
events: ['email:received']
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**错误示例**(缺少参数):
|
|
208
|
+
```javascript
|
|
209
|
+
// ❌ 错误 - 没有传递必需参数
|
|
210
|
+
{ type: 'tool', name: 'email_auto_reply', args: {} }
|
|
211
|
+
|
|
212
|
+
// ✅ 正确 - 从事件中提取参数
|
|
213
|
+
{ type: 'tool', name: 'email_auto_reply', args: {
|
|
214
|
+
to: '{{_event.email.from}}',
|
|
215
|
+
subject: '{{_event.email.subject}}',
|
|
216
|
+
body: '{{_event.email.body}}'
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**注意**:`email_auto_reply` 需要 `to`、`subject`、`body` 三个必需参数,必须从 `{{_event.email.xxx}}` 提取。
|
|
222
|
+
|
|
223
|
+
## 生命周期
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
Goal 创建 → [条件满足] → ACTIVE → 执行 actions → COMPLETED/FAILED
|
|
227
|
+
↑ ↓
|
|
228
|
+
└────── 重新激活 ← ─────────────┘
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
- **pending** - 待激活,满足条件后自动变为 active
|
|
232
|
+
- **active** - 执行中,循环处理 actions
|
|
233
|
+
- **completed** - 所有 actions 执行完毕
|
|
234
|
+
- **failed** - 达到最大尝试次数或检测到循环
|
|
@@ -138,6 +138,45 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
138
138
|
}
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
+
**重要:使用 `{{result}}` 引用上一步结果(推荐)**
|
|
142
|
+
|
|
143
|
+
上一步骤的结果自动保存在 `{{result}}` 中,可以直接提取字段:
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"type": "tool",
|
|
148
|
+
"name": "获取IP",
|
|
149
|
+
"tool": "fetch",
|
|
150
|
+
"args": {
|
|
151
|
+
"url": "https://api.ipify.org?format=json"
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"type": "tool",
|
|
156
|
+
"name": "发送通知",
|
|
157
|
+
"tool": "notification_send",
|
|
158
|
+
"args": {
|
|
159
|
+
"title": "IP 信息",
|
|
160
|
+
"message": "当前公网IP: {{result.body.ip}}"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
支持的引用格式:
|
|
166
|
+
|
|
167
|
+
| 格式 | 说明 |
|
|
168
|
+
|------|------|
|
|
169
|
+
| `{{result}}` | 上一步完整结果 |
|
|
170
|
+
| `{{result.body}}` | 提取 body 字段 |
|
|
171
|
+
| `{{result.body.ip}}` | 从 body 提取嵌套字段 |
|
|
172
|
+
| `{{result.body.data[0].name}}` | 支持数组索引 |
|
|
173
|
+
| `{{lastResult}}` | result 的别名 |
|
|
174
|
+
| `{{lastResult.error}}` | 从错误对象提取信息 |
|
|
175
|
+
| `{{variables.xxx}}` | 显式引用 context.variables |
|
|
176
|
+
| `{{input.xxx}}` | 引用工作流输入参数 |
|
|
177
|
+
|
|
178
|
+
**自动 JSON 解析**:如果字段值是 JSON 字符串,会自动解析为对象后再提取嵌套字段。
|
|
179
|
+
|
|
141
180
|
### 3. loop - 循环步骤
|
|
142
181
|
|
|
143
182
|
重复执行一组步骤:
|
|
@@ -215,6 +254,7 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
215
254
|
|
|
216
255
|
### 示例:获取IP并发送通知
|
|
217
256
|
|
|
257
|
+
**推荐写法**(使用 `{{result}}` 直接引用上一步结果):
|
|
218
258
|
```json
|
|
219
259
|
{
|
|
220
260
|
"name": "get-ip-notify",
|
|
@@ -227,23 +267,41 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
227
267
|
"args": {
|
|
228
268
|
"url": "https://api.ipify.org?format=json",
|
|
229
269
|
"proxy": true
|
|
230
|
-
}
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"type": "tool",
|
|
274
|
+
"name": "发送通知",
|
|
275
|
+
"tool": "notification_send",
|
|
276
|
+
"args": {
|
|
277
|
+
"title": "IP 信息",
|
|
278
|
+
"message": "当前公网IP: {{result.body.ip}}"
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**旧写法**(仍支持,但不推荐):
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"name": "get-ip-notify-old",
|
|
289
|
+
"steps": [
|
|
290
|
+
{
|
|
291
|
+
"type": "tool",
|
|
292
|
+
"tool": "fetch",
|
|
293
|
+
"args": { "url": "https://api.ipify.org?format=json" },
|
|
231
294
|
"outputVariable": "ipResult"
|
|
232
295
|
},
|
|
233
296
|
{
|
|
234
297
|
"type": "script",
|
|
235
|
-
"name": "提取IP",
|
|
236
298
|
"outputVariable": "currentIp",
|
|
237
299
|
"script": "var r=context.variables.ipResult; return (r&&r.success&&r.body)?(typeof r.body==='object'?r.body.ip:r.body.trim()):'获取失败';"
|
|
238
300
|
},
|
|
239
301
|
{
|
|
240
302
|
"type": "tool",
|
|
241
|
-
"name": "发送通知",
|
|
242
303
|
"tool": "notification_send",
|
|
243
|
-
"args": {
|
|
244
|
-
"title": "IP 信息",
|
|
245
|
-
"message": "当前公网IP: {{currentIp}}"
|
|
246
|
-
}
|
|
304
|
+
"args": { "message": "当前公网IP: {{currentIp}}" }
|
|
247
305
|
}
|
|
248
306
|
]
|
|
249
307
|
}
|
|
@@ -282,13 +340,15 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
282
340
|
|
|
283
341
|
## 注意事项
|
|
284
342
|
|
|
285
|
-
1.
|
|
286
|
-
2. **
|
|
287
|
-
3. **JSON
|
|
288
|
-
4. **
|
|
289
|
-
5. **context.
|
|
290
|
-
6.
|
|
291
|
-
7.
|
|
343
|
+
1. **优先使用 `{{result}}` 引用**:上一步结果直接用 `{{result.field}}` 提取,比 script 更简洁
|
|
344
|
+
2. **script 必须 return**:`script` 是函数体,必须用 return 返回值
|
|
345
|
+
3. **JSON 中 script 单行写**:用分号分隔多个语句,不要换行
|
|
346
|
+
4. **JSON 中不能有注释**:注释会导致 JSON 解析失败
|
|
347
|
+
5. **context.variables** 在所有步骤间共享,可存储中间结果
|
|
348
|
+
6. **context.input** 是工作流的输入参数
|
|
349
|
+
7. 循环变量 `i` 从 0 开始计数
|
|
350
|
+
8. 条件分支的 `condition` 是 JavaScript 表达式字符串
|
|
351
|
+
9. **自动 JSON 解析**:`{{result.body}}` 如果是 JSON 字符串会自动解析
|
|
292
352
|
|
|
293
353
|
## 最佳实践
|
|
294
354
|
|