foliko 1.1.2 → 1.1.4

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.
Files changed (205) hide show
  1. package/.agent/agents/code-assistant.json +14 -0
  2. package/.agent/agents/email-assistant.json +14 -0
  3. package/.agent/agents/file-assistant.json +15 -0
  4. package/.agent/agents/system-assistant.json +15 -0
  5. package/.agent/agents/web-assistant.json +12 -0
  6. package/.agent/data/ambient/goals.json +50 -0
  7. package/.agent/data/ambient/memories.json +7 -0
  8. package/.agent/data/default.json +3 -412
  9. package/.agent/data/plugins-state.json +174 -173
  10. package/.agent/data/scheduler/tasks.json +1 -0
  11. package/.agent/memory/core.md +1 -0
  12. package/.agent/memory/project/mnn93ogy-ypjn27.md +9 -0
  13. package/.agent/memory/project/mnn98fqy-5nhc1u.md +25 -0
  14. package/.agent/memory/reference/mnq3oenw-46haj6.md +63 -0
  15. package/.agent/memory/reference/mnq5qxm2-mjoooh.md +116 -0
  16. package/.agent/memory/user/mnm67t9m-x8rekk.md +9 -0
  17. package/.agent/memory/user/mnn5mmqh-w6aktx.md +11 -0
  18. package/.agent/memory/user/mnnbfhhn-dk1bd1.md +22 -0
  19. package/.agent/package.json +8 -0
  20. package/.agent/plugins/__pycache__/file_writer.cpython-312.pyc +0 -0
  21. package/.agent/plugins/daytona/README.md +89 -0
  22. package/.agent/plugins/daytona/index.js +377 -0
  23. package/.agent/plugins/daytona/package.json +12 -0
  24. package/.agent/plugins/marknative/README.md +134 -0
  25. package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
  26. package/.agent/plugins/marknative/index.js +256 -0
  27. package/.agent/plugins/marknative/package.json +12 -0
  28. package/.agent/plugins/marknative/update-readme.js +134 -0
  29. package/.agent/plugins/poster-plugin/emojis/rocket.png +1 -0
  30. package/.agent/plugins/poster-plugin/fonts/SegoeUI Emoji.ttf +0 -0
  31. package/.agent/plugins/poster-plugin/src/elements/text.js +3 -1
  32. package/.agent/plugins/poster-plugin/src/fonts.js +10 -0
  33. package/.agent/plugins/poster-plugin/yarn.lock +1007 -0
  34. package/.agent/plugins/system-info/index.js +387 -0
  35. package/.agent/plugins/system-info/package.json +4 -0
  36. package/.agent/plugins/system-info/test.js +40 -0
  37. package/.agent/plugins.json +11 -5
  38. package/.agent/python-scripts/test_sample.py +24 -0
  39. package/.agent/sessions/cli_default.json +1869 -691
  40. package/.agent/skills/agent-browser/SKILL.md +311 -0
  41. package/.agent/skills/agent-browser/TEST_PLAN.md +200 -0
  42. package/.agent/skills/sysinfo/SKILL.md +38 -0
  43. package/.agent/skills/sysinfo/system-info.sh +130 -0
  44. package/.agent/skills/workflow/SKILL.md +324 -0
  45. package/.agent/weixin.json +6 -0
  46. package/.agent/workflows/email-digest.json +50 -0
  47. package/.agent/workflows/file-backup.json +21 -0
  48. package/.agent/workflows/get-ip-notify.json +32 -0
  49. package/.agent/workflows/news-aggregator.json +93 -0
  50. package/.agent/workflows/news-dashboard-v2.json +94 -0
  51. package/.agent/workflows/notification-batch.json +32 -0
  52. package/.claude/settings.local.json +1 -20
  53. package/.env.example +56 -56
  54. package/README.md +441 -441
  55. package/cli/src/commands/chat.js +22 -13
  56. package/cli/src/ui/chat-ui.js +50 -37
  57. package/output/emoji-segoe-test-v2.png +0 -0
  58. package/output/emoji-segoe-test.png +0 -0
  59. package/output/emoji-test.png +0 -0
  60. package/output/emoji-windows-test.png +0 -0
  61. package/output/foliko-emoji-poster.png +0 -0
  62. package/output/foliko-muji-poster-final.png +0 -0
  63. package/output/foliko-muji-poster-v2.png +0 -0
  64. package/output/foliko-muji-poster.png +0 -0
  65. package/output/foliko-share.png +0 -0
  66. package/output/progress-circle-test.png +0 -0
  67. package/output/vb-agent-poster.png +0 -0
  68. package/package.json +1 -2
  69. package/plugins/default-plugins.js +4 -3
  70. package/plugins/extension-executor-plugin.js +12 -91
  71. package/plugins/file-system-plugin.js +19 -4
  72. package/plugins/memory-plugin.js +33 -4
  73. package/plugins/subagent-plugin.js +14 -37
  74. package/plugins/weixin-plugin.js +40 -168
  75. package/skills/find-skills/AGENTS.md +162 -162
  76. package/skills/find-skills/SKILL.md +133 -133
  77. package/skills/poster-guide/SKILL.md +669 -1426
  78. package/src/core/agent-chat.js +439 -269
  79. package/src/core/agent.js +3 -6
  80. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +0 -26
  81. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +0 -97
  82. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +0 -101
  83. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +0 -31
  84. package/.agent/.shared/ui-ux-pro-max/data/products.csv +0 -97
  85. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +0 -24
  86. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +0 -45
  87. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
  88. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
  89. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -53
  90. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
  91. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
  92. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
  93. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
  94. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +0 -54
  95. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +0 -61
  96. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
  97. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
  98. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +0 -50
  99. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +0 -59
  100. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +0 -58
  101. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +0 -101
  102. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
  103. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +0 -31
  104. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  105. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  106. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +0 -258
  107. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +0 -1067
  108. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +0 -106
  109. package/.agent/ARCHITECTURE.md +0 -288
  110. package/.agent/agents/ambient-agent.md +0 -57
  111. package/.agent/agents/debugger.md +0 -55
  112. package/.agent/agents/email-assistant.md +0 -49
  113. package/.agent/agents/file-manager.md +0 -42
  114. package/.agent/agents/python-developer.md +0 -60
  115. package/.agent/agents/scheduler.md +0 -59
  116. package/.agent/agents/web-developer.md +0 -45
  117. package/.agent/data/puppeteer-sessions/undefined.json +0 -6
  118. package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
  119. package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
  120. package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
  121. package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
  122. package/.agent/mcp_config_updated.json +0 -12
  123. package/.agent/plugins/poster-plugin/fonts/NotoColorEmoji-Regular.ttf +0 -0
  124. package/.agent/plugins/puppeteer-plugin/README.md +0 -147
  125. package/.agent/plugins/puppeteer-plugin/index.js +0 -1418
  126. package/.agent/plugins/puppeteer-plugin/package.json +0 -9
  127. package/.agent/rules/GEMINI.md +0 -273
  128. package/.agent/rules/allow-rule.md +0 -77
  129. package/.agent/rules/log-rule.md +0 -83
  130. package/.agent/rules/security-rule.md +0 -93
  131. package/.agent/scripts/auto_preview.py +0 -148
  132. package/.agent/scripts/checklist.py +0 -217
  133. package/.agent/scripts/session_manager.py +0 -120
  134. package/.agent/scripts/verify_all.py +0 -327
  135. package/.agent/sessions/weixin_o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat.json +0 -11097
  136. package/.agent/skills/api-patterns/SKILL.md +0 -81
  137. package/.agent/skills/api-patterns/api-style.md +0 -42
  138. package/.agent/skills/api-patterns/auth.md +0 -24
  139. package/.agent/skills/api-patterns/documentation.md +0 -26
  140. package/.agent/skills/api-patterns/graphql.md +0 -41
  141. package/.agent/skills/api-patterns/rate-limiting.md +0 -31
  142. package/.agent/skills/api-patterns/response.md +0 -37
  143. package/.agent/skills/api-patterns/rest.md +0 -40
  144. package/.agent/skills/api-patterns/scripts/api_validator.py +0 -211
  145. package/.agent/skills/api-patterns/security-testing.md +0 -122
  146. package/.agent/skills/api-patterns/trpc.md +0 -41
  147. package/.agent/skills/api-patterns/versioning.md +0 -22
  148. package/.agent/skills/app-builder/SKILL.md +0 -75
  149. package/.agent/skills/app-builder/agent-coordination.md +0 -71
  150. package/.agent/skills/app-builder/feature-building.md +0 -53
  151. package/.agent/skills/app-builder/project-detection.md +0 -34
  152. package/.agent/skills/app-builder/scaffolding.md +0 -118
  153. package/.agent/skills/app-builder/tech-stack.md +0 -40
  154. package/.agent/skills/app-builder/templates/SKILL.md +0 -39
  155. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +0 -76
  156. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +0 -92
  157. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +0 -88
  158. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +0 -88
  159. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +0 -83
  160. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +0 -90
  161. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +0 -90
  162. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +0 -122
  163. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +0 -122
  164. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +0 -169
  165. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +0 -134
  166. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +0 -83
  167. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +0 -119
  168. package/.agent/skills/architecture/SKILL.md +0 -55
  169. package/.agent/skills/architecture/context-discovery.md +0 -43
  170. package/.agent/skills/architecture/examples.md +0 -94
  171. package/.agent/skills/architecture/pattern-selection.md +0 -68
  172. package/.agent/skills/architecture/patterns-reference.md +0 -50
  173. package/.agent/skills/architecture/trade-off-analysis.md +0 -77
  174. package/.agent/skills/clean-code/SKILL.md +0 -201
  175. package/.agent/skills/doc.md +0 -177
  176. package/.agent/skills/frontend-design/SKILL.md +0 -418
  177. package/.agent/skills/frontend-design/animation-guide.md +0 -331
  178. package/.agent/skills/frontend-design/color-system.md +0 -311
  179. package/.agent/skills/frontend-design/decision-trees.md +0 -418
  180. package/.agent/skills/frontend-design/motion-graphics.md +0 -306
  181. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +0 -183
  182. package/.agent/skills/frontend-design/scripts/ux_audit.py +0 -722
  183. package/.agent/skills/frontend-design/typography-system.md +0 -345
  184. package/.agent/skills/frontend-design/ux-psychology.md +0 -1116
  185. package/.agent/skills/frontend-design/visual-effects.md +0 -383
  186. package/.agent/skills/i18n-localization/SKILL.md +0 -154
  187. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +0 -241
  188. package/.agent/skills/mcp-builder/SKILL.md +0 -176
  189. package/.agent/skills/web-design-guidelines/SKILL.md +0 -57
  190. package/.agent/workflows/brainstorm.md +0 -113
  191. package/.agent/workflows/create.md +0 -59
  192. package/.agent/workflows/debug.md +0 -103
  193. package/.agent/workflows/deploy.md +0 -176
  194. package/.agent/workflows/enhance.md +0 -63
  195. package/.agent/workflows/orchestrate.md +0 -237
  196. package/.agent/workflows/plan.md +0 -89
  197. package/.agent/workflows/preview.md +0 -81
  198. package/.agent/workflows/simple-test.md +0 -42
  199. package/.agent/workflows/status.md +0 -86
  200. package/.agent/workflows/structured-orchestrate.md +0 -180
  201. package/.agent/workflows/test.md +0 -144
  202. package/.agent/workflows/ui-ux-pro-max.md +0 -296
  203. package/output/beef-love-poster.png +0 -0
  204. package/output/international-news-daily.png +0 -0
  205. package/poster-test-2.png +0 -0
