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.
@@ -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. delay - 延时步骤
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
- ### 6. sequential - 顺序步骤
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
+ ```