@statelyai/agent 2.0.0-alpha.28 → 2.0.0-alpha.29

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 (75) hide show
  1. package/dist/ai-sdk.cjs +149 -26
  2. package/dist/ai-sdk.d.cts +57 -34
  3. package/dist/ai-sdk.d.mts +57 -34
  4. package/dist/ai-sdk.mjs +147 -23
  5. package/dist/{decision-RQ0iv0oZ.mjs → decision-Bl_rKQnU.mjs} +73 -7
  6. package/dist/{decision-CmM8-HHz.cjs → decision-oevZnkBe.cjs} +112 -29
  7. package/dist/{text-logic-f5F5sCdc.cjs → event-log-Dtb16p1p.cjs} +813 -6
  8. package/dist/{text-logic-CIqHAmBi.mjs → event-log-GPZO9p7_.mjs} +679 -3
  9. package/dist/{event-log-store-BIPOz-di.d.mts → event-log-store-CN9ygggF.d.cts} +90 -5
  10. package/dist/{event-log-store-2xzFmgr2.d.cts → event-log-store-DS836wch.d.mts} +90 -5
  11. package/dist/event-log-store-bCdskPNS.cjs +95 -0
  12. package/dist/event-log-store-yalq8C77.mjs +84 -0
  13. package/dist/index.cjs +571 -58
  14. package/dist/index.d.cts +104 -510
  15. package/dist/index.d.mts +104 -510
  16. package/dist/index.mjs +542 -32
  17. package/dist/log.cjs +77 -20
  18. package/dist/log.d.cts +5 -5
  19. package/dist/log.d.mts +5 -5
  20. package/dist/log.mjs +58 -3
  21. package/dist/machines.cjs +1 -1
  22. package/dist/machines.d.cts +15 -15
  23. package/dist/machines.d.mts +15 -15
  24. package/dist/machines.mjs +1 -1
  25. package/dist/model-source-C7FFP2Sj.mjs +39 -0
  26. package/dist/model-source-DjJPjGSP.cjs +44 -0
  27. package/dist/openai.cjs +10 -10
  28. package/dist/openai.d.cts +27 -25
  29. package/dist/openai.d.mts +27 -25
  30. package/dist/openai.mjs +2 -2
  31. package/dist/otel.cjs +5 -4
  32. package/dist/otel.d.cts +5 -7
  33. package/dist/otel.d.mts +5 -7
  34. package/dist/otel.mjs +5 -3
  35. package/dist/{run-agent-COXXc0RW.d.mts → run-agent-C9ubX8Tx.d.cts} +87 -30
  36. package/dist/{run-agent-xNTxpt82.mjs → run-agent-CuQT1xSS.mjs} +170 -42
  37. package/dist/{run-agent-ByO-Bxyd.d.cts → run-agent-CxSyZmIE.d.mts} +87 -30
  38. package/dist/{run-agent-Dmf8GV2d.cjs → run-agent-cToZ3K42.cjs} +219 -86
  39. package/dist/{setup-agent-DV4cTou-.cjs → setup-agent-DTF3NQg3.cjs} +31 -20
  40. package/dist/setup-agent-DlbgwsIJ.d.cts +577 -0
  41. package/dist/{setup-agent-BuanDXeh.mjs → setup-agent-DniLvDu7.mjs} +15 -9
  42. package/dist/setup-agent-tsc3vm5I.d.mts +577 -0
  43. package/dist/tanstack-ai.cjs +627 -0
  44. package/dist/tanstack-ai.d.cts +204 -0
  45. package/dist/tanstack-ai.d.mts +204 -0
  46. package/dist/tanstack-ai.mjs +618 -0
  47. package/dist/testing.cjs +98 -985
  48. package/dist/testing.d.cts +51 -347
  49. package/dist/testing.d.mts +51 -347
  50. package/dist/testing.mjs +86 -973
  51. package/dist/{text-logic-IjfYy9DP.d.cts → text-logic-9fv1i9aK.d.cts} +50 -10
  52. package/dist/{text-logic-D-czVPYp.d.mts → text-logic-BDbGjYMh.d.mts} +50 -10
  53. package/dist/{types-BgNbNKnJ.d.mts → types-Dp5_Ru4R.d.cts} +2 -2
  54. package/dist/{types-hR5f5YXa.d.cts → types-Dp5_Ru4R.d.mts} +2 -2
  55. package/dist/usage-D8UphgEA.d.mts +17 -0
  56. package/dist/usage-R1NTmLxY.d.cts +17 -0
  57. package/dist/{utils-_q7F-AZu.d.mts → utils-BnXdWih3.d.mts} +1 -2
  58. package/dist/{utils-o4YRdHJX.d.cts → utils-ebVpCYoF.d.cts} +1 -2
  59. package/dist/validate.cjs +239 -8
  60. package/dist/validate.d.cts +110 -3
  61. package/dist/validate.d.mts +110 -3
  62. package/dist/validate.mjs +238 -7
  63. package/dist/verify-B5qGC5WN.mjs +1181 -0
  64. package/dist/verify-CBuYIpsa.d.mts +414 -0
  65. package/dist/verify-Cqghu4gz.cjs +1222 -0
  66. package/dist/verify-DYH_2VzU.d.cts +414 -0
  67. package/package.json +44 -31
  68. package/readme.md +38 -26
  69. package/skills/generate-machine/SKILL.md +140 -66
  70. package/skills/improve-machine/SKILL.md +190 -0
  71. package/skills/improve-machine/reference.md +96 -0
  72. package/dist/event-log-store-2pAFiWuc.mjs +0 -576
  73. package/dist/event-log-store-C-COhIXP.cjs +0 -702
  74. package/dist/usage-BdEjFuIi.mjs +0 -5
  75. package/dist/usage-efOQPdf_.cjs +0 -10
