@hexabot-ai/agentic 3.1.2-alpha.1 → 3.1.2-alpha.3

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.
@@ -9,6 +9,7 @@ exports.executeLoop = executeLoop;
9
9
  exports.updateAccumulator = updateAccumulator;
10
10
  exports.shouldStopLoop = shouldStopLoop;
11
11
  const workflow_values_1 = require("../workflow-values");
12
+ const suspension_continuation_1 = require("./suspension-continuation");
12
13
  /**
13
14
  * Execute a loop step by iterating over input items and executing child steps.
14
15
  *
@@ -49,30 +50,23 @@ async function executeForEachLoop(env, step, state, path, startIndex) {
49
50
  index,
50
51
  ]);
51
52
  if (suspension) {
52
- return {
53
- ...suspension,
54
- continue: async (resumeData) => {
55
- const next = await suspension.continue(resumeData);
56
- if (next) {
57
- return next;
53
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(suspension, async () => {
54
+ const postScope = buildScope(env, iterationState, { item, index }, accumulator);
55
+ accumulator = await updateAccumulator(step, postScope, accumulator);
56
+ const shouldStop = await shouldStopLoop(step, postScope);
57
+ if (shouldStop) {
58
+ state.accumulator = accumulator;
59
+ if (step.accumulate && step.name) {
60
+ state.output[step.name] = { [step.accumulate.as]: accumulator };
58
61
  }
59
- const postScope = buildScope(env, iterationState, { item, index }, accumulator);
60
- accumulator = await updateAccumulator(step, postScope, accumulator);
61
- const shouldStop = await shouldStopLoop(step, postScope);
62
- if (shouldStop) {
63
- state.accumulator = accumulator;
64
- if (step.accumulate && step.name) {
65
- state.output[step.name] = { [step.accumulate.as]: accumulator };
66
- }
67
- return undefined;
68
- }
69
- return executeForEachLoop(env, step, {
70
- ...iterationState,
71
- accumulator,
72
- iterationStack: state.iterationStack,
73
- }, path, index + 1);
74
- },
75
- };
62
+ return undefined;
63
+ }
64
+ return executeForEachLoop(env, step, {
65
+ ...iterationState,
66
+ accumulator,
67
+ iterationStack: state.iterationStack,
68
+ }, path, index + 1);
69
+ });
76
70
  }
77
71
  const postScope = buildScope(env, iterationState, { item, index }, accumulator);
78
72
  accumulator = await updateAccumulator(step, postScope, accumulator);
@@ -104,22 +98,15 @@ async function executeWhileLoop(env, step, state, path, startIndex) {
104
98
  index,
105
99
  ]);
106
100
  if (suspension) {
107
- return {
108
- ...suspension,
109
- continue: async (resumeData) => {
110
- const next = await suspension.continue(resumeData);
111
- if (next) {
112
- return next;
113
- }
114
- const postScope = buildScope(env, iterationState, { item: undefined, index }, accumulator);
115
- accumulator = await updateAccumulator(step, postScope, accumulator);
116
- return executeWhileLoop(env, step, {
117
- ...iterationState,
118
- accumulator,
119
- iterationStack: state.iterationStack,
120
- }, path, index + 1);
121
- },
122
- };
101
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(suspension, async () => {
102
+ const postScope = buildScope(env, iterationState, { item: undefined, index }, accumulator);
103
+ accumulator = await updateAccumulator(step, postScope, accumulator);
104
+ return executeWhileLoop(env, step, {
105
+ ...iterationState,
106
+ accumulator,
107
+ iterationStack: state.iterationStack,
108
+ }, path, index + 1);
109
+ });
123
110
  }
124
111
  const postScope = buildScope(env, iterationState, { item: undefined, index }, accumulator);
125
112
  accumulator = await updateAccumulator(step, postScope, accumulator);
@@ -7,6 +7,7 @@
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
8
  exports.executeParallel = executeParallel;
9
9
  const skip_helpers_1 = require("./skip-helpers");
10
+ const suspension_continuation_1 = require("./suspension-continuation");
10
11
  /**
11
12
  * Execute a set of steps in parallel order, respecting the configured strategy.
12
13
  *
@@ -23,22 +24,15 @@ async function executeParallel(env, step, state, path, startIndex = 0) {
23
24
  const childPath = [...path, 'parallel', index];
24
25
  const suspension = await env.executeStep(child, state, childPath);
25
26
  if (suspension) {
26
- return {
27
- ...suspension,
28
- continue: async (resumeData) => {
29
- const next = await suspension.continue(resumeData);
30
- if (next) {
31
- return next;
27
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(suspension, async () => {
28
+ if (step.strategy === 'wait_any') {
29
+ if (index + 1 < step.steps.length) {
30
+ (0, skip_helpers_1.markStepsSkipped)(env, step.steps.slice(index + 1), state.iterationStack);
32
31
  }
33
- if (step.strategy === 'wait_any') {
34
- if (index + 1 < step.steps.length) {
35
- (0, skip_helpers_1.markStepsSkipped)(env, step.steps.slice(index + 1), state.iterationStack);
36
- }
37
- return undefined;
38
- }
39
- return executeParallel(env, step, state, path, index + 1);
40
- },
41
- };
32
+ return undefined;
33
+ }
34
+ return executeParallel(env, step, state, path, index + 1);
35
+ });
42
36
  }
43
37
  if (step.strategy === 'wait_any') {
44
38
  if (index + 1 < step.steps.length) {
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ /*
3
+ * Hexabot — Fair Core License (FCL-1.0-ALv2)
4
+ * Copyright (c) 2025 Hexastack.
5
+ * Full terms: see LICENSE.md.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.wrapSuspensionContinuation = wrapSuspensionContinuation;
9
+ /**
10
+ * Compose a suspension with the continuation that should run once it completes.
11
+ *
12
+ * When resuming a suspension yields another suspension from the same logical
13
+ * step, the follow-up suspension still needs to remember how to continue the
14
+ * surrounding flow after that step eventually finishes.
15
+ */
16
+ function wrapSuspensionContinuation(suspension, onComplete) {
17
+ return {
18
+ ...suspension,
19
+ continue: async (resumeData) => {
20
+ const next = await suspension.continue(resumeData);
21
+ if (next) {
22
+ return wrapSuspensionContinuation(next, onComplete);
23
+ }
24
+ return onComplete();
25
+ },
26
+ };
27
+ }
@@ -11,6 +11,7 @@ exports.buildSuspensionForPath = buildSuspensionForPath;
11
11
  const loop_executor_1 = require("./step-executors/loop-executor");
