foliko 1.0.65 → 1.0.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +145 -142
- package/package.json +1 -1
- package/plugins/ambient-agent-plugin.js +158 -46
- package/plugins/email.js +49 -17
- package/skills/ambient-agent/SKILL.md +234 -0
- package/src/capabilities/workflow-engine.js +363 -181
- package/src/core/agent-chat.js +26 -4
|
@@ -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
|
|
32
|
-
constructor(
|
|
33
|
-
this.
|
|
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
|
-
|
|
45
|
-
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
59
|
+
return results
|
|
53
60
|
}
|
|
54
|
-
}
|
|
55
61
|
|
|
56
|
-
/**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
|
|
67
|
-
|
|
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:${
|
|
135
|
+
log: (...args) => console.log(`[Script:${step.id}]`, ...args)
|
|
77
136
|
}
|
|
78
137
|
}
|
|
79
138
|
|
|
80
|
-
// 执行脚本
|
|
81
139
|
let result
|
|
82
|
-
if (typeof
|
|
83
|
-
result = await
|
|
84
|
-
} else if (typeof
|
|
85
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
157
|
|
|
113
|
-
|
|
114
|
-
|
|
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
|
|
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(`[
|
|
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(`[
|
|
184
|
+
console.warn(`[StepExecutor] Branch condition error:`, err.message)
|
|
142
185
|
}
|
|
143
186
|
}
|
|
144
187
|
|
|
145
188
|
// 执行默认分支
|
|
146
|
-
if (
|
|
147
|
-
console.log(`[
|
|
148
|
-
|
|
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
196
|
|
|
158
|
-
/**
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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
|
-
|
|
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 <
|
|
200
|
-
context.variables[
|
|
201
|
-
|
|
202
|
-
console.log(`[Workflow] Loop iteration ${i}`)
|
|
207
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
208
|
+
context.variables[loopVariable] = i
|
|
209
|
+
console.log(`[StepExecutor] Loop iteration ${i}`)
|
|
203
210
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const result = await
|
|
207
|
-
|
|
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 (
|
|
219
|
+
if (step.until) {
|
|
212
220
|
let shouldStop = false
|
|
213
|
-
if (typeof
|
|
214
|
-
shouldStop =
|
|
215
|
-
} else if (typeof
|
|
216
|
-
|
|
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(`[
|
|
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
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
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
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
256
|
+
/**
|
|
257
|
+
* 执行消息步骤(ExplorerLoop 专用)
|
|
258
|
+
*/
|
|
259
|
+
async executeMessage(step, context) {
|
|
260
|
+
console.log(`[StepExecutor] Executing message step`)
|
|
263
261
|
|
|
264
|
-
|
|
262
|
+
const agent = this._getActiveAgent()
|
|
263
|
+
if (!agent) {
|
|
264
|
+
return { success: false, error: '没有可用的代理' }
|
|
265
|
+
}
|
|
265
266
|
|
|
266
|
-
|
|
267
|
-
|
|
267
|
+
let content = step.content || ''
|
|
268
|
+
// 支持变量引用
|
|
269
|
+
content = this._resolveValue(content, context)
|
|
268
270
|
|
|
269
|
-
//
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
|
|
277
|
-
|
|
278
|
-
|
|
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
|
-
|
|
289
|
-
|
|
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
|
-
|
|
295
|
-
|
|
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,14 @@ class ToolStep extends WorkflowStep {
|
|
|
312
328
|
|
|
313
329
|
_resolveValue(value, context) {
|
|
314
330
|
if (typeof value === 'string') {
|
|
315
|
-
// 替换 {{variable}} 或 {{variables.name}} 语法
|
|
316
331
|
return value.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (match, path) => {
|
|
317
|
-
// 支持 variables.xxx 或直接 xxx 格式
|
|
318
332
|
if (path.startsWith('variables.')) {
|
|
319
333
|
return this._getNestedValue(context, path) ?? match
|
|
320
334
|
} else if (path.startsWith('context.')) {
|
|
321
335
|
return this._getNestedValue(context, path) ?? match
|
|
322
336
|
} else {
|
|
323
|
-
// 尝试从 context.variables 获取
|
|
324
337
|
const val = this._getNestedValue(context.variables, path)
|
|
325
338
|
if (val !== undefined) return val
|
|
326
|
-
// 尝试从 context 直接获取
|
|
327
339
|
return this._getNestedValue(context, path) ?? match
|
|
328
340
|
}
|
|
329
341
|
})
|
|
@@ -351,6 +363,175 @@ class ToolStep extends WorkflowStep {
|
|
|
351
363
|
}
|
|
352
364
|
}
|
|
353
365
|
|
|
366
|
+
/**
|
|
367
|
+
* 工作流步骤基类
|
|
368
|
+
*/
|
|
369
|
+
class WorkflowStep {
|
|
370
|
+
constructor(config) {
|
|
371
|
+
this.id = config.id || `step_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
372
|
+
this.type = config.type
|
|
373
|
+
this.name = config.name || ''
|
|
374
|
+
this.description = config.description || ''
|
|
375
|
+
this.condition = config.condition || null
|
|
376
|
+
this.timeout = config.timeout || 30000
|
|
377
|
+
this.retry = config.retry || { enabled: false, maxAttempts: 3, delay: 1000 }
|
|
378
|
+
this.onSuccess = config.onSuccess || null
|
|
379
|
+
this.onFailure = config.onFailure || null
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async execute(context, engine) {
|
|
383
|
+
throw new Error('execute() must be implemented by subclass')
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
validate() {
|
|
387
|
+
if (!this.type) {
|
|
388
|
+
throw new Error('Step must have a type')
|
|
389
|
+
}
|
|
390
|
+
return true
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* 脚本步骤
|
|
396
|
+
*/
|
|
397
|
+
class ScriptStep extends WorkflowStep {
|
|
398
|
+
constructor(config) {
|
|
399
|
+
super({ ...config, type: StepType.SCRIPT })
|
|
400
|
+
this.script = config.script
|
|
401
|
+
this.outputVariable = config.outputVariable || null
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
async execute(context, engine) {
|
|
405
|
+
// 使用 StepExecutor 执行脚本逻辑
|
|
406
|
+
const executor = new StepExecutor(engine.framework)
|
|
407
|
+
const stepConfig = {
|
|
408
|
+
id: this.id,
|
|
409
|
+
name: this.name,
|
|
410
|
+
type: StepType.SCRIPT,
|
|
411
|
+
script: this.script,
|
|
412
|
+
outputVariable: this.outputVariable
|
|
413
|
+
}
|
|
414
|
+
return await executor.executeScript(stepConfig, context)
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* 条件步骤
|
|
420
|
+
*/
|
|
421
|
+
class ConditionStep extends WorkflowStep {
|
|
422
|
+
constructor(config) {
|
|
423
|
+
super({ ...config, type: StepType.CONDITION })
|
|
424
|
+
this.branches = config.branches || []
|
|
425
|
+
this.defaultBranch = config.defaultBranch || null
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
async execute(context, engine) {
|
|
429
|
+
const executor = new StepExecutor(engine.framework)
|
|
430
|
+
const stepConfig = {
|
|
431
|
+
id: this.id,
|
|
432
|
+
name: this.name,
|
|
433
|
+
type: StepType.CONDITION,
|
|
434
|
+
branches: this.branches,
|
|
435
|
+
defaultBranch: this.defaultBranch
|
|
436
|
+
}
|
|
437
|
+
return await executor.executeCondition(stepConfig, context)
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* 顺序步骤
|
|
443
|
+
*/
|
|
444
|
+
class SequentialStep extends WorkflowStep {
|
|
445
|
+
constructor(config) {
|
|
446
|
+
super({ ...config, type: StepType.SEQUENTIAL })
|
|
447
|
+
this.steps = config.steps || []
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async execute(context, engine) {
|
|
451
|
+
const executor = new StepExecutor(engine.framework)
|
|
452
|
+
const stepConfig = {
|
|
453
|
+
id: this.id,
|
|
454
|
+
name: this.name,
|
|
455
|
+
type: StepType.SEQUENTIAL,
|
|
456
|
+
steps: this.steps
|
|
457
|
+
}
|
|
458
|
+
return await executor.executeSequential(stepConfig, context)
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* 循环步骤
|
|
464
|
+
*/
|
|
465
|
+
class LoopStep extends WorkflowStep {
|
|
466
|
+
constructor(config) {
|
|
467
|
+
super({ ...config, type: StepType.LOOP })
|
|
468
|
+
this.maxIterations = config.maxIterations || 10
|
|
469
|
+
this.loopVariable = config.loopVariable || 'loopIndex'
|
|
470
|
+
this.steps = config.steps || []
|
|
471
|
+
this.until = config.until || null
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
async execute(context, engine) {
|
|
475
|
+
const executor = new StepExecutor(engine.framework)
|
|
476
|
+
const stepConfig = {
|
|
477
|
+
id: this.id,
|
|
478
|
+
name: this.name,
|
|
479
|
+
type: StepType.LOOP,
|
|
480
|
+
maxIterations: this.maxIterations,
|
|
481
|
+
loopVariable: this.loopVariable,
|
|
482
|
+
steps: this.steps,
|
|
483
|
+
until: this.until
|
|
484
|
+
}
|
|
485
|
+
return await executor.executeLoop(stepConfig, context)
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* 延迟步骤
|
|
491
|
+
*/
|
|
492
|
+
class DelayStep extends WorkflowStep {
|
|
493
|
+
constructor(config) {
|
|
494
|
+
super({ ...config, type: StepType.DELAY })
|
|
495
|
+
this.delayMs = config.delayMs || 1000
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
async execute(context, engine) {
|
|
499
|
+
const executor = new StepExecutor(engine.framework)
|
|
500
|
+
const stepConfig = {
|
|
501
|
+
id: this.id,
|
|
502
|
+
name: this.name,
|
|
503
|
+
type: StepType.DELAY,
|
|
504
|
+
delayMs: this.delayMs
|
|
505
|
+
}
|
|
506
|
+
return await executor.executeDelay(stepConfig, context)
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* 工具步骤
|
|
512
|
+
*/
|
|
513
|
+
class ToolStep extends WorkflowStep {
|
|
514
|
+
constructor(config) {
|
|
515
|
+
super({ ...config, type: StepType.TOOL })
|
|
516
|
+
this.tool = config.tool
|
|
517
|
+
this.args = config.args || {}
|
|
518
|
+
this.outputVariable = config.outputVariable || null
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
async execute(context, engine) {
|
|
522
|
+
const executor = new StepExecutor(engine.framework)
|
|
523
|
+
const stepConfig = {
|
|
524
|
+
id: this.id,
|
|
525
|
+
name: this.name,
|
|
526
|
+
type: StepType.TOOL,
|
|
527
|
+
tool: this.tool,
|
|
528
|
+
args: this.args,
|
|
529
|
+
outputVariable: this.outputVariable
|
|
530
|
+
}
|
|
531
|
+
return await executor.executeTool(stepConfig, context)
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
354
535
|
/**
|
|
355
536
|
* 工作流引擎
|
|
356
537
|
*/
|
|
@@ -634,6 +815,7 @@ module.exports = {
|
|
|
634
815
|
WorkflowEngine,
|
|
635
816
|
WorkflowStep,
|
|
636
817
|
StepType,
|
|
818
|
+
StepExecutor,
|
|
637
819
|
ScriptStep,
|
|
638
820
|
ConditionStep,
|
|
639
821
|
SequentialStep,
|