foliko 1.0.73 → 1.0.75

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 (237) hide show
  1. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
  2. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
  3. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
  4. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
  5. package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
  6. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
  7. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
  8. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  9. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  10. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  11. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  12. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  13. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  14. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  15. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
  16. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  17. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  18. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  19. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  20. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
  21. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
  22. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  23. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  24. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
  25. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  26. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  27. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
  28. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
  29. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
  30. package/.agent/ARCHITECTURE.md +288 -0
  31. package/.agent/agents/ambient-agent.md +57 -0
  32. package/.agent/agents/debugger.md +55 -0
  33. package/.agent/agents/email-assistant.md +49 -0
  34. package/.agent/agents/file-manager.md +42 -0
  35. package/.agent/agents/python-developer.md +60 -0
  36. package/.agent/agents/scheduler.md +59 -0
  37. package/.agent/agents/web-developer.md +45 -0
  38. package/.agent/data/default.json +29 -0
  39. package/.agent/data/plugins-state.json +255 -0
  40. package/.agent/mcp_config.json +4 -0
  41. package/.agent/mcp_config_updated.json +12 -0
  42. package/.agent/plugins.json +5 -0
  43. package/.agent/rules/GEMINI.md +273 -0
  44. package/.agent/rules/allow-rule.md +77 -0
  45. package/.agent/rules/log-rule.md +83 -0
  46. package/.agent/rules/security-rule.md +93 -0
  47. package/.agent/scripts/auto_preview.py +148 -0
  48. package/.agent/scripts/checklist.py +217 -0
  49. package/.agent/scripts/session_manager.py +120 -0
  50. package/.agent/scripts/verify_all.py +327 -0
  51. package/.agent/skills/api-patterns/SKILL.md +81 -0
  52. package/.agent/skills/api-patterns/api-style.md +42 -0
  53. package/.agent/skills/api-patterns/auth.md +24 -0
  54. package/.agent/skills/api-patterns/documentation.md +26 -0
  55. package/.agent/skills/api-patterns/graphql.md +41 -0
  56. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  57. package/.agent/skills/api-patterns/response.md +37 -0
  58. package/.agent/skills/api-patterns/rest.md +40 -0
  59. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  60. package/.agent/skills/api-patterns/security-testing.md +122 -0
  61. package/.agent/skills/api-patterns/trpc.md +41 -0
  62. package/.agent/skills/api-patterns/versioning.md +22 -0
  63. package/.agent/skills/app-builder/SKILL.md +75 -0
  64. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  65. package/.agent/skills/app-builder/feature-building.md +53 -0
  66. package/.agent/skills/app-builder/project-detection.md +34 -0
  67. package/.agent/skills/app-builder/scaffolding.md +118 -0
  68. package/.agent/skills/app-builder/tech-stack.md +40 -0
  69. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  70. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  71. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  72. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  73. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  74. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  75. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  76. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  77. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  78. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  79. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  80. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  81. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  82. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  83. package/.agent/skills/architecture/SKILL.md +55 -0
  84. package/.agent/skills/architecture/context-discovery.md +43 -0
  85. package/.agent/skills/architecture/examples.md +94 -0
  86. package/.agent/skills/architecture/pattern-selection.md +68 -0
  87. package/.agent/skills/architecture/patterns-reference.md +50 -0
  88. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  89. package/.agent/skills/clean-code/SKILL.md +201 -0
  90. package/.agent/skills/doc.md +177 -0
  91. package/.agent/skills/frontend-design/SKILL.md +418 -0
  92. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  93. package/.agent/skills/frontend-design/color-system.md +311 -0
  94. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  95. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  96. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  97. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  98. package/.agent/skills/frontend-design/typography-system.md +345 -0
  99. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  100. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  101. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  102. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  103. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  104. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  105. package/.agent/workflows/brainstorm.md +113 -0
  106. package/.agent/workflows/create.md +59 -0
  107. package/.agent/workflows/debug.md +103 -0
  108. package/.agent/workflows/deploy.md +176 -0
  109. package/.agent/workflows/enhance.md +63 -0
  110. package/.agent/workflows/orchestrate.md +237 -0
  111. package/.agent/workflows/plan.md +89 -0
  112. package/.agent/workflows/preview.md +81 -0
  113. package/.agent/workflows/simple-test.md +42 -0
  114. package/.agent/workflows/status.md +86 -0
  115. package/.agent/workflows/structured-orchestrate.md +180 -0
  116. package/.agent/workflows/test.md +144 -0
  117. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  118. package/.claude/settings.local.json +157 -149
  119. package/.editorconfig +56 -0
  120. package/.husky/pre-commit +4 -0
  121. package/.lintstagedrc +7 -0
  122. package/.prettierignore +29 -0
  123. package/.prettierrc +11 -0
  124. package/CLAUDE.md +2 -0
  125. package/README.md +64 -55
  126. package/SPEC.md +102 -61
  127. package/cli/bin/foliko.js +4 -4
  128. package/cli/src/commands/chat.js +53 -51
  129. package/cli/src/commands/list.js +40 -37
  130. package/cli/src/index.js +18 -18
  131. package/cli/src/ui/chat-ui.js +78 -76
  132. package/cli/src/utils/ansi.js +15 -15
  133. package/cli/src/utils/markdown.js +112 -116
  134. package/docker-compose.yml +1 -1
  135. package/docs/ai-sdk-optimization.md +655 -636
  136. package/docs/features.md +80 -80
  137. package/docs/quick-reference.md +49 -46
  138. package/docs/user-manual.md +411 -380
  139. package/examples/ambient-example.js +95 -97
  140. package/examples/basic.js +115 -110
  141. package/examples/bootstrap.js +52 -43
  142. package/examples/mcp-example.js +56 -53
  143. package/examples/skill-example.js +49 -49
  144. package/examples/test-chat.js +60 -58
  145. package/examples/test-mcp.js +49 -43
  146. package/examples/test-reload.js +38 -40
  147. package/examples/test-telegram.js +3 -3
  148. package/examples/test-tg-bot.js +7 -4
  149. package/examples/test-tg-simple.js +4 -3
  150. package/examples/test-tg.js +3 -3
  151. package/examples/test-think.js +13 -7
  152. package/examples/test-web-plugin.js +61 -56
  153. package/examples/test-weixin-feishu.js +40 -37
  154. package/examples/workflow.js +49 -49
  155. package/foliko-1.0.75.tgz +0 -0
  156. package/package.json +37 -3
  157. package/plugins/ai-plugin.js +7 -5
  158. package/plugins/ambient-agent/EventWatcher.js +113 -0
  159. package/plugins/ambient-agent/ExplorerLoop.js +640 -0
  160. package/plugins/ambient-agent/GoalManager.js +197 -0
  161. package/plugins/ambient-agent/Reflector.js +95 -0
  162. package/plugins/ambient-agent/StateStore.js +90 -0
  163. package/plugins/ambient-agent/constants.js +101 -0
  164. package/plugins/ambient-agent/index.js +579 -0
  165. package/plugins/default-plugins.js +62 -49
  166. package/plugins/email/constants.js +64 -0
  167. package/plugins/email/handlers.js +461 -0
  168. package/plugins/email/index.js +278 -0
  169. package/plugins/email/monitor.js +269 -0
  170. package/plugins/email/parser.js +138 -0
  171. package/plugins/email/reply.js +151 -0
  172. package/plugins/email/utils.js +124 -0
  173. package/plugins/feishu-plugin.js +23 -19
  174. package/plugins/file-system-plugin.js +469 -120
  175. package/plugins/install-plugin.js +6 -4
  176. package/plugins/python-executor-plugin.js +3 -1
  177. package/plugins/python-plugin-loader.js +10 -8
  178. package/plugins/rules-plugin.js +5 -3
  179. package/plugins/scheduler-plugin.js +18 -16
  180. package/plugins/session-plugin.js +3 -1
  181. package/plugins/storage-plugin.js +5 -3
  182. package/plugins/subagent-plugin.js +152 -92
  183. package/plugins/telegram-plugin.js +26 -19
  184. package/plugins/think-plugin.js +4 -2
  185. package/plugins/tools-plugin.js +3 -1
  186. package/plugins/web-plugin.js +15 -13
  187. package/plugins/weixin-plugin.js +43 -36
  188. package/reports/system-health-report-20260401.md +79 -0
  189. package/skills/ambient-agent/SKILL.md +49 -39
  190. package/skills/foliko-dev/AGENTS.md +64 -61
  191. package/skills/foliko-dev/SKILL.md +125 -119
  192. package/skills/mcp-usage/SKILL.md +19 -17
  193. package/skills/python-plugin-dev/SKILL.md +16 -15
  194. package/skills/skill-guide/SKILL.md +12 -12
  195. package/skills/subagent-guide/SKILL.md +237 -0
  196. package/skills/workflow-guide/SKILL.md +90 -45
  197. package/skills/workflow-troubleshooting/DEBUGGING.md +36 -21
  198. package/skills/workflow-troubleshooting/SKILL.md +156 -79
  199. package/src/capabilities/index.js +4 -4
  200. package/src/capabilities/skill-manager.js +211 -197
  201. package/src/capabilities/workflow-engine.js +461 -547
  202. package/src/core/agent-chat.js +426 -279
  203. package/src/core/agent.js +453 -248
  204. package/src/core/framework.js +183 -149
  205. package/src/core/index.js +8 -8
  206. package/src/core/plugin-base.js +52 -52
  207. package/src/core/plugin-manager.js +377 -281
  208. package/src/core/provider.js +35 -32
  209. package/src/core/sub-agent-config.js +264 -0
  210. package/src/core/system-prompt-builder.js +120 -0
  211. package/src/core/tool-registry.js +416 -33
  212. package/src/core/tool-router.js +149 -68
  213. package/src/executors/executor-base.js +58 -58
  214. package/src/executors/mcp-executor.js +269 -257
  215. package/src/index.js +5 -17
  216. package/src/utils/circuit-breaker.js +301 -0
  217. package/src/utils/error-boundary.js +363 -0
  218. package/src/utils/error.js +374 -0
  219. package/src/utils/event-emitter.js +20 -20
  220. package/src/utils/id.js +133 -0
  221. package/src/utils/index.js +217 -3
  222. package/src/utils/logger.js +181 -0
  223. package/src/utils/plugin-helpers.js +90 -0
  224. package/src/utils/retry.js +122 -0
  225. package/src/utils/sandbox.js +292 -0
  226. package/test/tool-registry-validation.test.js +218 -0
  227. package/test_report.md +70 -0
  228. package/website/docs/api.html +169 -107
  229. package/website/docs/configuration.html +296 -144
  230. package/website/docs/plugin-development.html +154 -85
  231. package/website/docs/project-structure.html +110 -109
  232. package/website/docs/skill-development.html +117 -61
  233. package/website/index.html +209 -205
  234. package/website/script.js +20 -17
  235. package/website/styles.css +1 -1
  236. package/plugins/ambient-agent-plugin.js +0 -1565
  237. package/plugins/email.js +0 -1142
