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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "moflo",
3
- "version": "4.8.52-rc.2",
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.1",
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"
@@ -2,5 +2,5 @@
2
2
  * Auto-generated by build. Do not edit manually.
3
3
  * Source of truth: root package.json → scripts/sync-version.mjs
4
4
  */
5
- export const VERSION = '4.8.52-rc.2';
5
+ export const VERSION = '4.8.52';
6
6
  //# sourceMappingURL=version.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moflo/cli",
3
- "version": "4.8.52-rc.2",
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
- await this.memory.write('tasklist', wfId, {
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
  }