12
12
  const parallel_executor_1 = require("./step-executors/parallel-executor");
13
13
  const skip_helpers_1 = require("./step-executors/skip-helpers");
14
+ const suspension_continuation_1 = require("./step-executors/suspension-continuation");
14
15
  const workflow_event_emitter_1 = require("./workflow-event-emitter");
15
16
  /**
16
17
  * Parse a suspended step id into its execution path and iteration stack.
@@ -154,16 +155,7 @@ function buildSuspensionForPath(deps, steps, state, targetPath, pathPrefix, iter
154
155
  }
155
156
  const resumed = await executeStep(step, state, currentPath);
156
157
  if (resumed) {
157
- return {
158
- ...resumed,
159
- continue: async (nextResumeData) => {
160
- const next = await resumed.continue(nextResumeData);
161
- if (next) {
162
- return next;
163
- }
164
- return deps.executeFlow(steps, state, pathPrefix, current + 1);
165
- },
166
- };
158
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(resumed, () => deps.executeFlow(steps, state, pathPrefix, current + 1));
167
159
  }
168
160
  return deps.executeFlow(steps, state, pathPrefix, current + 1);
169
161
  }
@@ -188,22 +180,19 @@ function buildSuspensionForPath(deps, steps, state, targetPath, pathPrefix, iter
188
180
  return null;
189
181
  }
190
182
  const childIndex = typeof childPath[0] === 'number' ? childPath[0] : 0;
191
- return {
192
- ...childSuspension,
193
- continue: async (resumeData) => {
194
- const next = await childSuspension.continue(resumeData);
195
- if (next) {
196
- return next;
183
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(childSuspension, async () => {
184
+ if (step.strategy === 'wait_any') {
185
+ if (childIndex + 1 < step.steps.length) {
186
+ (0, skip_helpers_1.markStepsSkipped)(env, step.steps.slice(childIndex + 1), state.iterationStack ?? []);
197
187
  }
198
- if (step.strategy === 'wait_any') {
199
- if (childIndex + 1 < step.steps.length) {
200
- (0, skip_helpers_1.markStepsSkipped)(env, step.steps.slice(childIndex + 1), state.iterationStack ?? []);
201
- }
202
- return undefined;
203
- }
204
- return (0, parallel_executor_1.executeParallel)(env, step, state, currentPath, childIndex + 1);
205
- },
206
- };
188
+ return deps.executeFlow(steps, state, pathPrefix, current + 1);
189
+ }
190
+ const next = await (0, parallel_executor_1.executeParallel)(env, step, state, currentPath, childIndex + 1);
191
+ if (next) {
192
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(next, () => deps.executeFlow(steps, state, pathPrefix, current + 1));
193
+ }
194
+ return deps.executeFlow(steps, state, pathPrefix, current + 1);
195
+ });
207
196
  }
208
197
  if (step.type === workflow_event_emitter_1.StepType.Conditional) {
209
198
  if (rest[0] !== 'branch' || typeof rest[1] !== 'number') {
@@ -219,16 +208,7 @@ function buildSuspensionForPath(deps, steps, state, targetPath, pathPrefix, iter
219
208
  if (!branchSuspension) {
220
209
  return null;
221
210
  }
222
- return {
223
- ...branchSuspension,
224
- continue: async (resumeData) => {
225
- const next = await branchSuspension.continue(resumeData);
226
- if (next) {
227
- return next;
228
- }
229
- return deps.executeFlow(steps, state, pathPrefix, current + 1);
230
- },
231
- };
211
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(branchSuspension, () => deps.executeFlow(steps, state, pathPrefix, current + 1));
232
212
  }
233
213
  if (step.type === workflow_event_emitter_1.StepType.Loop) {
234
214
  if (rest.length < 1 || typeof rest[0] !== 'string') {
@@ -256,46 +236,53 @@ function buildSuspensionForPath(deps, steps, state, targetPath, pathPrefix, iter
256
236
  return null;
257
237
  }
258
238
  const accumulator = iterationState.accumulator ?? state.accumulator ?? undefined;
259
- return {
260
- ...childSuspension,
261
- continue: async (resumeData) => {
262
- const next = await childSuspension.continue(resumeData);
263
- if (next) {
264
- return next;
265
- }
266
- const scope = {
267
- input: iterationState.input,
268
- context: env.context.state,
269
- output: iterationState.output,
270
- iteration: iterationState.iteration ?? {
271
- item: undefined,
272
- index: iterationIndex,
273
- },
274
- accumulator,
275
- };
276
- const updatedAccumulator = await (0, loop_executor_1.updateAccumulator)(step, scope, accumulator);
277
- const shouldStop = await (0, loop_executor_1.shouldStopLoop)(step, scope);
278
- state.output = iterationState.output;
279
- if (step.accumulate && step.name) {
280
- state.output[step.name] = {
281
- [step.accumulate.as]: updatedAccumulator,
282
- };
283
- }
284
- if (step.accumulate) {
285
- state.accumulator = updatedAccumulator;
286
- }
287
- if (shouldStop) {
288
- return undefined;
289
- }
290
- const baseState = {
291
- ...iterationState,
292
- iterationStack: ancestorIterationStack,
293
- accumulator: updatedAccumulator,
294
- output: state.output,
239
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(childSuspension, async () => {
240
+ const scope = {
241
+ input: iterationState.input,
242
+ context: env.context.state,
243
+ output: iterationState.output,
244
+ iteration: iterationState.iteration ?? {
245
+ item: undefined,
246
+ index: iterationIndex,
247
+ },
248
+ accumulator,
249
+ };
250
+ const updatedAccumulator = await (0, loop_executor_1.updateAccumulator)(step, scope, accumulator);
251
+ const shouldStop = await (0, loop_executor_1.shouldStopLoop)(step, scope);
252
+ state.output = iterationState.output;
253
+ if (step.accumulate && step.name) {
254
+ state.output[step.name] = {
255
+ [step.accumulate.as]: updatedAccumulator,
295
256
  };
296
- return (0, loop_executor_1.executeLoop)(env, step, baseState, currentPath, iterationIndex + 1);
297
- },
298
- };
257
+ }
258
+ if (step.accumulate) {
259
+ state.accumulator = updatedAccumulator;
260
+ }
261
+ if (shouldStop) {
262
+ return deps.executeFlow(steps, state, pathPrefix, current + 1);
263
+ }
264
+ const baseState = {
265
+ ...iterationState,
266
+ iterationStack: ancestorIterationStack,
267
+ accumulator: updatedAccumulator,
268
+ output: state.output,
269
+ };
270
+ const next = await (0, loop_executor_1.executeLoop)(env, step, baseState, currentPath, iterationIndex + 1);
271
+ state.output = baseState.output;
272
+ if (step.accumulate) {
273
+ state.accumulator = baseState.accumulator;
274
+ }
275
+ if (next) {
276
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(next, async () => {
277
+ state.output = baseState.output;
278
+ if (step.accumulate) {
279
+ state.accumulator = baseState.accumulator;
280
+ }
281
+ return deps.executeFlow(steps, state, pathPrefix, current + 1);
282
+ });
283
+ }
284
+ return deps.executeFlow(steps, state, pathPrefix, current + 1);
285
+ });
299
286
  }
300
287
  return null;
301
288
  }
@@ -11,6 +11,7 @@ const runner_runtime_control_1 = require("./runner-runtime-control");
11
11
  const conditional_executor_1 = require("./step-executors/conditional-executor");
12
12
  const loop_executor_1 = require("./step-executors/loop-executor");
13
13
  const parallel_executor_1 = require("./step-executors/parallel-executor");
14
+ const suspension_continuation_1 = require("./step-executors/suspension-continuation");
14
15
  const task_executor_1 = require("./step-executors/task-executor");
15
16
  const suspension_rebuilder_1 = require("./suspension-rebuilder");
16
17
  const workflow_event_emitter_1 = require("./workflow-event-emitter");
@@ -408,16 +409,7 @@ class WorkflowRunner {
408
409
  const stepPath = [...path, index];
409
410
  const suspension = await this.executeStep(step, state, stepPath);
410
411
  if (suspension) {
411
- return {
412
- ...suspension,
413
- continue: async (resumeData) => {
414
- const next = await suspension.continue(resumeData);
415
- if (next) {
416
- return next;
417
- }
418
- return this.executeFlow(steps, state, path, index + 1);
419
- },
420
- };
412
+ return (0, suspension_continuation_1.wrapSuspensionContinuation)(suspension, () => this.executeFlow(steps, state, path, index + 1));
421
413
  }
422
414
  }
423
415
  return undefined;
@@ -4,6 +4,7 @@
4
4
  * Full terms: see LICENSE.md.
5
5
  */