@@ -2,13 +2,15 @@
2
2
  * WorkflowEngine 工作流引擎
3
3
  * 支持结构化工作流定义和执行
4
4
  */
5
-
6
- const { EventEmitter } = require('../utils/event-emitter')
7
- const { Plugin } = require('../core/plugin-base')
8
- const { z } = require('zod')
9
- const fs = require('fs')
10
- const path = require('path')
11
-
5
+ const { EventEmitter } = require('../utils/event-emitter');
6
+ const { Plugin } = require('../core/plugin-base');
7
+ const { logger } = require('../utils/logger');
8
+ const log = logger.child('Workflow');
9
+ const { z } = require('zod');
10
+ const { runScriptSafely, evaluateInSandbox, runWorkflowFileSafely, runWorkflowSafely } = require('../utils/sandbox');
11
+ const fs = require('fs');
12
+ const crypto = require('crypto');
13
+ const path = require('path');
12
14
  /**
13
15
  * 工作流步骤类型
14
16
  */
@@ -27,41 +29,38 @@ const StepType = {
27
29
  OUTPUT: 'output',
28
30
  MESSAGE: 'message',
29
31
  THINK: 'think',
30
- WORKFLOW: 'workflow' // 嵌套工作流
31
- }
32
-
32
+ WORKFLOW: 'workflow', // 嵌套工作流
33
+ };
33
34
  /**
34
35
  * StepExecutor - 统一的步骤执行器
35
36
  * 同时被 WorkflowEngine 和 ExplorerLoop 使用
36
37
  */
37
38
  class StepExecutor {
38
39
  constructor(framework) {
39
- this.framework = framework
40
+ this.framework = framework;
41
+ this._log = logger.child('StepExecutor');
40
42
  }
41
-
42
43
  /**
43
44
  * 执行单个步骤
44
45
  */
45
46
  async executeStep(step, context) {
46
- const handler = this._getStepHandler(step.type)
47
+ const handler = this._getStepHandler(step.type);
47
48
  if (!handler) {
48
- throw new Error(`Unknown step type: ${step.type}`)
49
+ throw new Error(`Unknown step type: ${step.type}`);
49
50
  }
50
- return await handler.call(this, step, context)
51
+ return await handler.call(this, step, context);
51
52
  }
52
-
53
53
  /**
54
54
  * 执行多个步骤(顺序)
55
55
  */
56
56
  async executeSteps(steps, context) {
57
- const results = []
57
+ const results = [];
58
58
  for (const step of steps) {
59
- const result = await this.executeStep(step, context)
60
- results.push(result)
59
+ const result = await this.executeStep(step, context);
60
+ results.push(result);
61
61
  }
62
- return results
62
+ return results;
63
63
  }
64
-
65
64
  /**
66
65
  * 获取步骤类型处理器
67
66
  */
@@ -78,378 +77,324 @@ class StepExecutor {
78
77
  [StepType.SEQUENTIAL]: this.executeSequential,
79
78
  [StepType.MESSAGE]: this.executeMessage,
80
79
  [StepType.THINK]: this.executeThink,
81
- [StepType.WORKFLOW]: this.executeWorkflowStep
82
- }
83
- return handlers[type]
80
+ [StepType.WORKFLOW]: this.executeWorkflowStep,
81
+ };
82
+ return handlers[type];
84
83
  }
85
-
86
84
  /**
87
85
  * 执行 switch 步骤
88
86
  */
89
87
  async executeSwitch(step, context) {
90
- console.log(`[StepExecutor] Executing switch: ${step.name || step.id}`)
91
-
92
- const value = this._resolveValue(step.value, context)
93
- const branches = step.branches || []
94
-
88
+ this._log.debug(` Executing switch: ${step.name || step.id}`);
89
+ const value = this._resolveValue(step.value, context);
90
+ const branches = step.branches || [];
95
91
  for (const branch of branches) {
96
- const caseValue = this._resolveValue(branch.case, context)
92
+ const caseValue = this._resolveValue(branch.case, context);
97
93
  if (value === caseValue) {
98
- console.log(`[StepExecutor] Switch matched case: ${caseValue}`)
94
+ this._log.debug(` Switch matched case: ${caseValue}`);
99
95
  if (branch.steps && branch.steps.length > 0) {
100
- return await this.executeSteps(branch.steps, context)
96
+ return await this.executeSteps(branch.steps, context);
101
97
  }
102
- return { matched: caseValue }
98
+ return { matched: caseValue };
103
99
  }
104
100
  }
105
-
106
101
  // 默认分支
107
102
  if (step.default && step.default.steps) {
108
- console.log(`[StepExecutor] Executing switch default branch`)
109
- return await this.executeSteps(step.default.steps, context)
103
+ this._log.debug(` Executing switch default branch`);
104
+ return await this.executeSteps(step.default.steps, context);
110
105
  }
111
-
112
- return { matched: null, value }
106
+ return { matched: null, value };
113
107
  }
114
-
115
108
  /**
116
109
  * 执行 try-catch 步骤
117
110
  */
118
111
  async executeTry(step, context) {
119
- console.log(`[StepExecutor] Executing try-catch: ${step.name || step.id}`)
120
-
112
+ this._log.debug(` Executing try-catch: ${step.name || step.id}`);
121
113
  try {
122
114
  if (step.try && step.try.steps) {
123
- const result = await this.executeSteps(step.try.steps, context)
124
- return { success: true, result }
115
+ const result = await this.executeSteps(step.try.steps, context);
116
+ return { success: true, result };
125
117
  }
126
- return { success: true }
118
+ return { success: true };
127
119
  } catch (err) {
128
- console.log(`[StepExecutor] Try block failed, executing catch: ${err.message}`)
120
+ this._log.debug(` Try block failed, executing catch: ${err.message}`);
129
121
  if (step.catch && step.catch.steps) {
130
- const catchResult = await this.executeSteps(step.catch.steps, context)
131
- return { success: false, error: err.message, caught: catchResult }
122
+ const catchResult = await this.executeSteps(step.catch.steps, context);
123
+ return { success: false, error: err.message, caught: catchResult };
132
124
  }
133
- return { success: false, error: err.message }
125
+ return { success: false, error: err.message };
134
126
  }
135
127
  }
136
-
137
128
  /**
138
129
  * 执行嵌套工作流步骤
139
130
  */
140
131
  async executeWorkflowStep(step, context) {
141
- console.log(`[StepExecutor] Executing nested workflow: ${step.name || step.id}`)
142
-
132
+ this._log.debug(` Executing nested workflow: ${step.name || step.id}`);
143
133
  if (!step.workflow) {
144
- throw new Error('Workflow step requires a workflow definition')
134
+ throw new Error('Workflow step requires a workflow definition');
145
135
  }
146
-
147
136
  // 执行嵌套工作流
148
- const result = await this.framework.pluginManager.get('workflow').executeWorkflow(
149
- step.workflow,
150
- step.input || {},
151
- context.variables._sessionId
152
- )
153
-
137
+ const result = await this.framework.pluginManager
138
+ .get('workflow')
139
+ .executeWorkflow(step.workflow, step.input || {}, context.variables._sessionId);
154
140
  // 将嵌套工作流的输出合并到当前上下文
155
141
  if (result.output) {
156
142
  for (const [key, value] of Object.entries(result.output)) {
157
- context.variables[key] = value
143
+ context.variables[key] = value;
158
144
  }
159
145
  }
160
-
161
- return result
146
+ return result;
162
147
  }
163
-
164
148
  /**
165
149
  * 执行并行步骤
166
150
  */
