foliko 1.0.65 → 1.0.67

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.
@@ -22,74 +22,130 @@ const StepType = {
22
22
  DELAY: 'delay',
23
23
  TOOL: 'tool',
24
24
  INPUT: 'input',
25
- OUTPUT: 'output'
25
+ OUTPUT: 'output',
26
+ MESSAGE: 'message',
27
+ THINK: 'think'
26
28
  }
27
29
 
28
30
  /**
29
- * 工作流步骤基类
31
+ * StepExecutor - 统一的步骤执行器
32
+ * 同时被 WorkflowEngine 和 ExplorerLoop 使用
30
33
  */
31
- class WorkflowStep {
32
- constructor(config) {
33
- this.id = config.id || `step_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
34
- this.type = config.type
35
- this.name = config.name || ''
36
- this.description = config.description || ''
37
- this.condition = config.condition || null
38
- this.timeout = config.timeout || 30000
39
- this.retry = config.retry || { enabled: false, maxAttempts: 3, delay: 1000 }
40
- this.onSuccess = config.onSuccess || null
41
- this.onFailure = config.onFailure || null
34
+ class StepExecutor {
35
+ constructor(framework) {
36
+ this.framework = framework
42
37
  }
43
38
 
44
- async execute(context, engine) {
45
- throw new Error('execute() must be implemented by subclass')
39
+ /**
40
+ * 执行单个步骤
41
+ */
42
+ async executeStep(step, context) {
43
+ const handler = this._getStepHandler(step.type)
44
+ if (!handler) {
45
+ throw new Error(`Unknown step type: ${step.type}`)
46
+ }
47
+ return await handler.call(this, step, context)
46
48
  }
47
49
 
48
- validate() {
49
- if (!this.type) {
50
- throw new Error('Step must have a type')
50
+ /**
51
+ * 执行多个步骤(顺序)
52
+ */
53
+ async executeSteps(steps, context) {
54
+ const results = []
55
+ for (const step of steps) {
56
+ const result = await this.executeStep(step, context)
57
+ results.push(result)
51
58
  }
52
- return true
59
+ return results
53
60
  }
54
- }
55
61
 
56
- /**
57
- * 脚本步骤
58
- */
59
- class ScriptStep extends WorkflowStep {
60
- constructor(config) {
61
- super({ ...config, type: StepType.SCRIPT })
62
- this.script = config.script
63
- this.outputVariable = config.outputVariable || null
62
+ /**
63
+ * 获取步骤类型处理器
64
+ */
65
+ _getStepHandler(type) {
66
+ const handlers = {
67
+ [StepType.TOOL]: this.executeTool,
68
+ [StepType.SCRIPT]: this.executeScript,
69
+ [StepType.CONDITION]: this.executeCondition,
70
+ [StepType.LOOP]: this.executeLoop,
71
+ [StepType.DELAY]: this.executeDelay,
72
+ [StepType.SEQUENTIAL]: this.executeSequential,
73
+ [StepType.MESSAGE]: this.executeMessage,
74
+ [StepType.THINK]: this.executeThink
75
+ }
76
+ return handlers[type]
64
77
  }
65
78
 
66
- async execute(context, engine) {
67
- console.log(`[Workflow] Executing script step: ${this.name || this.id}`)
79
+ /**
80
+ * 执行工具步骤
81
+ */
82
+ async executeTool(step, context) {
83
+ if (!step.tool) {
84
+ throw new Error('Tool step requires a tool name')
85
+ }
86
+
87
+ console.log(`[StepExecutor] Executing tool: ${step.tool}`)
88
+
89
+ // 解析工具参数,支持变量引用
90
+ const resolvedArgs = this._resolveArgs(step.args || {}, context)
91
+
92
+ // 获取当前 sessionId
93
+ let sessionId = context.variables?._sessionId
94
+ if (!sessionId && this.framework.getExecutionContext) {
95
+ const ctx = this.framework.getExecutionContext()
96
+ sessionId = ctx?.sessionId
97
+ }
98
+
99
+ // 执行工具
100
+ let result
101
+ if (sessionId && this.framework.runWithContext) {
102
+ result = await this.framework.runWithContext(
103
+ { sessionId },
104
+ async () => await this.framework.executeTool(step.tool, resolvedArgs)
105
+ )
106
+ } else {
107
+ result = await this.framework.executeTool(step.tool, resolvedArgs)
108
+ }
109
+
110
+ // 保存结果到变量
111
+ if (step.outputVariable) {
112
+ context.variables[step.outputVariable] = result
113
+ }
114
+ context.lastResult = result
115
+
116
+ if (result && result.error) {
117
+ console.warn(`[StepExecutor] Tool ${step.tool} returned error: ${result.error}`)
118
+ }
119
+
120
+ return result
121
+ }
122
+
123
+ /**
124
+ * 执行脚本步骤
125
+ */
126
+ async executeScript(step, context) {
127
+ console.log(`[StepExecutor] Executing script step: ${step.name || step.id}`)
68
128
 
69
129
  try {
70
- // 创建安全的脚本执行环境
71
130
  const scriptContext = {
72
131
  input: context.input,
73
132
  variables: context.variables,
74
133
  previousResult: context.lastResult,
75
134
  console: {
76
- log: (...args) => console.log(`[Script:${this.id}]`, ...args)
135
+ log: (...args) => console.log(`[Script:${step.id}]`, ...args)
77
136
  }
78
137
  }
79
138
 
80
- // 执行脚本
81
139
  let result
82
- if (typeof this.script === 'function') {
83
- result = await this.script(scriptContext)
84
- } else if (typeof this.script === 'string') {
85
- // eslint-disable-next-line no-new-func
86
- const fn = new Function('context', `return (async () => { ${this.script} })()`)
140
+ if (typeof step.script === 'function') {
141
+ result = await step.script(scriptContext)
142
+ } else if (typeof step.script === 'string') {
143
+ const fn = new Function('context', `return (async () => { ${step.script} })()`)
87
144
  result = await fn(scriptContext)
88
145
  }
89
146
 
90
- // 保存结果到变量
91
- if (this.outputVariable) {
92
- context.variables[this.outputVariable] = result
147
+ if (step.outputVariable) {
148
+ context.variables[step.outputVariable] = result
93
149
  }
94
150
  context.lastResult = result
95
151
 
@@ -98,128 +154,79 @@ class ScriptStep extends WorkflowStep {
98
154
  throw new Error(`Script execution failed: ${err.message}`)
99
155
  }
100
156
  }
101
- }
102
157
 
103
- /**
104
- * 条件步骤
105
- */
106
- class ConditionStep extends WorkflowStep {
107
- constructor(config) {
108
- super({ ...config, type: StepType.CONDITION })
109
- this.branches = config.branches || []
110
- this.defaultBranch = config.defaultBranch || null
111
- }
112
-
113
- async execute(context, engine) {
114
- console.log(`[Workflow] Evaluating condition: ${this.name || this.id}`)
158
+ /**
159
+ * 执行条件步骤
160
+ */
161
+ async executeCondition(step, context) {
162
+ console.log(`[StepExecutor] Evaluating condition: ${step.name || step.id}`)
115
163
 
116
- for (const branch of this.branches) {
164
+ for (const branch of (step.branches || [])) {
117
165
  try {
118
166
  let conditionValue
119
167
  if (typeof branch.condition === 'function') {
120
168
  conditionValue = branch.condition(context)
121
169
  } else if (typeof branch.condition === 'string') {
122
- // eslint-disable-next-line no-new-func
123
170
  const fn = new Function('context', `with(context.variables) { return (${branch.condition}) }`)
124
171
  conditionValue = fn(context)
125
172
  }
126
173
 
127
174
  if (conditionValue) {
128
- console.log(`[Workflow] Condition matched: ${branch.name || branch.stepId}`)
175
+ console.log(`[StepExecutor] Condition matched: ${branch.name || branch.stepId}`)
129
176
 
130
177
  if (branch.steps && branch.steps.length > 0) {
131
- // 执行分支步骤
132
- for (const stepConfig of branch.steps) {
133
- const step = engine.createStep(stepConfig)
134
- await step.execute(context, engine)
135
- }
178
+ await this.executeSteps(branch.steps, context)
136
179
  }
137
180
 
138
- return branch.stepId
181
+ return branch.stepId || branch.name
139
182
  }
140
183
  } catch (err) {
141
- console.warn(`[Workflow] Branch condition error:`, err.message)
184
+ console.warn(`[StepExecutor] Branch condition error:`, err.message)
142
185
  }
143
186
  }
144
187
 
145
188
  // 执行默认分支
146
- if (this.defaultBranch && this.defaultBranch.steps) {
147
- console.log(`[Workflow] Executing default branch`)
148
- for (const stepConfig of this.defaultBranch.steps) {
149
- const step = engine.createStep(stepConfig)
150
- await step.execute(context, engine)
151
- }
189
+ if (step.defaultBranch && step.defaultBranch.steps) {
190
+ console.log(`[StepExecutor] Executing default branch`)
191
+ await this.executeSteps(step.defaultBranch.steps, context)
152
192
  }
153
193
 
154
194
  return null
155
195
  }
156
- }
157
-
158
- /**
159
- * 顺序步骤
160
- */
161
- class SequentialStep extends WorkflowStep {
162
- constructor(config) {
163
- super({ ...config, type: StepType.SEQUENTIAL })
164
- this.steps = config.steps || []
165
- }
166
-
167
- async execute(context, engine) {
168
- console.log(`[Workflow] Executing sequential: ${this.name || this.id}`)
169
-
170
- const results = []
171
-
172
- for (const stepConfig of this.steps) {
173
- const step = engine.createStep(stepConfig)
174
- const result = await step.execute(context, engine)
175
- results.push(result)
176
- }
177
-
178
- return results
179
- }
180
- }
181
-
182
- /**
183
- * 循环步骤
184
- */
185
- class LoopStep extends WorkflowStep {
186
- constructor(config) {
187
- super({ ...config, type: StepType.LOOP })
188
- this.maxIterations = config.maxIterations || 10
189
- this.loopVariable = config.loopVariable || 'loopIndex'
190
- this.steps = config.steps || []
191
- this.until = config.until || null // 终止条件
192
- }
193
196
 
194
- async execute(context, engine) {
195
- console.log(`[Workflow] Executing loop: ${this.name || this.id}`)
197
+ /**
198
+ * 执行循环步骤
199
+ */
200
+ async executeLoop(step, context) {
201
+ console.log(`[StepExecutor] Executing loop: ${step.name || step.id}`)
196
202
 
197
203
  const results = []
204
+ const maxIterations = step.maxIterations || 10
205
+ const loopVariable = step.loopVariable || 'loopIndex'
198
206
 
199
- for (let i = 0; i < this.maxIterations; i++) {
200
- context.variables[this.loopVariable] = i
207
+ for (let i = 0; i < maxIterations; i++) {
208
+ context.variables[loopVariable] = i
209
+ console.log(`[StepExecutor] Loop iteration ${i}`)
201
210
 
202
- console.log(`[Workflow] Loop iteration ${i}`)
203
-
204
- for (const stepConfig of this.steps) {
205
- const step = engine.createStep(stepConfig)
206
- const result = await step.execute(context, engine)
207
- results.push(result)
211
+ const iterationResults = []
212
+ for (const stepConfig of (step.steps || [])) {
213
+ const result = await this.executeStep(stepConfig, context)
214
+ iterationResults.push(result)
208
215
  }
216
+ results.push(iterationResults)
209
217
 
210
218
  // 检查终止条件
211
- if (this.until) {
219
+ if (step.until) {
212
220
  let shouldStop = false
213
- if (typeof this.until === 'function') {
214
- shouldStop = this.until(context)
215
- } else if (typeof this.until === 'string') {
216
- // eslint-disable-next-line no-new-func
217
- const fn = new Function('context', `with(context.variables) { return (${this.until}) }`)
221
+ if (typeof step.until === 'function') {
222
+ shouldStop = step.until(context)
223
+ } else if (typeof step.until === 'string') {
224
+ const fn = new Function('context', `with(context.variables) { return (${step.until}) }`)
218
225
  shouldStop = fn(context)
219
226
  }
220
227
 
221
228
  if (shouldStop) {
222
- console.log(`[Workflow] Loop terminated at iteration ${i}`)
229
+ console.log(`[StepExecutor] Loop terminated at iteration ${i}`)
223
230
  break
224
231
  }
225
232
  }
@@ -227,80 +234,89 @@ class LoopStep extends WorkflowStep {
227
234
 
228
235
  return results
229
236
  }
230
- }
231
-
232
- /**
233
- * 延迟步骤
234
- */
235
- class DelayStep extends WorkflowStep {
236
- constructor(config) {
237
- super({ ...config, type: StepType.DELAY })
238
- this.delayMs = config.delayMs || 1000
239
- }
240
237
 
241
- async execute(context, engine) {
242
- console.log(`[Workflow] Delaying ${this.delayMs}ms`)
243
- await new Promise(resolve => setTimeout(resolve, this.delayMs))
238
+ /**
239
+ * 执行延迟步骤
240
+ */
241
+ async executeDelay(step, context) {
242
+ const delayMs = step.delayMs || 1000
243
+ console.log(`[StepExecutor] Delaying ${delayMs}ms`)
244
+ await new Promise(resolve => setTimeout(resolve, delayMs))
244
245
  return null
245
246
  }
246
- }
247
247
 
248
- /**
249
- * 工具步骤
250
- */
251
- class ToolStep extends WorkflowStep {
252
- constructor(config) {
253
- super({ ...config, type: StepType.TOOL })
254
- this.tool = config.tool
255
- this.args = config.args || {}
256
- this.outputVariable = config.outputVariable || null
248
+ /**
249
+ * 执行顺序步骤
250
+ */
251
+ async executeSequential(step, context) {
252
+ console.log(`[StepExecutor] Executing sequential: ${step.name || step.id}`)
253
+ return await this.executeSteps(step.steps || [], context)
257
254
  }
258
255
 
259
- async execute(context, engine) {
260
- if (!this.tool) {
261
- throw new Error('Tool step requires a tool name')
262
- }
256
+ /**
257
+ * 执行消息步骤(ExplorerLoop 专用)
258
+ */
259
+ async executeMessage(step, context) {
260
+ console.log(`[StepExecutor] Executing message step`)
263
261
 
264
- console.log(`[Workflow] Executing tool: ${this.tool}`)
262
+ const agent = this._getActiveAgent()
263
+ if (!agent) {
264
+ return { success: false, error: '没有可用的代理' }
265
+ }
265
266
 
266
- // 解析工具参数,支持变量引用
267
- const resolvedArgs = this._resolveArgs(this.args, context)
267
+ let content = step.content || ''
268
+ // 支持变量引用
269
+ content = this._resolveValue(content, context)
268
270
 
269
- // 获取当前 sessionId(从上下文变量或执行上下文)
270
- let sessionId = context.variables._sessionId
271
- if (!sessionId && engine.framework.getExecutionContext) {
272
- const ctx = engine.framework.getExecutionContext()
273
- sessionId = ctx?.sessionId
271
+ // 如果有事件上下文,附加到消息
272
+ if (context.variables?._event) {
273
+ content = `${content}\n\n[事件上下文: ${JSON.stringify(context.variables._event)}]`
274
274
  }
275
275
 
276
- // 使用 sessionId 上下文执行工具
277
- let result
278
- if (sessionId && engine.framework.runWithContext) {
279
- result = await engine.framework.runWithContext(
280
- { sessionId },
281
- async () => await engine.framework.executeTool(this.tool, resolvedArgs)
282
- )
283
- } else {
284
- result = await engine.framework.executeTool(this.tool, resolvedArgs)
285
- }
276
+ const result = await agent.pushMessage(content)
277
+ return { success: true, result }
278
+ }
286
279
 
287
- // 保存结果到变量
288
- if (this.outputVariable) {
289
- context.variables[this.outputVariable] = result
280
+ /**
281
+ * 执行思考步骤(ExplorerLoop 专用)
282
+ */
283
+ async executeThink(step, context) {
284
+ console.log(`[StepExecutor] Executing think step`)
285
+
286
+ const thinkPlugin = this.framework.pluginManager?.get('think')
287
+ if (!thinkPlugin) {
288
+ return { success: false, error: '思考插件不可用' }
290
289
  }
291
- context.lastResult = result
292
290
 
293
- // 检查工具执行结果
294
- if (result && result.error) {
295
- console.warn(`[Workflow] Tool ${this.tool} returned error: ${result.error}`)
291
+ let topic = step.topic || 'Ambient代理反思'
292
+ topic = this._resolveValue(topic, context)
293
+
294
+ if (context.variables?._event) {
295
+ topic = `${topic}\n\n[事件上下文: ${JSON.stringify(context.variables._event)}]`
296
296
  }
297
297
 
298
+ const result = await thinkPlugin._triggerThinking({
299
+ topic,
300
+ mode: step.mode || 'reflect',
301
+ depth: step.depth || 2
302
+ })
303
+
298
304
  return result
299
305
  }
300
306
 
307
+ /**
308
+ * 获取活跃代理
309
+ */
310
+ _getActiveAgent() {
311
+ if (this.framework._mainAgent) {
312
+ return this.framework._mainAgent
313
+ }
314
+ const agents = this.framework._agents || []
315
+ return agents.length > 0 ? agents[agents.length - 1] : null
316
+ }
317
+
301
318
  /**
302
319
  * 解析参数中的变量引用
303
- * 支持 {{variableName}} 语法
304
320
  */
305
321
  _resolveArgs(args, context) {
306
322
  const resolved = {}
@@ -312,18 +328,31 @@ class ToolStep extends WorkflowStep {
312
328
 
313
329
  _resolveValue(value, context) {
314
330
  if (typeof value === 'string') {
315
- // 替换 {{variable}} 或 {{variables.name}} 语法
331
+ // 支持多种引用格式:
332
+ // {{result}} - 上一步结果 (lastResult)
333
+ // {{result.body.ip}} - 从上一步结果提取嵌套字段
334
+ // {{variables.xxx}} - 显式引用 context.variables
335
+ // {{context.xxx}} - 显式引用 context 根属性
336
+ // {{lastResult}} - 上一步结果(result 的别名)
316
337
  return value.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (match, path) => {
317
- // 支持 variables.xxx 或直接 xxx 格式
338
+ // result lastResult 都指向 context.lastResult
339
+ if (path === 'result' || path === 'lastResult') {
340
+ return context.lastResult ?? match
341
+ }
342
+ if (path.startsWith('result.') || path.startsWith('lastResult.')) {
343
+ const nestedPath = path.replace(/^(result|lastResult)\./, '')
344
+ const val = this._getNestedValue(context.lastResult, nestedPath)
345
+ if (val !== undefined) return val
346
+ return match
347
+ }
318
348
  if (path.startsWith('variables.')) {
319
349
  return this._getNestedValue(context, path) ?? match
320
350
  } else if (path.startsWith('context.')) {
321
351
  return this._getNestedValue(context, path) ?? match
322
352
  } else {
323
- // 尝试从 context.variables 获取
353
+ // 先从 variables 查找,再从 context 根属性查找
324
354
  const val = this._getNestedValue(context.variables, path)
325
355
  if (val !== undefined) return val
326
- // 尝试从 context 直接获取
327
356
  return this._getNestedValue(context, path) ?? match
328
357
  }
329
358
  })
@@ -345,12 +374,189 @@ class ToolStep extends WorkflowStep {
345
374
  let current = obj
346
375
  for (const part of parts) {
347
376
  if (current === null || current === undefined) return undefined
377
+ // 如果当前值是字符串,尝试解析为 JSON
378
+ if (typeof current === 'string' && part !== '0' && part !== 'length') {
379
+ try {
380
+ current = JSON.parse(current)
381
+ } catch {
382
+ // 解析失败,继续用原值
383
+ }
384
+ }
348
385
  current = current[part]
349
386
  }
350
387
  return current
351
388
  }
352
389
  }
353
390
 
391
+ /**
392
+ * 工作流步骤基类
393
+ */
394
+ class WorkflowStep {
395
+ constructor(config) {
396
+ this.id = config.id || `step_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
397
+ this.type = config.type
398
+ this.name = config.name || ''
399
+ this.description = config.description || ''
400
+ this.condition = config.condition || null
401
+ this.timeout = config.timeout || 30000
402
+ this.retry = config.retry || { enabled: false, maxAttempts: 3, delay: 1000 }
403
+ this.onSuccess = config.onSuccess || null
404
+ this.onFailure = config.onFailure || null
405
+ }
406
+
407
+ async execute(context, engine) {
408
+ throw new Error('execute() must be implemented by subclass')
409
+ }
410
+
411
+ validate() {
412
+ if (!this.type) {
413
+ throw new Error('Step must have a type')
414
+ }
415
+ return true
416
+ }
417
+ }
418
+
419
+ /**
420
+ * 脚本步骤
421
+ */
422
+ class ScriptStep extends WorkflowStep {
423
+ constructor(config) {
424
+ super({ ...config, type: StepType.SCRIPT })
425
+ this.script = config.script
426
+ this.outputVariable = config.outputVariable || null
427
+ }
428
+
429
+ async execute(context, engine) {
430
+ // 使用 StepExecutor 执行脚本逻辑
431
+ const executor = new StepExecutor(engine.framework)
432
+ const stepConfig = {
433
+ id: this.id,
434
+ name: this.name,
435
+ type: StepType.SCRIPT,
436
+ script: this.script,
437
+ outputVariable: this.outputVariable
438
+ }
439
+ return await executor.executeScript(stepConfig, context)
440
+ }
441
+ }
442
+
443
+ /**
444
+ * 条件步骤
445
+ */
446
+ class ConditionStep extends WorkflowStep {
447
+ constructor(config) {
448
+ super({ ...config, type: StepType.CONDITION })
449
+ this.branches = config.branches || []
450
+ this.defaultBranch = config.defaultBranch || null
451
+ }
452
+
453
+ async execute(context, engine) {
454
+ const executor = new StepExecutor(engine.framework)
455
+ const stepConfig = {
456
+ id: this.id,
457
+ name: this.name,
458
+ type: StepType.CONDITION,
459
+ branches: this.branches,
460
+ defaultBranch: this.defaultBranch
461
+ }
462
+ return await executor.executeCondition(stepConfig, context)
463
+ }
464
+ }
465
+
466
+ /**
467
+ * 顺序步骤
468
+ */
469
+ class SequentialStep extends WorkflowStep {
470
+ constructor(config) {
471
+ super({ ...config, type: StepType.SEQUENTIAL })
472
+ this.steps = config.steps || []
473
+ }
474
+
475
+ async execute(context, engine) {
476
+ const executor = new StepExecutor(engine.framework)
477
+ const stepConfig = {
478
+ id: this.id,
479
+ name: this.name,
480
+ type: StepType.SEQUENTIAL,
481
+ steps: this.steps
482
+ }
483
+ return await executor.executeSequential(stepConfig, context)
484
+ }
485
+ }
486
+
487
+ /**
488
+ * 循环步骤
489
+ */
490
+ class LoopStep extends WorkflowStep {
491
+ constructor(config) {
492
+ super({ ...config, type: StepType.LOOP })
493
+ this.maxIterations = config.maxIterations || 10
494
+ this.loopVariable = config.loopVariable || 'loopIndex'
495
+ this.steps = config.steps || []
496
+ this.until = config.until || null
497
+ }
498
+
499
+ async execute(context, engine) {
500
+ const executor = new StepExecutor(engine.framework)
501
+ const stepConfig = {
502
+ id: this.id,
503
+ name: this.name,
504
+ type: StepType.LOOP,
505
+ maxIterations: this.maxIterations,
506
+ loopVariable: this.loopVariable,
507
+ steps: this.steps,
508
+ until: this.until
509
+ }
510
+ return await executor.executeLoop(stepConfig, context)
511
+ }
512
+ }
513
+
514
+ /**
515
+ * 延迟步骤
516
+ */
517
+ class DelayStep extends WorkflowStep {
518
+ constructor(config) {
519
+ super({ ...config, type: StepType.DELAY })
520
+ this.delayMs = config.delayMs || 1000
521
+ }
522
+
523
+ async execute(context, engine) {
524
+ const executor = new StepExecutor(engine.framework)
525
+ const stepConfig = {
526
+ id: this.id,
527
+ name: this.name,
528
+ type: StepType.DELAY,
529
+ delayMs: this.delayMs
530
+ }
531
+ return await executor.executeDelay(stepConfig, context)
532
+ }
533
+ }
534
+
535
+ /**
536
+ * 工具步骤
537
+ */
538
+ class ToolStep extends WorkflowStep {
539
+ constructor(config) {
540
+ super({ ...config, type: StepType.TOOL })
541
+ this.tool = config.tool
542
+ this.args = config.args || {}
543
+ this.outputVariable = config.outputVariable || null
544
+ }
545
+
546
+ async execute(context, engine) {
547
+ const executor = new StepExecutor(engine.framework)
548
+ const stepConfig = {
549
+ id: this.id,
550
+ name: this.name,
551
+ type: StepType.TOOL,
552
+ tool: this.tool,
553
+ args: this.args,
554
+ outputVariable: this.outputVariable
555
+ }
556
+ return await executor.executeTool(stepConfig, context)
557
+ }
558
+ }
559
+
354
560
  /**
355
561
  * 工作流引擎
356
562
  */
@@ -634,6 +840,7 @@ module.exports = {
634
840
  WorkflowEngine,
635
841
  WorkflowStep,
636
842
  StepType,
843
+ StepExecutor,
637
844
  ScriptStep,
638
845
  ConditionStep,
639
846
  SequentialStep,