6
6
  import { evaluateValue } from '../workflow-values';
7
+ import { wrapSuspensionContinuation } from './suspension-continuation';
7
8
  /**
8
9
  * Execute a loop step by iterating over input items and executing child steps.
9
10
  *
@@ -44,30 +45,23 @@ async function executeForEachLoop(env, step, state, path, startIndex) {
44
45
  index,
45
46
  ]);
46
47
  if (suspension) {
47
- return {
48
- ...suspension,
49
- continue: async (resumeData) => {
50
- const next = await suspension.continue(resumeData);
51
- if (next) {
52
- return next;
48
+ return wrapSuspensionContinuation(suspension, async () => {
49
+ const postScope = buildScope(env, iterationState, { item, index }, accumulator);
50
+ accumulator = await updateAccumulator(step, postScope, accumulator);
51
+ const shouldStop = await shouldStopLoop(step, postScope);
52
+ if (shouldStop) {
53
+ state.accumulator = accumulator;
54
+ if (step.accumulate && step.name) {
55
+ state.output[step.name] = { [step.accumulate.as]: accumulator };
53
56
  }
54
- const postScope = buildScope(env, iterationState, { item, index }, accumulator);
55
- accumulator = await updateAccumulator(step, postScope, accumulator);
56
- const shouldStop = await shouldStopLoop(step, postScope);
57
- if (shouldStop) {
58
- state.accumulator = accumulator;
59
- if (step.accumulate && step.name) {
60
- state.output[step.name] = { [step.accumulate.as]: accumulator };
61
- }
62
- return undefined;
63
- }
64
- return executeForEachLoop(env, step, {
65
- ...iterationState,
66
- accumulator,
67
- iterationStack: state.iterationStack,
68
- }, path, index + 1);
69
- },
70
- };
57
+ return undefined;
58
+ }
59
+ return executeForEachLoop(env, step, {
60
+ ...iterationState,
61
+ accumulator,
62
+ iterationStack: state.iterationStack,
63
+ }, path, index + 1);
64
+ });
71
65
  }
72
66
  const postScope = buildScope(env, iterationState, { item, index }, accumulator);
73
67
  accumulator = await updateAccumulator(step, postScope, accumulator);
@@ -99,22 +93,15 @@ async function executeWhileLoop(env, step, state, path, startIndex) {
99
93
  index,
100
94
  ]);
101
95
  if (suspension) {
102
- return {
103
- ...suspension,
104
- continue: async (resumeData) => {
105
- const next = await suspension.continue(resumeData);
106
- if (next) {
107
- return next;
108
- }
109
- const postScope = buildScope(env, iterationState, { item: undefined, index }, accumulator);
110
- accumulator = await updateAccumulator(step, postScope, accumulator);
111
- return executeWhileLoop(env, step, {
112
- ...iterationState,
113
- accumulator,
114
- iterationStack: state.iterationStack,
115
- }, path, index + 1);
116
- },
117
- };
96
+ return wrapSuspensionContinuation(suspension, async () => {
97
+ const postScope = buildScope(env, iterationState, { item: undefined, index }, accumulator);
98
+ accumulator = await updateAccumulator(step, postScope, accumulator);
99
+ return executeWhileLoop(env, step, {
100
+ ...iterationState,
101
+ accumulator,
102
+ iterationStack: state.iterationStack,
103
+ }, path, index + 1);
104
+ });
118
105
  }
119
106
  const postScope = buildScope(env, iterationState, { item: undefined, index }, accumulator);
120
107
  accumulator = await updateAccumulator(step, postScope, accumulator);
@@ -4,6 +4,7 @@
4
4
  * Full terms: see LICENSE.md.
5
5
  */