167
151
  async executeParallel(step, context) {
168
- console.log(`[StepExecutor] Executing parallel: ${step.name || step.id}`)
169
-
170
- const steps = step.steps || []
152
+ this._log.debug(` Executing parallel: ${step.name || step.id}`);
153
+ const steps = step.steps || [];
171
154
  if (steps.length === 0) {
172
- return []
155
+ return [];
173
156
  }
174
-
175
157
  // 并行执行所有步骤
176
- const promises = steps.map(stepConfig => {
177
- return this.executeStep(stepConfig, context)
178
- })
179
-
180
- const results = await Promise.all(promises)
181
- return results
158
+ const promises = steps.map((stepConfig) => {
159
+ return this.executeStep(stepConfig, context);
160
+ });
161
+ const results = await Promise.all(promises);
162
+ return results;
182
163
  }
183
-
184
164
  /**
185
165
  * 执行工具步骤
186
166
  */
187
167
  async executeTool(step, context) {
188
168
  if (!step.tool) {
189
- throw new Error('Tool step requires a tool name')
169
+ throw new Error('Tool step requires a tool name');
190
170
  }
191
-
192
- console.log(`[StepExecutor] Executing tool: ${step.tool}`)
193
-
171
+ this._log.debug(` Executing tool: ${step.tool}`);
194
172
  // 解析工具参数,支持变量引用
195
- let resolvedArgs = this._resolveArgs(step.args || {}, context)
196
-
173
+ let resolvedArgs = this._resolveArgs(step.args || {}, context);
197
174
  // 兼容旧格式:处理 step.input 字段(${stepId.output} 引用)
198
175
  // 将 input 注入到 args.input_data,供 python-execute 使用
199
176
  if (step.input) {
200
- const resolvedInput = this._resolveArgs(step.input, context)
201
- resolvedArgs.input_data = resolvedInput
177
+ const resolvedInput = this._resolveArgs(step.input, context);
178
+ resolvedArgs.input_data = resolvedInput;
202
179
  }
203
-
204
180
  // 获取当前 sessionId
205
- let sessionId = context.variables?._sessionId
181
+ let sessionId = context.variables?._sessionId;
206
182
  if (!sessionId && this.framework.getExecutionContext) {
207
- const ctx = this.framework.getExecutionContext()
208
- sessionId = ctx?.sessionId
183
+ const ctx = this.framework.getExecutionContext();
184
+ sessionId = ctx?.sessionId;
209
185
  }
210
-
211
186
  // 执行工具
212
- let result
187
+ let result;
213
188
  if (sessionId && this.framework.runWithContext) {
214
189
  result = await this.framework.runWithContext(
215
190
  { sessionId },
216
191
  async () => await this.framework.executeTool(step.tool, resolvedArgs)
217
- )
192
+ );
218
193
  } else {
219
- result = await this.framework.executeTool(step.tool, resolvedArgs)
194
+ result = await this.framework.executeTool(step.tool, resolvedArgs);
220
195
  }
221
-
222
196
  // 保存结果到变量
223
197
  // 支持 output 作为 outputVariable 的别名
224
- const outputVar = step.outputVariable || step.output
198
+ const outputVar = step.outputVariable || step.output;
225
199
  if (outputVar) {
226
- context.variables[outputVar] = result
200
+ context.variables[outputVar] = result;
227
201
  }
228
- context.lastResult = result
229
-
202
+ context.lastResult = result;
230
203
  if (result && result.error) {
231
- console.warn(`[StepExecutor] Tool ${step.tool} returned error: ${result.error}`)
204
+ this._log.warn(` Tool ${step.tool} returned error: ${result.error}`);
232
205
  }
233
-
234
- return result
206
+ return result;
235
207
  }
236
-
237
208
  /**
238
209
  * 执行脚本步骤
239
210
  */
240
211
  async executeScript(step, context) {
241
- console.log(`[StepExecutor] Executing script step: ${step.name || step.id}`)
242
-
212
+ this._log.debug(` Executing script step: ${step.name || step.id}`);
213
+ // 安全警告:使用 new Function() 执行用户脚本存在风险
214
+ if (typeof step.script === 'string') {
215
+ this._log.warn(
216
+ ` [SECURITY WARNING] Executing user script via new Function() - ensure script is from trusted source`
217
+ );
218
+ }
243
219
  try {
244
220
  // 兼容旧格式:处理 step.input 字段(${stepId.output} 引用)
245
- let resolvedInput = context.input || {}
221
+ let resolvedInput = context.input || {};
246
222
  if (step.input && typeof step.input === 'object') {
247
- resolvedInput = this._resolveArgs(step.input, context)
223
+ resolvedInput = this._resolveArgs(step.input, context);
248
224
  }
249
-
250
225
  const scriptContext = {
251
226
  input: resolvedInput,
252
- input_data: resolvedInput, // 兼容 input_data 变量名
227
+ input_data: resolvedInput, // 兼容 input_data 变量名
253
228
  variables: context.variables,
254
229
  previousResult: context.lastResult,
255
230
  console: {
256
- log: (...args) => console.log(`[Script:${step.id}]`, ...args)
257
- }
258
- }
259
-
260
- let result
231
+ log: (...args) => {
232
+ const s = logger.child('Script');
233
+ s.debug(`[\${step.id}]`, ...args);
234
+ },
235
+ },
236
+ };
237
+ let result;
261
238
  if (typeof step.script === 'function') {
262
- result = await step.script(scriptContext)
239
+ result = await step.script(scriptContext);
263
240
  } else if (typeof step.script === 'string') {
264
- const fn = new Function('context', `return (async () => { ${step.script} })()`)
265
- result = await fn(scriptContext)
241
+ // 使用沙箱执行用户脚本,防止恶意代码执行
242
+ result = await runScriptSafely(step.script, scriptContext, { timeout: 10000 });
266
243
  }
267
-
268
244
  // 支持 output 作为 outputVariable 的别名
269
- const outputVar = step.outputVariable || step.output
245
+ const outputVar = step.outputVariable || step.output;
270
246
  if (outputVar) {
271
- context.variables[outputVar] = result
247
+ context.variables[outputVar] = result;
272
248
  }
273
- context.lastResult = result
274
-
275
- return result
249
+ context.lastResult = result;
250
+ return result;
276
251
  } catch (err) {
277
- throw new Error(`Script execution failed: ${err.message}`)
252
+ throw new Error(`Script execution failed: ${err.message}`);
278
253
  }
279
254
  }
280
-
281
255
  /**
282
256
  * 执行条件步骤
283
257
  */
284
258
  async executeCondition(step, context) {
285
- console.log(`[StepExecutor] Evaluating condition: ${step.name || step.id}`)
286
-
287
- for (const branch of (step.branches || [])) {
259
+ this._log.debug(` Evaluating condition: ${step.name || step.id}`);
260
+ for (const branch of step.branches || []) {
288
261
  try {
289
- let conditionValue
262
+ let conditionValue;
290
263
  if (typeof branch.condition === 'function') {
291
- conditionValue = branch.condition(context)
264
+ conditionValue = branch.condition(context);
292
265
  } else if (typeof branch.condition === 'string') {
293
- const fn = new Function('context', `with(context.variables) { return (${branch.condition}) }`)
294
- conditionValue = fn(context)
266
+ // 使用沙箱评估条件,防止恶意代码执行
267
+ conditionValue = await evaluateInSandbox(branch.condition, context, { timeout: 5000 });
295
268
  }
296
-
297
269
  if (conditionValue) {
298
- console.log(`[StepExecutor] Condition matched: ${branch.name || branch.stepId}`)
299
-
270
+ this._log.debug(` Condition matched: ${branch.name || branch.stepId}`);
300
271
  if (branch.steps && branch.steps.length > 0) {
301
- await this.executeSteps(branch.steps, context)
272
+ await this.executeSteps(branch.steps, context);
302
273
  }
303
-
304
- return branch.stepId || branch.name
274
+ return branch.stepId || branch.name;
305
275
  }
306
276
  } catch (err) {
307
- console.warn(`[StepExecutor] Branch condition error:`, err.message)
277
+ this._log.warn(` Branch condition error:`, err.message);
308
278
  }
309
279
  }
310
-
311
280
  // 执行默认分支
312
281
  if (step.defaultBranch && step.defaultBranch.steps) {
313
- console.log(`[StepExecutor] Executing default branch`)
314
- await this.executeSteps(step.defaultBranch.steps, context)
282
+ this._log.debug(` Executing default branch`);
283
+ await this.executeSteps(step.defaultBranch.steps, context);
315
284
  }
316
-
317
- return null
285
+ return null;
318
286
  }
319
-
320
287
  /**
321
288
  * 执行循环步骤
322
289
  */
323
290
  async executeLoop(step, context) {
324
- console.log(`[StepExecutor] Executing loop: ${step.name || step.id}`)
325
-
326
- const results = []
327
- const maxIterations = step.maxIterations || 10
328
- const loopVariable = step.loopVariable || 'loopIndex'
329
-
291
+ this._log.debug(` Executing loop: ${step.name || step.id}`);
292
+ const results = [];
293
+ const maxIterations = step.maxIterations || 10;
294
+ const loopVariable = step.loopVariable || 'loopIndex';
330
295
  for (let i = 0; i < maxIterations; i++) {
331
- context.variables[loopVariable] = i
332
- console.log(`[StepExecutor] Loop iteration ${i}`)
333
-
334
- const iterationResults = []
335
- for (const stepConfig of (step.steps || [])) {
336
- const result = await this.executeStep(stepConfig, context)
337
- iterationResults.push(result)
296
+ context.variables[loopVariable] = i;
297
+ this._log.debug(` Loop iteration ${i}`);
298
+ const iterationResults = [];
299
+ for (const stepConfig of step.steps || []) {
300
+ const result = await this.executeStep(stepConfig, context);
301
+ iterationResults.push(result);
338
302
  }
339
- results.push(iterationResults)
340
-
303
+ results.push(iterationResults);
341
304
  // 检查终止条件
342
305
  if (step.until) {
343
- let shouldStop = false
306
+ let shouldStop = false;
344
307
  if (typeof step.until === 'function') {
345
- shouldStop = step.until(context)
308
+ shouldStop = step.until(context);
346
309
  } else if (typeof step.until === 'string') {
347
- const fn = new Function('context', `with(context.variables) { return (${step.until}) }`)
348
- shouldStop = fn(context)
310
+ // 使用沙箱评估循环条件,防止恶意代码执行
311
+ shouldStop = await evaluateInSandbox(step.until, context, { timeout: 5000 });
349
312
  }
350
-
351
313
  if (shouldStop) {
352
- console.log(`[StepExecutor] Loop terminated at iteration ${i}`)
353
- break
314
+ this._log.debug(` Loop terminated at iteration ${i}`);
315
+ break;
354
316
  }
355
317
  }
356
318
  }
357
-
358
- return results
319
+ return results;
359
320
  }
360
-
361
321
  /**
362
322
  * 执行延迟步骤
363
323
  */
364
324
  async executeDelay(step, context) {
365
- const delayMs = step.delayMs || 1000
366
- console.log(`[StepExecutor] Delaying ${delayMs}ms`)
367
- await new Promise(resolve => setTimeout(resolve, delayMs))
368
- return null
325
+ const delayMs = step.delayMs || 1000;
326
+ this._log.debug(` Delaying ${delayMs}ms`);
327
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
328
+ return null;
369
329
  }
370
-
371
330
  /**
372
331
  * 执行顺序步骤
373
332
  */
374
333
  async executeSequential(step, context) {
375
- console.log(`[StepExecutor] Executing sequential: ${step.name || step.id}`)
376
- return await this.executeSteps(step.steps || [], context)
334
+ this._log.debug(` Executing sequential: ${step.name || step.id}`);
335
+ return await this.executeSteps(step.steps || [], context);
377
336
  }
378
-
379
337
  /**
380
338
  * 执行消息步骤(ExplorerLoop 专用)
381
339
  */
382
340
  async executeMessage(step, context) {
383
- console.log(`[StepExecutor] Executing message step`)
384
-
341
+ this._log.debug(` Executing message step`);
385
342
  // 使用子Agent处理消息,避免阻塞主agent
386
343
  const messageAgent = this.framework.createSubAgent({
387
344
  name: 'workflow_message',
388
- role: '工作流任务执行助手,专注于处理工作流中的消息任务'
389
- })
390
-
391
- let content = step.content || ''
345
+ role: '工作流任务执行助手,专注于处理工作流中的消息任务',
346
+ });
347
+ let content = step.content || '';
392
348
  // 支持变量引用
393
- content = this._resolveValue(content, context)
394
-
349
+ content = this._resolveValue(content, context);
395
350
  // 如果有事件上下文,附加到消息
396
351
  if (context.variables?._event) {
397
- content = `${content}\n\n[事件上下文: ${JSON.stringify(context.variables._event)}]`
352
+ content = `${content}\n\n[事件上下文: ${JSON.stringify(context.variables._event)}]`;
398
353
  }
399
-
400
- const result = await messageAgent.chat(content)
401
- return { success: true, result }
354
+ const result = await messageAgent.chat(content);
355
+ return { success: true, result };
402
356
  }
