@positronic/core 0.0.56 → 0.0.57

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.
Files changed (60) hide show
  1. package/dist/src/dsl/agent-messages.js +4 -75
  2. package/dist/src/dsl/brain-runner.js +131 -47
  3. package/dist/src/dsl/brain-state-machine.js +318 -482
  4. package/dist/src/dsl/builder/brain.js +35 -1
  5. package/dist/src/dsl/constants.js +14 -2
  6. package/dist/src/dsl/create-brain.js +4 -1
  7. package/dist/src/dsl/execution/constants.js +2 -2
  8. package/dist/src/dsl/execution/event-stream.js +812 -270
  9. package/dist/src/dsl/signal-validation.js +157 -0
  10. package/dist/src/dsl/types.js +2 -2
  11. package/dist/src/index.js +5 -2
  12. package/dist/src/memory/scoped-memory.js +176 -0
  13. package/dist/src/memory/types.js +12 -0
  14. package/dist/src/tools/index.js +90 -37
  15. package/dist/src/ui/generate-ui.js +6 -3
  16. package/dist/src/yaml/data-validator.js +195 -0
  17. package/dist/types/clients/types.d.ts +39 -2
  18. package/dist/types/clients/types.d.ts.map +1 -1
  19. package/dist/types/dsl/agent-messages.d.ts +8 -14
  20. package/dist/types/dsl/agent-messages.d.ts.map +1 -1
  21. package/dist/types/dsl/brain-runner.d.ts +27 -7
  22. package/dist/types/dsl/brain-runner.d.ts.map +1 -1
  23. package/dist/types/dsl/brain-state-machine.d.ts +92 -23
  24. package/dist/types/dsl/brain-state-machine.d.ts.map +1 -1
  25. package/dist/types/dsl/brain.d.ts +2 -2
  26. package/dist/types/dsl/brain.d.ts.map +1 -1
  27. package/dist/types/dsl/builder/brain.d.ts +51 -3
  28. package/dist/types/dsl/builder/brain.d.ts.map +1 -1
  29. package/dist/types/dsl/constants.d.ts +8 -0
  30. package/dist/types/dsl/constants.d.ts.map +1 -1
  31. package/dist/types/dsl/create-brain.d.ts +13 -1
  32. package/dist/types/dsl/create-brain.d.ts.map +1 -1
  33. package/dist/types/dsl/definitions/blocks.d.ts +3 -3
  34. package/dist/types/dsl/definitions/blocks.d.ts.map +1 -1
  35. package/dist/types/dsl/definitions/events.d.ts +40 -3
  36. package/dist/types/dsl/definitions/events.d.ts.map +1 -1
  37. package/dist/types/dsl/definitions/run-params.d.ts +17 -9
  38. package/dist/types/dsl/definitions/run-params.d.ts.map +1 -1
  39. package/dist/types/dsl/execution/constants.d.ts +2 -2
  40. package/dist/types/dsl/execution/constants.d.ts.map +1 -1
  41. package/dist/types/dsl/execution/event-stream.d.ts +12 -5
  42. package/dist/types/dsl/execution/event-stream.d.ts.map +1 -1
  43. package/dist/types/dsl/signal-validation.d.ts +36 -0
  44. package/dist/types/dsl/signal-validation.d.ts.map +1 -0
  45. package/dist/types/dsl/types.d.ts +57 -1
  46. package/dist/types/dsl/types.d.ts.map +1 -1
  47. package/dist/types/index.d.ts +12 -7
  48. package/dist/types/index.d.ts.map +1 -1
  49. package/dist/types/memory/scoped-memory.d.ts +22 -0
  50. package/dist/types/memory/scoped-memory.d.ts.map +1 -0
  51. package/dist/types/memory/types.d.ts +106 -0
  52. package/dist/types/memory/types.d.ts.map +1 -0
  53. package/dist/types/tools/index.d.ts +82 -15
  54. package/dist/types/tools/index.d.ts.map +1 -1
  55. package/dist/types/ui/generate-ui.d.ts.map +1 -1
  56. package/dist/types/yaml/data-validator.d.ts +27 -1
  57. package/dist/types/yaml/data-validator.d.ts.map +1 -1
  58. package/dist/types/yaml/types.d.ts +10 -0
  59. package/dist/types/yaml/types.d.ts.map +1 -1
  60. package/package.json +1 -1
@@ -64,33 +64,6 @@ function _object_spread_props(target, source) {
64
64
  }
65
65
  return target;
66
66
  }
67
- function _object_without_properties(source, excluded) {
68
- if (source == null) return {};
69
- var target = _object_without_properties_loose(source, excluded);
70
- var key, i;
71
- if (Object.getOwnPropertySymbols) {
72
- var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
73
- for(i = 0; i < sourceSymbolKeys.length; i++){
74
- key = sourceSymbolKeys[i];
75
- if (excluded.indexOf(key) >= 0) continue;
76
- if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
77
- target[key] = source[key];
78
- }
79
- }
80
- return target;
81
- }
82
- function _object_without_properties_loose(source, excluded) {
83
- if (source == null) return {};
84
- var target = {};
85
- var sourceKeys = Object.keys(source);
86
- var key, i;
87
- for(i = 0; i < sourceKeys.length; i++){
88
- key = sourceKeys[i];
89
- if (excluded.indexOf(key) >= 0) continue;
90
- target[key] = source[key];
91
- }
92
- return target;
93
- }
94
67
  function _to_consumable_array(arr) {
95
68
  return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
96
69
  }
@@ -110,104 +83,39 @@ var createMachine = robot3.createMachine, state = robot3.state, transition = rob
110
83
  import { BRAIN_EVENTS, STATUS } from './constants.js';
111
84
  import { applyPatches } from './json-patch.js';
112
85
  // ============================================================================
113
- // Tree Helper Functions
86
+ // Tree Reconstruction Helper (for consumers who need tree representation)
114
87
  // ============================================================================
