moflo 4.8.52-rc.2 → 4.8.52
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/package.json +2 -2
- package/src/packages/cli/dist/src/version.js +1 -1
- package/src/packages/cli/package.json +1 -1
- package/src/packages/workflows/dist/commands/bash-command.js +1 -1
- package/src/packages/workflows/dist/core/loop-executor.js +8 -0
- package/src/packages/workflows/dist/core/runner.js +39 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moflo",
|
|
3
|
-
"version": "4.8.52
|
|
3
|
+
"version": "4.8.52",
|
|
4
4
|
"description": "MoFlo — AI agent orchestration for Claude Code. Forked from ruflo/claude-flow with patches applied to source, plus feature-level orchestration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"@types/js-yaml": "^4.0.9",
|
|
113
113
|
"@types/node": "^20.19.37",
|
|
114
114
|
"eslint": "^8.0.0",
|
|
115
|
-
"moflo": "^4.8.52-rc.
|
|
115
|
+
"moflo": "^4.8.52-rc.2",
|
|
116
116
|
"tsx": "^4.21.0",
|
|
117
117
|
"typescript": "^5.9.3",
|
|
118
118
|
"vitest": "^4.0.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moflo/cli",
|
|
3
|
-
"version": "4.8.52
|
|
3
|
+
"version": "4.8.52",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MoFlo CLI — AI agent orchestration with specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -78,7 +78,7 @@ export const bashCommand = {
|
|
|
78
78
|
stderr: stderr.trim(),
|
|
79
79
|
exitCode,
|
|
80
80
|
},
|
|
81
|
-
error: success ? undefined : `Command exited with code ${exitCode}`,
|
|
81
|
+
error: success ? undefined : `Command exited with code ${exitCode}${stderr.trim() ? ': ' + stderr.trim() : ''}`,
|
|
82
82
|
duration: Date.now() - start,
|
|
83
83
|
});
|
|
84
84
|
});
|
|
@@ -27,11 +27,15 @@ export async function executeLoopIterations(loopStep, loopOutput, variables, err
|
|
|
27
27
|
const prevItem = variables[itemVar];
|
|
28
28
|
const hadIndex = indexVar in variables;
|
|
29
29
|
const prevIndex = variables[indexVar];
|
|
30
|
+
const hadLoop = 'loop' in variables;
|
|
31
|
+
const prevLoop = variables['loop'];
|
|
30
32
|
for (let idx = 0; idx < items.length; idx++) {
|
|
31
33
|
if (signal?.aborted)
|
|
32
34
|
break;
|
|
33
35
|
variables[itemVar] = items[idx];
|
|
34
36
|
variables[indexVar] = idx;
|
|
37
|
+
// Inject `loop` namespace so {loop.<itemVar>} references resolve
|
|
38
|
+
variables['loop'] = { [itemVar]: items[idx], [indexVar]: idx };
|
|
35
39
|
const iterOutput = {};
|
|
36
40
|
let iterFailed = false;
|
|
37
41
|
for (let s = 0; s < nestedSteps.length; s++) {
|
|
@@ -71,6 +75,10 @@ export async function executeLoopIterations(loopStep, loopOutput, variables, err
|
|
|
71
75
|
variables[indexVar] = prevIndex;
|
|
72
76
|
else
|
|
73
77
|
delete variables[indexVar];
|
|
78
|
+
if (hadLoop)
|
|
79
|
+
variables['loop'] = prevLoop;
|
|
80
|
+
else
|
|
81
|
+
delete variables['loop'];
|
|
74
82
|
return { success: allSucceeded, outputs: iterationOutputs };
|
|
75
83
|
}
|
|
76
84
|
//# sourceMappingURL=loop-executor.js.map
|
|
@@ -43,14 +43,14 @@ export class WorkflowRunner {
|
|
|
43
43
|
code: 'DEFINITION_VALIDATION_FAILED',
|
|
44
44
|
message: 'Workflow definition is invalid',
|
|
45
45
|
details: defValidation.errors,
|
|
46
|
-
}]);
|
|
46
|
+
}], definition.name);
|
|
47
47
|
}
|
|
48
48
|
if (options.parentMofloLevel && definition.mofloLevel) {
|
|
49
49
|
if (compareMofloLevels(definition.mofloLevel, options.parentMofloLevel) > 0) {
|
|
50
50
|
return this.failureResult(workflowId, startTime, [{
|
|
51
51
|
code: 'MOFLO_LEVEL_DENIED',
|
|
52
52
|
message: `Nested workflow mofloLevel "${definition.mofloLevel}" exceeds parent level "${options.parentMofloLevel}"`,
|
|
53
|
-
}]);
|
|
53
|
+
}], definition.name);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
const { resolved: resolvedArgs, errors: argErrors } = resolveArguments(definition.arguments ?? {}, args);
|
|
@@ -59,7 +59,7 @@ export class WorkflowRunner {
|
|
|
59
59
|
code: 'ARGUMENT_VALIDATION_FAILED',
|
|
60
60
|
message: 'Argument validation failed',
|
|
61
61
|
details: argErrors,
|
|
62
|
-
}]);
|
|
62
|
+
}], definition.name);
|
|
63
63
|
}
|
|
64
64
|
// Pre-flight prerequisite checks (Story #193)
|
|
65
65
|
if (!options.dryRun) {
|
|
@@ -70,7 +70,7 @@ export class WorkflowRunner {
|
|
|
70
70
|
return this.failureResult(workflowId, startTime, [{
|
|
71
71
|
code: 'PREREQUISITES_FAILED',
|
|
72
72
|
message: formatPrerequisiteErrors(prereqResults),
|
|
73
|
-
}]);
|
|
73
|
+
}], definition.name);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -127,7 +127,9 @@ export class WorkflowRunner {
|
|
|
127
127
|
maxNestingDepth: options.maxNestingDepth ?? DEFAULT_MAX_NESTING_DEPTH,
|
|
128
128
|
};
|
|
129
129
|
try {
|
|
130
|
-
await this.storeProgress(workflowId, 'running', 0, definition.steps.length
|
|
130
|
+
await this.storeProgress(workflowId, 'running', 0, definition.steps.length, {
|
|
131
|
+
workflowName: definition.name, startedAt: startTime,
|
|
132
|
+
});
|
|
131
133
|
const stepIndex = new Map();
|
|
132
134
|
for (let idx = 0; idx < definition.steps.length; idx++) {
|
|
133
135
|
stepIndex.set(definition.steps[idx].id, idx);
|
|
@@ -205,7 +207,9 @@ export class WorkflowRunner {
|
|
|
205
207
|
break;
|
|
206
208
|
}
|
|
207
209
|
}
|
|
208
|
-
await this.storeProgress(workflowId, 'running', stepResults.length, definition.steps.length
|
|
210
|
+
await this.storeProgress(workflowId, 'running', stepResults.length, definition.steps.length, {
|
|
211
|
+
workflowName: definition.name, startedAt: startTime,
|
|
212
|
+
});
|
|
209
213
|
try {
|
|
210
214
|
options.onStepComplete?.(result, i, definition.steps.length);
|
|
211
215
|
}
|
|
@@ -217,7 +221,9 @@ export class WorkflowRunner {
|
|
|
217
221
|
errors.push({ code: 'WORKFLOW_CANCELLED', message: 'Workflow was cancelled' });
|
|
218
222
|
}
|
|
219
223
|
const finalStatus = cancelled ? 'cancelled' : errors.length > 0 ? 'failed' : 'completed';
|
|
220
|
-
await this.storeProgress(workflowId, finalStatus, stepResults.length, definition.steps.length
|
|
224
|
+
await this.storeProgress(workflowId, finalStatus, stepResults.length, definition.steps.length, {
|
|
225
|
+
workflowName: definition.name, startedAt: startTime, errors,
|
|
226
|
+
});
|
|
221
227
|
const outputs = {};
|
|
222
228
|
for (const sr of stepResults) {
|
|
223
229
|
if (sr.status === 'succeeded' && sr.output) {
|
|
@@ -254,15 +260,37 @@ export class WorkflowRunner {
|
|
|
254
260
|
gateway: DENY_ALL_GATEWAY,
|
|
255
261
|
...(this.connectorAccessor ? { tools: this.connectorAccessor } : {}) };
|
|
256
262
|
}
|
|
257
|
-
async storeProgress(wfId, status, done, total) {
|
|
263
|
+
async storeProgress(wfId, status, done, total, extra) {
|
|
258
264
|
try {
|
|
259
|
-
|
|
265
|
+
const now = Date.now();
|
|
266
|
+
const record = {
|
|
260
267
|
status, completedSteps: done, totalSteps: total, updatedAt: new Date().toISOString(),
|
|
261
|
-
}
|
|
268
|
+
};
|
|
269
|
+
if (extra?.workflowName)
|
|
270
|
+
record.workflowName = extra.workflowName;
|
|
271
|
+
if (extra?.startedAt) {
|
|
272
|
+
record.startedAt = extra.startedAt;
|
|
273
|
+
record.duration = now - extra.startedAt;
|
|
274
|
+
}
|
|
275
|
+
// Map status to boolean success for dashboard compatibility
|
|
276
|
+
if (status === 'completed')
|
|
277
|
+
record.success = true;
|
|
278
|
+
else if (status === 'failed')
|
|
279
|
+
record.success = false;
|
|
280
|
+
else if (status === 'cancelled')
|
|
281
|
+
record.success = false;
|
|
282
|
+
// Include error summary on terminal states
|
|
283
|
+
if (extra?.errors && extra.errors.length > 0 && (status === 'failed' || status === 'cancelled')) {
|
|
284
|
+
record.error = extra.errors.map(e => e.message).join('; ');
|
|
285
|
+
}
|
|
286
|
+
await this.memory.write('tasklist', wfId, record);
|
|
262
287
|
}
|
|
263
288
|
catch { /* Best-effort */ }
|
|
264
289
|
}
|
|
265
|
-
failureResult(workflowId, startTime, errors) {
|
|
290
|
+
async failureResult(workflowId, startTime, errors, workflowName) {
|
|
291
|
+
await this.storeProgress(workflowId, 'failed', 0, 0, {
|
|
292
|
+
workflowName, startedAt: startTime, errors,
|
|
293
|
+
});
|
|
266
294
|
return { workflowId, success: false, steps: [], outputs: {}, errors,
|
|
267
295
|
duration: Date.now() - startTime, cancelled: false };
|
|
268
296
|
}
|