403
-
404
357
  /**
405
358
  * 执行思考步骤(ExplorerLoop 专用)
406
359
  */
407
360
  async executeThink(step, context) {
408
- console.log(`[StepExecutor] Executing think step`)
409
-
410
- const thinkPlugin = this.framework.pluginManager?.get('think')
361
+ this._log.debug(` Executing think step`);
362
+ const thinkPlugin = this.framework.pluginManager?.get('think');
411
363
  if (!thinkPlugin) {
412
- return { success: false, error: '思考插件不可用' }
364
+ return { success: false, error: '思考插件不可用' };
413
365
  }
414
-
415
- let topic = step.topic || 'Ambient代理反思'
416
- topic = this._resolveValue(topic, context)
417
-
366
+ let topic = step.topic || 'Ambient代理反思';
367
+ topic = this._resolveValue(topic, context);
418
368
  if (context.variables?._event) {
419
- topic = `${topic}\n\n[事件上下文: ${JSON.stringify(context.variables._event)}]`
369
+ topic = `${topic}\n\n[事件上下文: ${JSON.stringify(context.variables._event)}]`;
420
370
  }
421
-
422
371
  const result = await thinkPlugin._triggerThinking({
423
372
  topic,
424
373
  mode: step.mode || 'reflect',
425
- depth: step.depth || 2
426
- })
427
-
428
- return result
374
+ depth: step.depth || 2,
375
+ });
376
+ return result;
429
377
  }
430
-
431
378
  /**
432
379
  * 获取活跃代理
433
380
  */
434
381
  _getActiveAgent() {
435
382
  if (this.framework._mainAgent) {
436
- return this.framework._mainAgent
383
+ return this.framework._mainAgent;
437
384
  }
438
- const agents = this.framework._agents || []
439
- return agents.length > 0 ? agents[agents.length - 1] : null
385
+ const agents = this.framework._agents || [];
386
+ return agents.length > 0 ? agents[agents.length - 1] : null;
440
387
  }
441
-
442
388
  /**
443
389
  * 解析参数中的变量引用
444
390
  */
445
391
  _resolveArgs(args, context) {
446
- const resolved = {}
392
+ const resolved = {};
447
393
  for (const [key, value] of Object.entries(args)) {
448
- resolved[key] = this._resolveValue(value, context)
394
+ resolved[key] = this._resolveValue(value, context);
449
395
  }
450
- return resolved
396
+ return resolved;
451
397
  }
452
-
453
398
  _resolveValue(value, context) {
454
399
  if (typeof value === 'string') {
455
400
  // 支持多种引用格式:
@@ -460,290 +405,267 @@ class StepExecutor {
460
405
  // {{lastResult}} - 上一步结果(result 的别名)
461
406
  // ${stepId.output} - 引用指定 id 步骤的输出(兼容旧格式)
462
407
  // ${stepId.output.path} - 从指定步骤输出提取字段
463
- let result = value
464
-
408
+ let result = value;
465
409
  // 先处理 ${stepId.output} 格式(兼容旧格式)
466
410
  result = result.replace(/\$\{([^}]+)\}/g, (match, path) => {
467
- const stepOutputs = context.variables._stepOutputs || {}
411
+ const stepOutputs = context.variables._stepOutputs || {};
468
412
  if (path === 'output') {
469
413
  // ${output} 等同于 ${stepId.output} 引用上一步
470
- return context.lastResult ?? match
414
+ return context.lastResult ?? match;
471
415
  }
472
416
  if (path.includes('.')) {
473
417
  // ${stepId.output.field} 格式
474
- const [stepId, ...fieldParts] = path.split('.')
475
- const stepOutput = stepOutputs[stepId]
418
+ const [stepId, ...fieldParts] = path.split('.');
419
+ const stepOutput = stepOutputs[stepId];
476
420
  if (stepOutput !== undefined) {
477
- const val = this._getNestedValue(stepOutput, fieldParts.join('.'))
478
- if (val !== undefined) return val
421
+ const val = this._getNestedValue(stepOutput, fieldParts.join('.'));
422
+ if (val !== undefined) return val;
479
423
  }
480
424
  } else {
481
425
  // ${stepId.output} 格式
482
- const stepOutput = stepOutputs[path]
483
- if (stepOutput !== undefined) return stepOutput
426
+ const stepOutput = stepOutputs[path];
427
+ if (stepOutput !== undefined) return stepOutput;
484
428
  }
485
- return match
486
- })
487
-
429
+ return match;
430
+ });
488
431
  // 再处理 {{...}} 格式(支持 _event.email.from 等嵌套属性)
489
432
  result = result.replace(/\{\{([^}]+)\}\}/g, (match, path) => {
490
433
  // result 和 lastResult 都指向 context.lastResult
491
434
  if (path === 'result' || path === 'lastResult') {
492
- return context.lastResult ?? match
435
+ return context.lastResult ?? match;
493
436
  }
494
437
  if (path.startsWith('result.') || path.startsWith('lastResult.')) {
495
- const nestedPath = path.replace(/^(result|lastResult)\./, '')
496
- const val = this._getNestedValue(context.lastResult, nestedPath)
497
- if (val !== undefined) return val
498
- return match
438
+ const nestedPath = path.replace(/^(result|lastResult)\./, '');
439
+ const val = this._getNestedValue(context.lastResult, nestedPath);
440
+ if (val !== undefined) return val;
441
+ return match;
499
442
  }
500
443
  if (path.startsWith('variables.')) {
501
- return this._getNestedValue(context, path) ?? match
444
+ return this._getNestedValue(context, path) ?? match;
502
445
  } else if (path.startsWith('context.')) {
503
- return this._getNestedValue(context, path) ?? match
446
+ return this._getNestedValue(context, path) ?? match;
504
447
  } else {
505
448
  // 先从 variables 查找,再从 context 根属性查找
506
- const val = this._getNestedValue(context.variables, path)
507
- if (val !== undefined) return val
508
- return this._getNestedValue(context, path) ?? match
449
+ const val = this._getNestedValue(context.variables, path);
450
+ if (val !== undefined) return val;
451
+ return this._getNestedValue(context, path) ?? match;
509
452
  }
510
- })
511
-
512
- return result
453
+ });
454
+ return result;
513
455
  } else if (Array.isArray(value)) {
514
- return value.map(v => this._resolveValue(v, context))
456
+ return value.map((v) => this._resolveValue(v, context));
515
457
  } else if (typeof value === 'object' && value !== null) {
516
- const resolved = {}
458
+ const resolved = {};
517
459
  for (const [k, v] of Object.entries(value)) {
518
- resolved[k] = this._resolveValue(v, context)
460
+ resolved[k] = this._resolveValue(v, context);
519
461
  }
520
- return resolved
462
+ return resolved;
521
463
  }
