foliko 2.0.5 → 2.0.6
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 +4 -1
- package/.cli_default_systemPrompt.md +291 -0
- package/.editorconfig +56 -56
- package/.lintstagedrc +7 -7
- package/.prettierignore +29 -29
- package/.prettierrc +11 -11
- package/CLAUDE.md +3 -0
- package/Dockerfile +63 -63
- package/README.md +20 -3
- package/docs/architecture.md +34 -2
- package/docs/extensions.md +199 -0
- package/docs/migration.md +100 -0
- package/docs/public-api.md +280 -24
- package/docs/usage.md +122 -30
- package/install.ps1 +129 -129
- package/install.sh +121 -121
- package/package.json +1 -1
- package/plugins/core/audit/index.js +1 -1
- package/plugins/core/default/bootstrap.js +44 -19
- package/plugins/core/python-loader/index.js +43 -25
- package/plugins/core/skill-manager/PROMPT.md +6 -0
- package/plugins/core/skill-manager/index.js +402 -115
- package/plugins/core/sub-agent/PROMPT.md +10 -0
- package/plugins/core/sub-agent/index.js +36 -3
- package/plugins/core/think/index.js +1 -0
- package/plugins/core/workflow/index.js +82 -22
- package/plugins/executors/data-splitter/PROMPT.md +13 -0
- package/plugins/executors/data-splitter/index.js +5 -4
- package/plugins/executors/extension/extension-registry.js +145 -0
- package/plugins/executors/extension/index.js +405 -437
- package/plugins/executors/extension/prompt-builder.js +359 -0
- package/plugins/executors/extension/skill-helper.js +143 -0
- package/plugins/messaging/feishu/index.js +5 -3
- package/plugins/messaging/qq/index.js +6 -4
- package/plugins/messaging/telegram/index.js +6 -3
- package/plugins/messaging/weixin/index.js +5 -3
- package/plugins/tools/PROMPT.md +26 -0
- package/plugins/tools/index.js +6 -5
- package/skills/find-skills/SKILL.md +133 -133
- package/skills/foliko/AGENTS.md +196 -43
- package/skills/foliko/SKILL.md +157 -28
- package/skills/mcp/SKILL.md +77 -118
- package/skills/plugins/SKILL.md +89 -3
- package/skills/python/SKILL.md +57 -39
- package/skills/skill-guide/SKILL.md +42 -34
- package/skills/workflows/SKILL.md +224 -9
- package/skills/workflows/workflow-troubleshooting/SKILL.md +221 -281
- package/src/agent/chat.js +48 -27
- package/src/agent/main.js +34 -13
- package/src/agent/prompt-registry.js +56 -16
- package/src/agent/prompts/PROMPT.md +3 -0
- package/src/agent/sub.js +1 -1
- package/src/cli/ui/chat-ui-old.js +5 -2
- package/src/cli/ui/chat-ui.js +5 -2
- package/src/common/constants.js +12 -0
- package/src/common/error-capture.js +91 -0
- package/src/common/logger.js +2 -2
- package/src/context/compressor.js +6 -2
- package/src/executors/mcp-executor.js +105 -125
- package/src/framework/framework.js +23 -11
- package/src/index.js +4 -0
- package/src/plugin/base.js +908 -5
- package/src/plugin/manager.js +29 -8
- package/src/tool/schema.js +32 -9
- package/website/index.html +821 -0
package/skills/python/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: python-plugin-dev
|
|
3
|
-
description: Python 插件开发指南。当用户说"创建 Python 插件"、"用 Python 写插件"时立即调用此 skill。注意:只适合python 开发插件
|
|
3
|
+
description: Python 插件开发指南。当用户说"创建 Python 插件"、"用 Python 写插件"时立即调用此 skill。注意:只适合 python 开发插件
|
|
4
4
|
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -8,44 +8,40 @@ allowed-tools: Read, Write, Edit, Glob, Grep, Bash
|
|
|
8
8
|
|
|
9
9
|
## ext_call 调用方式
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
每个 Python 插件自动注册为独立扩展 `python:<插件名>`,通过 `ext_call` + `ext_skill` 统一调用:
|
|
12
12
|
|
|
13
13
|
```javascript
|
|
14
|
+
// 1. 先查询参数
|
|
15
|
+
ext_skill({ plugin: "python:<插件名>" })
|
|
16
|
+
|
|
17
|
+
// 2. 用结构化对象参数调用
|
|
14
18
|
ext_call({
|
|
15
|
-
plugin: "
|
|
16
|
-
tool: "
|
|
17
|
-
args: {
|
|
19
|
+
plugin: "python:<插件名>", // 格式:python:<插件名>
|
|
20
|
+
tool: "<工具名>", // 纯工具名(不带插件名前缀)
|
|
21
|
+
args: { /* Zod 结构化参数 */ }
|
|
18
22
|
});
|
|
19
23
|
```
|
|
20
24
|
|
|
21
|
-
**注意**:插件下的工具调用时,`tool` 参数格式为:
|
|
22
|
-
|
|
23
|
-
- 如果工具名是 `query_data`,插件名是 `test_nested_plugin`
|
|
24
|
-
- 调用时:`plugin: "python"`, `tool: "test_nested_plugin_query_data"`
|
|
25
|
-
- 即:自动将 `插件名_工具名` 合并为 `tool` 参数
|
|
26
|
-
|
|
27
25
|
**示例**:
|
|
28
26
|
|
|
29
27
|
```javascript
|
|
30
|
-
// 插件名:
|
|
28
|
+
// 插件名: my-plugin, 工具名: hello
|
|
31
29
|
ext_call({
|
|
32
|
-
plugin: 'python',
|
|
33
|
-
tool: '
|
|
30
|
+
plugin: 'python:my-plugin',
|
|
31
|
+
tool: 'hello',
|
|
34
32
|
args: { name: 'Foliko' },
|
|
35
33
|
});
|
|
36
34
|
|
|
37
35
|
// 插件名: test_nested_plugin, 工具名: query_data
|
|
38
36
|
ext_call({
|
|
39
|
-
plugin: 'python',
|
|
40
|
-
tool: '
|
|
37
|
+
plugin: 'python:test_nested_plugin',
|
|
38
|
+
tool: 'query_data',
|
|
41
39
|
args: { filter: { name: 'Alice' } },
|
|
42
40
|
});
|
|
43
41
|
```
|
|
44
42
|
|
|
45
43
|
## 概述
|
|
46
44
|
|
|
47
|
-
## 概述
|
|
48
|
-
|
|
49
45
|
Python 插件允许用 Python 语言开发工具,插件代码运行在 Python 环境中,可以调用所有 Python 库。
|
|
50
46
|
|
|
51
47
|
## 插件存放位置
|
|
@@ -105,11 +101,12 @@ def calc(params):
|
|
|
105
101
|
return {"success": True, "result": result}
|
|
106
102
|
```
|
|
107
103
|
|
|
108
|
-
**重要**:`
|
|
104
|
+
**重要**:`TOOLS` 字段定义了插件提供的所有工具。框架会自动:
|
|
109
105
|
|
|
110
|
-
1.
|
|
111
|
-
2.
|
|
112
|
-
3.
|
|
106
|
+
1. 把插件注册为 `python:<插件名>` 扩展
|
|
107
|
+
2. 每个工具作为该扩展下的 tool(tool 名为原始名,不带前缀)
|
|
108
|
+
3. 附加到系统提示词【Extensions 扩展工具】部分
|
|
109
|
+
4. 可通过 `ext_call({ plugin: "python:<插件名>", tool: "<工具名>", args: {...} })` 调用
|
|
113
110
|
|
|
114
111
|
## 工具函数规范
|
|
115
112
|
|
|
@@ -135,13 +132,13 @@ def calc(params):
|
|
|
135
132
|
|
|
136
133
|
## 使用方式
|
|
137
134
|
|
|
138
|
-
通过 `ext_call`
|
|
135
|
+
通过 `ext_call` 调用(`python:<插件名>` 是固定格式):
|
|
139
136
|
|
|
140
137
|
```javascript
|
|
141
138
|
ext_call({
|
|
142
|
-
plugin: 'python',
|
|
143
|
-
tool: '
|
|
144
|
-
args: { name: 'Foliko' },
|
|
139
|
+
plugin: 'python:my-plugin', // python:<插件名>
|
|
140
|
+
tool: 'hello', // 纯工具名(不带插件名前缀)
|
|
141
|
+
args: { name: 'Foliko' }, // 工具参数
|
|
145
142
|
});
|
|
146
143
|
```
|
|
147
144
|
|
|
@@ -149,7 +146,7 @@ ext_call({
|
|
|
149
146
|
|
|
150
147
|
## 嵌套参数支持
|
|
151
148
|
|
|
152
|
-
`ext_call` 的 `args`
|
|
149
|
+
`ext_call` 的 `args` 参数支持多层嵌套结构,可以传递复杂的数据对象。
|
|
153
150
|
|
|
154
151
|
### 支持的参数类型
|
|
155
152
|
|
|
@@ -167,15 +164,15 @@ ext_call({
|
|
|
167
164
|
```javascript
|
|
168
165
|
// 简单参数
|
|
169
166
|
ext_call({
|
|
170
|
-
plugin: 'python',
|
|
171
|
-
tool: '
|
|
167
|
+
plugin: 'python:my-plugin',
|
|
168
|
+
tool: 'query',
|
|
172
169
|
args: { table: 'users' },
|
|
173
170
|
});
|
|
174
171
|
|
|
175
172
|
// 嵌套 filter
|
|
176
173
|
ext_call({
|
|
177
|
-
plugin: 'python',
|
|
178
|
-
tool: '
|
|
174
|
+
plugin: 'python:my-plugin',
|
|
175
|
+
tool: 'query_data',
|
|
179
176
|
args: {
|
|
180
177
|
filter: {
|
|
181
178
|
name: 'Alice',
|
|
@@ -191,8 +188,8 @@ ext_call({
|
|
|
191
188
|
|
|
192
189
|
// 带 options 的复杂查询
|
|
193
190
|
ext_call({
|
|
194
|
-
plugin: 'python',
|
|
195
|
-
tool: '
|
|
191
|
+
plugin: 'python:my-plugin',
|
|
192
|
+
tool: 'query_data',
|
|
196
193
|
args: {
|
|
197
194
|
filter: { status: 'active' },
|
|
198
195
|
options: {
|
|
@@ -226,10 +223,9 @@ def query_data(params):
|
|
|
226
223
|
|
|
227
224
|
### 注意事项
|
|
228
225
|
|
|
229
|
-
1.
|
|
230
|
-
2.
|
|
231
|
-
3.
|
|
232
|
-
4. **数组对象**:支持数组和嵌套对象的任意组合
|
|
226
|
+
1. **嵌套深度**:支持任意深度的嵌套对象
|
|
227
|
+
2. **空值处理**:使用 `.get()` 方法并提供默认值,避免 KeyError
|
|
228
|
+
3. **数组对象**:支持数组和嵌套对象的任意组合
|
|
233
229
|
|
|
234
230
|
## 示例:天气查询插件
|
|
235
231
|
|
|
@@ -274,6 +270,16 @@ def get_weather(params):
|
|
|
274
270
|
return {"success": False, "error": str(e)}
|
|
275
271
|
```
|
|
276
272
|
|
|
273
|
+
调用方式:
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
ext_call({
|
|
277
|
+
plugin: 'python:weather', // python:<插件名>
|
|
278
|
+
tool: 'get_weather', // 纯工具名
|
|
279
|
+
args: { city: '上海' },
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
277
283
|
## 示例:文件处理插件
|
|
278
284
|
|
|
279
285
|
```python
|
|
@@ -330,6 +336,16 @@ def write_file(params):
|
|
|
330
336
|
return {"success": False, "error": str(e)}
|
|
331
337
|
```
|
|
332
338
|
|
|
339
|
+
调用方式:
|
|
340
|
+
|
|
341
|
+
```javascript
|
|
342
|
+
ext_call({
|
|
343
|
+
plugin: 'python:file_processor',
|
|
344
|
+
tool: 'read_file',
|
|
345
|
+
args: { path: '/tmp/test.txt' },
|
|
346
|
+
});
|
|
347
|
+
```
|
|
348
|
+
|
|
333
349
|
## 注意事项
|
|
334
350
|
|
|
335
351
|
1. **文件格式** - 必须是单个 `.py` 文件
|
|
@@ -338,12 +354,14 @@ def write_file(params):
|
|
|
338
354
|
4. **工具函数名** - 必须与 TOOLS 中定义的 name 一致
|
|
339
355
|
5. **异常处理** - 所有可能出错的地方都要 try-except
|
|
340
356
|
6. **编码** - 文件使用 UTF-8 编码
|
|
357
|
+
7. **命名空间** - 扩展名格式为 `python:<PLUGIN.name>`,工具名是 `TOOLS[].name`(不带前缀)
|
|
341
358
|
|
|
342
359
|
## 开发流程
|
|
343
360
|
|
|
344
361
|
1. **编写插件代码** - 在 `.foliko/plugins/` 下创建 `.py` 文件
|
|
345
|
-
2. **自动加载** -
|
|
346
|
-
3.
|
|
362
|
+
2. **自动加载** - 框架启动时自动注册到 `python:<插件名>` 扩展
|
|
363
|
+
3. **测试** - 在聊天中用 `/<插件名>:<工具名>` 测试,或让 LLM 用 `ext_call` 调用
|
|
364
|
+
4. **调试** - 查看返回的 `success` 和 `error` 信息
|
|
347
365
|
|
|
348
366
|
## 常用 Python 库
|
|
349
367
|
|
|
@@ -176,13 +176,17 @@ module.exports = [
|
|
|
176
176
|
|
|
177
177
|
### ext_call 调用格式
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
每个 skill 自动注册为 `skill:<技能名>` 扩展,通过 `ext_call` + `ext_skill` 统一调用。
|
|
180
180
|
|
|
181
181
|
```javascript
|
|
182
|
+
// 1. 先查询命令参数
|
|
183
|
+
ext_skill({ plugin: "skill:<技能名>" })
|
|
184
|
+
|
|
185
|
+
// 2. 用命令行字符串调用
|
|
182
186
|
ext_call({
|
|
183
|
-
plugin: "skill",
|
|
184
|
-
tool: "<
|
|
185
|
-
args: { command: "
|
|
187
|
+
plugin: "skill:<技能名>",
|
|
188
|
+
tool: "<commandname>",
|
|
189
|
+
args: { command: "-n Alice -l en" }
|
|
186
190
|
});
|
|
187
191
|
```
|
|
188
192
|
|
|
@@ -190,31 +194,31 @@ ext_call({
|
|
|
190
194
|
|
|
191
195
|
| 参数 | 类型 | 说明 |
|
|
192
196
|
|------|------|------|
|
|
193
|
-
| `plugin` | string | 固定为 `"skill"` |
|
|
194
|
-
| `tool` | string |
|
|
195
|
-
| `args
|
|
197
|
+
| `plugin` | string | 固定为 `"skill:<技能名>"`,如 `skill:test-skill` |
|
|
198
|
+
| `tool` | string | 命令名(不带技能前缀),如 `greet` |
|
|
199
|
+
| `args` | object | 固定为 `{ command: "命令行字符串" }` |
|
|
196
200
|
|
|
197
201
|
**示例:**
|
|
198
202
|
|
|
199
203
|
```javascript
|
|
200
|
-
// 调用 test-skill 的 greet
|
|
204
|
+
// 调用 test-skill 的 greet 命令
|
|
201
205
|
ext_call({
|
|
202
|
-
plugin: "skill",
|
|
203
|
-
tool: "
|
|
204
|
-
args: { command: "" }
|
|
206
|
+
plugin: "skill:test-skill",
|
|
207
|
+
tool: "greet",
|
|
208
|
+
args: { command: "-n Alice" }
|
|
205
209
|
});
|
|
206
210
|
|
|
207
|
-
// 调用 test-skill 的 greet
|
|
211
|
+
// 调用 test-skill 的 greet 命令,带可选 lang
|
|
208
212
|
ext_call({
|
|
209
|
-
plugin: "skill",
|
|
210
|
-
tool: "
|
|
211
|
-
args: { command: "Alice" }
|
|
213
|
+
plugin: "skill:test-skill",
|
|
214
|
+
tool: "greet",
|
|
215
|
+
args: { command: "-n Alice -l en" }
|
|
212
216
|
});
|
|
213
217
|
|
|
214
218
|
// 调用 test-skill 的 echo 命令
|
|
215
219
|
ext_call({
|
|
216
|
-
plugin: "skill",
|
|
217
|
-
tool: "
|
|
220
|
+
plugin: "skill:test-skill",
|
|
221
|
+
tool: "echo",
|
|
218
222
|
args: { command: "Hello World" }
|
|
219
223
|
});
|
|
220
224
|
```
|
|
@@ -383,13 +387,17 @@ module.exports = [
|
|
|
383
387
|
|
|
384
388
|
### ext_call 调用格式
|
|
385
389
|
|
|
386
|
-
|
|
390
|
+
每个 skill 自动注册为 `skill:<技能名>` 扩展,通过 `ext_call` + `ext_skill` 统一调用。
|
|
387
391
|
|
|
388
392
|
```javascript
|
|
393
|
+
// 1. 先查询命令参数
|
|
394
|
+
ext_skill({ plugin: "skill:<技能名>" })
|
|
395
|
+
|
|
396
|
+
// 2. 用命令行字符串调用
|
|
389
397
|
ext_call({
|
|
390
|
-
plugin: "skill",
|
|
391
|
-
tool: "<
|
|
392
|
-
args: { command: "
|
|
398
|
+
plugin: "skill:<技能名>",
|
|
399
|
+
tool: "<commandname>",
|
|
400
|
+
args: { command: "-n Alice -l en" }
|
|
393
401
|
});
|
|
394
402
|
```
|
|
395
403
|
|
|
@@ -397,31 +405,31 @@ ext_call({
|
|
|
397
405
|
|
|
398
406
|
| 参数 | 类型 | 说明 |
|
|
399
407
|
|------|------|------|
|
|
400
|
-
| `plugin` | string | 固定为 `"skill"` |
|
|
401
|
-
| `tool` | string |
|
|
402
|
-
| `args
|
|
408
|
+
| `plugin` | string | 固定为 `"skill:<技能名>"`,如 `skill:test-skill` |
|
|
409
|
+
| `tool` | string | 命令名(不带技能前缀),如 `greet` |
|
|
410
|
+
| `args` | object | 固定为 `{ command: "命令行字符串" }` |
|
|
403
411
|
|
|
404
412
|
**示例:**
|
|
405
413
|
|
|
406
414
|
```javascript
|
|
407
|
-
// 调用 test-skill 的 greet
|
|
415
|
+
// 调用 test-skill 的 greet 命令
|
|
408
416
|
ext_call({
|
|
409
|
-
plugin: "skill",
|
|
410
|
-
tool: "
|
|
411
|
-
args: { command: "" }
|
|
417
|
+
plugin: "skill:test-skill",
|
|
418
|
+
tool: "greet",
|
|
419
|
+
args: { command: "-n Alice" }
|
|
412
420
|
});
|
|
413
421
|
|
|
414
|
-
// 调用 test-skill 的 greet
|
|
422
|
+
// 调用 test-skill 的 greet 命令,带可选 lang
|
|
415
423
|
ext_call({
|
|
416
|
-
plugin: "skill",
|
|
417
|
-
tool: "
|
|
418
|
-
args: { command: "Alice" }
|
|
424
|
+
plugin: "skill:test-skill",
|
|
425
|
+
tool: "greet",
|
|
426
|
+
args: { command: "-n Alice -l en" }
|
|
419
427
|
});
|
|
420
428
|
|
|
421
429
|
// 调用 test-skill 的 echo 命令
|
|
422
430
|
ext_call({
|
|
423
|
-
plugin: "skill",
|
|
424
|
-
tool: "
|
|
431
|
+
plugin: "skill:test-skill",
|
|
432
|
+
tool: "echo",
|
|
425
433
|
args: { command: "Hello World" }
|
|
426
434
|
});
|
|
427
435
|
```
|
|
@@ -144,6 +144,18 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
144
144
|
| `args` | object | 否 | 工具参数 |
|
|
145
145
|
| `outputVariable` | string | 否 | 结果保存到的变量名 |
|
|
146
146
|
|
|
147
|
+
**重要:`args` vs `params` 字段**:
|
|
148
|
+
|
|
149
|
+
工作流引擎使用 `args` 字段传递工具参数,不是 `params`:
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
// ✅ 正确
|
|
153
|
+
{ "type": "tool", "tool": "fetch", "args": { "url": "https://..." } }
|
|
154
|
+
|
|
155
|
+
// ❌ 错误
|
|
156
|
+
{ "type": "tool", "tool": "fetch", "params": { "url": "https://..." } }
|
|
157
|
+
```
|
|
158
|
+
|
|
147
159
|
**args 中支持变量引用**:
|
|
148
160
|
|
|
149
161
|
使用 `{{variableName}}` 语法引用 context.variables 中的变量:
|
|
@@ -199,9 +211,61 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
199
211
|
|
|
200
212
|
**自动 JSON 解析**:如果字段值是 JSON 字符串,会自动解析为对象后再提取嵌套字段。
|
|
201
213
|
|
|
202
|
-
### 3.
|
|
214
|
+
### 3. 调用扩展工具(ext_call)
|
|
215
|
+
|
|
216
|
+
使用 `ext_call` 工具调用插件扩展的命令(如 skill 插件的命令):
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"type": "tool",
|
|
221
|
+
"name": "调用视频创作命令",
|
|
222
|
+
"tool": "ext_call",
|
|
223
|
+
"args": {
|
|
224
|
+
"plugin": "skill:creator",
|
|
225
|
+
"tool": "creator",
|
|
226
|
+
"args": {
|
|
227
|
+
"aspectRatio": "16:9",
|
|
228
|
+
"title": true,
|
|
229
|
+
"voice": "female-shaonv-jingpin"
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"outputVariable": "videoId"
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**参数说明**:
|
|
237
|
+
|
|
238
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
239
|
+
| ------- | ------ | ---- | ----------------------- |
|
|
240
|
+
| `plugin` | string | 是 | 扩展名(格式:`skill:<技能名>` / `mcp:<server>` / `python:<插件名>`) |
|
|
241
|
+
| `tool` | string | 是 | 工具名(不带扩展名前缀) |
|
|
242
|
+
| `args` | object | 是 | Zod 结构化参数(无需拼装命令字符串) |
|
|
243
|
+
|
|
244
|
+
**调用 skill 命令示例**:
|
|
245
|
+
|
|
246
|
+
```json
|
|
247
|
+
{
|
|
248
|
+
"type": "tool",
|
|
249
|
+
"name": "创建项目",
|
|
250
|
+
"tool": "ext_call",
|
|
251
|
+
"args": {
|
|
252
|
+
"plugin": "skill:creator",
|
|
253
|
+
"tool": "creator",
|
|
254
|
+
"args": {
|
|
255
|
+
"aspectRatio": "16:9",
|
|
256
|
+
"title": true,
|
|
257
|
+
"voice": "female-shaonv-jingpin",
|
|
258
|
+
"audio": true
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 4. loop - 循环步骤
|
|
265
|
+
|
|
266
|
+
支持两种循环模式:
|
|
203
267
|
|
|
204
|
-
|
|
268
|
+
**模式一:固定次数循环**
|
|
205
269
|
|
|
206
270
|
```json
|
|
207
271
|
{
|
|
@@ -216,7 +280,63 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
216
280
|
- `maxIterations`: 最大迭代次数
|
|
217
281
|
- `loopVariable`: 循环计数器变量名(从 0 开始)
|
|
218
282
|
|
|
219
|
-
|
|
283
|
+
**模式二:数组迭代循环(over)**
|
|
284
|
+
|
|
285
|
+
```json
|
|
286
|
+
{
|
|
287
|
+
"type": "loop",
|
|
288
|
+
"name": "处理幻灯片",
|
|
289
|
+
"over": "input.slides",
|
|
290
|
+
"as": "slide",
|
|
291
|
+
"index": "slideIndex",
|
|
292
|
+
"maxIterations": 10,
|
|
293
|
+
"steps": [
|
|
294
|
+
{
|
|
295
|
+
"type": "tool",
|
|
296
|
+
"tool": "ext_call",
|
|
297
|
+
"args": {
|
|
298
|
+
"plugin": "skill:creator",
|
|
299
|
+
"tool": "addSlide",
|
|
300
|
+
"args": {
|
|
301
|
+
"videoId": "{{videoId}}",
|
|
302
|
+
"slideIndex": "{{slideIndex}}",
|
|
303
|
+
"bgColor": "{{slide.bgColor}}"
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
]
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
- `over`: 要迭代的数组路径(如 `input.slides`、`slide.cards`)
|
|
312
|
+
- `as`: 每个元素的变量名(如 `slide`)
|
|
313
|
+
- `index`: 索引变量名(如 `slideIndex`,从 0 开始)
|
|
314
|
+
- `maxIterations`: 最大迭代次数(可选,默认为数组长度)
|
|
315
|
+
|
|
316
|
+
**嵌套循环示例**:
|
|
317
|
+
|
|
318
|
+
```json
|
|
319
|
+
{
|
|
320
|
+
"type": "loop",
|
|
321
|
+
"over": "input.slides",
|
|
322
|
+
"as": "slide",
|
|
323
|
+
"index": "slideIndex",
|
|
324
|
+
"steps": [
|
|
325
|
+
{
|
|
326
|
+
"name": "处理数据卡片",
|
|
327
|
+
"type": "loop",
|
|
328
|
+
"over": "slide.cards",
|
|
329
|
+
"as": "card",
|
|
330
|
+
"index": "cardIndex",
|
|
331
|
+
"steps": [
|
|
332
|
+
{ "type": "tool", "tool": "addCard", "args": { ... } }
|
|
333
|
+
]
|
|
334
|
+
}
|
|
335
|
+
]
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### 5. condition - 条件分支
|
|
220
340
|
|
|
221
341
|
根据条件选择执行分支:
|
|
222
342
|
|
|
@@ -239,7 +359,7 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
239
359
|
}
|
|
240
360
|
```
|
|
241
361
|
|
|
242
|
-
###
|
|
362
|
+
### 6. switch - 开关分支
|
|
243
363
|
|
|
244
364
|
根据值匹配执行对应分支(类似编程语言的 switch-case):
|
|
245
365
|
|
|
@@ -260,7 +380,7 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
260
380
|
- `branches`: 分支数组,匹配第一个 `case` 等于 `value` 的分支
|
|
261
381
|
- `default`: 默认分支(可选)
|
|
262
382
|
|
|
263
|
-
###
|
|
383
|
+
### 7. try - 异常捕获
|
|
264
384
|
|
|
265
385
|
尝试执行,失败时执行 catch 分支:
|
|
266
386
|
|
|
@@ -284,7 +404,7 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
284
404
|
- `try`: 尝试执行的步骤
|
|
285
405
|
- `catch`: 捕获异常后执行的步骤
|
|
286
406
|
|
|
287
|
-
###
|
|
407
|
+
### 8. parallel - 并行执行
|
|
288
408
|
|
|
289
409
|
多个步骤同时并行执行:
|
|
290
410
|
|
|
@@ -302,7 +422,7 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
302
422
|
|
|
303
423
|
返回数组形式的执行结果。
|
|
304
424
|
|
|
305
|
-
###
|
|
425
|
+
### 9. workflow - 嵌套工作流
|
|
306
426
|
|
|
307
427
|
在一个工作流中调用另一个工作流:
|
|
308
428
|
|
|
@@ -322,7 +442,7 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
322
442
|
|
|
323
443
|
子工作流的输出会合并到父工作流的上下文变量中。
|
|
324
444
|
|
|
325
|
-
###
|
|
445
|
+
### 10. delay - 延时步骤
|
|
326
446
|
|
|
327
447
|
等待指定毫秒数:
|
|
328
448
|
|
|
@@ -334,7 +454,7 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
334
454
|
}
|
|
335
455
|
```
|
|
336
456
|
|
|
337
|
-
###
|
|
457
|
+
### 11. sequential - 顺序步骤
|
|
338
458
|
|
|
339
459
|
将多个步骤组合为顺序执行(可嵌套使用):
|
|
340
460
|
|
|
@@ -644,3 +764,98 @@ allowed-tools: execute_workflow,workflow_reload
|
|
|
644
764
|
"default": { "steps": [{ "type": "tool", "tool": "notification_send", "args": {"message": "未知状态"} }] }
|
|
645
765
|
}
|
|
646
766
|
```
|
|
767
|
+
|
|
768
|
+
### 示例:ext_call + loop 调用 skill 命令处理列表
|
|
769
|
+
|
|
770
|
+
**调用 skill 插件命令的正确方式**:
|
|
771
|
+
|
|
772
|
+
```json
|
|
773
|
+
{
|
|
774
|
+
"name": "process-videos",
|
|
775
|
+
"description": "使用 ext_call 调用 skill 命令处理多个视频",
|
|
776
|
+
"input": {
|
|
777
|
+
"videos": ["video1.mp4", "video2.mp4", "video3.mp4"]
|
|
778
|
+
},
|
|
779
|
+
"steps": [
|
|
780
|
+
{
|
|
781
|
+
"type": "script",
|
|
782
|
+
"name": "初始化",
|
|
783
|
+
"outputVariable": "videoList",
|
|
784
|
+
"script": "return context.input.videos || [];"
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
"type": "loop",
|
|
788
|
+
"name": "处理每个视频",
|
|
789
|
+
"maxIterations": 10,
|
|
790
|
+
"loopVariable": "i",
|
|
791
|
+
"steps": [
|
|
792
|
+
{
|
|
793
|
+
"type": "condition",
|
|
794
|
+
"name": "检查是否还有视频",
|
|
795
|
+
"branches": [
|
|
796
|
+
{
|
|
797
|
+
"name": "有视频",
|
|
798
|
+
"condition": "context.variables.i < context.variables.videoList.length",
|
|
799
|
+
"steps": [
|
|
800
|
+
{
|
|
801
|
+
"type": "script",
|
|
802
|
+
"name": "获取当前视频",
|
|
803
|
+
"outputVariable": "currentVideo",
|
|
804
|
+
"script": "return context.variables.videoList[context.variables.i];"
|
|
805
|
+
},
|
|
806
|
+
{
|
|
807
|
+
"type": "tool",
|
|
808
|
+
"name": "处理视频",
|
|
809
|
+
"tool": "ext_call",
|
|
810
|
+
"args": {
|
|
811
|
+
"plugin": "skill:creator",
|
|
812
|
+
"tool": "addClip",
|
|
813
|
+
"args": {
|
|
814
|
+
"videoId": "{{videoId}}",
|
|
815
|
+
"video": "{{currentVideo}}"
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
]
|
|
820
|
+
}
|
|
821
|
+
]
|
|
822
|
+
}
|
|
823
|
+
]
|
|
824
|
+
}
|
|
825
|
+
]
|
|
826
|
+
}
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
**关键点**:
|
|
830
|
+
|
|
831
|
+
1. **使用 `type: "tool"` + `tool: "ext_call"`** 调用扩展命令
|
|
832
|
+
2. **嵌套的 `args` 对象** 包含 `plugin`、`tool`、`args`
|
|
833
|
+
3. **loop 使用 `maxIterations`** 控制最大循环次数
|
|
834
|
+
4. **条件判断使用 `condition`** 字段
|
|
835
|
+
|
|
836
|
+
### 常见错误
|
|
837
|
+
|
|
838
|
+
```json
|
|
839
|
+
// ❌ 错误 - 使用 action: "ext_call"(不支持的类型)
|
|
840
|
+
{
|
|
841
|
+
"name": "createProject",
|
|
842
|
+
"action": "ext_call",
|
|
843
|
+
"params": {
|
|
844
|
+
"plugin": "skill:creator",
|
|
845
|
+
"tool": "creator",
|
|
846
|
+
"args": { "aspectRatio": "16:9" }
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// ✅ 正确 - 使用 type: "tool" + tool: "ext_call"
|
|
851
|
+
{
|
|
852
|
+
"name": "createProject",
|
|
853
|
+
"type": "tool",
|
|
854
|
+
"tool": "ext_call",
|
|
855
|
+
"args": {
|
|
856
|
+
"plugin": "skill:creator",
|
|
857
|
+
"tool": "creator",
|
|
858
|
+
"args": { "aspectRatio": "16:9" }
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
```
|