@@ -1,8 +1,6 @@
1
- const require_text_logic = require("./text-logic-f5F5sCdc.cjs");
2
- const require_decision = require("./decision-CmM8-HHz.cjs");
3
- const require_usage = require("./usage-efOQPdf_.cjs");
4
- const require_event_log_store = require("./event-log-store-C-COhIXP.cjs");
5
- require("./validate.cjs");
1
+ const require_event_log = require("./event-log-Dtb16p1p.cjs");
2
+ const require_decision = require("./decision-oevZnkBe.cjs");
3
+ const require_event_log_store = require("./event-log-store-bCdskPNS.cjs");
6
4
  let xstate = require("xstate");
7
5
  let xstate_durable = require("xstate/durable");
8
6
  //#region src/run-agent.ts
@@ -14,7 +12,10 @@ let xstate_durable = require("xstate/durable");
14
12
  * a snapshot mutated out of band), not a recoverable resume: pass the log
15
13
  * alone, or the matching snapshot.
16
14
  */
17
- var AgentSnapshotDivergedError = class extends require_text_logic.AgentError {
15
+ var AgentSnapshotDivergedError = class extends require_event_log.AgentError {
16
+ expected;
17
+ actual;
18
+ logIndex;
18
19
  constructor(expected, actual, logIndex) {
19
20
  super("snapshot-diverged", `createAgentRuntime: the resume snapshot disagrees with the event log at index ${logIndex}: the log replays to state hash '${expected}', the snapshot hashes '${actual}'.`);
20
21
  this.expected = expected;
@@ -27,9 +28,9 @@ function hashResumeSnapshot(snapshot) {
27
28
  if (snapshot !== null && typeof snapshot === "object" && "agentMeta" in snapshot) {
28
29
  const rest = {};
29
30
  for (const [key, value] of Object.entries(snapshot)) if (key !== "agentMeta") rest[key] = value;
30
- return require_event_log_store.getSnapshotStateHash(rest);
31
+ return require_event_log.getSnapshotStateHash(rest);
31
32
  }
32
- return require_event_log_store.getSnapshotStateHash(snapshot);
33
+ return require_event_log.getSnapshotStateHash(snapshot);
33
34
  }
34
35
  function readAgentMeta(snapshot) {
35
36
  const meta = snapshot?.agentMeta;
@@ -146,7 +147,7 @@ let nextRunAgentTraceId = 1;
146
147
  * ]
147
148
  * ```
148
149
  */
149
- var AgentMaxModelCallsExceededError = class extends require_text_logic.AgentError {
150
+ var AgentMaxModelCallsExceededError = class extends require_event_log.AgentError {
150
151
  /** The budget that was exceeded (`options.maxModelCalls`). */
151
152
  maxModelCalls;
152
153
  constructor(maxModelCalls) {
@@ -215,7 +216,7 @@ function assertBindable(machine, effectiveSources, executors) {
215
216
  isChild: false,
216
217
  childPath: "",
217
218
  rebindable: true,
218
- visited: new Set([machine])
219
+ visited: /* @__PURE__ */ new Set([machine])
219
220
  });
220
221
  }
221
222
  function assertMachineBindable(machine, effectiveSources, executors, ctx) {
@@ -228,7 +229,7 @@ function assertMachineBindable(machine, effectiveSources, executors, ctx) {
228
229
  assertChildMachineBindable(src, src, stateName, executors, ctx);
229
230
  continue;
230
231
  }
231
- if ((require_text_logic.isTextLogic(src) || require_decision.isDecisionLogic(src)) && !require_text_logic.executorBoundLogics.has(src)) throw new Error(`createAgentRuntime: ${where} '${stateName}' invokes a direct-object actor logic (kind: '${src.kind}'). Direct-object invoke srcs cannot be rebound by the agent runtime — either call '.withExecutor(...)' on the logic before invoking it, or register it as a string-keyed actor source instead (machine.provide({ actors: { name: logic } })) and invoke it by name.`);
232
+ if ((require_event_log.isTextLogic(src) || require_decision.isDecisionLogic(src)) && !require_event_log.executorBoundLogics.has(src)) throw new Error(`createAgentRuntime: ${where} '${stateName}' invokes a direct-object actor logic (kind: '${src.kind}'). Direct-object invoke srcs cannot be rebound by the agent runtime — either call '.withExecutor(...)' on the logic before invoking it, or register it as a string-keyed actor source instead (machine.provide({ actors: { name: logic } })) and invoke it by name.`);
232
233
  continue;
233
234
  }
234
235
  const logic = effectiveSources[src];
@@ -238,19 +239,19 @@ function assertMachineBindable(machine, effectiveSources, executors, ctx) {
238
239
  continue;
239
240
  }
240
241
  if (require_decision.isDecisionLogic(logic)) {
241
- if (require_text_logic.executorBoundLogics.has(logic)) continue;
242
+ if (require_event_log.executorBoundLogics.has(logic)) continue;
242
243
  if (!ctx.rebindable) throw unrebindableChildRequestError(ctx.childPath, stateName, src, "decision");
243
244
  if (!executors.decide) throw new Error(`createAgentRuntime: ${where} '${stateName}' invokes decision source '${src}' but no 'decide' executor was provided to createAgentRuntime(...).`);
244
245
  continue;
245
246
  }
246
- if (require_text_logic.isTextLogic(logic)) {
247
- if (require_text_logic.executorBoundLogics.has(logic)) continue;
247
+ if (require_event_log.isTextLogic(logic)) {
248
+ if (require_event_log.executorBoundLogics.has(logic)) continue;
248
249
  if (!ctx.rebindable) throw unrebindableChildRequestError(ctx.childPath, stateName, src, logic.mode === "stream" ? "streaming text" : "text");
249
250
  if (logic.mode === "stream" && !executors.streamText) throw new Error(`createAgentRuntime: ${where} '${stateName}' invokes streaming text source '${src}' but no 'streamText' executor was provided to createAgentRuntime(...).`);
250
251
  if (logic.mode !== "stream" && !executors.generateText) throw new Error(`createAgentRuntime: ${where} '${stateName}' invokes text source '${src}' but no 'generateText' executor was provided to createAgentRuntime(...).`);
251
252
  continue;
252
253
  }
253
- if (require_text_logic.isUnboundPlaceholder(logic)) throw new Error(`createAgentRuntime: ${where} '${stateName}' invokes actor source '${src}', which has no host execution. Provide it via machine.provide({ actors: { '${src}': ... } }) or createAgentRuntime(machine, { actors: { '${src}': ... } }).`);
254
+ if (require_event_log.isUnboundPlaceholder(logic)) throw new Error(`createAgentRuntime: ${where} '${stateName}' invokes actor source '${src}', which has no host execution. Provide it via machine.provide({ actors: { '${src}': ... } }) or createAgentRuntime(machine, { actors: { '${src}': ... } }).`);
254
255
  }
255
256
  }
256
257
  /** Descends the bind-time walk into an invoked child state machine, guarding
@@ -264,7 +265,7 @@ function assertChildMachineBindable(childMachine, childSrc, stateName, executors
264
265
  isChild: true,
265
266
  childPath,
266
267
  rebindable: ctx.rebindable && typeof childSrc === "string",
267
- visited: new Set([...ctx.visited, childMachine])
268
+ visited: /* @__PURE__ */ new Set([...ctx.visited, childMachine])
268
269
  });
269
270
  }
270
271
  /** The loud bind-time error for an unbound agent request reached under a
@@ -395,11 +396,11 @@ function bindTextLogic(logic, runCtx) {
395
396
  ...id !== "" ? { requestId: id } : {},
396
397
  ...callKey !== void 0 ? { callKey } : {}
397
398
  });
398
- const output = await require_text_logic.normalizeGeneratorResult(raw, id);
399
+ const output = await require_event_log.normalizeGeneratorResult(raw, id);
399
400
  const rawReasoning = raw?.reasoning;
400
401
  const reasoning = typeof rawReasoning === "string" ? rawReasoning : void 0;
401
- const usage = require_text_logic.getCallUsage(raw);
402
- const finishReason = require_text_logic.getCallFinishReason(raw);
402
+ const usage = require_event_log.getCallUsage(raw);
403
+ const finishReason = require_event_log.getCallFinishReason(raw);
403
404
  if (usage) runCtx.recordUsage?.(usage, {
404
405
  kind: "text",
405
406
  ...id !== "" ? { id } : {},
@@ -418,7 +419,7 @@ function bindTextLogic(logic, runCtx) {
418
419
  }, self);
419
420
  return {
420
421
  result: output,
421
- messages: require_text_logic.responseMessagesOf(raw)
422
+ messages: require_event_log.responseMessagesOf(raw)
422
423
  };
423
424
  } catch (error) {
424
425
  runCtx.emitTrace?.({
@@ -451,8 +452,8 @@ function createCountingDecide(runCtx, self) {
451
452
  ...info?.requestId === void 0 && id !== "" ? { requestId: id } : {},
452
453
  ...info?.callKey === void 0 && callKey !== void 0 ? { callKey } : {}
453
454
  });
454
- const usage = require_text_logic.getCallUsage(result);
455
- const finishReason = require_text_logic.getCallFinishReason(result);
455
+ const usage = require_event_log.getCallUsage(result);
456
+ const finishReason = require_event_log.getCallFinishReason(result);
456
457
  if (usage) {
457
458
  const { src } = selfIdAndSrc(self);
458
459
  runCtx.recordUsage?.(usage, {
@@ -509,17 +510,53 @@ function bindDecisionLogic(logic, runCtx) {
509
510
  eventTypes: declaredEventTypes
510
511
  }) : [];
511
512
  const lowered = logic.request(input);
512
- const chosen = await require_decision.resolveDecision({
513
+ const request = {
513
514
  ...lowered,
514
515
  id,
515
516
  name: lowered.name ?? id,
516
517
  input,
517
518
  events
518
- }, { decide: createCountingDecide(runCtx, self) }, {
519
- maxRetries: logic.maxRetries,
519
+ };
520
+ const withheld = [];
521
+ const options = require_decision.acceptedDecisionOptions(request, (event) => {
522
+ let accepted;
523
+ try {
524
+ accepted = actorRef ? actorRef.getSnapshot().can(event) : true;
525
+ } catch {
526
+ accepted = false;
527
+ }
528
+ if (!accepted) withheld.push(event);
529
+ return accepted;
530
+ });
531
+ if (options) {
532
+ request.options = options;
533
+ request.withheld = withheld;
534
+ }
535
+ if (options?.length === 0) {
536
+ const error = new require_decision.AgentDecisionExhaustedError([]);
537
+ error.message = `Decision '${request.name}' has no offered option the current snapshot accepts; no model call was made.`;
538
+ runCtx.emitTrace?.({
539
+ type: "request.start",
540
+ request
541
+ }, self);
542
+ runCtx.emitTrace?.({
543
+ type: "request.error",
544
+ request,
545
+ error
546
+ }, self);
547
+ throw error;
548
+ }
549
+ const decide = createCountingDecide(runCtx, self);
550
+ let priorAttempts = [];
551
+ const chosen = await require_decision.resolveDecision(request, { decide: (attemptRequest, info) => {
552
+ priorAttempts = attemptRequest.attempts;
553
+ return decide(attemptRequest, info);
554
+ } }, {
555
+ maxRetries: lowered.maxRetries ?? logic.maxRetries,
520
556
  signal,
521
557
  canTake: (event) => actorRef ? actorRef.getSnapshot().can(event) : true
522
558
  });
559
+ if (priorAttempts.length > 0) runCtx.noteDecision?.(chosen, priorAttempts);
523
560
  actorRef?.send(chosen);
524
561
  await Promise.resolve();
525
562
  return chosen;
@@ -560,7 +597,7 @@ function rootTraceState(root) {
560
597
  if (!state) {
561
598
  const logic = root.logic;
562
599
  const machineId = (logic?.config)?.id ?? logic?.id ?? "(machine)";
563
- const machineVersion = logic ? require_text_logic.resolveMachineVersion(logic) : "";
600
+ const machineVersion = logic ? require_event_log.resolveMachineVersion(logic) : "";
564
601
  state = {
565
602
  runId: `run_${nextProvideRunId++}`,
566
603
  seq: 0,
@@ -619,13 +656,13 @@ function provideBindContext(machine, executors, options) {
619
656
  consumeModelCall: () => {},
620
657
  recordUsage: (usage, source, self) => {
621
658
  deliverUsageEvent({
622
- type: require_usage.AGENT_USAGE_EVENT_TYPE,
659
+ type: require_event_log.AGENT_USAGE_EVENT_TYPE,
623
660
  ...source,
624
661
  usage
625
662
  }, () => self?._parent);
626
663
  },
627
664
  actorHolder: { actorRef: void 0 },
628
- schemas: require_text_logic.getRegisteredAgentExecutionOptions(machine).schemas
665
+ schemas: require_event_log.getRegisteredAgentExecutionOptions(machine).schemas
629
666
  };
630
667
  }
631
668
  /**
@@ -702,12 +739,12 @@ function bindChildMachineForProvide(childMachine, executors, options, visited) {
702
739
  */
703
740
  function resolveMachineInput(machine, input) {
704
741
  if (input === void 0) return input;
705
- const schema = require_text_logic.getRegisteredAgentExecutionOptions(machine).schemas?.input;
706
- if (!require_text_logic.isStandardSchema(schema)) return input;
742
+ const schema = require_event_log.getRegisteredAgentExecutionOptions(machine).schemas?.input;
743
+ if (!require_event_log.isStandardSchema(schema)) return input;
707
744
  try {
708
- return require_text_logic.validateSchemaSync(schema, input);
745
+ return require_event_log.validateSchemaSync(schema, input);
709
746
  } catch (error) {
710
- throw new require_text_logic.AgentError("invalid-machine-input", `createAgentRuntime: machine input failed validation against the declared input schema: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
747
+ throw new require_event_log.AgentError("invalid-machine-input", `createAgentRuntime: machine input failed validation against the declared input schema: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
711
748
  }
712
749
  }
713
750
  /**
@@ -726,17 +763,17 @@ function resolveMachineInput(machine, input) {
726
763
  */
727
764
  function rebindChildMachine(childMachine, runCtx, visited, ctxFor) {
728
765
  if (visited.has(childMachine)) return childMachine;
729
- const childVisited = new Set([...visited, childMachine]);
766
+ const childVisited = /* @__PURE__ */ new Set([...visited, childMachine]);
730
767
  runCtx = ctxFor ? ctxFor(childMachine) : runCtx;
731
768
  const sources = childMachine.sources.actors;
732
769
  const wrapped = {};
733
770
  for (const [key, logic] of Object.entries(sources)) {
734
771
  if (require_decision.isDecisionLogic(logic)) {
735
- if (!require_text_logic.executorBoundLogics.has(logic)) wrapped[key] = bindDecisionLogic(logic, runCtx);
772
+ if (!require_event_log.executorBoundLogics.has(logic)) wrapped[key] = bindDecisionLogic(logic, runCtx);
736
773
  continue;
737
774
  }
738
- if (require_text_logic.isTextLogic(logic)) {
739
- if (!require_text_logic.executorBoundLogics.has(logic)) wrapped[key] = bindTextLogic(logic, runCtx);
775
+ if (require_event_log.isTextLogic(logic)) {
776
+ if (!require_event_log.executorBoundLogics.has(logic)) wrapped[key] = bindTextLogic(logic, runCtx);
740
777
  continue;
741
778
  }
742
779
  if (isStateMachineLogic(logic)) {
@@ -747,6 +784,15 @@ function rebindChildMachine(childMachine, runCtx, visited, ctxFor) {
747
784
  }
748
785
  return Object.keys(wrapped).length > 0 ? childMachine.provide({ actors: wrapped }) : childMachine;
749
786
  }
787
+ const timerId = (timer) => JSON.stringify(timer);
788
+ function toTimerInput(event) {
789
+ const id = event.id;
790
+ if (event.type !== "xstate.timer" || typeof id !== "string" || !id.startsWith("{")) return event;
791
+ return {
792
+ type: "xstate.timer",
793
+ ...JSON.parse(id)
794
+ };
795
+ }
750
796
  /**
751
797
  * The blocking host: opens the run, delivers `event` if given, then applies
752
798
  * every event that arrives until the run is quiescent, and returns the
@@ -757,7 +803,7 @@ async function runToQuiescence(runtime, init = {}) {
757
803
  let [state, effects] = await runtime.start(init);
758
804
  await runtime.execute(effects);
759
805
  if (init.event !== void 0 && state.status === "active") {
760
- [state, effects] = runtime.transition(state, init.event);
806
+ [state, effects] = runtime.transition(state, init.event, init.attempts !== void 0 ? { attempts: init.attempts } : void 0);
761
807
  await runtime.execute(effects);
762
808
  }
763
809
  for (let event; event = await runtime.nextEvent();) {
@@ -767,6 +813,52 @@ async function runToQuiescence(runtime, init = {}) {
767
813
  return runtime.finish();
768
814
  }
769
815
  /**
816
+ * Runs `machine` to quiescence in one call: {@link createAgentRuntime} over
817
+ * `options`, then {@link runToQuiescence} with the same object as its init.
818
+ * One options object carries both halves (`executors`, `store`, callbacks,
819
+ * and `input` | `snapshot` + `event`), and the result is the same
820
+ * {@link AgentRunResult}. With {@link AgentRunOptions.onIdle}, idle states are
821
+ * answered in place and the call returns only `done` or `error`.
822
+ *
823
+ * Reach for {@link createAgentRuntime} directly when the host needs the loop
824
+ * itself: a non-blocking durable host, events pushed mid-run, or a custom stop
825
+ * or checkpoint policy.
826
+ *
827
+ * @example
828
+ * ```ts
829
+ * const result = await runAgent(machine, { input: { topic }, executors });
830
+ * if (result.status === "done") console.log(result.output);
831
+ * ```
832
+ *
833
+ * @example
834
+ * ```ts
835
+ * // Resume a run a request handler left idle.
836
+ * const result = await runAgent(machine, { executors, snapshot, event });
837
+ * ```
838
+ */
839
+ async function runAgent(machine, options = {}) {
840
+ const { onIdle, ...rest } = options;
841
+ let result = await runToQuiescence(createAgentRuntime(machine, rest), rest);
842
+ if (!onIdle) return result;
843
+ const maxModelCalls = rest.maxModelCalls ?? 100;
844
+ let modelCalls = result.usage.modelCalls;
845
+ const { input: _input, events: _events, attempts: _attempts, ...resumeOptions } = rest;
846
+ while (result.status === "idle" && result.ignored === void 0) {
847
+ const event = await onIdle(result.snapshot);
848
+ result = await runToQuiescence(createAgentRuntime(machine, {
849
+ ...resumeOptions,
850
+ maxModelCalls: maxModelCalls - modelCalls
851
+ }), {
852
+ ...resumeOptions,
853
+ ...rest.store === void 0 ? { events: result.events } : {},
854
+ snapshot: result.persist(),
855
+ event
856
+ });
857
+ modelCalls += result.usage.modelCalls;
858
+ }
859
+ return result;
860
+ }
861
+ /**
770
862
  * Entry-by-entry check that the caller's `events` IS the store's thread. Equal
771
863
  * lengths prove nothing: a fork, a rolled-back replay, or a concurrent writer
772
864
  * that appended and truncated all produce a divergent log of the same size,
@@ -778,7 +870,7 @@ function assertThreadMatchesEvents(threadId, stored, events) {
778
870
  const givenEntry = events[index];
779
871
  const storedHash = storedEntry.verification?.stateHash;
780
872
  const givenHash = givenEntry.verification?.stateHash;
781
- if (!(storedEntry.id === givenEntry.id && storedEntry.index === givenEntry.index && require_event_log_store.canonicalEventJson(storedEntry.event) === require_event_log_store.canonicalEventJson(givenEntry.event) && (storedHash === void 0 || givenHash === void 0 || storedHash === givenHash))) throw new require_text_logic.AgentError("event-log-conflict", `createAgentRuntime: the given \`events\` diverge from thread "${threadId}" at index ${index} (stored entry '${storedEntry.id}', given '${givenEntry.id}') — the log passed in is not this thread's log.`);
873
+ if (!(storedEntry.id === givenEntry.id && storedEntry.index === givenEntry.index && require_event_log.canonicalEventJson(storedEntry.event) === require_event_log.canonicalEventJson(givenEntry.event) && (storedHash === void 0 || givenHash === void 0 || storedHash === givenHash))) throw new require_event_log.AgentError("event-log-conflict", `createAgentRuntime: the given \`events\` diverge from thread "${threadId}" at index ${index} (stored entry '${storedEntry.id}', given '${givenEntry.id}') — the log passed in is not this thread's log.`);
782
874
  }
783
875
  }
784
876
  const QUIESCENT = Symbol("quiescent");
@@ -805,7 +897,7 @@ const QUIESCENT = Symbol("quiescent");
805
897
  * while (r.status === 'idle') {
806
898
  * const event = await promptUser(getAcceptedEvents(r.snapshot));
807
899
  * r = await runToQuiescence(createAgentRuntime(machine, { executors }), {
808
- * snapshot: r.snapshot,
900
+ * snapshot: r.persist(),
809
901
  * event,
810
902
  * });
811
903
  * }
@@ -825,7 +917,7 @@ function createAgentRuntime(machine, options = {}) {
825
917
  const runId = `run_${nextRunAgentTraceId++}`;
826
918
  let traceSeq = 0;
827
919
  const machineId = machine.config.id ?? machine.id ?? "(machine)";
828
- const machineVersion = require_text_logic.resolveMachineVersion(machine);
920
+ const machineVersion = require_event_log.resolveMachineVersion(machine);
829
921
  const onTrace = createTraceDispatch({
830
922
  onTrace: (payload) => {
831
923
  options.onTrace?.({
@@ -853,7 +945,7 @@ function createAgentRuntime(machine, options = {}) {
853
945
  const logEntries = [];
854
946
  const store = options.store;
855
947
  const threadId = options.threadId;
856
- if (store !== void 0 && (threadId === void 0 || threadId === "")) throw new require_text_logic.AgentError("missing-thread-id", "createAgentRuntime: `threadId` is required when `store` is given — it names the log thread to read and append to.");
948
+ if (store !== void 0 && (threadId === void 0 || threadId === "")) throw new require_event_log.AgentError("missing-thread-id", "createAgentRuntime: `threadId` is required when `store` is given — it names the log thread to read and append to.");
857
949
  let journalChain = Promise.resolve();
858
950
  let journalPending = 0;
859
951
  let journalError;
@@ -904,24 +996,32 @@ function createAgentRuntime(machine, options = {}) {
904
996
  let current;
905
997
  let logMachine = machine;
906
998
  let loggingEnabled = true;
907
- const appendLogEntry = (event, snapshot) => {
999
+ const attemptsByEvent = /* @__PURE__ */ new WeakMap();
1000
+ let logFold;
1001
+ const appendLogEntry = (event, attempts) => {
908
1002
  if (!loggingEnabled) return;
909
- const entry = require_event_log_store.createReplayEntry(logMachine, logEntries, event, {
1003
+ const entry = require_event_log.createReplayEntry(logMachine, logEntries, event, {
910
1004
  machineVersion,
911
- verification: verificationEnabled,
912
- ...verificationEnabled && snapshot !== void 0 ? { snapshot } : {}
1005
+ verification: false,
1006
+ ...attempts !== void 0 ? { attempts } : {}
913
1007
  });
1008
+ if (verificationEnabled && logFold !== null) try {
1009
+ logFold ??= require_event_log.foldLog(logMachine, logEntries, {
1010
+ machineVersion,
1011
+ verify: false
1012
+ });
1013
+ entry.verification = { stateHash: require_event_log.getSnapshotStateHash(logFold.apply(entry)) };
1014
+ } catch {
1015
+ logFold = null;
1016
+ }
914
1017
  logEntries.push(entry);
915
1018
  journalEntry(entry);
916
1019
  options.onEvent?.(entry);
917
1020
  return entry;
918
1021
  };
919
- const usageEntrySnapshot = () => {
920
- if (current && (current.status !== "active" || !declaresUsageTransition(current))) return current;
921
- };
922
1022
  const recordUsage = (usage, source = {}) => {
923
1023
  const event = {
924
- type: require_usage.AGENT_USAGE_EVENT_TYPE,
1024
+ type: require_event_log.AGENT_USAGE_EVENT_TYPE,
925
1025
  ...source,
926
1026
  usage
927
1027
  };
@@ -935,17 +1035,17 @@ function createAgentRuntime(machine, options = {}) {
935
1035
  });
936
1036
  return true;
937
1037
  });
938
- if (!delivered) appendLogEntry(event, usageEntrySnapshot());
1038
+ if (!delivered) appendLogEntry(event);
939
1039
  };
940
1040
  const runUsage = () => ({
941
- ...require_event_log_store.getUsageFromEvents(logEntries.slice(resumedLogLength)),
1041
+ ...require_event_log.getUsageFromEvents(logEntries.slice(resumedLogLength)),
942
1042
  modelCalls: modelCallCount
943
1043
  });
944
1044
  const warnNonSerializableContext = (snapshot) => {
945
1045
  if (warnedNonSerializable || process.env.NODE_ENV === "production") return;
946
1046
  let offending = [];
947
1047
  try {
948
- offending = require_text_logic.findNonSerializableContextPaths(snapshot.context);
1048
+ offending = require_event_log.findNonSerializableContextPaths(snapshot.context);
949
1049
  } catch {
950
1050
  return;
951
1051
  }
@@ -976,7 +1076,15 @@ function createAgentRuntime(machine, options = {}) {
976
1076
  actorHolder,
977
1077
  awaitJournal,
978
1078
  runId,
979
- schemas: require_text_logic.getRegisteredAgentExecutionOptions(machine).schemas
1079
+ schemas: require_event_log.getRegisteredAgentExecutionOptions(machine).schemas,
1080
+ noteDecision: (event, attempts) => {
1081
+ try {
1082
+ require_event_log.assertJsonSerializable(attempts, "attempts");
1083
+ } catch {
1084
+ return;
1085
+ }
1086
+ attemptsByEvent.set(event, attempts);
1087
+ }
980
1088
  };
981
1089
  const wrappedSources = {};
982
1090
  for (const [key, logic] of Object.entries(effectiveSources)) {
@@ -984,12 +1092,12 @@ function createAgentRuntime(machine, options = {}) {
984
1092
  wrappedSources[key] = bindDecisionLogic(logic, runCtx);
985
1093
  continue;
986
1094
  }
987
- if (require_text_logic.isTextLogic(logic)) {
988
- if (!require_text_logic.executorBoundLogics.has(logic)) wrappedSources[key] = bindTextLogic(logic, runCtx);
1095
+ if (require_event_log.isTextLogic(logic)) {
1096
+ if (!require_event_log.executorBoundLogics.has(logic)) wrappedSources[key] = bindTextLogic(logic, runCtx);
989
1097
  continue;
990
1098
  }
991
1099
  if (isStateMachineLogic(logic)) {
992
- const rebound = rebindChildMachine(logic, runCtx, new Set([machine]));
1100
+ const rebound = rebindChildMachine(logic, runCtx, /* @__PURE__ */ new Set([machine]));
993
1101
  if (rebound !== logic) wrappedSources[key] = rebound;
994
1102
  continue;
995
1103
  }
@@ -1014,7 +1122,8 @@ function createAgentRuntime(machine, options = {}) {
1014
1122
  const inProcessTimers = options.timers === void 0 || options.timers === "in-process";
1015
1123
  const timerHandles = /* @__PURE__ */ new Map();
1016
1124
  const timerKey = (source, id) => `${source?.address ?? "(root)"}::${id}`;
1017
- const armTimer = (source, isRoot, id, delay) => {
1125
+ const armTimer = (source, isRoot, timer, delay) => {
1126
+ const id = timerId(timer);
1018
1127
  if (isRoot && !inProcessTimers) {
1019
1128
  options.timers.schedule({
1020
1129
  id,
@@ -1028,7 +1137,7 @@ function createAgentRuntime(machine, options = {}) {
1028
1137
  timerHandles.delete(key);
1029
1138
  const timerEvent = {
1030
1139
  type: "xstate.timer",
1031
- id
1140
+ ...timer
1032
1141
  };
1033
1142
  if (isRoot) enqueue(timerEvent);
1034
1143
  else source?.send(timerEvent);
@@ -1113,10 +1222,11 @@ function createAgentRuntime(machine, options = {}) {
1113
1222
  if (source.address === execution.rootAddress) emitFromRoot(event);
1114
1223
  else source._emit?.(event);
1115
1224
  },
1116
- scheduleTimer: (source, id, delay) => {
1117
- armTimer(source, source.address === execution.rootAddress, id, delay);
1225
+ scheduleTimer: (source, timer, delay) => {
1226
+ armTimer(source, source.address === execution.rootAddress, timer, delay);
1118
1227
  },
1119
- cancelTimer: (source, id) => {
1228
+ cancelTimer: (source, timer) => {
1229
+ const id = timerId(timer);
1120
1230
  const isRoot = source.address === execution.rootAddress;
1121
1231
  if (isRoot && !inProcessTimers) {
1122
1232
  options.timers.cancel(id);
@@ -1127,7 +1237,8 @@ function createAgentRuntime(machine, options = {}) {
1127
1237
  timerHandles.delete(key);
1128
1238
  },
1129
1239
  cancelAllTimers: (source) => {
1130
- const prefix = timerKey(source.address === execution.rootAddress ? void 0 : source, "");
1240
+ const isRoot = source.address === execution.rootAddress;
1241
+ const prefix = timerKey(isRoot ? void 0 : source, "");
1131
1242
  for (const [key, handle] of timerHandles) if (key.startsWith(prefix)) {
1132
1243
  clearTimeout(handle);
1133
1244
  timerHandles.delete(key);
@@ -1136,9 +1247,11 @@ function createAgentRuntime(machine, options = {}) {
1136
1247
  }, inspect ? { inspect } : void 0);
1137
1248
  const runErrorCause = (error) => budgetExceeded ? "max-model-calls" : wrapsDecisionExhausted(error) ? "decision-exhausted" : "machine";
1138
1249
  const commit = (snapshot, event) => {
1250
+ const from = { value: (current ?? snapshot).value };
1139
1251
  current = snapshot;
1140
1252
  onTrace({
1141
1253
  type: "machine.transition",
1254
+ from,
1142
1255
  snapshot,
1143
1256
  event
1144
1257
  });
@@ -1151,7 +1264,7 @@ function createAgentRuntime(machine, options = {}) {
1151
1264
  };
1152
1265
  return {
1153
1266
  async start(init = {}) {
1154
- if (started) throw new require_text_logic.AgentError("runtime-started", "createAgentRuntime: `start` was already called.");
1267
+ if (started) throw new require_event_log.AgentError("runtime-started", "createAgentRuntime: `start` was already called.");
1155
1268
  started = true;
1156
1269
  let resumeEvents = init.events;
1157
1270
  if (store !== void 0) {
@@ -1180,7 +1293,7 @@ function createAgentRuntime(machine, options = {}) {
1180
1293
  */
1181
1294
  const appendInitEntry = (candidates, metadata) => {
1182
1295
  for (const candidate of candidates) for (const verification of verificationEnabled ? [true, false] : [false]) try {
1183
- const entry = require_event_log_store.initEntry(logMachine, candidate, {
1296
+ const entry = require_event_log.initEntry(logMachine, candidate, {
1184
1297
  machineVersion,
1185
1298
  verification,
1186
1299
  metadata
@@ -1198,10 +1311,10 @@ function createAgentRuntime(machine, options = {}) {
1198
1311
  return [...restored !== void 0 ? [{ snapshot: restored }] : [], { snapshot: init.snapshot }];
1199
1312
  };
1200
1313
  if (resumeEvents !== void 0 && resumeEvents.length > 0) {
1201
- require_event_log_store.validateReplayEntries(resumeEvents);
1314
+ require_event_log.validateReplayEntries(resumeEvents);
1202
1315
  const tail = resumeEvents[resumeEvents.length - 1];
1203
- const inheritedExecutionId = require_event_log_store.getLogExecutionId(resumeEvents);
1204
- if (resumeEvents[0].machineId !== machineId) throw new require_event_log_store.AgentMachineVersionMismatchError(tail.id, tail.index, {
1316
+ const inheritedExecutionId = require_event_log.getLogExecutionId(resumeEvents);
1317
+ if (resumeEvents[0].machineId !== machineId) throw new require_event_log.AgentMachineVersionMismatchError(tail.id, tail.index, {
1205
1318
  machineId,
1206
1319
  machineVersion
1207
1320
  }, {
@@ -1217,20 +1330,22 @@ function createAgentRuntime(machine, options = {}) {
1217
1330
  if (!(init.snapshot !== void 0 && inheritedExecutionId !== void 0 && cachedMeta?.logId === inheritedExecutionId && cachedMeta.logIndex === resumeEvents.length && tailStateHash !== void 0 && hashResumeSnapshot(init.snapshot) === tailStateHash)) {
1218
1331
  const cachedIndex = cachedMeta?.logIndex;
1219
1332
  if (init.snapshot !== void 0 && typeof cachedIndex === "number" && cachedIndex >= 1 && cachedIndex <= resumeEvents.length && resumeEvents[cachedIndex - 1].verification?.stateHash !== void 0) {
1220
- const expected = require_event_log_store.getSnapshotStateHash(require_event_log_store.replay(logMachine, resumeEvents.slice(0, cachedIndex), {
1333
+ const atCache = require_event_log.replay(logMachine, resumeEvents.slice(0, cachedIndex), {
1221
1334
  machineVersion,
1222
1335
  verify: false
1223
- }).persistedSnapshot);
1336
+ });
1337
+ const expected = require_event_log.getSnapshotStateHash(atCache.persistedSnapshot);
1224
1338
  const actual = hashResumeSnapshot(init.snapshot);
1225
1339
  if (expected !== actual) throw new AgentSnapshotDivergedError(expected, actual, cachedIndex);
1226
1340
  }
1227
- effectiveSnapshot = require_event_log_store.replay(logMachine, resumeEvents, {
1341
+ logFold = require_event_log.foldLog(logMachine, resumeEvents, {
1228
1342
  machineVersion,
1229
1343
  verify: true
1230
- }).persistedSnapshot;
1344
+ });
1345
+ effectiveSnapshot = logFold.persistedSnapshot;
1231
1346
  }
1232
1347
  } else {
1233
- if (init.snapshot === void 0) throw new require_event_log_store.AgentMachineVersionMismatchError(tail.id, tail.index, {
1348
+ if (init.snapshot === void 0) throw new require_event_log.AgentMachineVersionMismatchError(tail.id, tail.index, {
1234
1349
  machineId,
1235
1350
  machineVersion
1236
1351
  }, {
@@ -1238,7 +1353,7 @@ function createAgentRuntime(machine, options = {}) {
1238
1353
  machineVersion: tail.machineVersion
1239
1354
  });
1240
1355
  const bridgeMeta = readAgentMeta(init.snapshot);
1241
- if (inheritedExecutionId === void 0 || bridgeMeta?.logId !== inheritedExecutionId) throw new require_event_log_store.AgentMachineVersionMismatchError(tail.id, tail.index, {
1356
+ if (inheritedExecutionId === void 0 || bridgeMeta?.logId !== inheritedExecutionId) throw new require_event_log.AgentMachineVersionMismatchError(tail.id, tail.index, {
1242
1357
  machineId,
1243
1358
  machineVersion
1244
1359
  }, {
@@ -1275,7 +1390,7 @@ function createAgentRuntime(machine, options = {}) {
1275
1390
  if (memoized !== void 0) return memoized;
1276
1391
  const startedHere = siteCallCounts.get(siteId) ?? 0;
1277
1392
  siteCallCounts.set(siteId, startedHere + 1);
1278
- const key = `${logExecutionId}:${siteId}#${require_event_log_store.agentCallOccurrence(resumedHistory, siteId) + startedHere}`;
1393
+ const key = `${logExecutionId}:${siteId}#${require_event_log.agentCallOccurrence(resumedHistory, siteId) + startedHere}`;
1279
1394
  if (self !== void 0) mintedCallKeys.set(self, key);
1280
1395
  return key;
1281
1396
  };
@@ -1287,11 +1402,13 @@ function createAgentRuntime(machine, options = {}) {
1287
1402
  ...effectiveSnapshot !== void 0 ? { snapshot: effectiveSnapshot } : {},
1288
1403
  ...resumeEvent !== void 0 ? { event: resumeEvent } : {}
1289
1404
  });
1290
- if (options.signal) if (options.signal.aborted) stopReason = {
1291
- cause: "aborted",
1292
- error: options.signal.reason ?? /* @__PURE__ */ new Error("Aborted")
1293
- };
1294
- else options.signal.addEventListener("abort", onAbort);
1405
+ if (options.signal) {
1406
+ if (options.signal.aborted) stopReason = {
1407
+ cause: "aborted",
1408
+ error: options.signal.reason ?? /* @__PURE__ */ new Error("Aborted")
1409
+ };
1410
+ else options.signal.addEventListener("abort", onAbort);
1411
+ }
1295
1412
  let snapshot;
1296
1413
  let effects = [];
1297
1414
  const initEvent = {
@@ -1323,12 +1440,15 @@ function createAgentRuntime(machine, options = {}) {
1323
1440
  commit(snapshot, initEvent);
1324
1441
  return [snapshot, effects];
1325
1442
  },
1326
- transition(state, event) {
1327
- if (finished) throw new require_text_logic.AgentError("runtime-finished", "createAgentRuntime: the run has finished; start a new runtime to continue.");
1443
+ transition(state, event, transitionOptions) {
1444
+ if (finished) throw new require_event_log.AgentError("runtime-finished", "createAgentRuntime: the run has finished; start a new runtime to continue.");
1328
1445
  if (stopReason !== void 0) return [state, []];
1446
+ event = toTimerInput(event);
1447
+ const attempts = transitionOptions?.attempts ?? attemptsByEvent.get(event);
1448
+ if (transitionOptions?.attempts !== void 0) require_event_log.assertJsonSerializable(transitionOptions.attempts, "attempts");
1329
1449
  const [next, effects] = execution.transition(state, event);
1330
1450
  if (!fromMailbox.has(event) && next === state && effects.length === 0) ignoredEvent = event;
1331
- appendLogEntry(event, next);
1451
+ appendLogEntry(event, attempts);
1332
1452
  commit(next, event);
1333
1453
  return [next, effects];
1334
1454
  },
@@ -1354,7 +1474,7 @@ function createAgentRuntime(machine, options = {}) {
1354
1474
  }
1355
1475
  },
1356
1476
  async finish() {
1357
- if (finished) throw new require_text_logic.AgentError("runtime-finished", "createAgentRuntime: `finish` was already called.");
1477
+ if (finished) throw new require_event_log.AgentError("runtime-finished", "createAgentRuntime: `finish` was already called.");
1358
1478
  const snapshot = current;
1359
1479
  let outcome;
1360
1480
  if (stopReason !== void 0) outcome = {
@@ -1460,7 +1580,8 @@ function inspectTransitions(handler) {
1460
1580
  * ```
1461
1581
  *
1462
1582
  * Only ROOT-actor transitions are traced (matching the runtime's
1463
- * `machine.transition`); child-actor transitions are ignored. Attribute the
1583
+ * `machine.transition`); child-actor transitions are ignored. Each event's
1584
+ * `from.value` is the root's previous state value, tracked per root actor. Attribute the
1464
1585
  * event via its envelope `runId`.
1465
1586
  *
1466
1587
  * By design this path has NO `run.start`/`run.end` events: `createActor` has no
@@ -1471,13 +1592,19 @@ function inspectTransitions(handler) {
1471
1592
  * with `actor.on('*', ...)` if you need them.
1472
1593
  */
1473
1594
  function traceTransitions(onTrace) {
1595
+ const lastValue = /* @__PURE__ */ new WeakMap();
1474
1596
  return (inspectionEvent) => {
1475
1597
  if (inspectionEvent.type !== "@xstate.transition") return;
1476
1598
  const actorRef = inspectionEvent.actorRef;
1477
1599
  if (actorRef?._parent) return;
1478
- onTrace(stampRootTrace(actorRef, {
1600
+ const root = actorRef;
1601
+ const snapshot = inspectionEvent.snapshot;
1602
+ const from = { value: lastValue.get(root) ?? snapshot.value };
1603
+ lastValue.set(root, snapshot.value);
1604
+ onTrace(stampRootTrace(root, {
1479
1605
  type: "machine.transition",
1480
- snapshot: inspectionEvent.snapshot,
1606
+ from,
1607
+ snapshot,
1481
1608
  event: inspectionEvent.event
1482
1609
  }));
1483
1610
  };
@@ -1565,6 +1692,12 @@ Object.defineProperty(exports, "isStateMachineLogic", {
1565
1692
  return isStateMachineLogic;
1566
1693
  }
1567
1694
  });
1695
+ Object.defineProperty(exports, "runAgent", {
1696
+ enumerable: true,
1697
+ get: function() {
1698
+ return runAgent;
1699
+ }
1700
+ });
1568
1701
  Object.defineProperty(exports, "runToQuiescence", {
1569
1702
  enumerable: true,
1570
1703
  get: function() {