@@ -0,0 +1,324 @@
1
+ ---
2
+ name: workflow
3
+ description: 工作流引擎 - 定义和执行结构化工作流,支持顺序、条件分支、循环、延迟、工具调用等步骤类型
4
+ allowed-tools: execute_workflow,reloadWorkflows
5
+ ---
6
+
7
+ # Workflow 工作流
8
+
9
+ 工作流引擎用于定义和执行结构化的工作流程,支持多种步骤类型,可以组合使用实现复杂逻辑。
10
+
11
+ ## 快速开始
12
+
13
+ ### 创建工作流文件
14
+
15
+ 工作流定义文件放在 `.agent/workflows/` 目录下,支持 `.json` 和 `.js` 格式:
16
+
17
+ ```json
18
+ {
19
+ "name": "example-workflow",
20
+ "description": "示例工作流",
21
+ "steps": [
22
+ { "type": "script", "name": "步骤1", "script": "return 'Hello';" },
23
+ { "type": "tool", "name": "发送通知", "tool": "notification_send", "args": { "title": "标题", "message": "内容" } }
24
+ ]
25
+ }
26
+ ```
27
+
28
+ ### 执行工作流
29
+
30
+ ```javascript
31
+ // 通过 execute_workflow 工具执行
32
+ await execute_workflow({
33
+ workflow: "get-ip-notify" // 工作流名称(自动从 .agent/workflows/ 加载)
34
+ })
35
+
36
+ // 或直接传入工作流定义
37
+ await execute_workflow({
38
+ workflow: {
39
+ steps: [
40
+ { "type": "script", "name": "Hello", "script": "return 'Hello World';" }
41
+ ]
42
+ }
43
+ })
44
+ ```
45
+
46
+ ### 重要注意事项
47
+
48
+ 1. **script 必须用 return 返回值**:`script` 是函数体,不是表达式
49
+ 2. **JSON 中不能使用多行字符串**:所有 script 内容写成单行,用分号分隔
50
+ 3. **JSON 中不能有注释**:注释会导致 JSON 解析失败
51
+
52
+ ## 步骤类型
53
+
54
+ ### 1. script - 脚本步骤
55
+
56
+ 执行 JavaScript 代码,**必须用 return 返回值**:
57
+
58
+ ```json
59
+ {
60
+ "type": "script",
61
+ "name": "计算",
62
+ "outputVariable": "result",
63
+ "script": "var a=10; var b=20; context.variables.sum=a+b; return a+b;"
64
+ }
65
+ ```
66
+
67
+ **正确写法**:
68
+ ```json
69
+ { "script": "return context.variables.value + 1;" }
70
+ ```
71
+
72
+ **错误写法**(缺少 return):
73
+ ```json
74
+ { "script": "context.variables.value + 1;" }
75
+ ```
76
+
77
+ **JSON 中 script 只能写单行**,不能换行。如果逻辑复杂,建议拆成多个 script 步骤。
78
+
79
+ **script 中的可用对象**:
80
+ - `context.input` - 工作流输入参数
81
+ - `context.variables` - 工作流变量(可读写),存储在 outputVariable 中的值
82
+ - `context.lastResult` - 上一步骤的返回值
83
+ - `context.variables.loopIndex` - 循环中的当前索引
84
+
85
+ ### 2. tool - 工具调用步骤
86
+
87
+ 在工作流中调用框架注册的工具:
88
+
89
+ ```json
90
+ {
91
+ "type": "tool",
92
+ "name": "发送通知",
93
+ "tool": "notification_send",
94
+ "args": {
95
+ "title": "标题",
96
+ "message": "内容"
97
+ },
98
+ "outputVariable": "result"
99
+ }
100
+ ```
101
+
102
+ **参数说明**:
103
+
104
+ | 字段 | 类型 | 必填 | 说明 |
105
+ |------|------|------|------|
106
+ | `tool` | string | 是 | 工具名称 |
107
+ | `args` | object | 否 | 工具参数 |
108
+ | `outputVariable` | string | 否 | 结果保存到的变量名,可通过 `context.variables.xxx` 访问 |
109
+
110
+ **args 中支持变量引用**:
111
+
112
+ 使用 `{{variableName}}` 语法引用 context.variables 中的变量:
113
+
114
+ ```json
115
+ {
116
+ "type": "tool",
117
+ "name": "发送通知",
118
+ "tool": "notification_send",
119
+ "args": {
120
+ "title": "IP 信息",
121
+ "message": "当前公网IP: {{currentIp}}"
122
+ }
123
+ }
124
+ ```
125
+
126
+ 变量引用规则:
127
+ - `{{currentIp}}` → 从 context.variables.currentIp 获取
128
+ - `{{emailResult.success}}` → 支持嵌套属性访问
129
+
130
+ **完整示例 - 获取IP并发送通知**:
131
+
132
+ ```json
133
+ {
134
+ "name": "get-ip-notify",
135
+ "description": "获取本机IP并发送通知",
136
+ "steps": [
137
+ {
138
+ "type": "tool",
139
+ "name": "获取IP信息",
140
+ "tool": "fetch",
141
+ "args": {
142
+ "url": "https://api.ipify.org?format=json",
143
+ "proxy": true
144
+ },
145
+ "outputVariable": "ipResult"
146
+ },
147
+ {
148
+ "type": "script",
149
+ "name": "提取IP",
150
+ "outputVariable": "currentIp",
151
+ "script": "var r=context.variables.ipResult; return (r&&r.success&&r.body)?(typeof r.body==='object'?r.body.ip:r.body.trim()):'获取失败';"
152
+ },
153
+ {
154
+ "type": "tool",
155
+ "name": "发送通知",
156
+ "tool": "notification_send",
157
+ "args": {
158
+ "title": "IP 信息",
159
+ "message": "当前公网IP: {{currentIp}}"
160
+ }
161
+ }
162
+ ]
163
+ }
164
+ ```
165
+
166
+ ### 3. condition - 条件分支
167
+
168
+ 根据条件选择执行分支:
169
+
170
+ ```json
171
+ {
172
+ "type": "condition",
173
+ "name": "判断",
174
+ "branches": [
175
+ {
176
+ "name": "大于10",
177
+ "condition": "context.variables.value > 10",
178
+ "steps": [
179
+ { "type": "script", "name": "处理大数", "script": "context.variables.status='big'; return true;" }
180
+ ]
181
+ },
182
+ {
183
+ "name": "小于等于10",
184
+ "condition": "context.variables.value <= 10",
185
+ "steps": [
186
+ { "type": "script", "name": "处理小数", "script": "context.variables.status='small'; return true;" }
187
+ ]
188
+ }
189
+ ]
190
+ }
191
+ ```
192
+
193
+ **condition 中的 condition 写法**:
194
+ - 比较运算符:`>`、`<`、`>=`、`<=`、`===`、`!==`
195
+ - 逻辑运算符:`&&`、`||`、`!`
196
+ - 必须返回 boolean 值
197
+
198
+ ### 4. loop - 循环步骤
199
+
200
+ 重复执行一组步骤:
201
+
202
+ ```json
203
+ {
204
+ "type": "loop",
205
+ "name": "循环3次",
206
+ "maxIterations": 3,
207
+ "loopVariable": "i",
208
+ "until": "context.variables.i >= 2",
209
+ "steps": [
210
+ { "type": "script", "name": "迭代", "script": "context.variables.count=context.variables.i+1; return context.variables.i;" }
211
+ ]
212
+ }
213
+ ```
214
+
215
+ ### 5. delay - 延迟步骤
216
+
217
+ 等待指定时间:
218
+
219
+ ```json
220
+ {
221
+ "type": "delay",
222
+ "name": "等待1秒",
223
+ "delayMs": 1000
224
+ }
225
+ ```
226
+
227
+ ### 6. sequential - 顺序步骤
228
+
229
+ 将多个步骤组合为顺序执行(可嵌套使用):
230
+
231
+ ```json
232
+ {
233
+ "type": "sequential",
234
+ "name": "顺序执行",
235
+ "steps": [
236
+ { "type": "script", "name": "步骤1", "script": "return 1;" },
237
+ { "type": "script", "name": "步骤2", "script": "return 2;" }
238
+ ]
239
+ }
240
+ ```
241
+
242
+ ## sessionId 传递
243
+
244
+ 工作流执行时会自动获取当前 sessionId,所有 tool 调用都会使用该 sessionId。
245
+
246
+ **调用流程**:
247
+ 1. `execute_workflow` 从执行上下文获取 sessionId
248
+ 2. sessionId 存入 `context.variables._sessionId`
249
+ 3. ToolStep 执行工具时使用该 sessionId
250
+
251
+ **这确保了通知会发送到当前会话**。
252
+
253
+ ## 工具
254
+
255
+ ### execute_workflow
256
+
257
+ 执行指定的工作流。
258
+
259
+ ```javascript
260
+ // 按名称执行(从 .agent/workflows/ 加载)
261
+ await execute_workflow({
262
+ workflow: "get-ip-notify"
263
+ })
264
+
265
+ // 传入工作流定义
266
+ await execute_workflow({
267
+ workflow: {
268
+ steps: [
269
+ { "type": "script", "script": "return 'test';" }
270
+ ]
271
+ }
272
+ })
273
+
274
+ // 带输入参数
275
+ await execute_workflow({
276
+ workflow: "my-workflow",
277
+ input: { key: "value" }
278
+ })
279
+ ```
280
+
281
+ ### reloadWorkflows
282
+
283
+ 重载所有工作流(当添加或修改工作流后调用)。
284
+
285
+ ```javascript
286
+ await reloadWorkflows()
287
+ ```
288
+
289
+ ## 最佳实践
290
+
291
+ 1. **script 必须 return**:`script` 是函数体,必须用 return 返回值
292
+ 2. **JSON 中 script 单行写**:用分号分隔多个语句,不要换行
293
+ 3. **拆分复杂逻辑**:复杂的 script 拆成多个简单步骤
294
+ 4. **使用 outputVariable**:需要跨步骤使用的值,存入 context.variables
295
+ 5. **条件判断加 else**:condition 分支要有兜底处理
296
+ 6. **合理设置循环次数**:loop 的 maxIterations 不要过大
297
+
298
+ **错误示例**:
299
+ ```json
300
+ // ❌ 错误 - script 没有 return
301
+ { "type": "script", "script": "context.variables.count + 1;" }
302
+
303
+ // ❌ 错误 - JSON 多行字符串
304
+ {
305
+ "script": "
306
+ const a = 10;
307
+ return a + 1;
308
+ "
309
+ }
310
+
311
+ // ❌ 错误 - JSON 中有注释
312
+ {
313
+ "script": "return 1; // 这是注释"
314
+ }
315
+ ```
316
+
317
+ **正确示例**:
318
+ ```json
319
+ // ✅ 正确
320
+ { "type": "script", "outputVariable": "count", "script": "return (context.variables.count||0) + 1;" }
321
+
322
+ // ✅ 正确 - 复杂逻辑拆成多步
323
+ { "type": "script", "script": "context.variables.a=10; context.variables.b=20; return context.variables.a+context.variables.b;" }
324
+ ```
@@ -0,0 +1,6 @@
1
+ {
2
+ "token": "456b1c0cb5f7@im.bot:06000038355b2b75ffe34f60575352ea07fcb8",
3
+ "baseUrl": "https://ilinkai.weixin.qq.com",
4
+ "accountId": "456b1c0cb5f7@im.bot",
5
+ "userId": "o9cq80zgZqKPA2-s59PN43GdDy1w@im.wechat"
6
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "email-digest",
3
+ "description": "邮件摘要工作流 - 读取未读邮件并生成摘要",
4
+ "steps": [
5
+ {
6
+ "type": "tool",
7
+ "name": "获取未读数",
8
+ "tool": "email_unread_count",
9
+ "args": {},
10
+ "outputVariable": "unreadResult"
11
+ },
12
+ {
13
+ "type": "condition",
14
+ "name": "检查是否有新邮件",
15
+ "branches": [
16
+ {
17
+ "name": "有新邮件",
18
+ "condition": "context.variables.unreadResult && context.variables.unreadResult.unreadCount > 0",
19
+ "steps": [
20
+ {
21
+ "type": "script",
22
+ "name": "记录状态",
23
+ "script": "context.variables.status='有新邮件'; return true;"
24
+ }
25
+ ]
26
+ },
27
+ {
28
+ "name": "无新邮件",
29
+ "condition": "!context.variables.unreadResult || context.variables.unreadResult.unreadCount === 0",
30
+ "steps": [
31
+ {
32
+ "type": "script",
33
+ "name": "记录状态",
34
+ "script": "context.variables.status='无新邮件'; return false;"
35
+ }
36
+ ]
37
+ }
38
+ ]
39
+ },
40
+ {
41
+ "type": "tool",
42
+ "name": "发送通知",
43
+ "tool": "notification_send",
44
+ "args": {
45
+ "title": "邮件摘要",
46
+ "message": "未读邮件数: {{unreadResult.unreadCount}}"
47
+ }
48
+ }
49
+ ]
50
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "file-backup",
3
+ "description": "文件备份工作流",
4
+ "steps": [
5
+ {
6
+ "type": "script",
7
+ "name": "准备路径",
8
+ "outputVariable": "backupInfo",
9
+ "script": "context.variables.source='.'; context.variables.dest='/backup'; return {source:'.',dest:'/backup'};"
10
+ },
11
+ {
12
+ "type": "tool",
13
+ "name": "发送通知",
14
+ "tool": "notification_send",
15
+ "args": {
16
+ "title": "备份开始",
17
+ "message": "开始备份文件"
18
+ }
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "get-ip-notify",
3
+ "description": "从 ifconfig.me 获取公网 IP 地址并发送系统通知",
4
+ "steps": [
5
+ {
6
+ "type": "tool",
7
+ "name": "获取IP信息",
8
+ "tool": "fetch",
9
+ "args": {
10
+ "url": "https://ifconfig.me/ip",
11
+ "timeout": 30000,
12
+ "proxy": true
13
+ },
14
+ "outputVariable": "ipResult"
15
+ },
16
+ {
17
+ "type": "script",
18
+ "name": "提取IP",
19
+ "outputVariable": "currentIp",
20
+ "script": "var r=context.variables.ipResult; var ip=r&&r.success&&r.body?r.body.trim():null; return ip||'获取失败';"
21
+ },
22
+ {
23
+ "type": "tool",
24
+ "name": "发送通知",
25
+ "tool": "notification_send",
26
+ "args": {
27
+ "title": "IP 信息",
28
+ "message": "当前公网IP: {{currentIp}}"
29
+ }
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "news-aggregator",
3
+ "description": "从多个新闻源(百度新闻、BBC、Reddit)获取新闻,整理生成网页",
4
+ "steps": [
5
+ {
6
+ "type": "script",
7
+ "name": "初始化新闻存储",
8
+ "outputVariable": "allNews",
9
+ "script": "context.variables.allNews=[]; context.variables.sources=['百度新闻','BBC','Reddit']; return context.variables.allNews;"
10
+ },
11
+ {
12
+ "type": "tool",
13
+ "name": "获取百度新闻",
14
+ "tool": "fetch",
15
+ "args": {
16
+ "url": "https://top.baidu.com/board?tab=realtime",
17
+ "timeout": 15000,
18
+ "proxy": true
19
+ },
20
+ "outputVariable": "baiduNewsResult"
21
+ },
22
+ {
23
+ "type": "tool",
24
+ "name": "获取BBC新闻",
25
+ "tool": "fetch",
26
+ "args": {
27
+ "url": "https://feeds.bbci.co.uk/news/world/rss.xml",
28
+ "timeout": 15000,
29
+ "proxy": true
30
+ },
31
+ "outputVariable": "bbcNewsResult"
32
+ },
33
+ {
34
+ "type": "tool",
35
+ "name": "获取Reddit新闻",
36
+ "tool": "fetch",
37
+ "args": {
38
+ "url": "https://www.reddit.com/r/news/.json?limit=20",
39
+ "timeout": 15000,
40
+ "proxy": true
41
+ },
42
+ "outputVariable": "redditNewsResult"
43
+ },
44
+ {
45
+ "type": "script",
46
+ "name": "处理百度新闻",
47
+ "outputVariable": "baiduNews",
48
+ "script": "var r=context.variables.baiduNewsResult; if(r&&r.success&&r.body){try{var matches=r.body.match(/href=\"\\/news\\/([^\"]+)\"[^>]*>([^<]+)<\\/a>/g);if(!matches)matches=r.body.match(/\"query\":\"([^\"]+)\"/g);var items=[];if(matches)for(var i=0;i<Math.min(matches.length,10);i++){var m=matches[i].match(/\"query\":\"([^\"]+)\"/)||matches[i].match(/>([^<]+)</);if(m&&m[1])items.push(m[1].trim());}context.variables.baiduNews=items.length?items:['百度新闻:页面解析中...'];}catch(e){context.variables.baiduNews=['百度新闻:获取成功'];}}else{context.variables.baiduNews=['百度新闻:获取失败'];}return context.variables.baiduNews;"
49
+ },
50
+ {
51
+ "type": "script",
52
+ "name": "处理BBC新闻",
53
+ "outputVariable": "bbcNews",
54
+ "script": "var r=context.variables.bbcNewsResult; var items=[]; if(r&&r.success&&r.body){try{var titles=r.body.match(/<title><!\\[CDATA\\[([^\\]]+)\\]\\]><\\/title>/g)||r.body.match(/<title>([^<]+)<\\/title>/g);if(titles)for(var i=1;i<Math.min(titles.length,11);i++){var m=titles[i].match(/\\[([^\\]]+)\\]/);if(m&&m[1]&&m[1]!=='BBC News')items.push(m[1]);}}catch(e){}if(items.length===0)items=['BBC:获取成功'];}else{items=['BBC:获取失败'];}context.variables.bbcNews=items; return items;"
55
+ },
56
+ {
57
+ "type": "script",
58
+ "name": "处理Reddit新闻",
59
+ "outputVariable": "redditNews",
60
+ "script": "var r=context.variables.redditNewsResult; var items=[]; if(r&&r.success&&r.body){try{var data=typeof r.body==='string'?JSON.parse(r.body):r.body;if(data&&data.data&&data.data.children){data.data.children.slice(0,10).forEach(function(item){if(item.data&&item.data.title)items.push(item.data.title);});}}catch(e){}if(items.length===0)items=['Reddit:获取成功'];}else{items=['Reddit:获取失败'];}context.variables.redditNews=items; return items;"
61
+ },
62
+ {
63
+ "type": "script",
64
+ "name": "生成HTML网页",
65
+ "outputVariable": "htmlContent",
66
+ "script": "var now=new Date();var dateStr=now.toLocaleDateString('zh-CN',{year:'numeric',month:'long',day:'numeric',hour:'2-digit',minute:'2-digit'});var baidu=context.variables.baiduNews||[];var bbc=context.variables.bbcNews||[];var reddit=context.variables.redditNews||[];var html='<!DOCTYPE html>\\n<html lang=\"zh-CN\">\\n<head>\\n<meta charset=\"UTF-8\">\\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\\n<title>全球新闻聚合 - '+dateStr+'</title>\\n<style>\\n*{margin:0;padding:0;box-sizing:border-box;}\\nbody{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);min-height:100vh;padding:20px;}\\n.container{max-width:1200px;margin:0 auto;}\\nh1{text-align:center;color:#fff;margin-bottom:30px;font-size:2.5em;text-shadow:2px 2px 4px rgba(0,0,0,0.3);}\\n.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(350px,1fr));gap:25px;}\\n.card{background:#fff;border-radius:16px;overflow:hidden;box-shadow:0 10px 40px rgba(0,0,0,0.2);transition:transform 0.3s ease;}\\n.card:hover{transform:translateY(-5px);}\\n.card-header{padding:20px;color:#fff;font-weight:bold;font-size:1.3em;}\\n.card-header.baidu{background:linear-gradient(135deg,#4e54c8,#8f94fb);}\\n.card-header.bbc{background:linear-gradient(135deg,#b21f1f,#f64f59);}\\n.card-header.reddit{background:linear-gradient(135deg,#ff4500,#ff6a33);}\\n.card-body{padding:20px;}\\n.news-list{list-style:none;}\\n.news-list li{padding:12px 0;border-bottom:1px solid #eee;cursor:pointer;transition:all 0.2s;}\\n.news-list li:last-child{border-bottom:none;}\\n.news-list li:hover{color:#667eea;padding-left:10px;}\\n.news-list li::before{content:\"• \";color:#667eea;font-weight:bold;margin-right:8px;}\\n.timestamp{text-align:center;color:#999;font-size:0.9em;margin-top:20px;}\\n</style>\\n</head>\\n<body>\\n<div class=\"container\">\\n<h1>📰 全球新闻聚合</h1>\\n<div class=\"grid\">\\n<div class=\"card\"><div class=\"card-header baidu\">🇨🇳 百度新闻</div><div class=\"card-body\"><ul class=\"news-list\">';baidu.forEach(function(n){html+='<li>'+n+'</li>';});html+='</ul></div></div>\\n<div class=\"card\"><div class=\"card-header bbc\">🇬🇧 BBC News</div><div class=\"card-body\"><ul class=\"news-list\">';bbc.forEach(function(n){html+='<li>'+n+'</li>';});html+='</ul></div></div>\\n<div class=\"card\"><div class=\"card-header reddit\">🤖 Reddit News</div><div class=\"card-body\"><ul class=\"news-list\">';reddit.forEach(function(n){html+='<li>'+n+'</li>';});html+='</ul></div></div>\\n</div>\\n<p class=\"timestamp\">更新时间: '+dateStr+' | 数据来源: 百度新闻、BBC、Reddit</p>\\n</div>\\n</body>\\n</html>';return html;"
67
+ },
68
+ {
69
+ "type": "script",
70
+ "name": "生成文件名",
71
+ "outputVariable": "filePath",
72
+ "script": "var now=new Date();var dateStr=now.toISOString().slice(0,10).replace(/-/g,'');var timestamp=Date.now();context.variables.filePath='D:/Code/vb-agent/news-'+dateStr+'-'+timestamp+'.html';return context.variables.filePath;"
73
+ },
74
+ {
75
+ "type": "tool",
76
+ "name": "保存HTML文件",
77
+ "tool": "write_file",
78
+ "args": {
79
+ "path": "{{filePath}}",
80
+ "content": "{{htmlContent}}"
81
+ }
82
+ },
83
+ {
84
+ "type": "tool",
85
+ "name": "发送完成通知",
86
+ "tool": "notification_send",
87
+ "args": {
88
+ "title": "📰 新闻聚合完成",
89
+ "message": "已从百度新闻、BBC、Reddit获取新闻\\n网页已生成: {{filePath}}"
90
+ }
91
+ }
92
+ ]
93
+ }
@@ -0,0 +1,94 @@
1
+ {
2
+ "name": "news-dashboard-v2",
3
+ "description": "新闻汇总工作流v2 - 从网络获取真实新闻数据并生成网页",
4
+ "version": "2.2",
5
+ "steps": [
6
+ {
7
+ "id": "step-1",
8
+ "type": "tool",
9
+ "name": "获取当前日期时间",
10
+ "tool": "get_time",
11
+ "output": "dateResult"
12
+ },
13
+ {
14
+ "id": "step-2",
15
+ "type": "tool",
16
+ "name": "获取百度热搜",
17
+ "tool": "fetch",
18
+ "args": {
19
+ "url": "https://top.baidu.com/board?tab=realtime",
20
+ "timeout": 15000,
21
+ "proxy": true
22
+ },
23
+ "output": "baiduResult"
24
+ },
25
+ {
26
+ "id": "step-3",
27
+ "type": "tool",
28
+ "name": "获取BBC国际新闻",
29
+ "tool": "fetch",
30
+ "args": {
31
+ "url": "https://feeds.bbci.co.uk/news/world/rss.xml",
32
+ "timeout": 15000,
33
+ "proxy": true
34
+ },
35
+ "output": "bbcResult"
36
+ },
37
+ {
38
+ "id": "step-4",
39
+ "type": "tool",
40
+ "name": "获取Reddit热门",
41
+ "tool": "fetch",
42
+ "args": {
43
+ "url": "https://www.reddit.com/r/popular/hot.json?limit=15",
44
+ "timeout": 15000,
45
+ "proxy": true
46
+ },
47
+ "output": "redditResult"
48
+ },
49
+ {
50
+ "id": "step-5",
51
+ "type": "tool",
52
+ "name": "获取香港新闻",
53
+ "tool": "fetch",
54
+ "args": {
55
+ "url": "https://rsshub.app/rsshub/rss",
56
+ "timeout": 15000,
57
+ "proxy": true
58
+ },
59
+ "output": "hkResult"
60
+ },
61
+ {
62
+ "id": "step-6",
63
+ "type": "script",
64
+ "name": "处理新闻数据",
65
+ "script": "var dateResult = context.variables.dateResult || {};\nvar baiduResult = context.variables.baiduResult || {};\nvar bbcResult = context.variables.bbcResult || {};\nvar redditResult = context.variables.redditResult || {};\nvar hkResult = context.variables.hkResult || {};\n\nvar dateStr = (dateResult.beijingTime || dateResult.formatted || {}).beijingTime || new Date().toLocaleString('zh-CN');\nvar baiduRaw = typeof baiduResult === 'string' ? baiduResult : (baiduResult.body || baiduResult.content || JSON.stringify(baiduResult));\nvar bbcRaw = typeof bbcResult === 'string' ? bbcResult : (bbcResult.body || bbcResult.content || JSON.stringify(bbcResult));\nvar redditRaw = typeof redditResult === 'string' ? redditResult : (redditResult.body || redditResult.content || JSON.stringify(redditResult));\nvar hkRaw = typeof hkResult === 'string' ? hkResult : (hkResult.body || hkResult.content || JSON.stringify(hkResult));\n\nvar baiduNews = [];\nif (baiduRaw) {\n var titleMatch = baiduRaw.match(/<a[^>]*class=\"c-single-text-ellipsis\"[^>]*>([^<]+)<\\/a>/g);\n if (titleMatch) {\n for (var i = 0; i < Math.min(titleMatch.length, 20); i++) {\n baiduNews.push({rank: i + 1, title: titleMatch[i].replace(/<[^>]+>/g, '').trim()});\n }\n }\n}\n\nvar bbcNews = [];\nif (bbcRaw) {\n var itemMatch = bbcRaw.match(/<item[^>]*>[\\s\\S]*?<\\/item>/g);\n if (itemMatch) {\n for (var i = 0; i < Math.min(itemMatch.length, 15); i++) {\n var t = itemMatch[i].match(/<title>([^<]+)<\\/title>/);\n var l = itemMatch[i].match(/<link>([^<]+)<\\/link>/);\n if (t) {\n bbcNews.push({title: t[1].trim(), link: l ? l[1].trim() : '#'});\n }\n }\n }\n}\n\nvar redditNews = [];\nif (redditRaw) {\n try {\n var data = JSON.parse(redditRaw);\n var children = (data.data || {}).children || [];\n for (var i = 0; i < Math.min(children.length, 10); i++) {\n var d = children[i].data || {};\n redditNews.push({rank: i + 1, title: d.title || '', score: d.score || 0, subreddit: d.subreddit || ''});\n }\n } catch(e) {}\n}\n\nvar hkNews = [];\nif (hkRaw) {\n var itemMatch = hkRaw.match(/<item[^>]*>[\\s\\S]*?<\\/item>/g);\n if (itemMatch) {\n for (var i = 0; i < Math.min(itemMatch.length, 10); i++) {\n var t = itemMatch[i].match(/<title>([^<]+)<\\/title>/);\n var l = itemMatch[i].match(/<link>([^<]+)<\\/link>/);\n if (t) {\n hkNews.push({title: t[1].trim(), link: l ? l[1].trim() : '#'});\n }\n }\n }\n}\n\nreturn {date: dateStr, baidu: baiduNews, bbc: bbcNews, reddit: redditNews, hk: hkNews};",
66
+ "output": "processedNews"
67
+ },
68
+ {
69
+ "id": "step-7",
70
+ "type": "script",
71
+ "name": "生成完整HTML",
72
+ "script": "var newsData = context.variables.processedNews || {};\nvar dateStr = newsData.date || new Date().toLocaleString('zh-CN');\nvar baidu = newsData.baidu || [];\nvar bbc = newsData.bbc || [];\nvar reddit = newsData.reddit || [];\nvar hk = newsData.hk || [];\n\nfunction renderRank(rank, isHot) {\n if (isHot && rank <= 3) {\n var colors = ['#ff6b6b', '#ffa502', '#26de81'];\n return '<span style=\"background:' + colors[rank - 1] + ';color:white;padding:2px 8px;border-radius:4px;font-weight:bold;\">' + rank + '</span>';\n }\n return '<span style=\"color:#888;\">' + rank + '</span>';\n}\n\nfunction renderItem(item, index, isHot) {\n var rank = index + 1;\n var title = item.title || '';\n var link = item.link || '#';\n var score = item.score || 0;\n var subreddit = item.subreddit || '';\n var rankHtml = renderRank(rank, isHot);\n if (link && link !== '#') {\n return '<li class=\"news-item\">' + rankHtml + ' <a href=\"' + link + '\" target=\"_blank\">' + title + '</a></li>';\n } else if (subreddit) {\n return '<li class=\"news-item\">' + rankHtml + ' <span style=\"color:#ff4500;\">r/' + subreddit + '</span> ' + title + ' <span style=\"color:#888;font-size:0.8em;\">▲ ' + score + '</span></li>';\n }\n return '<li class=\"news-item\">' + rankHtml + ' ' + title + '</li>';\n}\n\nfunction renderList(items, isHot) {\n return items.map(function(item, i) { return renderItem(item, i, isHot); }).join('\\n');\n}\n\nvar html = '<!DOCTYPE html><html lang=\"zh-CN\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>新闻汇总 - ' + dateStr + '</title><style>*{box-sizing:border-box;margin:0;padding:0}body{font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,sans-serif;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);min-height:100vh;padding:20px}.container{max-width:1200px;margin:0 auto}header{text-align:center;color:white;padding:30px 0}header h1{font-size:2.5em;margin-bottom:10px;text-shadow:2px 2px 4px rgba(0,0,0,0.2)}header p{opacity:0.9;font-size:1.1em}.tabs{display:flex;gap:10px;margin-bottom:20px;flex-wrap:wrap;justify-content:center}.tab-btn{padding:12px 24px;border:none;border-radius:25px;cursor:pointer;font-size:1em;font-weight:600;transition:all 0.3s;background:rgba(255,255,255,0.2);color:white}.tab-btn:hover,.tab-btn.active{background:white;color:#667eea}.tab-content{display:none;background:white;border-radius:20px;padding:30px;box-shadow:0 20px 60px rgba(0,0,0,0.2)}.tab-content.active{display:block}.tab-content h2{color:#333;margin-bottom:20px;padding-bottom:10px;border-bottom:3px solid #667eea;display:inline-block}.news-item{padding:12px 0;border-bottom:1px solid #eee;display:flex;align-items:center;gap:10px}.news-item:last-child{border-bottom:none}.news-item a{color:#333;text-decoration:none;flex:1}.news-item a:hover{color:#667eea}.news-list{list-style:none}.empty{color:#888;text-align:center;padding:40px}@media(max-width:768px){body{padding:10px}header h1{font-size:1.8em}.tab-btn{padding:10px 16px;font-size:0.9em}.tab-content{padding:20px}}</style></head><body><div class=\"container\"><header><h1>📰 新闻汇总</h1><p>更新时间: ' + dateStr + '</p></header><div class=\"tabs\"><button class=\"tab-btn active\" onclick=\"showTab(\\'baidu\\')\">🔥 百度热搜</button><button class=\"tab-btn\" onclick=\"showTab(\\'bbc\\')\">🌍 BBC国际</button><button class=\"tab-btn\" onclick=\"showTab(\\'hk\\')\">🇭🇰 香港新闻</button><button class=\"tab-btn\" onclick=\"showTab(\\'reddit\\')\">💬 Reddit热帖</button></div><div id=\"baidu\" class=\"tab-content active\"><h2>🔥 百度热搜</h2><ul class=\"news-list\">' + (baidu.length > 0 ? renderList(baidu, true) : '<li class=\"empty\">正在获取数据...</li>') + '</ul></div><div id=\"bbc\" class=\"tab-content\"><h2>🌍 BBC国际新闻</h2><ul class=\"news-list\">' + (bbc.length > 0 ? renderList(bbc, false) : '<li class=\"empty\">正在获取数据...</li>') + '</ul></div><div id=\"hk\" class=\"tab-content\"><h2>🇭🇰 香港新闻</h2><ul class=\"news-list\">' + (hk.length > 0 ? renderList(hk, false) : '<li class=\"empty\">正在获取数据...</li>') + '</ul></div><div id=\"reddit\" class=\"tab-content\"><h2>💬 Reddit热门帖子</h2><ul class=\"news-list\">' + (reddit.length > 0 ? renderList(reddit, false) : '<li class=\"empty\">正在获取数据...</li>') + '</ul></div></div><script>function showTab(n){document.querySelectorAll(\".tab-content\").forEach(function(e){e.classList.remove(\"active\")});document.querySelectorAll(\".tab-btn\").forEach(function(e){e.classList.remove(\"active\")});document.getElementById(n).classList.add(\"active\");event.target.classList.add(\"active\")}</script></body></html>';\nreturn html;",
73
+ "output": "finalHtml"
74
+ },
75
+ {
76
+ "id": "step-8",
77
+ "type": "tool",
78
+ "name": "保存HTML文件",
79
+ "tool": "write_file",
80
+ "args": {
81
+ "path": "D:\\Code\\vb-agent\\news.html",
82
+ "content": "${step-7.output}"
83
+ },
84
+ "output": "savedPath"
85
+ },
86
+ {
87
+ "id": "step-9",
88
+ "type": "script",
89
+ "name": "返回结果",
90
+ "script": "return JSON.stringify({success: true, message: '新闻汇总工作流执行完成', output_file: 'D:\\\\Code\\\\vb-agent\\\\news.html', note: '新闻数据已从网络获取并生成网页'}, null, 2);",
91
+ "output": "workflowResult"
92
+ }
93
+ ]
94
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "notification-batch",
3
+ "description": "批量通知工作流",
4
+ "steps": [
5
+ {
6
+ "type": "script",
7
+ "name": "初始化",
8
+ "script": "context.variables.total=3; context.variables.sent=0; return {total:3};"
9
+ },
10
+ {
11
+ "type": "loop",
12
+ "name": "发送通知",
13
+ "maxIterations": 3,
14
+ "steps": [
15
+ {
16
+ "type": "script",
17
+ "name": "计数",
18
+ "script": "context.variables.sent=context.variables.sent+1;"
19
+ },
20
+ {
21
+ "type": "tool",
22
+ "name": "发送单个通知",
23
+ "tool": "notification_send",
24
+ "args": {
25
+ "title": "进度",
26
+ "message": "已发送: {{sent}}/{{total}}"
27
+ }
28
+ }
29
+ ]
30
+ }
31
+ ]
32
+ }