522
- return value
464
+ return value;
523
465
  }
524
-
525
466
  _getNestedValue(obj, path) {
526
- if (!obj) return undefined
527
- const parts = path.split('.')
528
- let current = obj
467
+ if (!obj) return undefined;
468
+ const parts = path.split('.');
469
+ let current = obj;
529
470
  for (const part of parts) {
530
- if (current === null || current === undefined) return undefined
471
+ if (current === null || current === undefined) return undefined;
531
472
  // 如果当前值是字符串,尝试解析为 JSON
532
473
  if (typeof current === 'string' && part !== '0' && part !== 'length') {
533
474
  try {
534
- current = JSON.parse(current)
475
+ current = JSON.parse(current);
535
476
  } catch {
536
477
  // 解析失败,继续用原值
537
478
  }
538
479
  }
539
- current = current[part]
480
+ current = current[part];
540
481
  }
541
- return current
482
+ return current;
542
483
  }
543
484
  }
544
-
545
485
  /**
546
486
  * 工作流步骤基类
547
487
  */
548
488
  class WorkflowStep {
549
489
  constructor(config) {
550
- this.id = config.id || `step_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
551
- this.type = config.type
552
- this.name = config.name || ''
553
- this.description = config.description || ''
554
- this.condition = config.condition || null
555
- this.timeout = config.timeout || 30000
556
- this.retry = config.retry || { enabled: false, maxAttempts: 3, delay: 1000 }
557
- this.onSuccess = config.onSuccess || null
558
- this.onFailure = config.onFailure || null
490
+ this.id = config.id || `step_${Date.now()}_${crypto.randomBytes(6).toString('base64url')}`;
491
+ this.type = config.type;
492
+ this.name = config.name || '';
493
+ this.description = config.description || '';
494
+ this.condition = config.condition || null;
495
+ this.timeout = config.timeout || 30000;
496
+ this.retry = config.retry || { enabled: false, maxAttempts: 3, delay: 1000 };
497
+ this.onSuccess = config.onSuccess || null;
498
+ this.onFailure = config.onFailure || null;
559
499
  }
560
-
561
500
  async execute(context, engine) {
562
- throw new Error('execute() must be implemented by subclass')
501
+ throw new Error('execute() must be implemented by subclass');
563
502
  }
564
-
565
503
  validate() {
566
504
  if (!this.type) {
567
- throw new Error('Step must have a type')
505
+ throw new Error('Step must have a type');
568
506
  }
569
- return true
507
+ return true;
570
508
  }
571
509
  }
572
-
573
510
  /**
574
511
  * 脚本步骤
575
512
  */
576
513
  class ScriptStep extends WorkflowStep {
577
514
  constructor(config) {
578
- super({ ...config, type: StepType.SCRIPT })
579
- this.script = config.script
580
- this.outputVariable = config.outputVariable || null
515
+ super({ ...config, type: StepType.SCRIPT });
516
+ this.script = config.script;
517
+ this.outputVariable = config.outputVariable || null;
581
518
  }
582
-
583
519
  async execute(context, engine) {
584
520
  // 使用 StepExecutor 执行脚本逻辑
585
- const executor = new StepExecutor(engine.framework)
521
+ const executor = new StepExecutor(engine.framework);
586
522
  const stepConfig = {
587
523
  id: this.id,
588
524
  name: this.name,
589
525
  type: StepType.SCRIPT,
590
526
  script: this.script,
591
- outputVariable: this.outputVariable
592
- }
593
- return await executor.executeScript(stepConfig, context)
527
+ outputVariable: this.outputVariable,
528
+ };
529
+ return await executor.executeScript(stepConfig, context);
594
530
  }
595
531
  }
596
-
597
532
  /**
598
533
  * 条件步骤
599
534
  */
600
535
  class ConditionStep extends WorkflowStep {
601
536
  constructor(config) {
602
- super({ ...config, type: StepType.CONDITION })
603
- this.branches = config.branches || []
604
- this.defaultBranch = config.defaultBranch || null
537
+ super({ ...config, type: StepType.CONDITION });
538
+ this.branches = config.branches || [];
539
+ this.defaultBranch = config.defaultBranch || null;
605
540
  }
606
-
607
541
  async execute(context, engine) {
608
- const executor = new StepExecutor(engine.framework)
542
+ const executor = new StepExecutor(engine.framework);
609
543
  const stepConfig = {
610
544
  id: this.id,
611
545
  name: this.name,
612
546
  type: StepType.CONDITION,
613
547
  branches: this.branches,
614
- defaultBranch: this.defaultBranch
615
- }
616
- return await executor.executeCondition(stepConfig, context)
548
+ defaultBranch: this.defaultBranch,
549
+ };
550
+ return await executor.executeCondition(stepConfig, context);
617
551
  }
618
552
  }
619
-
620
553
  /**
621
554
  * 并行步骤
622
555
  */
623
556
  class ParallelStep extends WorkflowStep {
624
557
  constructor(config) {
625
- super({ ...config, type: StepType.PARALLEL })
626
- this.steps = config.steps || []
558
+ super({ ...config, type: StepType.PARALLEL });
559
+ this.steps = config.steps || [];
627
560
  }
628
-
629
561
  async execute(context, engine) {
630
- const executor = new StepExecutor(engine.framework)
562
+ const executor = new StepExecutor(engine.framework);
631
563
  const stepConfig = {
632
564
  id: this.id,
633
565
  name: this.name,
634
566
  type: StepType.PARALLEL,
635
- steps: this.steps
636
- }
637
- return await executor.executeParallel(stepConfig, context)
567
+ steps: this.steps,
568
+ };
569
+ return await executor.executeParallel(stepConfig, context);
638
570
  }
639
571
  }
640
-
641
572
  /**
642
573
  * Switch 步骤
643
574
  */
644
575
  class SwitchStep extends WorkflowStep {
645
576
  constructor(config) {
646
- super({ ...config, type: StepType.SWITCH })
647
- this.value = config.value
648
- this.branches = config.branches || []
649
- this.default = config.default || null
577
+ super({ ...config, type: StepType.SWITCH });
578
+ this.value = config.value;
579
+ this.branches = config.branches || [];
580
+ this.default = config.default || null;
650
581
  }
651
-
652
582
  async execute(context, engine) {
653
- const executor = new StepExecutor(engine.framework)
583
+ const executor = new StepExecutor(engine.framework);
654
584
  const stepConfig = {
655
585
  id: this.id,
656
586
  name: this.name,
657
587
  type: StepType.SWITCH,
658
588
  value: this.value,
659
589
  branches: this.branches,
660
- default: this.default
661
- }
662
- return await executor.executeSwitch(stepConfig, context)
590
+ default: this.default,
591
+ };
592
+ return await executor.executeSwitch(stepConfig, context);
663
593
  }
664
594
  }
665
-
666
595
  /**
667
596
  * Try-Catch 步骤
668
597
  */
669
598
  class TryStep extends WorkflowStep {
670
599
  constructor(config) {
671
- super({ ...config, type: StepType.TRY })
672
- this.try = config.try || {}
673
- this.catch = config.catch || {}
600
+ super({ ...config, type: StepType.TRY });
601
+ this.try = config.try || {};
602
+ this.catch = config.catch || {};
674
603
  }
675
-
676
604
  async execute(context, engine) {
677
- const executor = new StepExecutor(engine.framework)
605
+ const executor = new StepExecutor(engine.framework);
678
606
  const stepConfig = {
679
607
  id: this.id,
680
608
  name: this.name,
681
609
  type: StepType.TRY,
682
610
  try: this.try,
683
- catch: this.catch
684
- }
685
- return await executor.executeTry(stepConfig, context)
611
+ catch: this.catch,
612
+ };
613
+ return await executor.executeTry(stepConfig, context);
686
614
  }
687
615
  }
688
-
689
616
  /**
690
617
  * 嵌套工作流步骤
691
618
  */
692
619
  class NestedWorkflowStep extends WorkflowStep {
693
620
  constructor(config) {
694
- super({ ...config, type: StepType.WORKFLOW })
695
- this.workflow = config.workflow
696
- this.input = config.input || {}
621
+ super({ ...config, type: StepType.WORKFLOW });
622
+ this.workflow = config.workflow;
623
+ this.input = config.input || {};
697
624
  }
698
-
699
625
  async execute(context, engine) {
700
- const executor = new StepExecutor(engine.framework)
626
+ const executor = new StepExecutor(engine.framework);
701
627
  const stepConfig = {
702
628
  id: this.id,
703
629
  name: this.name,
704
630
  type: StepType.WORKFLOW,
705
631
  workflow: this.workflow,
706
- input: this.input
707
- }
708
- return await executor.executeWorkflowStep(stepConfig, context)
632
+ input: this.input,
633
+ };
634
+ return await executor.executeWorkflowStep(stepConfig, context);
709
635
  }
710
636
  }
711
-
712
637
  /**
713
638
  * 顺序步骤
714
639
  */
715
640
  class SequentialStep extends WorkflowStep {
716
641
  constructor(config) {
717
- super({ ...config, type: StepType.SEQUENTIAL })
718
- this.steps = config.steps || []
642
+ super({ ...config, type: StepType.SEQUENTIAL });
643
+ this.steps = config.steps || [];
719
644
  }
720
-
721
645
  async execute(context, engine) {
722
- const executor = new StepExecutor(engine.framework)
646
+ const executor = new StepExecutor(engine.framework);
723
647
  const stepConfig = {
724
648
  id: this.id,
725
649
  name: this.name,
726
650
  type: StepType.SEQUENTIAL,
727
- steps: this.steps
728
- }
729
- return await executor.executeSequential(stepConfig, context)
651
+ steps: this.steps,
652
+ };
653
+ return await executor.executeSequential(stepConfig, context);
730
654
  }
731
655
  }
732
-
733
656
  /**
734
657
  * 循环步骤
735
658
  */
736
659
  class LoopStep extends WorkflowStep {
737
660
  constructor(config) {
738
- super({ ...config, type: StepType.LOOP })
739
- this.maxIterations = config.maxIterations || 10
740
- this.loopVariable = config.loopVariable || 'loopIndex'
741
- this.steps = config.steps || []
742
- this.until = config.until || null
661
+ super({ ...config, type: StepType.LOOP });
662
+ this.maxIterations = config.maxIterations || 10;
663
+ this.loopVariable = config.loopVariable || 'loopIndex';
664
+ this.steps = config.steps || [];
665
+ this.until = config.until || null;
743
666
  }
744
-
745
667
  async execute(context, engine) {
746
- const executor = new StepExecutor(engine.framework)
668
+ const executor = new StepExecutor(engine.framework);
747
669
  const stepConfig = {
748
670
  id: this.id,
749
671
  name: this.name,
@@ -751,48 +673,44 @@ class LoopStep extends WorkflowStep {
751
673
  maxIterations: this.maxIterations,
752
674
  loopVariable: this.loopVariable,
753
675
  steps: this.steps,
754
- until: this.until
755
- }
756
- return await executor.executeLoop(stepConfig, context)
676
+ until: this.until,
677
+ };
678
+ return await executor.executeLoop(stepConfig, context);
757
679
  }
758
680
  }
759
-
760
681
  /**
761
682
  * 延迟步骤
762
683
  */
763
684
  class DelayStep extends WorkflowStep {
764
685
  constructor(config) {
765
- super({ ...config, type: StepType.DELAY })
766
- this.delayMs = config.delayMs || 1000
686
+ super({ ...config, type: StepType.DELAY });
687
+ this.delayMs = config.delayMs || 1000;
767
688
  }
768
-
769
689
  async execute(context, engine) {
770
- const executor = new StepExecutor(engine.framework)
690
+ const executor = new StepExecutor(engine.framework);
771
691
  const stepConfig = {
772
692
  id: this.id,
773
693
  name: this.name,
774
694
  type: StepType.DELAY,
775
- delayMs: this.delayMs
776
- }
777
- return await executor.executeDelay(stepConfig, context)
695
+ delayMs: this.delayMs,
696
+ };
697
+ return await executor.executeDelay(stepConfig, context);
778
698
  }
779
699
  }
780
-
781
700
  /**
782
701
  * 工具步骤
783
702
  */
784
703
  class ToolStep extends WorkflowStep {
785
704
  constructor(config) {
786
- super({ ...config, type: StepType.TOOL })
787
- this.tool = config.tool
788
- this.args = config.args || {}
789
- this.outputVariable = config.outputVariable || null
790
- this.output = config.output || null // 兼容旧格式
791
- this.input = config.input || null // 兼容旧格式:input 字段
705
+ super({ ...config, type: StepType.TOOL });
706
+ this.tool = config.tool;
707
+ this.args = config.args || {};
708
+ this.outputVariable = config.outputVariable || null;
709
+ this.output = config.output || null; // 兼容旧格式
710
+ this.input = config.input || null; // 兼容旧格式:input 字段
792
711
  }
793
-
794
712
  async execute(context, engine) {
795
- const executor = new StepExecutor(engine.framework)
713
+ const executor = new StepExecutor(engine.framework);
796
714
  const stepConfig = {
797
715
  id: this.id,
798
716
  name: this.name,
@@ -800,31 +718,28 @@ class ToolStep extends WorkflowStep {
800
718
  tool: this.tool,
801
719
  args: this.args,
802
720
  outputVariable: this.outputVariable,
803
- output: this.output, // 传递 output
804
- input: this.input // 传递 input
805
- }
806
- return await executor.executeTool(stepConfig, context)
721
+ output: this.output, // 传递 output
722
+ input: this.input, // 传递 input
723
+ };
724
+ return await executor.executeTool(stepConfig, context);
807
725
  }
808
726
  }
809
-
810
727
  /**
811
728
  * 工作流引擎
812
729
  */
813
730
  class WorkflowEngine extends EventEmitter {
814
731
  constructor(framework) {
815
- super()
816
- this.framework = framework
817
- this._steps = new Map()
732
+ super();
733
+ this.framework = framework;
734
+ this._steps = new Map();
818
735
  }
819
-
820
736
  /**
821
737
  * 注册自定义步骤类型
822
738
  */
823
739
  registerStepType(type, StepClass) {
824
- this._steps.set(type, StepClass)
740
+ this._steps.set(type, StepClass);
825
741
  }
826
-
827
- /**
742
+ /**
828
743
  * 创建步骤实例
829
744
  * 自动推断步骤类型:
830
745
  * - 有 tool 字段 -> tool 类型
@@ -839,51 +754,47 @@ class WorkflowEngine extends EventEmitter {
839
754
  * - 有 workflow 字段 -> workflow 类型
840
755
  */
841
756
  createStep(config) {
842
- let type = config.type
843
-
757
+ let type = config.type;
844
758
  // 自动推断类型
845
759
  if (!type) {
846
760
  if (config.tool) {
847
- type = StepType.TOOL
761
+ type = StepType.TOOL;
848
762
  } else if (config.code || config.script) {
849
- type = StepType.SCRIPT
763
+ type = StepType.SCRIPT;
850
764
  } else if (config.try || config.catch) {
851
- type = StepType.TRY
765
+ type = StepType.TRY;
852
766
  } else if (config.value !== undefined && config.branches) {
853
- type = StepType.SWITCH
767
+ type = StepType.SWITCH;
854
768
  } else if (config.parallel === true || config.mode === 'parallel') {
855
- type = StepType.PARALLEL
769
+ type = StepType.PARALLEL;
856
770
  } else if (config.workflow) {
857
- type = StepType.WORKFLOW
771
+ type = StepType.WORKFLOW;
858
772
  } else if (config.branches) {
859
- type = StepType.CONDITION
773
+ type = StepType.CONDITION;
860
774
  } else if (config.steps && (config.loopVariable || config.maxIterations)) {
861
- type = StepType.LOOP
775
+ type = StepType.LOOP;
862
776
  } else if (config.steps) {
863
- type = StepType.SEQUENTIAL
777
+ type = StepType.SEQUENTIAL;
864
778
  } else if (config.delayMs !== undefined) {
865
- type = StepType.DELAY
779
+ type = StepType.DELAY;
866
780
  } else if (config.message) {
867
- type = StepType.MESSAGE
781
+ type = StepType.MESSAGE;
868
782
  } else if (config.topic) {
869
- type = StepType.THINK
783
+ type = StepType.THINK;
870
784
  }
871
785
  }
872
-
873
786
  if (!type) {
874
- throw new Error(`Cannot infer step type for step: ${JSON.stringify(config).substring(0, 100)}`)
787
+ throw new Error(
788
+ `Cannot infer step type for step: ${JSON.stringify(config).substring(0, 100)}`
789
+ );
875
790
  }
876
-
877
- const StepClass = this._steps.get(type)
878
-
791
+ const StepClass = this._steps.get(type);
879
792
  if (!StepClass) {
880
- throw new Error(`Unknown step type: ${type}`)
793
+ throw new Error(`Unknown step type: ${type}`);
881
794
  }
882
-
883
795
  // 确保配置有 type 字段
884
- return new StepClass({ ...config, type })
796
+ return new StepClass({ ...config, type });
885
797
  }
886
-
887
798
  /**
888
799
  * 创建工作流上下文
889
800
  */
@@ -892,290 +803,293 @@ class WorkflowEngine extends EventEmitter {
892
803
  input,
893
804
  variables,
894
805
  lastResult: null,
895
- results: []
896
- }
806
+ results: [],
807
+ };
897
808
  }
898
809
  }
899
-
900
810
  /**
901
811
  * WorkflowManagerPlugin
902
812
  */
903
813
  class WorkflowPlugin extends Plugin {
904
814
  constructor(config = {}) {
905
- super()
906
- this.name = 'workflow'
907
- this.version = '1.0.0'
908
- this.description = '工作流引擎,支持结构化工作流定义和执行'
909
- this.priority = 6
910
- this.system = true
911
-
912
- this._framework = null
913
- this._engine = null
914
- this._workflowsDir = config.workflowsDir || '.agent/workflows'
915
- this._workflows = new Map()
916
- this._workflowTools = new Map()
815
+ super();
816
+ this.name = 'workflow';
817
+ this.version = '1.0.0';
818
+ this.description = '工作流引擎,支持结构化工作流定义和执行';
819
+ this.priority = 6;
820
+ this.system = true;
821
+ this._framework = null;
822
+ this._engine = null;
823
+ this._workflowsDir = config.workflowsDir || '.agent/workflows';
824
+ this._workflows = new Map();
825
+ this._workflowTools = new Map();
917
826
  }
918
-
919
827
  install(framework) {
920
- this._framework = framework
921
- this._engine = new WorkflowEngine(framework)
922
-
828
+ this._framework = framework;
829
+ this._engine = new WorkflowEngine(framework);
923
830
  // 注册内置步骤类型
924
- this._engine.registerStepType(StepType.SCRIPT, ScriptStep)
925
- this._engine.registerStepType(StepType.CONDITION, ConditionStep)
926
- this._engine.registerStepType(StepType.SWITCH, SwitchStep)
927
- this._engine.registerStepType(StepType.TRY, TryStep)
928
- this._engine.registerStepType(StepType.PARALLEL, ParallelStep)
929
- this._engine.registerStepType(StepType.SEQUENTIAL, SequentialStep)
930
- this._engine.registerStepType(StepType.LOOP, LoopStep)
931
- this._engine.registerStepType(StepType.DELAY, DelayStep)
932
- this._engine.registerStepType(StepType.TOOL, ToolStep)
933
- this._engine.registerStepType(StepType.WORKFLOW, NestedWorkflowStep)
934
-
831
+ this._engine.registerStepType(StepType.SCRIPT, ScriptStep);
832
+ this._engine.registerStepType(StepType.CONDITION, ConditionStep);
833
+ this._engine.registerStepType(StepType.SWITCH, SwitchStep);
834
+ this._engine.registerStepType(StepType.TRY, TryStep);
835
+ this._engine.registerStepType(StepType.PARALLEL, ParallelStep);
836
+ this._engine.registerStepType(StepType.SEQUENTIAL, SequentialStep);
837
+ this._engine.registerStepType(StepType.LOOP, LoopStep);
838
+ this._engine.registerStepType(StepType.DELAY, DelayStep);
839
+ this._engine.registerStepType(StepType.TOOL, ToolStep);
840
+ this._engine.registerStepType(StepType.WORKFLOW, NestedWorkflowStep);
935
841
  // 注册工作流执行工具
936
842
  framework.registerTool({
937
843
  name: 'execute_workflow',
938
844
  description: '执行指定的工作流',
939
845
  inputSchema: z.object({
940
846
  workflow: z.string().describe('工作流定义(JSON 或 JavaScript 代码)'),
941
- input: z.object({}).optional().describe('工作流输入参数')
847
+ input: z.object({}).optional().describe('工作流输入参数'),
942
848
  }),
943
849
  execute: async (args, framework) => {
944
850
  // 获取当前 sessionId
945
- let sessionId = null
946
- const ctx = framework.getExecutionContext()
851
+ let sessionId = null;
852
+ const ctx = framework.getExecutionContext();
947
853
  if (ctx?.sessionId) {
948
- sessionId = ctx.sessionId
854
+ sessionId = ctx.sessionId;
949
855
  }
950
- return await this.executeWorkflow(args.workflow, args.input || {}, sessionId)
951
- }
952
- })
953
-
954
- return this
856
+ return await this.executeWorkflow(args.workflow, args.input || {}, sessionId);
857
+ },
858
+ });
859
+ return this;
955
860
  }
956
-
957
861
  start(framework) {
958
- this._loadWorkflows()
959
- this._registerWorkflowTools()
960
-
862
+ this._loadWorkflows();
863
+ this._registerWorkflowTools();
961
864
  // 注册 reloadWorkflows 工具
962
865
  framework.registerTool({
963
866
  name: 'reloadWorkflows',
964
867
  description: '重载所有工作流,当用户添加或修改工作流后调用此工具',
965
868
  inputSchema: z.object({}),
966
869
  execute: async () => {
967
- this.reload(this._framework)
870
+ this.reload(this._framework);
968
871
  return {
969
872
  success: true,
970
873
  message: `Workflows reloaded. Total: ${this._workflows.size}`,
971
- workflows: Array.from(this._workflows.keys())
972
- }
973
- }
974
- })
975
-
976
- return this
874
+ workflows: Array.from(this._workflows.keys()),
875
+ };
876
+ },
877
+ });
878
+ return this;
977
879
  }
978
-
979
880
  /**
980
881
  * 加载目录中的工作流定义
981
882
  */
982
883
  _loadWorkflows() {
983
- const dir = path.resolve(process.cwd(), this._workflowsDir)
884
+ const dir = path.resolve(process.cwd(), this._workflowsDir);
984
885
  if (!fs.existsSync(dir)) {
985
- fs.mkdirSync(dir, { recursive: true })
986
- console.log(`[Workflow] Created workflows directory: ${dir}`)
987
- return
886
+ fs.mkdirSync(dir, { recursive: true });
887
+ log.info(` Created workflows directory: ${dir}`);
888
+ return;
988
889
  }
989
-
990
890
  try {
991
- const files = fs.readdirSync(dir)
891
+ const files = fs.readdirSync(dir);
992
892
  for (const file of files) {
993
- if (!file.endsWith('.json') && !file.endsWith('.js')) continue
994
-
995
- const filePath = path.join(dir, file)
996
- const workflowName = path.basename(file, path.extname(file))
997
-
893
+ if (!file.endsWith('.json') && !file.endsWith('.js')) continue;
894
+ const filePath = path.join(dir, file);
895
+ const workflowName = path.basename(file, path.extname(file));
998
896
  // 跳过已存在的工作流
999
- if (this._workflows.has(workflowName)) continue
1000
-
897
+ if (this._workflows.has(workflowName)) continue;
1001
898
  try {
1002
- const content = fs.readFileSync(filePath, 'utf-8')
1003
- let workflowDef
1004
-
899
+ const content = fs.readFileSync(filePath, 'utf-8');
900
+ let workflowDef;
1005
901
  if (file.endsWith('.js')) {
1006
902
  // 执行 JS 文件获取工作流定义
1007
- // eslint-disable-next-line no-new-func
1008
- const fn = new Function('module', 'exports', 'require', 'process', 'console', '__dirname', '__filename', content)
1009
- const module = { exports: {} }
1010
- fn(module, module.exports, require, process, console, path.dirname(filePath), filePath)
1011
- workflowDef = module.exports.default || module.exports
903
+ // 使用沙箱加载工作流文件,防止恶意代码执行
904
+ workflowDef = runWorkflowFileSafely(content, { timeout: 10000 });
905
+ if (typeof workflowDef === 'function') {
906
+ workflowDef = workflowDef(this._engine || {});
907
+ }
908
+ workflowDef = workflowDef.default || workflowDef;
1012
909
  } else {
1013
- workflowDef = JSON.parse(content)
910
+ workflowDef = JSON.parse(content);
1014
911
  }
1015
-
1016
912
  if (workflowDef && workflowDef.steps) {
1017
- this._workflows.set(workflowName, workflowDef)
1018
- //console.log(`[Workflow] Loaded: ${workflowName}`)
913
+ this._workflows.set(workflowName, workflowDef);
914
+ //log.info(` Loaded: ${workflowName}`)
1019
915
  }
1020
916
  } catch (err) {
1021
- console.error(`[Workflow] Failed to load ${file}:`, err.message)
917
+ log.error(` Failed to load ${file}:`, err.message);
1022
918
  }
1023
919
  }
1024
920
  } catch (err) {
1025
- console.error('[Workflow] Failed to read workflows directory:', err.message)
921
+ log.error(' Failed to read workflows directory:', err.message);
1026
922
  }
1027
923
  }
1028
-
1029
924
  /**
1030
925
  * 注册工作流为工具
1031
926
  */
1032
927
  _registerWorkflowTools() {
1033
928
  for (const [name, workflow] of this._workflows) {
1034
- if (this._workflowTools.has(name)) continue
1035
-
1036
- const toolName = `workflow_${name}`
1037
- const description = workflow.description || `执行工作流: ${name}`
1038
-
929
+ if (this._workflowTools.has(name)) continue;
930
+ const toolName = `workflow_${name}`;
931
+ const description = workflow.description || `执行工作流: ${name}`;
1039
932
  this._framework.registerTool({
1040
933
  name: toolName,
1041
934
  description,
1042
935
  inputSchema: z.object({
1043
- input: z.object({}).optional().describe('工作流输入参数')
936
+ input: z.object({}).optional().describe('工作流输入参数'),
1044
937
  }),
1045
- execute: async (args) => {
1046
- return await this.executeWorkflow(workflow, args.input || {})
1047
- }
1048
- })
1049
-
1050
- this._workflowTools.set(name, toolName)
1051
- console.log(`[Workflow] Registered tool: ${toolName}`)
938
+ execute: async (args, framework) => {
939
+ // Get current sessionId to ensure notifications reach the correct session
940
+ let sessionId = null;
941
+ const ctx = framework?.getExecutionContext?.();
942
+ if (ctx?.sessionId) {
943
+ sessionId = ctx.sessionId;
944
+ }
945
+ return await this.executeWorkflow(workflow, args.input || {}, sessionId);
946
+ },
947
+ });
948
+ this._workflowTools.set(name, toolName);
949
+ log.info(` Registered tool: ${toolName}`);
1052
950
  }
1053
951
  }
1054
-
1055
952
  /**
1056
953
  * 重载工作流
1057
954
  */
1058
955
  reload(framework) {
1059
- console.log('[Workflow] Reloading...')
1060
- this._framework = framework
1061
-
956
+ // 清除模块缓存,确保重新加载最新代码
957
+ const modulePath = require.resolve('./src/capabilities/workflow-engine');
958
+ if (require.cache[modulePath]) {
959
+ delete require.cache[modulePath];
960
+ }
961
+ log.info(' Reloading...');
962
+ this._framework = framework;
1062
963
  // 重新创建 engine(确保使用最新代码)
1063
- this._engine = new (require('./src/capabilities/workflow-engine').WorkflowEngine)(framework)
1064
-
964
+ this._engine = new (require('./src/capabilities/workflow-engine').WorkflowEngine)(framework);
1065
965
  // 注册内置步骤类型
1066
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.SCRIPT, require('./src/capabilities/workflow-engine').ScriptStep)
1067
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.TOOL, require('./src/capabilities/workflow-engine').ToolStep)
1068
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.CONDITION, require('./src/capabilities/workflow-engine').ConditionStep)
1069
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.SWITCH, require('./src/capabilities/workflow-engine').SwitchStep)
1070
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.TRY, require('./src/capabilities/workflow-engine').TryStep)
1071
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.PARALLEL, require('./src/capabilities/workflow-engine').ParallelStep)
1072
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.SEQUENTIAL, require('./src/capabilities/workflow-engine').SequentialStep)
1073
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.LOOP, require('./src/capabilities/workflow-engine').LoopStep)
1074
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.DELAY, require('./src/capabilities/workflow-engine').DelayStep)
1075
- this._engine.registerStepType(require('./src/capabilities/workflow-engine').StepType.WORKFLOW, require('./src/capabilities/workflow-engine').NestedWorkflowStep)
1076
-
966
+ this._engine.registerStepType(
967
+ require('./src/capabilities/workflow-engine').StepType.SCRIPT,
968
+ require('./src/capabilities/workflow-engine').ScriptStep
969
+ );
970
+ this._engine.registerStepType(
971
+ require('./src/capabilities/workflow-engine').StepType.TOOL,
972
+ require('./src/capabilities/workflow-engine').ToolStep
973
+ );
974
+ this._engine.registerStepType(
975
+ require('./src/capabilities/workflow-engine').StepType.CONDITION,
976
+ require('./src/capabilities/workflow-engine').ConditionStep
977
+ );
978
+ this._engine.registerStepType(
979
+ require('./src/capabilities/workflow-engine').StepType.SWITCH,
980
+ require('./src/capabilities/workflow-engine').SwitchStep
981
+ );
982
+ this._engine.registerStepType(
983
+ require('./src/capabilities/workflow-engine').StepType.TRY,
984
+ require('./src/capabilities/workflow-engine').TryStep
985
+ );
986
+ this._engine.registerStepType(
987
+ require('./src/capabilities/workflow-engine').StepType.PARALLEL,
988
+ require('./src/capabilities/workflow-engine').ParallelStep
989
+ );
990
+ this._engine.registerStepType(
991
+ require('./src/capabilities/workflow-engine').StepType.SEQUENTIAL,
992
+ require('./src/capabilities/workflow-engine').SequentialStep
993
+ );
994
+ this._engine.registerStepType(
995
+ require('./src/capabilities/workflow-engine').StepType.LOOP,
996
+ require('./src/capabilities/workflow-engine').LoopStep
997
+ );
998
+ this._engine.registerStepType(
999
+ require('./src/capabilities/workflow-engine').StepType.DELAY,
1000
+ require('./src/capabilities/workflow-engine').DelayStep
1001
+ );
1002
+ this._engine.registerStepType(
1003
+ require('./src/capabilities/workflow-engine').StepType.WORKFLOW,
1004
+ require('./src/capabilities/workflow-engine').NestedWorkflowStep
1005
+ );
1077
1006
  // 清除已注册的工具
1078
1007
  for (const toolName of this._workflowTools.values()) {
1079
1008
  // 工具注销需要框架支持,这里只清理内部状态
1080
1009
  }
1081
- this._workflowTools.clear()
1082
- this._workflows.clear()
1083
-
1010
+ this._workflowTools.clear();
1011
+ this._workflows.clear();
1084
1012
  // 重新加载
1085
- this._loadWorkflows()
1086
- this._registerWorkflowTools()
1087
-
1088
- console.log(`[Workflow] Reloaded. Total workflows: ${this._workflows.size}`)
1013
+ this._loadWorkflows();
1014
+ this._registerWorkflowTools();
1015
+ log.info(` Reloaded. Total workflows: ${this._workflows.size}`);
1089
1016
  }
1090
-
1091
1017
  /**
1092
1018
  * 执行工作流
1093
1019
  */
1094
1020
  async executeWorkflow(workflowDef, input = {}, sessionId = null) {
1095
1021
  try {
1096
- let workflow
1097
-
1022
+ let workflow;
1098
1023
  if (typeof workflowDef === 'string') {
1099
1024
  // 尝试作为工作流名称加载(先检查是否已加载的工作流)
1100
- const workflowName = workflowDef.trim()
1025
+ const workflowName = workflowDef.trim();
1101
1026
  if (this._workflows.has(workflowName)) {
1102
- workflow = this._workflows.get(workflowName)
1027
+ workflow = this._workflows.get(workflowName);
1103
1028
  } else {
1104
1029
  // 尝试解析 JSON 或执行代码
1105
1030
  try {
1106
- workflow = JSON.parse(workflowDef)
1031
+ workflow = JSON.parse(workflowDef);
1107
1032
  } catch {
1108
- // eslint-disable-next-line no-new-func
1109
- const fn = new Function('engine', 'return (' + workflowDef + ')')
1110
- workflow = fn(this._engine)
1033
+ // 使用沙箱解析工作流定义,防止恶意代码执行
1034
+ workflow = runWorkflowSafely(workflowDef, this._engine, { timeout: 5000 });
1111
1035
  }
1112
1036
  }
1113
1037
  } else {
1114
- workflow = workflowDef
1038
+ workflow = workflowDef;
1115
1039
  }
1116
-
1117
- const context = this._engine.createContext(input, {})
1118
-
1040
+ const context = this._engine.createContext(input, {});
1119
1041
  // 将 sessionId 存储到上下文变量,供工具步骤使用
1120
1042
  if (sessionId) {
1121
- context.variables._sessionId = sessionId
1043
+ context.variables._sessionId = sessionId;
1122
1044
  }
1123
-
1124
1045
  // 执行工作流步骤
1125
1046
  if (workflow.steps && Array.isArray(workflow.steps)) {
1126
- const results = []
1047
+ const results = [];
1127
1048
  // 按 id 存储步骤输出,供 ${id.output} 引用
1128
- context.variables._stepOutputs = {}
1049
+ context.variables._stepOutputs = {};
1129
1050
  for (const stepConfig of workflow.steps) {
1130
- const step = this._engine.createStep(stepConfig)
1131
- const result = await step.execute(context, this._engine)
1132
- results.push(result)
1051
+ const step = this._engine.createStep(stepConfig);
1052
+ const result = await step.execute(context, this._engine);
1053
+ results.push(result);
1133
1054
  // 如果步骤有 id,存储其输出
1134
1055
  if (stepConfig.id) {
1135
- context.variables._stepOutputs[stepConfig.id] = result
1056
+ context.variables._stepOutputs[stepConfig.id] = result;
1136
1057
  }
1137
1058
  }
1138
-
1139
1059
  // 只返回最后一步的结果(包含最终输出)和成功状态
1140
1060
  // 不返回所有中间结果,避免上下文超限
1141
- const lastResult = results.length > 0 ? results[results.length - 1] : null
1142
-
1061
+ const lastResult = results.length > 0 ? results[results.length - 1] : null;
1143
1062
  // 从 context.variables 中提取非下划线开头的用户变量
1144
1063
  // 下划线开头的是内部变量(如 _stepOutputs),不需要返回
1145
- const userVariables = {}
1064
+ const userVariables = {};
1146
1065
  for (const [key, value] of Object.entries(context.variables)) {
1147
1066
  if (!key.startsWith('_')) {
1148
- userVariables[key] = value
1067
+ userVariables[key] = value;
1149
1068
  }
1150
1069
  }
1151
-
1152
1070
  return {
1153
1071
  success: true,
1154
1072
  stepCount: workflow.steps.length,
1155
1073
  result: lastResult,
1156
- output: userVariables
1157
- }
1074
+ output: userVariables,
1075
+ };
1158
1076
  }
1159
-
1160
- return { success: true, output: {} }
1077
+ return { success: true, output: {} };
1161
1078
  } catch (err) {
1162
- return { success: false, error: err.message }
1079
+ return { success: false, error: err.message };
1163
1080
  }
1164
1081
  }
1165
-
1166
1082
  /**
1167
1083
  * 获取引擎
1168
1084
  */
1169
1085
  getEngine() {
1170
- return this._engine
1086
+ return this._engine;
1171
1087
  }
1172
-
1173
1088
  uninstall(framework) {
1174
- this._engine = null
1175
- this._framework = null
1089
+ this._engine = null;
1090
+ this._framework = null;
1176
1091
  }
1177
1092
  }
1178
-
1179
1093
  module.exports = {
1180
1094
  WorkflowPlugin,
1181
1095
  WorkflowEngine,
@@ -1191,5 +1105,5 @@ module.exports = {
1191
1105
  SequentialStep,
1192
1106
  LoopStep,
1193
1107
  DelayStep,
1194
- ToolStep
1195
- }
1108
+ ToolStep,
1109
+ };