foliko 1.0.68 → 1.0.69
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 +148 -145
- package/examples/basic.js +110 -110
- package/examples/mcp-example.js +53 -53
- package/examples/skill-example.js +49 -49
- package/examples/test-mcp.js +79 -79
- package/examples/test-reload.js +61 -61
- package/news-20260329-1774794949179.html +39 -0
- package/news-20260329-1774794970785.html +39 -0
- package/news-20260329-1774797491928.html +39 -0
- package/package.json +1 -1
- package/plugins/ambient-agent-plugin.js +333 -22
- package/plugins/email.js +106 -20
- package/plugins/file-system-plugin.js +76 -30
- package/plugins/python-executor-plugin.js +41 -8
- package/plugins/scheduler-plugin.js +6 -10
- package/plugins/web-plugin.js +8 -6
- package/skills/ambient-agent/SKILL.md +84 -14
- package/skills/workflow-guide/SKILL.md +214 -2
- package/skills/workflow-troubleshooting/DEBUGGING.md +182 -0
- package/skills/workflow-troubleshooting/SKILL.md +314 -0
- package/src/capabilities/workflow-engine.js +367 -22
- package/src/core/agent-chat.js +106 -14
- package/src/core/framework.js +81 -1
- package/src/executors/executor-base.js +58 -58
- package/test-server.js +0 -25
- package/test.txt +0 -3
|
@@ -70,6 +70,23 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
70
70
|
|
|
71
71
|
## 工作流步骤类型
|
|
72
72
|
|
|
73
|
+
### 支持的步骤类型
|
|
74
|
+
|
|
75
|
+
| 类型 | 说明 | 自动推断 |
|
|
76
|
+
|------|------|---------|
|
|
77
|
+
| `tool` | 工具调用 | 有 `tool` 字段 |
|
|
78
|
+
| `script` | JavaScript 脚本 | 有 `code` 或 `script` 字段 |
|
|
79
|
+
| `condition` | 条件分支 | 有 `branches` 字段 |
|
|
80
|
+
| `switch` | 开关分支 | 有 `value` + `branches` |
|
|
81
|
+
| `try` | 异常捕获 | 有 `try` 或 `catch` 字段 |
|
|
82
|
+
| `parallel` | 并行执行 | `"parallel": true` 或 `"mode": "parallel"` |
|
|
83
|
+
| `sequential` | 顺序执行 | 有 `steps` 字段 |
|
|
84
|
+
| `loop` | 循环执行 | 有 `steps` + `loopVariable`/`maxIterations` |
|
|
85
|
+
| `delay` | 延时等待 | 有 `delayMs` 字段 |
|
|
86
|
+
| `workflow` | 嵌套工作流 | 有 `workflow` 字段 |
|
|
87
|
+
| `message` | 发送消息 | 有 `message` 字段 |
|
|
88
|
+
| `think` | 主动思考 | 有 `topic` 字段 |
|
|
89
|
+
|
|
73
90
|
### 1. script - 脚本步骤
|
|
74
91
|
|
|
75
92
|
执行 JavaScript 脚本,**必须用 return 返回值**:
|
|
@@ -219,7 +236,90 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
219
236
|
}
|
|
220
237
|
```
|
|
221
238
|
|
|
222
|
-
### 5.
|
|
239
|
+
### 5. switch - 开关分支
|
|
240
|
+
|
|
241
|
+
根据值匹配执行对应分支(类似编程语言的 switch-case):
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"type": "switch",
|
|
246
|
+
"value": "{{status}}",
|
|
247
|
+
"branches": [
|
|
248
|
+
{ "case": "success", "steps": [...] },
|
|
249
|
+
{ "case": "error", "steps": [...] },
|
|
250
|
+
{ "case": "pending", "steps": [...] }
|
|
251
|
+
],
|
|
252
|
+
"default": { "steps": [...] }
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
- `value`: 要匹配的值,支持 `{{variable}}` 引用
|
|
257
|
+
- `branches`: 分支数组,匹配第一个 `case` 等于 `value` 的分支
|
|
258
|
+
- `default`: 默认分支(可选)
|
|
259
|
+
|
|
260
|
+
### 6. try - 异常捕获
|
|
261
|
+
|
|
262
|
+
尝试执行,失败时执行 catch 分支:
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"type": "try",
|
|
267
|
+
"name": "尝试执行",
|
|
268
|
+
"try": {
|
|
269
|
+
"steps": [
|
|
270
|
+
{ "type": "tool", "tool": "可能失败的工具", "args": {...} }
|
|
271
|
+
]
|
|
272
|
+
},
|
|
273
|
+
"catch": {
|
|
274
|
+
"steps": [
|
|
275
|
+
{ "type": "tool", "tool": "notification_send", "args": {"message": "执行失败: {{lastError}}"} }
|
|
276
|
+
]
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
- `try`: 尝试执行的步骤
|
|
282
|
+
- `catch`: 捕获异常后执行的步骤
|
|
283
|
+
|
|
284
|
+
### 7. parallel - 并行执行
|
|
285
|
+
|
|
286
|
+
多个步骤同时并行执行:
|
|
287
|
+
|
|
288
|
+
```json
|
|
289
|
+
{
|
|
290
|
+
"type": "parallel",
|
|
291
|
+
"name": "并行获取数据",
|
|
292
|
+
"steps": [
|
|
293
|
+
{ "type": "tool", "tool": "fetch", "args": {"url": "https://api1.com"}, "output": "data1" },
|
|
294
|
+
{ "type": "tool", "tool": "fetch", "args": {"url": "https://api2.com"}, "output": "data2" },
|
|
295
|
+
{ "type": "tool", "tool": "fetch", "args": {"url": "https://api3.com"}, "output": "data3" }
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
返回数组形式的执行结果。
|
|
301
|
+
|
|
302
|
+
### 8. workflow - 嵌套工作流
|
|
303
|
+
|
|
304
|
+
在一个工作流中调用另一个工作流:
|
|
305
|
+
|
|
306
|
+
```json
|
|
307
|
+
{
|
|
308
|
+
"type": "workflow",
|
|
309
|
+
"name": "调用子工作流",
|
|
310
|
+
"workflow": {
|
|
311
|
+
"name": "子工作流名称",
|
|
312
|
+
"steps": [...]
|
|
313
|
+
},
|
|
314
|
+
"input": {
|
|
315
|
+
"param1": "{{parentVar}}"
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
子工作流的输出会合并到父工作流的上下文变量中。
|
|
321
|
+
|
|
322
|
+
### 9. delay - 延时步骤
|
|
223
323
|
|
|
224
324
|
等待指定毫秒数:
|
|
225
325
|
|
|
@@ -231,7 +331,7 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
231
331
|
}
|
|
232
332
|
```
|
|
233
333
|
|
|
234
|
-
###
|
|
334
|
+
### 10. sequential - 顺序步骤
|
|
235
335
|
|
|
236
336
|
将多个步骤组合为顺序执行(可嵌套使用):
|
|
237
337
|
|
|
@@ -338,6 +438,91 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
338
438
|
}
|
|
339
439
|
```
|
|
340
440
|
|
|
441
|
+
### 示例:并行获取多个数据源
|
|
442
|
+
|
|
443
|
+
```json
|
|
444
|
+
{
|
|
445
|
+
"name": "multi-source-fetch",
|
|
446
|
+
"description": "并行获取多个数据源",
|
|
447
|
+
"steps": [
|
|
448
|
+
{
|
|
449
|
+
"type": "parallel",
|
|
450
|
+
"name": "并行获取数据",
|
|
451
|
+
"steps": [
|
|
452
|
+
{ "type": "tool", "tool": "fetch", "args": {"url": "https://api.baidu.com"}, "output": "baiduData" },
|
|
453
|
+
{ "type": "tool", "tool": "fetch", "args": {"url": "https://api.bbc.com"}, "output": "bbcData" },
|
|
454
|
+
{ "type": "tool", "tool": "fetch", "args": {"url": "https://api.reddit.com"}, "output": "redditData" }
|
|
455
|
+
]
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"type": "tool",
|
|
459
|
+
"tool": "notification_send",
|
|
460
|
+
"args": {
|
|
461
|
+
"message": "数据获取完成: 百度 {{result[0].length}} 字节, BBC {{result[1].length}} 字节"
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
]
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### 示例:try-catch 异常处理
|
|
469
|
+
|
|
470
|
+
```json
|
|
471
|
+
{
|
|
472
|
+
"name": "safe-execute",
|
|
473
|
+
"description": "带异常处理的工作流",
|
|
474
|
+
"steps": [
|
|
475
|
+
{
|
|
476
|
+
"type": "try",
|
|
477
|
+
"name": "尝试执行",
|
|
478
|
+
"try": {
|
|
479
|
+
"steps": [
|
|
480
|
+
{ "type": "tool", "tool": "fetch", "args": {"url": "https://可能失败的api.com"} }
|
|
481
|
+
]
|
|
482
|
+
},
|
|
483
|
+
"catch": {
|
|
484
|
+
"steps": [
|
|
485
|
+
{ "type": "script", "outputVariable": "errorMsg", "script": "return 'API 调用失败,使用备用数据';" }
|
|
486
|
+
]
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"type": "tool",
|
|
491
|
+
"tool": "notification_send",
|
|
492
|
+
"args": {
|
|
493
|
+
"message": "结果: {{result.result || result.error}}"
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
]
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### 示例:switch 分支处理
|
|
501
|
+
|
|
502
|
+
```json
|
|
503
|
+
{
|
|
504
|
+
"name": "status-handler",
|
|
505
|
+
"description": "根据状态分发处理",
|
|
506
|
+
"steps": [
|
|
507
|
+
{
|
|
508
|
+
"type": "script",
|
|
509
|
+
"outputVariable": "status",
|
|
510
|
+
"script": "return 'success';"
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"type": "switch",
|
|
514
|
+
"value": "{{status}}",
|
|
515
|
+
"branches": [
|
|
516
|
+
{ "case": "success", "steps": [{ "type": "tool", "tool": "notification_send", "args": {"message": "操作成功"} }] },
|
|
517
|
+
{ "case": "error", "steps": [{ "type": "tool", "tool": "notification_send", "args": {"message": "操作失败"} }] },
|
|
518
|
+
{ "case": "pending", "steps": [{ "type": "tool", "tool": "notification_send", "args": {"message": "操作进行中"} }] }
|
|
519
|
+
],
|
|
520
|
+
"default": { "steps": [{ "type": "tool", "tool": "notification_send", "args": {"message": "未知状态"} }] }
|
|
521
|
+
}
|
|
522
|
+
]
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
341
526
|
## 注意事项
|
|
342
527
|
|
|
343
528
|
1. **优先使用 `{{result}}` 引用**:上一步结果直接用 `{{result.field}}` 提取,比 script 更简洁
|
|
@@ -349,6 +534,10 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
349
534
|
7. 循环变量 `i` 从 0 开始计数
|
|
350
535
|
8. 条件分支的 `condition` 是 JavaScript 表达式字符串
|
|
351
536
|
9. **自动 JSON 解析**:`{{result.body}}` 如果是 JSON 字符串会自动解析
|
|
537
|
+
10. **类型自动推断**:如果步骤没有指定 `type`,会根据字段自动推断类型
|
|
538
|
+
11. **`${stepId.output}` 引用**:可引用指定 id 步骤的输出(兼容旧格式)
|
|
539
|
+
12. **`input` 字段**:可传递上一步输出给工具(兼容旧格式)
|
|
540
|
+
13. **try-catch 异常处理**:使用 try 包裹可能失败的步骤,catch 捕获错误
|
|
352
541
|
|
|
353
542
|
## 最佳实践
|
|
354
543
|
|
|
@@ -359,6 +548,9 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
359
548
|
5. 复杂的业务逻辑优先使用脚本步骤
|
|
360
549
|
6. **script 必须 return**:`script` 是函数体,必须用 return 返回值
|
|
361
550
|
7. **JSON 中 script 单行写**:用分号分隔多个语句,不要换行
|
|
551
|
+
8. **并行获取独立数据**:使用 `parallel` 同时获取多个数据源,节省时间
|
|
552
|
+
9. **使用 try-catch**:对可能失败的步骤使用异常捕获,避免整个工作流中断
|
|
553
|
+
10. **嵌套工作流**:将复杂工作流拆分为子工作流,提高复用性和可维护性
|
|
362
554
|
|
|
363
555
|
**错误示例**:
|
|
364
556
|
```json
|
|
@@ -377,6 +569,16 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
377
569
|
{
|
|
378
570
|
"script": "return 1; // 这是注释"
|
|
379
571
|
}
|
|
572
|
+
|
|
573
|
+
// ❌ 错误 - switch 缺少 default 兜底
|
|
574
|
+
{
|
|
575
|
+
"type": "switch",
|
|
576
|
+
"value": "{{status}}",
|
|
577
|
+
"branches": [
|
|
578
|
+
{ "case": "success", "steps": [...] }
|
|
579
|
+
]
|
|
580
|
+
// 没有 default 分支,匹配不到会静默忽略
|
|
581
|
+
}
|
|
380
582
|
```
|
|
381
583
|
|
|
382
584
|
**正确示例**:
|
|
@@ -386,4 +588,14 @@ allowed-tools: execute_workflow,reloadWorkflows
|
|
|
386
588
|
|
|
387
589
|
// ✅ 正确 - 复杂逻辑拆成多步
|
|
388
590
|
{ "type": "script", "script": "context.variables.a=10; context.variables.b=20; return context.variables.a+context.variables.b;" }
|
|
591
|
+
|
|
592
|
+
// ✅ 正确 - switch 有 default 兜底
|
|
593
|
+
{
|
|
594
|
+
"type": "switch",
|
|
595
|
+
"value": "{{status}}",
|
|
596
|
+
"branches": [
|
|
597
|
+
{ "case": "success", "steps": [...] }
|
|
598
|
+
],
|
|
599
|
+
"default": { "steps": [{ "type": "tool", "tool": "notification_send", "args": {"message": "未知状态"} }] }
|
|
600
|
+
}
|
|
389
601
|
```
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# 工作流开发调试指南
|
|
2
|
+
|
|
3
|
+
## 快速测试工作流
|
|
4
|
+
|
|
5
|
+
### 1. 使用 execute_workflow 直接测试
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
execute_workflow({
|
|
9
|
+
workflow: {
|
|
10
|
+
name: "test-workflow",
|
|
11
|
+
description: "测试工作流",
|
|
12
|
+
steps: [
|
|
13
|
+
{
|
|
14
|
+
id: "step1",
|
|
15
|
+
type: "tool",
|
|
16
|
+
tool: "python-execute",
|
|
17
|
+
args: {
|
|
18
|
+
code: "print('Hello from Python!')"
|
|
19
|
+
},
|
|
20
|
+
outputVariable: "result"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### 2. JSON 格式注意事项
|
|
28
|
+
|
|
29
|
+
- ✅ 使用双引号包裹字符串
|
|
30
|
+
- ✅ 确保 JSON 语法正确
|
|
31
|
+
- ❌ 避免在 JSON 中使用未转义的特殊字符
|
|
32
|
+
- ❌ 不要在 code 中混用单引号和双引号
|
|
33
|
+
|
|
34
|
+
### 3. 常见错误
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
Unexpected identifier 'xxx'
|
|
38
|
+
```
|
|
39
|
+
- 原因:JSON 格式错误,可能是引号或逗号问题
|
|
40
|
+
- 解决:检查 JSON 语法
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Unexpected end of JSON input
|
|
44
|
+
```
|
|
45
|
+
- 原因:模板字符串 `${}` 在 JSON 中导致解析错误
|
|
46
|
+
- 解决:不要在 JSON 中使用模板变量,改用纯 Python 代码
|
|
47
|
+
|
|
48
|
+
## 工作流重载问题
|
|
49
|
+
|
|
50
|
+
### 问题
|
|
51
|
+
添加新工作流后,`reloadWorkflows` 不会重新加载同名工作流。
|
|
52
|
+
|
|
53
|
+
### 解决
|
|
54
|
+
```bash
|
|
55
|
+
# 方法1:使用不同的文件名
|
|
56
|
+
news-dashboard-v3.json # 不会被 v2 覆盖
|
|
57
|
+
|
|
58
|
+
# 方法2:重启插件
|
|
59
|
+
reload_plugins() # 重载所有插件
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Python 执行最佳实践
|
|
63
|
+
|
|
64
|
+
### 1. 错误处理
|
|
65
|
+
```python
|
|
66
|
+
try:
|
|
67
|
+
req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'})
|
|
68
|
+
with urllib.request.urlopen(req, timeout=10) as resp:
|
|
69
|
+
data = resp.read().decode('utf-8')
|
|
70
|
+
print('SUCCESS')
|
|
71
|
+
except Exception as e:
|
|
72
|
+
print(f'ERROR: {e}')
|
|
73
|
+
# fallback 逻辑
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 2. 输出格式
|
|
77
|
+
```python
|
|
78
|
+
# 简单输出
|
|
79
|
+
print('Status: OK')
|
|
80
|
+
print(f'Count: {len(items)}')
|
|
81
|
+
|
|
82
|
+
# JSON 输出
|
|
83
|
+
import json
|
|
84
|
+
print('---JSON_START---')
|
|
85
|
+
print(json.dumps(data, ensure_ascii=False))
|
|
86
|
+
print('---JSON_END---')
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 3. 超时设置
|
|
90
|
+
```python
|
|
91
|
+
with urllib.request.urlopen(req, timeout=30) as resp: # 30秒超时
|
|
92
|
+
...
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 工作流步骤类型
|
|
96
|
+
|
|
97
|
+
| 类型 | 用途 | 示例 |
|
|
98
|
+
|------|------|------|
|
|
99
|
+
| `tool` | 调用工具 | `python-execute`, `shell`, `get_time` |
|
|
100
|
+
| `script` | 执行 JavaScript | 数据处理、变量操作 |
|
|
101
|
+
| `condition` | 条件分支 | if/else 逻辑 |
|
|
102
|
+
| `loop` | 循环执行 | 遍历列表 |
|
|
103
|
+
| `delay` | 延时等待 | 等待指定时间 |
|
|
104
|
+
| `message` | 消息通知 | 发送通知 |
|
|
105
|
+
| `think` | LLM 思考 | 反思/分析 |
|
|
106
|
+
|
|
107
|
+
## 工具输出变量
|
|
108
|
+
|
|
109
|
+
### 正确用法
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"id": "step1",
|
|
113
|
+
"type": "tool",
|
|
114
|
+
"tool": "get_time",
|
|
115
|
+
"outputVariable": "current_time"
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### 访问输出
|
|
120
|
+
```javascript
|
|
121
|
+
// 在 script 步骤中
|
|
122
|
+
context.input.current_time
|
|
123
|
+
|
|
124
|
+
// 在下一个 tool 步骤中
|
|
125
|
+
${step1.current_time}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 调试技巧
|
|
129
|
+
|
|
130
|
+
### 1. 打印中间变量
|
|
131
|
+
```python
|
|
132
|
+
print('Debug - data:', data)
|
|
133
|
+
print('Debug - length:', len(data))
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 2. 保存到文件
|
|
137
|
+
```python
|
|
138
|
+
with open('debug.log', 'w') as f:
|
|
139
|
+
f.write(str(data))
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 3. 逐步执行
|
|
143
|
+
```javascript
|
|
144
|
+
{
|
|
145
|
+
"steps": [
|
|
146
|
+
{ "id": "step1", ... }, // 先测试 step1
|
|
147
|
+
{ "id": "step2", ... } // 确认 step1 成功后添加
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 性能优化
|
|
153
|
+
|
|
154
|
+
### 1. 合并步骤
|
|
155
|
+
```javascript
|
|
156
|
+
// ❌ 多个小步骤
|
|
157
|
+
{ "id": "step1", "tool": "python-execute", "code": "a = 1" }
|
|
158
|
+
{ "id": "step2", "tool": "python-execute", "code": "b = 2" }
|
|
159
|
+
|
|
160
|
+
// ✅ 单个大步骤
|
|
161
|
+
{ "id": "step1", "tool": "python-execute", "code": "a = 1; b = 2; print(a + b)" }
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 2. 减少变量传递
|
|
165
|
+
```javascript
|
|
166
|
+
// ❌ 多步骤传递
|
|
167
|
+
{ "outputVariable": "data1" }
|
|
168
|
+
{ "outputVariable": "data2" }
|
|
169
|
+
|
|
170
|
+
// ✅ 单步骤完成
|
|
171
|
+
{ "outputVariable": "final_result" }
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 3. 超时设置
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"args": {
|
|
178
|
+
"code": "...",
|
|
179
|
+
"timeout": 60000 // 60秒超时
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|