6
6
  import { markStepsSkipped } from './skip-helpers';
7
+ import { wrapSuspensionContinuation } from './suspension-continuation';
7
8
  /**
8
9
  * Execute a set of steps in parallel order, respecting the configured strategy.
9
10
  *
@@ -20,22 +21,15 @@ export async function executeParallel(env, step, state, path, startIndex = 0) {
20
21
  const childPath = [...path, 'parallel', index];
21
22
  const suspension = await env.executeStep(child, state, childPath);
22
23
  if (suspension) {
23
- return {
24
- ...suspension,
25
- continue: async (resumeData) => {
26
- const next = await suspension.continue(resumeData);
27
- if (next) {
28
- return next;
24
+ return wrapSuspensionContinuation(suspension, async () => {
25
+ if (step.strategy === 'wait_any') {
26
+ if (index + 1 < step.steps.length) {
27
+ markStepsSkipped(env, step.steps.slice(index + 1), state.iterationStack);
29
28
  }
30
- if (step.strategy === 'wait_any') {
31
- if (index + 1 < step.steps.length) {
32
- markStepsSkipped(env, step.steps.slice(index + 1), state.iterationStack);
33
- }
34
- return undefined;
35
- }
36
- return executeParallel(env, step, state, path, index + 1);
37
- },
38
- };
29
+ return undefined;
30
+ }
31
+ return executeParallel(env, step, state, path, index + 1);
32
+ });
39
33
  }
40
34
  if (step.strategy === 'wait_any') {
41
35
  if (index + 1 < step.steps.length) {
@@ -0,0 +1,24 @@
1
+ /*
2
+ * Hexabot — Fair Core License (FCL-1.0-ALv2)
3
+ * Copyright (c) 2025 Hexastack.
4
+ * Full terms: see LICENSE.md.
5
+ */
6
+ /**
7
+ * Compose a suspension with the continuation that should run once it completes.
8
+ *
9
+ * When resuming a suspension yields another suspension from the same logical
10
+ * step, the follow-up suspension still needs to remember how to continue the
11
+ * surrounding flow after that step eventually finishes.
12
+ */
13
+ export function wrapSuspensionContinuation(suspension, onComplete) {
14
+ return {
15
+ ...suspension,
16
+ continue: async (resumeData) => {
17
+ const next = await suspension.continue(resumeData);
18
+ if (next) {
19
+ return wrapSuspensionContinuation(next, onComplete);
20
+ }
21
+ return onComplete();
22
+ },
23
+ };
24
+ }