115
88
  /**
116
- * Get the deepest (currently executing) brain in the tree.
117
- */ function getDeepestBrain(root) {
118
- if (!root) return null;
119
- var current = root;
120
- while(current.innerBrain){
121
- current = current.innerBrain;
122
- }
123
- return current;
124
- }
125
- /**
126
- * Clone tree with a new innerBrain attached to the deepest node.
127
- */ function cloneTreeWithNewInner(root, newInner) {
128
- if (!root.innerBrain) {
129
- return _object_spread_props(_object_spread({}, root), {
130
- innerBrain: newInner
131
- });
132
- }
133
- return _object_spread_props(_object_spread({}, root), {
134
- innerBrain: cloneTreeWithNewInner(root.innerBrain, newInner)
135
- });
136
- }
137
- /**
138
- * Clone tree replacing the deepest brain.
139
- */ function cloneTreeReplacingDeepest(root, replacement) {
140
- if (!root.innerBrain) {
141
- return replacement;
142
- }
143
- return _object_spread_props(_object_spread({}, root), {
144
- innerBrain: cloneTreeReplacingDeepest(root.innerBrain, replacement)
145
- });
146
- }
147
- /**
148
- * Clone tree updating steps on the deepest brain.
149
- */ function cloneTreeUpdatingDeepestSteps(root, newSteps) {
150
- if (!root.innerBrain) {
151
- return _object_spread_props(_object_spread({}, root), {
152
- steps: newSteps
153
- });
154
- }
155
- return _object_spread_props(_object_spread({}, root), {
156
- innerBrain: cloneTreeUpdatingDeepestSteps(root.innerBrain, newSteps)
157
- });
158
- }
159
- /**
160
- * Clone tree removing the deepest brain and attaching its steps to parent step.
161
- * Returns null if root is the deepest (no parent).
162
- */ function cloneTreeRemovingDeepest(root) {
163
- if (!root.innerBrain) {
164
- // Root is the deepest - can't remove, return null
165
- return null;
166
- }
167
- if (!root.innerBrain.innerBrain) {
168
- // root.innerBrain is the deepest - remove it and attach steps to parent step
169
- var completedBrain = root.innerBrain;
170
- var updatedSteps = root.steps.map(function(step) {
171
- if (step.id === completedBrain.parentStepId) {
172
- return _object_spread_props(_object_spread({}, step), {
173
- innerSteps: completedBrain.steps,
174
- status: STATUS.COMPLETE
175
- });
176
- }
177
- return step;
178
- });
179
- return _object_spread_props(_object_spread({}, root), {
180
- steps: updatedSteps,
181
- innerBrain: null
182
- });
183
- }
184
- // Recurse down
185
- return _object_spread_props(_object_spread({}, root), {
186
- innerBrain: cloneTreeRemovingDeepest(root.innerBrain)
187
- });
188
- }
189
- /**
190
- * Convert tree to flat array (for backwards compatibility).
191
- */ function treeToStack(root) {
192
- var stack = [];
193
- var current = root;
194
- while(current){
195
- stack.push({
196
- brainRunId: current.brainRunId,
197
- brainTitle: current.brainTitle,
198
- brainDescription: current.brainDescription,
199
- parentStepId: current.parentStepId,
200
- steps: current.steps
201
- });
202
- current = current.innerBrain;
89
+ * Reconstruct the RunningBrain tree from flat brains map and stack.
90
+ * Use this when you need a tree representation for UI rendering or debugging.
91
+ * The flat structures (brains, brainIdStack) are the source of truth.
92
+ */ export function reconstructBrainTree(brains, brainIdStack) {
93
+ if (brainIdStack.length === 0) return null;
94
+ var innerBrain = null;
95
+ // Build from deepest to root (reverse iteration)
96
+ for(var i = brainIdStack.length - 1; i >= 0; i--){
97
+ var brainId = brainIdStack[i];
98
+ var entry = brains[brainId];
99
+ if (!entry) continue;
100
+ innerBrain = {
101
+ brainRunId: entry.brainRunId,
102
+ brainTitle: entry.brainTitle,
103
+ brainDescription: entry.brainDescription,
104
+ parentStepId: entry.parentStepId,
105
+ steps: entry.steps,
106
+ innerBrain: innerBrain,
107
+ depth: entry.depth
108
+ };
203
109
  }
204
- return stack;
110
+ return innerBrain;
205
111
  }
206
112
  var createInitialContext = function(opts) {
207
113
  var _opts_initialState, _opts_options;
208
114
  return {
209
- rootBrain: null,
210
- brainStack: [],
115
+ // Flat storage (source of truth)
116
+ brains: {},
117
+ brainIdStack: [],
118
+ executionStack: [],
211
119
  depth: 0,
212
120
  brainRunId: null,
213
121
  currentStepId: null,
@@ -215,16 +123,19 @@ var createInitialContext = function(opts) {
215
123
  error: null,
216
124
  pendingWebhooks: null,
217
125
  currentState: (_opts_initialState = opts === null || opts === void 0 ? void 0 : opts.initialState) !== null && _opts_initialState !== void 0 ? _opts_initialState : {},
218
- currentEvent: null,
219
126
  options: (_opts_options = opts === null || opts === void 0 ? void 0 : opts.options) !== null && _opts_options !== void 0 ? _opts_options : {},
127
+ agentContext: null,
220
128
  status: STATUS.PENDING,
221
129
  isTopLevel: false,
222
130
  isRunning: false,
223
131
  isComplete: false,
224
132
  isPaused: false,
133
+ isWaiting: false,
225
134
  isError: false,
226
135
  isCancelled: false,
227
- topLevelStepCount: 0
136
+ isInAgentLoop: false,
137
+ topLevelStepCount: 0,
138
+ totalTokens: 0
228
139
  };
229
140
  };
230
141
  // ============================================================================
@@ -232,6 +143,7 @@ var createInitialContext = function(opts) {
232
143
  // ============================================================================
233
144
  var updateDerivedState = function(ctx, executionState) {
234
145
  // Map ExecutionState to STATUS - this gives consumers the authoritative status
146
+ // Note: agentLoop maps to RUNNING publicly (consumers don't need to know the difference)
235
147
  var status;
236
148
  switch(executionState){
237
149
  case 'idle':
@@ -240,9 +152,14 @@ var updateDerivedState = function(ctx, executionState) {
240
152
  case 'running':
241
153
  status = STATUS.RUNNING;
242
154
  break;
155
+ case 'agentLoop':
156
+ status = STATUS.RUNNING; // Publicly still "running"
157
+ break;
243
158
  case 'paused':
244
- // Paused brains are still considered "running" in terms of database status
245
- status = STATUS.RUNNING;
159
+ status = STATUS.PAUSED;
160
+ break;
161
+ case 'waiting':
162
+ status = STATUS.WAITING;
246
163
  break;
247
164
  case 'complete':
248
165
  status = STATUS.COMPLETE;
@@ -259,11 +176,13 @@ var updateDerivedState = function(ctx, executionState) {
259
176
  return _object_spread_props(_object_spread({}, ctx), {
260
177
  status: status,
261
178
  isTopLevel: ctx.depth === 1,
262
- isRunning: executionState === 'running',
179
+ isRunning: executionState === 'running' || executionState === 'agentLoop',
263
180
  isComplete: executionState === 'complete',
264
181
  isPaused: executionState === 'paused',
182
+ isWaiting: executionState === 'waiting',
265
183
  isError: executionState === 'error',
266
- isCancelled: executionState === 'cancelled'
184
+ isCancelled: executionState === 'cancelled',
185
+ isInAgentLoop: executionState === 'agentLoop'
267
186
  });
268
187
  };
269
188
  // ============================================================================
@@ -271,311 +190,211 @@ var updateDerivedState = function(ctx, executionState) {
271
190
  // ============================================================================
272
191
  var startBrain = reduce(function(ctx, param) {
273
192
  var brainRunId = param.brainRunId, brainTitle = param.brainTitle, brainDescription = param.brainDescription, initialState = param.initialState;
274
- var currentStepId = ctx.currentStepId, rootBrain = ctx.rootBrain, depth = ctx.depth, existingBrainRunId = ctx.brainRunId, currentState = ctx.currentState, options = ctx.options;
193
+ var currentStepId = ctx.currentStepId, depth = ctx.depth, existingBrainRunId = ctx.brainRunId, currentState = ctx.currentState, brains = ctx.brains, brainIdStack = ctx.brainIdStack, executionStack = ctx.executionStack;
275
194
  var newDepth = depth + 1;
276
- var newBrain = {
195
+ var brainInitialState = initialState !== null && initialState !== void 0 ? initialState : currentState;
196
+ // === NEW: Update flat structures ===
197
+ var parentBrainId = brainIdStack.length > 0 ? brainIdStack[brainIdStack.length - 1] : null;
198
+ var newBrainEntry = {
277
199
  brainRunId: brainRunId,
278
200
  brainTitle: brainTitle,
279
201
  brainDescription: brainDescription,
280
202
  parentStepId: currentStepId,
203
+ parentBrainId: parentBrainId,
281
204
  steps: [],
282
- innerBrain: null,
283
205
  depth: newDepth
284
206
  };
285
- // Build tree: if no root, this is root; else attach to deepest
286
- var newRootBrain = rootBrain ? cloneTreeWithNewInner(rootBrain, newBrain) : newBrain;
207
+ var newBrains = _object_spread_props(_object_spread({}, brains), _define_property({}, brainTitle, newBrainEntry));
208
+ var newBrainIdStack = _to_consumable_array(brainIdStack).concat([
209
+ brainTitle
210
+ ]);
211
+ var newExecutionStack = _to_consumable_array(executionStack).concat([
212
+ {
213
+ state: brainInitialState,
214
+ stepIndex: 0
215
+ }
216
+ ]);
287
217
  var newCtx = _object_spread_props(_object_spread({}, ctx), {
288
- rootBrain: newRootBrain,
289
- brainStack: treeToStack(newRootBrain),
218
+ brains: newBrains,
219
+ brainIdStack: newBrainIdStack,
220
+ executionStack: newExecutionStack,
290
221
  depth: newDepth,
291
222
  brainRunId: existingBrainRunId !== null && existingBrainRunId !== void 0 ? existingBrainRunId : brainRunId,
292
- currentState: newDepth === 1 ? initialState !== null && initialState !== void 0 ? initialState : currentState : currentState,
293
- currentEvent: {
294
- type: BRAIN_EVENTS.START,
295
- brainTitle: brainTitle,
296
- brainDescription: brainDescription,
297
- brainRunId: brainRunId,
298
- initialState: initialState !== null && initialState !== void 0 ? initialState : {},
299
- status: STATUS.RUNNING,
300
- options: options
301
- }
223
+ currentState: newDepth === 1 ? brainInitialState : currentState
302
224
  });
303
225
  return updateDerivedState(newCtx, 'running');
304
226
  });
305
- var restartBrain = reduce(function(ctx, param) {
306
- var brainRunId = param.brainRunId, brainTitle = param.brainTitle, brainDescription = param.brainDescription, initialState = param.initialState;
307
- var currentStepId = ctx.currentStepId, rootBrain = ctx.rootBrain, depth = ctx.depth, existingBrainRunId = ctx.brainRunId, options = ctx.options;
308
- // brain:restart can be either:
309
- // 1. A resume of an existing brain on the stack (same brainTitle) - should REPLACE
310
- // 2. A nested inner brain restarting (different brainTitle) - should ADD
311
- if (rootBrain) {
312
- var deepestBrain = getDeepestBrain(rootBrain);
313
- // If the deepest brain has the same title, this is a resume - replace it
314
- if (deepestBrain && deepestBrain.brainTitle === brainTitle) {
315
- var replacementBrain = {
316
- brainRunId: brainRunId,
317
- brainTitle: brainTitle,
318
- brainDescription: brainDescription,
319
- parentStepId: deepestBrain.parentStepId,
320
- steps: [],
321
- innerBrain: null,
322
- depth: deepestBrain.depth
323
- };
324
- var newRootBrain = cloneTreeReplacingDeepest(rootBrain, replacementBrain);
325
- var newCtx = _object_spread_props(_object_spread({}, ctx), {
326
- rootBrain: newRootBrain,
327
- brainStack: treeToStack(newRootBrain),
328
- // depth stays the same - we're replacing, not nesting
329
- brainRunId: existingBrainRunId !== null && existingBrainRunId !== void 0 ? existingBrainRunId : brainRunId,
330
- currentEvent: {
331
- type: BRAIN_EVENTS.RESTART,
332
- brainTitle: brainTitle,
333
- brainDescription: brainDescription,
334
- brainRunId: brainRunId,
335
- initialState: initialState !== null && initialState !== void 0 ? initialState : {},
336
- status: STATUS.RUNNING,
337
- options: options
338
- }
339
- });
340
- return updateDerivedState(newCtx, 'running');
341
- }
342
- // Different title - this is a nested inner brain restarting, ADD to tree
343
- var newDepth = depth + 1;
344
- var newBrain = {
345
- brainRunId: brainRunId,
346
- brainTitle: brainTitle,
347
- brainDescription: brainDescription,
348
- parentStepId: currentStepId,
349
- steps: [],
350
- innerBrain: null,
351
- depth: newDepth
352
- };
353
- var newRootBrain1 = cloneTreeWithNewInner(rootBrain, newBrain);
354
- var newCtx1 = _object_spread_props(_object_spread({}, ctx), {
355
- rootBrain: newRootBrain1,
356
- brainStack: treeToStack(newRootBrain1),
357
- depth: newDepth,
358
- brainRunId: existingBrainRunId !== null && existingBrainRunId !== void 0 ? existingBrainRunId : brainRunId,
359
- currentEvent: {
360
- type: BRAIN_EVENTS.RESTART,
361
- brainTitle: brainTitle,
362
- brainDescription: brainDescription,
363
- brainRunId: brainRunId,
364
- initialState: initialState !== null && initialState !== void 0 ? initialState : {},
365
- status: STATUS.RUNNING,
366
- options: options
367
- }
368
- });
369
- return updateDerivedState(newCtx1, 'running');
370
- }
371
- // No brain on stack - this is a fresh restart from idle state
372
- var newBrain1 = {
373
- brainRunId: brainRunId,
374
- brainTitle: brainTitle,
375
- brainDescription: brainDescription,
376
- parentStepId: null,
377
- steps: [],
378
- innerBrain: null,
379
- depth: 1
380
- };
381
- var newCtx2 = _object_spread_props(_object_spread({}, ctx), {
382
- rootBrain: newBrain1,
383
- brainStack: treeToStack(newBrain1),
384
- depth: 1,
385
- brainRunId: existingBrainRunId !== null && existingBrainRunId !== void 0 ? existingBrainRunId : brainRunId,
386
- currentEvent: {
387
- type: BRAIN_EVENTS.RESTART,
388
- brainTitle: brainTitle,
389
- brainDescription: brainDescription,
390
- brainRunId: brainRunId,
391
- initialState: initialState !== null && initialState !== void 0 ? initialState : {},
392
- status: STATUS.RUNNING,
393
- options: options
394
- }
395
- });
396
- return updateDerivedState(newCtx2, 'running');
397
- });
398
227
  var completeBrain = reduce(function(ctx) {
399
- var rootBrain = ctx.rootBrain, depth = ctx.depth, brainRunId = ctx.brainRunId, options = ctx.options;
400
- if (!rootBrain) return ctx;
401
- var completedBrain = getDeepestBrain(rootBrain);
402
- if (!completedBrain) return ctx;
228
+ var depth = ctx.depth, brains = ctx.brains, brainIdStack = ctx.brainIdStack, executionStack = ctx.executionStack;
229
+ if (brainIdStack.length === 0) return ctx;
403
230
  var newDepth = depth - 1;
404
231
  var isOuterBrainComplete = newDepth === 0;
405
- // When the outer brain completes, keep rootBrain so we can still display
406
- // the final state. Only remove inner brains (attaching their steps to parent).
407
- var newRootBrain = isOuterBrainComplete ? rootBrain : cloneTreeRemovingDeepest(rootBrain);
408
- var newCtx = _object_spread_props(_object_spread({}, ctx), {
409
- rootBrain: newRootBrain,
410
- brainStack: treeToStack(newRootBrain),
411
- depth: newDepth,
412
- currentEvent: {
413
- type: BRAIN_EVENTS.COMPLETE,
414
- brainTitle: completedBrain.brainTitle,
415
- brainDescription: completedBrain.brainDescription,
416
- brainRunId: brainRunId,
417
- status: STATUS.COMPLETE,
418
- options: options
232
+ // === NEW: Update flat structures ===
233
+ var newBrains = brains;
234
+ var newBrainIdStack = brainIdStack;
235
+ var newExecutionStack = executionStack;
236
+ if (!isOuterBrainComplete) {
237
+ // Pop the completed brain from stack
238
+ var completedBrainId = brainIdStack[brainIdStack.length - 1];
239
+ var completedBrain = brains[completedBrainId];
240
+ newBrainIdStack = brainIdStack.slice(0, -1);
241
+ newExecutionStack = executionStack.slice(0, -1);
242
+ // Attach completed brain's steps to parent step
243
+ if (completedBrain && newBrainIdStack.length > 0) {
244
+ var parentBrainId = newBrainIdStack[newBrainIdStack.length - 1];
245
+ var parentBrain = brains[parentBrainId];
246
+ if (parentBrain && completedBrain.parentStepId) {
247
+ var updatedSteps = parentBrain.steps.map(function(step) {
248
+ if (step.id === completedBrain.parentStepId) {
249
+ return _object_spread_props(_object_spread({}, step), {
250
+ innerSteps: completedBrain.steps,
251
+ status: STATUS.COMPLETE
252
+ });
253
+ }
254
+ return step;
255
+ });
256
+ newBrains = _object_spread_props(_object_spread({}, brains), _define_property({}, parentBrainId, _object_spread_props(_object_spread({}, parentBrain), {
257
+ steps: updatedSteps
258
+ })));
259
+ }
419
260
  }
261
+ }
262
+ // If outer brain complete, keep everything as-is for final state display
263
+ var newCtx = _object_spread_props(_object_spread({}, ctx), {
264
+ brains: newBrains,
265
+ brainIdStack: newBrainIdStack,
266
+ executionStack: newExecutionStack,
267
+ depth: newDepth
420
268
  });
421
269
  return updateDerivedState(newCtx, isOuterBrainComplete ? 'complete' : 'running');
422
270
  });
423
271
  var errorBrain = reduce(function(ctx, param) {
424
272
  var error = param.error;
425
- var rootBrain = ctx.rootBrain, brainRunId = ctx.brainRunId, options = ctx.options;
426
- var currentBrain = getDeepestBrain(rootBrain);
427
273
  var newCtx = _object_spread_props(_object_spread({}, ctx), {
428
- error: error,
429
- currentEvent: {
430
- type: BRAIN_EVENTS.ERROR,
431
- brainTitle: currentBrain === null || currentBrain === void 0 ? void 0 : currentBrain.brainTitle,
432
- brainDescription: currentBrain === null || currentBrain === void 0 ? void 0 : currentBrain.brainDescription,
433
- brainRunId: brainRunId,
434
- error: error,
435
- status: STATUS.ERROR,
436
- options: options
437
- }
274
+ error: error
438
275
  });
439
276
  return updateDerivedState(newCtx, 'error');
440
277
  });
441
278
  var cancelBrain = reduce(function(ctx) {
442
- var rootBrain = ctx.rootBrain, brainRunId = ctx.brainRunId, options = ctx.options;
443
- var currentBrain = getDeepestBrain(rootBrain);
444
- var newCtx = _object_spread_props(_object_spread({}, ctx), {
445
- currentEvent: {
446
- type: BRAIN_EVENTS.CANCELLED,
447
- brainTitle: currentBrain === null || currentBrain === void 0 ? void 0 : currentBrain.brainTitle,
448
- brainDescription: currentBrain === null || currentBrain === void 0 ? void 0 : currentBrain.brainDescription,
449
- brainRunId: brainRunId,
450
- status: STATUS.CANCELLED,
451
- options: options
452
- }
453
- });
454
- return updateDerivedState(newCtx, 'cancelled');
279
+ return updateDerivedState(ctx, 'cancelled');
455
280
  });
456
281
  var startStep = reduce(function(ctx, param) {
457
- var stepId = param.stepId, stepTitle = param.stepTitle;
458
- var rootBrain = ctx.rootBrain, brainRunId = ctx.brainRunId, options = ctx.options;
459
- // Add step to current brain's steps if not already there
460
- var newRootBrain = rootBrain;
461
- if (rootBrain) {
462
- var currentBrain = getDeepestBrain(rootBrain);
463
- if (currentBrain) {
464
- var existingStep = currentBrain.steps.find(function(s) {
465
- return s.id === stepId;
466
- });
467
- var newSteps;
468
- if (!existingStep) {
469
- newSteps = _to_consumable_array(currentBrain.steps).concat([
470
- {
471
- id: stepId,
472
- title: stepTitle,
473
- status: STATUS.RUNNING
474
- }
475
- ]);
476
- } else {
477
- newSteps = currentBrain.steps.map(function(s) {
478
- return s.id === stepId ? _object_spread_props(_object_spread({}, s), {
479
- status: STATUS.RUNNING
480
- }) : s;
481
- });
482
- }
483
- newRootBrain = cloneTreeUpdatingDeepestSteps(rootBrain, newSteps);
282
+ var stepId = param.stepId, stepTitle = param.stepTitle, stepIndex = param.stepIndex;
283
+ var brains = ctx.brains, brainIdStack = ctx.brainIdStack, executionStack = ctx.executionStack;
284
+ if (brainIdStack.length === 0) return ctx;
285
+ // === NEW: Update flat structures ===
286
+ var currentBrainId = brainIdStack[brainIdStack.length - 1];
287
+ var currentBrain = brains[currentBrainId];
288
+ if (!currentBrain) return ctx;
289
+ // Update current brain's steps
290
+ var existingStep = currentBrain.steps.find(function(s) {
291
+ return s.id === stepId;
292
+ });
293
+ var newSteps = existingStep ? currentBrain.steps.map(function(s) {
294
+ return s.id === stepId ? _object_spread_props(_object_spread({}, s), {
295
+ status: STATUS.RUNNING
296
+ }) : s;
297
+ }) : _to_consumable_array(currentBrain.steps).concat([
298
+ {
299
+ id: stepId,
300
+ title: stepTitle,
301
+ status: STATUS.RUNNING
484
302
  }
485
- }
303
+ ]);
304
+ var newBrains = _object_spread_props(_object_spread({}, brains), _define_property({}, currentBrainId, _object_spread_props(_object_spread({}, currentBrain), {
305
+ steps: newSteps
306
+ })));
307
+ // Update stepIndex in execution stack if provided
308
+ var newExecutionStack = stepIndex !== undefined && executionStack.length > 0 ? _to_consumable_array(executionStack.slice(0, -1)).concat([
309
+ _object_spread_props(_object_spread({}, executionStack[executionStack.length - 1]), {
310
+ stepIndex: stepIndex
311
+ })
312
+ ]) : executionStack;
486
313
  return _object_spread_props(_object_spread({}, ctx), {
487
- rootBrain: newRootBrain,
488
- brainStack: treeToStack(newRootBrain),
314
+ brains: newBrains,
315
+ executionStack: newExecutionStack,
489
316
  currentStepId: stepId,
490
- currentStepTitle: stepTitle,
491
- currentEvent: {
492
- type: BRAIN_EVENTS.STEP_START,
493
- brainRunId: brainRunId,
494
- stepId: stepId,
495
- stepTitle: stepTitle,
496
- status: STATUS.RUNNING,
497
- options: options
498
- }
317
+ currentStepTitle: stepTitle
499
318
  });
500
319
  });
501
320
  var completeStep = reduce(function(ctx, param) {
502
- var stepId = param.stepId, stepTitle = param.stepTitle, patch = param.patch;
503
- var rootBrain = ctx.rootBrain, depth = ctx.depth, currentState = ctx.currentState, topLevelStepCount = ctx.topLevelStepCount, brainRunId = ctx.brainRunId, options = ctx.options;
504
- var newRootBrain = rootBrain;
505
- if (rootBrain) {
506
- var currentBrain = getDeepestBrain(rootBrain);
507
- if (currentBrain) {
508
- var newSteps = currentBrain.steps.map(function(s) {
509
- return s.id === stepId ? _object_spread_props(_object_spread({}, s), {
510
- status: STATUS.COMPLETE,
511
- patch: patch
512
- }) : s;
513
- });
514
- newRootBrain = cloneTreeUpdatingDeepestSteps(rootBrain, newSteps);
515
- }
321
+ var stepId = param.stepId, patch = param.patch;
322
+ var brains = ctx.brains, brainIdStack = ctx.brainIdStack, executionStack = ctx.executionStack, depth = ctx.depth, currentState = ctx.currentState, topLevelStepCount = ctx.topLevelStepCount;
323
+ if (brainIdStack.length === 0) return ctx;
324
+ // === NEW: Update flat structures ===
325
+ var currentBrainId = brainIdStack[brainIdStack.length - 1];
326
+ var currentBrain = brains[currentBrainId];
327
+ if (!currentBrain) return ctx;
328
+ // Update step status
329
+ var newSteps = currentBrain.steps.map(function(s) {
330
+ return s.id === stepId ? _object_spread_props(_object_spread({}, s), {
331
+ status: STATUS.COMPLETE,
332
+ patch: patch
333
+ }) : s;
334
+ });
335
+ var newBrains = _object_spread_props(_object_spread({}, brains), _define_property({}, currentBrainId, _object_spread_props(_object_spread({}, currentBrain), {
336
+ steps: newSteps
337
+ })));
338
+ // Apply patch to execution stack and increment stepIndex
339
+ var newExecutionStack = executionStack;
340
+ if (executionStack.length > 0) {
341
+ var topEntry = executionStack[executionStack.length - 1];
342
+ var newState = patch ? applyPatches(topEntry.state, [
343
+ patch
344
+ ]) : topEntry.state;
345
+ // Increment stepIndex so resume knows to start from the NEXT step
346
+ newExecutionStack = _to_consumable_array(executionStack.slice(0, -1)).concat([
347
+ _object_spread_props(_object_spread({}, topEntry), {
348
+ state: newState,
349
+ stepIndex: topEntry.stepIndex + 1
350
+ })
351
+ ]);
516
352
  }
517
- // Apply patch to currentState only for top-level brain
518
- var newState = currentState;
353
+ // Apply patch to currentState only for top-level brain (for backwards compat)
354
+ var newState1 = currentState;
519
355
  var newStepCount = topLevelStepCount;
520
356
  if (depth === 1 && patch) {
521
- newState = applyPatches(currentState, [
357
+ newState1 = applyPatches(currentState, [
522
358
  patch
523
359
  ]);
524
360
  newStepCount = topLevelStepCount + 1;
525
361
  }
526
362
  return _object_spread_props(_object_spread({}, ctx), {
527
- rootBrain: newRootBrain,
528
- brainStack: treeToStack(newRootBrain),
529
- currentState: newState,
530
- topLevelStepCount: newStepCount,
531
- currentEvent: {
532
- type: BRAIN_EVENTS.STEP_COMPLETE,
533
- brainRunId: brainRunId,
534
- stepId: stepId,
535
- stepTitle: stepTitle,
536
- patch: patch,
537
- status: STATUS.RUNNING,
538
- options: options
539
- }
363
+ brains: newBrains,
364
+ executionStack: newExecutionStack,
365
+ currentState: newState1,
366
+ topLevelStepCount: newStepCount
540
367
  });
541
368
  });
542
369
  var webhookPause = reduce(function(ctx, param) {
543
370
  var waitFor = param.waitFor;
544
- var brainRunId = ctx.brainRunId, options = ctx.options;
545
371
  var newCtx = _object_spread_props(_object_spread({}, ctx), {
546
- pendingWebhooks: waitFor,
547
- currentEvent: {
548
- type: BRAIN_EVENTS.WEBHOOK,
549
- brainRunId: brainRunId,
550
- waitFor: waitFor,
551
- options: options
552
- }
372
+ pendingWebhooks: waitFor
553
373
  });
554
- return updateDerivedState(newCtx, 'paused');
374
+ return updateDerivedState(newCtx, 'waiting');
555
375
  });
556
- var webhookResponse = reduce(function(ctx, param) {
557
- var response = param.response;
558
- var brainRunId = ctx.brainRunId, options = ctx.options;
376
+ var pauseBrain = reduce(function(ctx) {
377
+ return updateDerivedState(ctx, 'paused');
378
+ });
379
+ var resumeBrain = reduce(function(ctx) {
380
+ return updateDerivedState(ctx, 'running');
381
+ });
382
+ var resumeToAgentLoop = reduce(function(ctx) {
383
+ return updateDerivedState(ctx, 'agentLoop');
384
+ });
385
+ var webhookResponse = reduce(function(ctx) {
559
386
  var newCtx = _object_spread_props(_object_spread({}, ctx), {
560
- pendingWebhooks: null,
561
- currentEvent: {
562
- type: BRAIN_EVENTS.WEBHOOK_RESPONSE,
563
- brainRunId: brainRunId,
564
- response: response,
565
- options: options
566
- }
387
+ pendingWebhooks: null
567
388
  });
568
389
  return updateDerivedState(newCtx, 'running');
569
390
  });
570
391
  var stepStatus = reduce(function(ctx, param) {
571
- var eventBrainRunId = param.brainRunId, steps = param.steps;
572
- var brainRunId = ctx.brainRunId, rootBrain = ctx.rootBrain, options = ctx.options;
573
- if (!rootBrain) return ctx;
574
- // Only update the current (deepest) brain in the tree.
575
- // STEP_STATUS is emitted by the currently executing brain, which is always
576
- // the deepest one. We can't match by brainRunId because nested brains share
577
- // the same brainRunId, which would incorrectly update all nested brains.
578
- var currentBrain = getDeepestBrain(rootBrain);
392
+ var steps = param.steps;
393
+ var brains = ctx.brains, brainIdStack = ctx.brainIdStack;
394
+ if (brainIdStack.length === 0) return ctx;
395
+ // === NEW: Update flat structures ===
396
+ var currentBrainId = brainIdStack[brainIdStack.length - 1];
397
+ var currentBrain = brains[currentBrainId];
579
398
  if (!currentBrain) return ctx;
580
399
  // Create a map of existing steps to preserve their patches
581
400
  var existingStepsById = new Map(currentBrain.steps.map(function(s) {
@@ -594,49 +413,87 @@ var stepStatus = reduce(function(ctx, param) {
594
413
  patch: existing.patch
595
414
  } : {});
596
415
  });
597
- var newRootBrain = cloneTreeUpdatingDeepestSteps(rootBrain, newSteps);
416
+ var newBrains = _object_spread_props(_object_spread({}, brains), _define_property({}, currentBrainId, _object_spread_props(_object_spread({}, currentBrain), {
417
+ steps: newSteps
418
+ })));
598
419
  return _object_spread_props(_object_spread({}, ctx), {
599
- rootBrain: newRootBrain,
600
- brainStack: treeToStack(newRootBrain),
601
- currentEvent: {
602
- type: BRAIN_EVENTS.STEP_STATUS,
603
- brainRunId: brainRunId,
604
- steps: steps,
605
- options: options
606
- }
420
+ brains: newBrains
607
421
  });
608
422
  });
609
- var stepRetry = reduce(function(ctx, param) {
610
- var stepId = param.stepId, stepTitle = param.stepTitle, error = param.error, attempt = param.attempt;
611
- var brainRunId = ctx.brainRunId, options = ctx.options;
423
+ // stepRetry is a no-op - we just let the event pass through
424
+ var stepRetry = reduce(function(ctx) {
425
+ return ctx;
426
+ });
427
+ // passthrough is now a no-op - we just let the event pass through
428
+ var passthrough = function() {
429
+ return reduce(function(ctx) {
430
+ return ctx;
431
+ });
432
+ };
433
+ // Reducer for agent iteration events that tracks tokens per-iteration
434
+ // This ensures tokens are counted even if the agent doesn't complete (e.g., webhook interruption)
435
+ var agentIteration = reduce(function(ctx, ev) {
436
+ var totalTokens = ctx.totalTokens;
437
+ var _ev_tokensThisIteration;
612
438
  return _object_spread_props(_object_spread({}, ctx), {
613
- currentEvent: {
614
- type: BRAIN_EVENTS.STEP_RETRY,
615
- brainRunId: brainRunId,
616
- stepId: stepId,
617
- stepTitle: stepTitle,
618
- error: error,
619
- attempt: attempt,
620
- options: options
621
- }
439
+ totalTokens: totalTokens + ((_ev_tokensThisIteration = ev.tokensThisIteration) !== null && _ev_tokensThisIteration !== void 0 ? _ev_tokensThisIteration : 0)
622
440
  });
623
441
  });
624
- var passthrough = function(eventType) {
625
- return reduce(function(ctx, ev) {
626
- var brainRunId = ctx.brainRunId, options = ctx.options;
627
- // Destructure to exclude 'type' (the action name) from being spread into currentEvent
628
- var _actionType = ev.type, eventData = _object_without_properties(ev, [
629
- "type"
630
- ]);
442
+ // Reducer for agent terminal events - clears agentContext since the agent has completed
443
+ var agentTerminal = function() {
444
+ return reduce(function(ctx) {
631
445
  return _object_spread_props(_object_spread({}, ctx), {
632
- currentEvent: _object_spread({
633
- type: eventType,
634
- brainRunId: brainRunId,
635
- options: options
636
- }, eventData)
446
+ agentContext: null
637
447
  });
638
448
  });
639
449
  };
450
+ // Reducer for AGENT_START - initializes agentContext
451
+ var agentStart = reduce(function(ctx, param) {
452
+ var stepId = param.stepId, stepTitle = param.stepTitle, prompt = param.prompt, system = param.system;
453
+ var newCtx = _object_spread_props(_object_spread({}, ctx), {
454
+ agentContext: {
455
+ stepId: stepId,
456
+ stepTitle: stepTitle,
457
+ prompt: prompt,
458
+ system: system,
459
+ responseMessages: [],
460
+ pendingToolCallId: null,
461
+ pendingToolName: null
462
+ }
463
+ });
464
+ return updateDerivedState(newCtx, 'agentLoop');
465
+ });
466
+ // Reducer for AGENT_RAW_RESPONSE_MESSAGE - accumulates messages in agentContext
467
+ var agentRawResponseMessage = reduce(function(ctx, param) {
468
+ var message = param.message;
469
+ var agentContext = ctx.agentContext;
470
+ // Accumulate the message in agentContext
471
+ var updatedAgentContext = agentContext ? _object_spread_props(_object_spread({}, agentContext), {
472
+ responseMessages: _to_consumable_array(agentContext.responseMessages).concat([
473
+ message
474
+ ])
475
+ }) : null;
476
+ return _object_spread_props(_object_spread({}, ctx), {
477
+ agentContext: updatedAgentContext
478
+ });
479
+ });
480
+ // Reducer for AGENT_WEBHOOK - records pending tool call in agentContext
481
+ var agentWebhook = reduce(function(ctx, param) {
482
+ var toolCallId = param.toolCallId, toolName = param.toolName;
483
+ var agentContext = ctx.agentContext;
484
+ // Update agentContext with pending tool info
485
+ var updatedAgentContext = agentContext ? _object_spread_props(_object_spread({}, agentContext), {
486
+ pendingToolCallId: toolCallId,
487
+ pendingToolName: toolName
488
+ }) : null;
489
+ return _object_spread_props(_object_spread({}, ctx), {
490
+ agentContext: updatedAgentContext
491
+ });
492
+ });
493
+ // Reducer for AGENT_USER_MESSAGE - no-op, just stays in agentLoop
494
+ var agentUserMessage = reduce(function(ctx) {
495
+ return ctx;
496
+ });
640
497
  // ============================================================================
641
498
  // Guards - Conditional transitions
642
499
  // ============================================================================
@@ -646,25 +503,67 @@ var isOuterBrain = guard(function(ctx) {
646
503
  var isInnerBrain = guard(function(ctx) {
647
504
  return ctx.depth > 1;
648
505
  });
506
+ // Guard to check if we have agentContext (for resuming to agentLoop)
507
+ var hasAgentContext = guard(function(ctx) {
508
+ return ctx.agentContext !== null;
509
+ });
649
510
  // ============================================================================
650
511
  // State Machine Definition
651
512
  // ============================================================================
513
+ // Define agent loop transitions as a reusable array for cleaner code
514
+ var agentLoopTransitions = [
515
+ // Agent micro-events that stay in agentLoop
516
+ transition(BRAIN_EVENTS.AGENT_ITERATION, 'agentLoop', agentIteration),
517
+ transition(BRAIN_EVENTS.AGENT_RAW_RESPONSE_MESSAGE, 'agentLoop', agentRawResponseMessage),
518
+ transition(BRAIN_EVENTS.AGENT_TOOL_CALL, 'agentLoop', passthrough()),
519
+ transition(BRAIN_EVENTS.AGENT_TOOL_RESULT, 'agentLoop', passthrough()),
520
+ transition(BRAIN_EVENTS.AGENT_ASSISTANT_MESSAGE, 'agentLoop', passthrough()),
521
+ transition(BRAIN_EVENTS.AGENT_USER_MESSAGE, 'agentLoop', agentUserMessage),
522
+ // AGENT_WEBHOOK records pending tool call but stays in agentLoop
523
+ transition(BRAIN_EVENTS.AGENT_WEBHOOK, 'agentLoop', agentWebhook)
524
+ ];
652
525
  // Internal machine factory - called with pre-built context
653
526
  var makeBrainMachine = function(initialContext) {
654
527
  return createMachine('idle', {
655
- idle: state(transition(BRAIN_EVENTS.START, 'running', startBrain), transition(BRAIN_EVENTS.RESTART, 'running', restartBrain)),
656
- running: state(// Nested brain lifecycle
657
- transition(BRAIN_EVENTS.START, 'running', startBrain), transition(BRAIN_EVENTS.RESTART, 'running', restartBrain), // Outer brain complete -> terminal
528
+ idle: state(transition(BRAIN_EVENTS.START, 'running', startBrain)),
529
+ // Standard step execution state
530
+ running: state(// Nested brain lifecycle - always uses START
531
+ transition(BRAIN_EVENTS.START, 'running', startBrain), // Outer brain complete -> terminal
658
532
  transition(BRAIN_EVENTS.COMPLETE, 'complete', isOuterBrain, completeBrain), // Inner brain complete -> stay running
659
533
  transition(BRAIN_EVENTS.COMPLETE, 'running', isInnerBrain, completeBrain), // Error (only outer brain errors are terminal)
660
534
  transition(BRAIN_EVENTS.ERROR, 'error', isOuterBrain, errorBrain), // Cancelled
661
- transition(BRAIN_EVENTS.CANCELLED, 'cancelled', cancelBrain), // Webhook -> paused
662
- transition(BRAIN_EVENTS.WEBHOOK, 'paused', webhookPause), // Webhook response (for resume from webhook - machine is already running)
535
+ transition(BRAIN_EVENTS.CANCELLED, 'cancelled', cancelBrain), // Paused (by signal)
536
+ transition(BRAIN_EVENTS.PAUSED, 'paused', pauseBrain), // Webhook -> waiting (for non-agent webhooks)
537
+ transition(BRAIN_EVENTS.WEBHOOK, 'waiting', webhookPause), // Webhook response (for resume from non-agent webhook)
663
538
  transition(BRAIN_EVENTS.WEBHOOK_RESPONSE, 'running', webhookResponse), // Step events
664
- transition(BRAIN_EVENTS.STEP_START, 'running', startStep), transition(BRAIN_EVENTS.STEP_COMPLETE, 'running', completeStep), transition(BRAIN_EVENTS.STEP_STATUS, 'running', stepStatus), transition(BRAIN_EVENTS.STEP_RETRY, 'running', stepRetry), // Agent events (pass-through with event data)
665
- transition(BRAIN_EVENTS.AGENT_START, 'running', passthrough(BRAIN_EVENTS.AGENT_START)), transition(BRAIN_EVENTS.AGENT_ITERATION, 'running', passthrough(BRAIN_EVENTS.AGENT_ITERATION)), transition(BRAIN_EVENTS.AGENT_TOOL_CALL, 'running', passthrough(BRAIN_EVENTS.AGENT_TOOL_CALL)), transition(BRAIN_EVENTS.AGENT_TOOL_RESULT, 'running', passthrough(BRAIN_EVENTS.AGENT_TOOL_RESULT)), transition(BRAIN_EVENTS.AGENT_ASSISTANT_MESSAGE, 'running', passthrough(BRAIN_EVENTS.AGENT_ASSISTANT_MESSAGE)), transition(BRAIN_EVENTS.AGENT_COMPLETE, 'running', passthrough(BRAIN_EVENTS.AGENT_COMPLETE)), transition(BRAIN_EVENTS.AGENT_TOKEN_LIMIT, 'running', passthrough(BRAIN_EVENTS.AGENT_TOKEN_LIMIT)), transition(BRAIN_EVENTS.AGENT_WEBHOOK, 'running', passthrough(BRAIN_EVENTS.AGENT_WEBHOOK))),
666
- paused: state(transition(BRAIN_EVENTS.WEBHOOK_RESPONSE, 'running', webhookResponse), transition(BRAIN_EVENTS.CANCELLED, 'cancelled', cancelBrain), // RESTART happens when resuming from webhook
667
- transition(BRAIN_EVENTS.RESTART, 'running', restartBrain)),
539
+ transition(BRAIN_EVENTS.STEP_START, 'running', startStep), transition(BRAIN_EVENTS.STEP_COMPLETE, 'running', completeStep), transition(BRAIN_EVENTS.STEP_STATUS, 'running', stepStatus), transition(BRAIN_EVENTS.STEP_RETRY, 'running', stepRetry), // AGENT_START transitions to the agentLoop state
540
+ transition(BRAIN_EVENTS.AGENT_START, 'agentLoop', agentStart)),
541
+ // Explicit agent loop state - isolates agent execution logic
542
+ agentLoop: state.apply(void 0, // Spread agent micro-transitions
543
+ _to_consumable_array(agentLoopTransitions).concat([
544
+ // Exit strategies - agent terminal events return to running
545
+ transition(BRAIN_EVENTS.AGENT_COMPLETE, 'running', agentTerminal()),
546
+ transition(BRAIN_EVENTS.AGENT_TOKEN_LIMIT, 'running', agentTerminal()),
547
+ transition(BRAIN_EVENTS.AGENT_ITERATION_LIMIT, 'running', agentTerminal()),
548
+ // Interruption handling - can pause or wait from agentLoop
549
+ transition(BRAIN_EVENTS.PAUSED, 'paused', pauseBrain),
550
+ transition(BRAIN_EVENTS.WEBHOOK, 'waiting', webhookPause),
551
+ // Error handling
552
+ transition(BRAIN_EVENTS.ERROR, 'error', isOuterBrain, errorBrain),
553
+ transition(BRAIN_EVENTS.CANCELLED, 'cancelled', cancelBrain)
554
+ ])),
555
+ paused: state(transition(BRAIN_EVENTS.CANCELLED, 'cancelled', cancelBrain), // RESUMED transitions out of paused state without creating a new brain
556
+ // If we have agentContext, resume to agentLoop; otherwise to running
557
+ transition(BRAIN_EVENTS.RESUMED, 'agentLoop', hasAgentContext, resumeToAgentLoop), transition(BRAIN_EVENTS.RESUMED, 'running', resumeBrain), // START is kept for backwards compatibility but RESUMED is preferred
558
+ transition(BRAIN_EVENTS.START, 'agentLoop', hasAgentContext, startBrain), transition(BRAIN_EVENTS.START, 'running', startBrain)),
559
+ waiting: state(// TODO: Could add PAUSED transition here to allow pausing a waiting brain.
560
+ // This would require queueing webhook responses (similar to USER_MESSAGE signals)
561
+ // so they can be processed when the brain is resumed.
562
+ // Webhook response - if we have agentContext, go back to agentLoop
563
+ transition(BRAIN_EVENTS.WEBHOOK_RESPONSE, 'agentLoop', hasAgentContext, webhookResponse), // Otherwise go to running
564
+ transition(BRAIN_EVENTS.WEBHOOK_RESPONSE, 'running', webhookResponse), transition(BRAIN_EVENTS.CANCELLED, 'cancelled', cancelBrain), // START can resume from waiting (after webhook response is processed)
565
+ // If we have agentContext, resume to agentLoop; otherwise to running
566
+ transition(BRAIN_EVENTS.START, 'agentLoop', hasAgentContext, startBrain), transition(BRAIN_EVENTS.START, 'running', startBrain)),
668
567
  // Terminal states - limited outgoing transitions
669
568
  complete: state(),
670
569
  error: state(// Allow STEP_STATUS after error so we can emit the final step statuses
@@ -719,71 +618,8 @@ var makeBrainMachine = function(initialContext) {
719
618
  */ export function sendEvent(machine, event) {
720
619
  machine.send(event);
721
620
  }
722
- // ============================================================================
723
- // Query Helpers (kept for backwards compatibility, but context is now preferred)
724
- // ============================================================================
725
- export function getDepth(machine) {
726
- return machine.context.depth;
727
- }
728
- export function isTopLevel(machine) {
729
- return machine.context.isTopLevel;
730
- }
731
- export function getCurrentStep(machine) {
732
- var _machine_context = machine.context, rootBrain = _machine_context.rootBrain, currentStepId = _machine_context.currentStepId;
733
- if (!rootBrain || !currentStepId) return null;
734
- var currentBrain = getDeepestBrain(rootBrain);
735
- var _currentBrain_steps_find;
736
- return (_currentBrain_steps_find = currentBrain === null || currentBrain === void 0 ? void 0 : currentBrain.steps.find(function(s) {
737
- return s.id === currentStepId;
738
- })) !== null && _currentBrain_steps_find !== void 0 ? _currentBrain_steps_find : null;
739
- }
740
- export function getBrainStack(machine) {
741
- return machine.context.brainStack;
742
- }
743
- export function getBrainRunId(machine) {
744
- return machine.context.brainRunId;
745
- }
746
- export function getExecutionState(machine) {
747
- return machine.machine.current;
748
- }
749
- export function getPendingWebhooks(machine) {
750
- return machine.context.pendingWebhooks;
751
- }
752
- export function getError(machine) {
753
- return machine.context.error;
754
- }
755
621
  /**
756
- * Get the completed steps from the state machine in the format needed for resume.
757
- * This reconstructs the nested step hierarchy from the brain tree.
758
- * Returns a deep copy to avoid mutating the state machine's context.
759
- */ export function getCompletedSteps(machine) {
760
- var rootBrain = machine.context.rootBrain;
761
- if (!rootBrain) {
762
- return [];
763
- }
764
- // Deep copy the steps, including any innerBrain's steps attached to parent step
765
- var copyStep = function(step) {
766
- var _step_innerSteps;
767
- return _object_spread_props(_object_spread({}, step), {
768
- innerSteps: (_step_innerSteps = step.innerSteps) === null || _step_innerSteps === void 0 ? void 0 : _step_innerSteps.map(copyStep)
769
- });
770
- };
771
- // Recursively build steps from the brain tree
772
- var copyBrainSteps = function(brain) {
773
- var steps = brain.steps.map(copyStep);
774
- // If there's a running inner brain, attach its steps to the parent step
775
- if (brain.innerBrain) {
776
- var parentStepId = brain.innerBrain.parentStepId;
777
- if (parentStepId) {
778
- var parentStep = steps.find(function(s) {
779
- return s.id === parentStepId;
780
- });
781
- if (parentStep) {
782
- parentStep.innerSteps = copyBrainSteps(brain.innerBrain);
783
- }
784
- }
785
- }
786
- return steps;
787
- };
788
- return copyBrainSteps(rootBrain);
789
- }
622
+ * Export a machine instance for signal validation.
623
+ * This is created once and used to query valid transitions.
624
+ * The machine is created with default initial context - only the state definitions matter for validation.
625
+ */ export var brainMachineDefinition = makeBrainMachine(createInitialContext());