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

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 (80) hide show
  1. package/dist/ai-sdk.cjs +150 -27
  2. package/dist/ai-sdk.d.cts +59 -36
  3. package/dist/ai-sdk.d.mts +59 -36
  4. package/dist/ai-sdk.mjs +148 -24
  5. package/dist/{decision-RQ0iv0oZ.mjs → decision-BHkvuImD.mjs} +74 -8
  6. package/dist/{decision-CmM8-HHz.cjs → decision-CIb7ddIv.cjs} +113 -30
  7. package/dist/{text-logic-f5F5sCdc.cjs → event-log-BZRfBRd7.cjs} +814 -7
  8. package/dist/{text-logic-CIqHAmBi.mjs → event-log-DJCMHek_.mjs} +680 -4
  9. package/dist/{event-log-store-BIPOz-di.d.mts → event-log-store-CIIJohjj.d.mts} +90 -5
  10. package/dist/{event-log-store-2xzFmgr2.d.cts → event-log-store-CLAC9q2Y.d.cts} +90 -5
  11. package/dist/event-log-store-DZR4IIWe.cjs +95 -0
  12. package/dist/event-log-store-DsP6GCRh.mjs +84 -0
  13. package/dist/index.cjs +576 -58
  14. package/dist/index.d.cts +104 -510
  15. package/dist/index.d.mts +104 -510
  16. package/dist/index.mjs +547 -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-BCKg4qJ1.cjs +44 -0
  26. package/dist/model-source-BaHwJ1wK.mjs +39 -0
  27. package/dist/openai.cjs +11 -11
  28. package/dist/openai.d.cts +28 -26
  29. package/dist/openai.d.mts +28 -26
  30. package/dist/openai.mjs +3 -3
  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-xNTxpt82.mjs → run-agent-BpHqkaZw.mjs} +181 -44
  36. package/dist/{run-agent-COXXc0RW.d.mts → run-agent-CAVt5R-r.d.mts} +95 -30
  37. package/dist/{run-agent-ByO-Bxyd.d.cts → run-agent-CTlMc3Jb.d.cts} +95 -30
  38. package/dist/{run-agent-Dmf8GV2d.cjs → run-agent-ctLCvNgL.cjs} +230 -88
  39. package/dist/{setup-agent-BuanDXeh.mjs → setup-agent-7rV_cujV.mjs} +15 -9
  40. package/dist/setup-agent-CGELn1qZ.d.mts +577 -0
  41. package/dist/setup-agent-CLPCkXsu.d.cts +577 -0
  42. package/dist/{setup-agent-DV4cTou-.cjs → setup-agent-DoUk7EdC.cjs} +31 -20
  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 +204 -985
  48. package/dist/testing.d.cts +132 -347
  49. package/dist/testing.d.mts +132 -347
  50. package/dist/testing.mjs +191 -973
  51. package/dist/{text-logic-IjfYy9DP.d.cts → text-logic-BRYOPWvY.d.mts} +52 -12
  52. package/dist/{text-logic-D-czVPYp.d.mts → text-logic-DmciuVUQ.d.cts} +52 -12
  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-BkM3z02Y.d.mts +17 -0
  56. package/dist/usage-Cm_ovz9V.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-COFWyprJ.mjs +1181 -0
  64. package/dist/verify-CVlsTZ-V.cjs +1222 -0
  65. package/dist/verify-Cn86rT8l.d.mts +414 -0
  66. package/dist/verify-Dzwd4Mvk.d.cts +414 -0
  67. package/package.json +44 -31
  68. package/readme.md +40 -28
  69. package/skills/add-evals/SKILL.md +129 -0
  70. package/skills/add-traces/SKILL.md +135 -0
  71. package/skills/generate-machine/SKILL.md +143 -69
  72. package/skills/graph-engineering/SKILL.md +33 -0
  73. package/skills/improve-machine/SKILL.md +241 -0
  74. package/skills/improve-machine/reference.md +101 -0
  75. package/skills/loop-to-machine/SKILL.md +183 -0
  76. package/skills/loop-to-machine/policy.md +158 -0
  77. package/dist/event-log-store-2pAFiWuc.mjs +0 -576
  78. package/dist/event-log-store-C-COhIXP.cjs +0 -702
  79. package/dist/usage-BdEjFuIi.mjs +0 -5
  80. package/dist/usage-efOQPdf_.cjs +0 -10
@@ -1,7 +1,6 @@
1
- import { E as findNonSerializableContextPaths, N as isStandardSchema, P as resolveMachineVersion, R as validateSchemaSync, _ as responseMessagesOf, b as getRegisteredAgentExecutionOptions, d as isTextLogic, f as normalizeGeneratorResult, l as getCallFinishReason, u as getCallUsage, v as executorBoundLogics, x as isUnboundPlaceholder, z as AgentError } from "./text-logic-CIqHAmBi.mjs";
2
- import { a as isDecisionLogic, l as getAcceptedEvents, s as resolveDecision, t as AgentDecisionExhaustedError } from "./decision-RQ0iv0oZ.mjs";
3
- import { t as AGENT_USAGE_EVENT_TYPE } from "./usage-BdEjFuIi.mjs";
4
- import { _ as getUsageFromEvents, b as replay, f as canonicalEventJson, g as getSnapshotStateHash, h as getLogExecutionId, l as agentCallOccurrence, o as AgentMachineVersionMismatchError, p as createReplayEntry, t as AgentEventLogConflictError, v as initEntry, x as validateReplayEntries } from "./event-log-store-2pAFiWuc.mjs";
1
+ import { B as responseMessagesOf, C as AGENT_USAGE_EVENT_TYPE, F as normalizeGeneratorResult, J as findNonSerializableContextPaths, M as getCallFinishReason, N as getCallUsage, P as isTextLogic, S as validateReplayEntries, U as getRegisteredAgentExecutionOptions, V as executorBoundLogics, W as isUnboundPlaceholder, _ as getUsageFromEvents, d as createReplayEntry, f as foldLog, g as getSnapshotStateHash, h as getLogExecutionId, i as AgentMachineVersionMismatchError, l as assertJsonSerializable, nt as resolveMachineVersion, ot as validateSchemaSync, s as agentCallOccurrence, st as AgentError, tt as isStandardSchema, u as canonicalEventJson, v as initEntry, x as replay } from "./event-log-DJCMHek_.mjs";
2
+ import { d as getAcceptedEvents, l as resolveDecision, n as acceptedDecisionOptions, s as isDecisionLogic, t as AgentDecisionExhaustedError } from "./decision-BHkvuImD.mjs";
3
+ import { t as AgentEventLogConflictError } from "./event-log-store-DsP6GCRh.mjs";
5
4
  import { createAsyncLogic, getNextTransitions, isMachineSnapshot, stopActor } from "xstate";
6
5
  import { createDurable } from "xstate/durable";
7
6
  //#region src/run-agent.ts
@@ -14,6 +13,9 @@ import { createDurable } from "xstate/durable";
14
13
  * alone, or the matching snapshot.
15
14
  */
16
15
  var AgentSnapshotDivergedError = class extends AgentError {
16
+ expected;
17
+ actual;
18
+ logIndex;
17
19
  constructor(expected, actual, logIndex) {
18
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}'.`);
19
21
  this.expected = expected;
@@ -214,7 +216,7 @@ function assertBindable(machine, effectiveSources, executors) {
214
216
  isChild: false,
215
217
  childPath: "",
216
218
  rebindable: true,
217
- visited: new Set([machine])
219
+ visited: /* @__PURE__ */ new Set([machine])
218
220
  });
219
221
  }
220
222
  function assertMachineBindable(machine, effectiveSources, executors, ctx) {
@@ -263,7 +265,7 @@ function assertChildMachineBindable(childMachine, childSrc, stateName, executors
263
265
  isChild: true,
264
266
  childPath,
265
267
  rebindable: ctx.rebindable && typeof childSrc === "string",
266
- visited: new Set([...ctx.visited, childMachine])
268
+ visited: /* @__PURE__ */ new Set([...ctx.visited, childMachine])
267
269
  });
268
270
  }
269
271
  /** The loud bind-time error for an unbound agent request reached under a
@@ -508,17 +510,53 @@ function bindDecisionLogic(logic, runCtx) {
508
510
  eventTypes: declaredEventTypes
509
511
  }) : [];
510
512
  const lowered = logic.request(input);
511
- const chosen = await resolveDecision({
513
+ const request = {
512
514
  ...lowered,
513
515
  id,
514
516
  name: lowered.name ?? id,
515
517
  input,
516
518
  events
517
- }, { decide: createCountingDecide(runCtx, self) }, {
518
- maxRetries: logic.maxRetries,
519
+ };
520
+ const withheld = [];
521
+ const options = 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 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 resolveDecision(request, { decide: (attemptRequest, info) => {
552
+ priorAttempts = attemptRequest.attempts;
553
+ return decide(attemptRequest, info);
554
+ } }, {
555
+ maxRetries: lowered.maxRetries ?? logic.maxRetries,
519
556
  signal,
520
557
  canTake: (event) => actorRef ? actorRef.getSnapshot().can(event) : true
521
558
  });
559
+ if (priorAttempts.length > 0) runCtx.noteDecision?.(chosen, priorAttempts);
522
560
  actorRef?.send(chosen);
523
561
  await Promise.resolve();
524
562
  return chosen;
@@ -725,7 +763,7 @@ function resolveMachineInput(machine, input) {
725
763
  */
726
764
  function rebindChildMachine(childMachine, runCtx, visited, ctxFor) {
727
765
  if (visited.has(childMachine)) return childMachine;
728
- const childVisited = new Set([...visited, childMachine]);
766
+ const childVisited = /* @__PURE__ */ new Set([...visited, childMachine]);
729
767
  runCtx = ctxFor ? ctxFor(childMachine) : runCtx;
730
768
  const sources = childMachine.sources.actors;
731
769
  const wrapped = {};
@@ -746,6 +784,15 @@ function rebindChildMachine(childMachine, runCtx, visited, ctxFor) {
746
784
  }
747
785
  return Object.keys(wrapped).length > 0 ? childMachine.provide({ actors: wrapped }) : childMachine;
748
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
+ }
749
796
  /**
750
797
  * The blocking host: opens the run, delivers `event` if given, then applies
751
798
  * every event that arrives until the run is quiescent, and returns the
@@ -756,7 +803,7 @@ async function runToQuiescence(runtime, init = {}) {
756
803
  let [state, effects] = await runtime.start(init);
757
804
  await runtime.execute(effects);
758
805
  if (init.event !== void 0 && state.status === "active") {
759
- [state, effects] = runtime.transition(state, init.event);
806
+ [state, effects] = runtime.transition(state, init.event, init.attempts !== void 0 ? { attempts: init.attempts } : void 0);
760
807
  await runtime.execute(effects);
761
808
  }
762
809
  for (let event; event = await runtime.nextEvent();) {
@@ -766,6 +813,52 @@ async function runToQuiescence(runtime, init = {}) {
766
813
  return runtime.finish();
767
814
  }
768
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
+ /**
769
862
  * Entry-by-entry check that the caller's `events` IS the store's thread. Equal
770
863
  * lengths prove nothing: a fork, a rolled-back replay, or a concurrent writer
771
864
  * that appended and truncated all produce a divergent log of the same size,
@@ -804,7 +897,7 @@ const QUIESCENT = Symbol("quiescent");
804
897
  * while (r.status === 'idle') {
805
898
  * const event = await promptUser(getAcceptedEvents(r.snapshot));
806
899
  * r = await runToQuiescence(createAgentRuntime(machine, { executors }), {
807
- * snapshot: r.snapshot,
900
+ * snapshot: r.persist(),
808
901
  * event,
809
902
  * });
810
903
  * }
@@ -825,6 +918,8 @@ function createAgentRuntime(machine, options = {}) {
825
918
  let traceSeq = 0;
826
919
  const machineId = machine.config.id ?? machine.id ?? "(machine)";
827
920
  const machineVersion = resolveMachineVersion(machine);
921
+ if (options.metadata !== void 0) assertJsonSerializable(options.metadata, "metadata");
922
+ const initMetadata = options.metadata === void 0 ? void 0 : structuredClone(options.metadata);
828
923
  const onTrace = createTraceDispatch({
829
924
  onTrace: (payload) => {
830
925
  options.onTrace?.({
@@ -903,21 +998,29 @@ function createAgentRuntime(machine, options = {}) {
903
998
  let current;
904
999
  let logMachine = machine;
905
1000
  let loggingEnabled = true;
906
- const appendLogEntry = (event, snapshot) => {
1001
+ const attemptsByEvent = /* @__PURE__ */ new WeakMap();
1002
+ let logFold;
1003
+ const appendLogEntry = (event, attempts) => {
907
1004
  if (!loggingEnabled) return;
908
1005
  const entry = createReplayEntry(logMachine, logEntries, event, {
909
1006
  machineVersion,
910
- verification: verificationEnabled,
911
- ...verificationEnabled && snapshot !== void 0 ? { snapshot } : {}
1007
+ verification: false,
1008
+ ...attempts !== void 0 ? { attempts } : {}
912
1009
  });
1010
+ if (verificationEnabled && logFold !== null) try {
1011
+ logFold ??= foldLog(logMachine, logEntries, {
1012
+ machineVersion,
1013
+ verify: false
1014
+ });
1015
+ entry.verification = { stateHash: getSnapshotStateHash(logFold.apply(entry)) };
1016
+ } catch {
1017
+ logFold = null;
1018
+ }
913
1019
  logEntries.push(entry);
914
1020
  journalEntry(entry);
915
1021
  options.onEvent?.(entry);
916
1022
  return entry;
917
1023
  };
918
- const usageEntrySnapshot = () => {
919
- if (current && (current.status !== "active" || !declaresUsageTransition(current))) return current;
920
- };
921
1024
  const recordUsage = (usage, source = {}) => {
922
1025
  const event = {
923
1026
  type: AGENT_USAGE_EVENT_TYPE,
@@ -934,7 +1037,7 @@ function createAgentRuntime(machine, options = {}) {
934
1037
  });
935
1038
  return true;
936
1039
  });
937
- if (!delivered) appendLogEntry(event, usageEntrySnapshot());
1040
+ if (!delivered) appendLogEntry(event);
938
1041
  };
939
1042
  const runUsage = () => ({
940
1043
  ...getUsageFromEvents(logEntries.slice(resumedLogLength)),
@@ -975,7 +1078,15 @@ function createAgentRuntime(machine, options = {}) {
975
1078
  actorHolder,
976
1079
  awaitJournal,
977
1080
  runId,
978
- schemas: getRegisteredAgentExecutionOptions(machine).schemas
1081
+ schemas: getRegisteredAgentExecutionOptions(machine).schemas,
1082
+ noteDecision: (event, attempts) => {
1083
+ try {
1084
+ assertJsonSerializable(attempts, "attempts");
1085
+ } catch {
1086
+ return;
1087
+ }
1088
+ attemptsByEvent.set(event, attempts);
1089
+ }
979
1090
  };
980
1091
  const wrappedSources = {};
981
1092
  for (const [key, logic] of Object.entries(effectiveSources)) {
@@ -988,7 +1099,7 @@ function createAgentRuntime(machine, options = {}) {
988
1099
  continue;
989
1100
  }
990
1101
  if (isStateMachineLogic(logic)) {
991
- const rebound = rebindChildMachine(logic, runCtx, new Set([machine]));
1102
+ const rebound = rebindChildMachine(logic, runCtx, /* @__PURE__ */ new Set([machine]));
992
1103
  if (rebound !== logic) wrappedSources[key] = rebound;
993
1104
  continue;
994
1105
  }
@@ -1013,7 +1124,8 @@ function createAgentRuntime(machine, options = {}) {
1013
1124
  const inProcessTimers = options.timers === void 0 || options.timers === "in-process";
1014
1125
  const timerHandles = /* @__PURE__ */ new Map();
1015
1126
  const timerKey = (source, id) => `${source?.address ?? "(root)"}::${id}`;
1016
- const armTimer = (source, isRoot, id, delay) => {
1127
+ const armTimer = (source, isRoot, timer, delay) => {
1128
+ const id = timerId(timer);
1017
1129
  if (isRoot && !inProcessTimers) {
1018
1130
  options.timers.schedule({
1019
1131
  id,
@@ -1027,7 +1139,7 @@ function createAgentRuntime(machine, options = {}) {
1027
1139
  timerHandles.delete(key);
1028
1140
  const timerEvent = {
1029
1141
  type: "xstate.timer",
1030
- id
1142
+ ...timer
1031
1143
  };
1032
1144
  if (isRoot) enqueue(timerEvent);
1033
1145
  else source?.send(timerEvent);
@@ -1112,10 +1224,11 @@ function createAgentRuntime(machine, options = {}) {
1112
1224
  if (source.address === execution.rootAddress) emitFromRoot(event);
1113
1225
  else source._emit?.(event);
1114
1226
  },
1115
- scheduleTimer: (source, id, delay) => {
1116
- armTimer(source, source.address === execution.rootAddress, id, delay);
1227
+ scheduleTimer: (source, timer, delay) => {
1228
+ armTimer(source, source.address === execution.rootAddress, timer, delay);
1117
1229
  },
1118
- cancelTimer: (source, id) => {
1230
+ cancelTimer: (source, timer) => {
1231
+ const id = timerId(timer);
1119
1232
  const isRoot = source.address === execution.rootAddress;
1120
1233
  if (isRoot && !inProcessTimers) {
1121
1234
  options.timers.cancel(id);
@@ -1126,7 +1239,8 @@ function createAgentRuntime(machine, options = {}) {
1126
1239
  timerHandles.delete(key);
1127
1240
  },
1128
1241
  cancelAllTimers: (source) => {
1129
- const prefix = timerKey(source.address === execution.rootAddress ? void 0 : source, "");
1242
+ const isRoot = source.address === execution.rootAddress;
1243
+ const prefix = timerKey(isRoot ? void 0 : source, "");
1130
1244
  for (const [key, handle] of timerHandles) if (key.startsWith(prefix)) {
1131
1245
  clearTimeout(handle);
1132
1246
  timerHandles.delete(key);
@@ -1135,9 +1249,11 @@ function createAgentRuntime(machine, options = {}) {
1135
1249
  }, inspect ? { inspect } : void 0);
1136
1250
  const runErrorCause = (error) => budgetExceeded ? "max-model-calls" : wrapsDecisionExhausted(error) ? "decision-exhausted" : "machine";
1137
1251
  const commit = (snapshot, event) => {
1252
+ const from = { value: (current ?? snapshot).value };
1138
1253
  current = snapshot;
1139
1254
  onTrace({
1140
1255
  type: "machine.transition",
1256
+ from,
1141
1257
  snapshot,
1142
1258
  event
1143
1259
  });
@@ -1216,17 +1332,19 @@ function createAgentRuntime(machine, options = {}) {
1216
1332
  if (!(init.snapshot !== void 0 && inheritedExecutionId !== void 0 && cachedMeta?.logId === inheritedExecutionId && cachedMeta.logIndex === resumeEvents.length && tailStateHash !== void 0 && hashResumeSnapshot(init.snapshot) === tailStateHash)) {
1217
1333
  const cachedIndex = cachedMeta?.logIndex;
1218
1334
  if (init.snapshot !== void 0 && typeof cachedIndex === "number" && cachedIndex >= 1 && cachedIndex <= resumeEvents.length && resumeEvents[cachedIndex - 1].verification?.stateHash !== void 0) {
1219
- const expected = getSnapshotStateHash(replay(logMachine, resumeEvents.slice(0, cachedIndex), {
1335
+ const atCache = replay(logMachine, resumeEvents.slice(0, cachedIndex), {
1220
1336
  machineVersion,
1221
1337
  verify: false
1222
- }).persistedSnapshot);
1338
+ });
1339
+ const expected = getSnapshotStateHash(atCache.persistedSnapshot);
1223
1340
  const actual = hashResumeSnapshot(init.snapshot);
1224
1341
  if (expected !== actual) throw new AgentSnapshotDivergedError(expected, actual, cachedIndex);
1225
1342
  }
1226
- effectiveSnapshot = replay(logMachine, resumeEvents, {
1343
+ logFold = foldLog(logMachine, resumeEvents, {
1227
1344
  machineVersion,
1228
1345
  verify: true
1229
- }).persistedSnapshot;
1346
+ });
1347
+ effectiveSnapshot = logFold.persistedSnapshot;
1230
1348
  }
1231
1349
  } else {
1232
1350
  if (init.snapshot === void 0) throw new AgentMachineVersionMismatchError(tail.id, tail.index, {
@@ -1254,16 +1372,23 @@ function createAgentRuntime(machine, options = {}) {
1254
1372
  logIndex: resumeEvents.length
1255
1373
  };
1256
1374
  seedInitEntry = () => appendInitEntry(snapshotInitCandidates(), {
1375
+ ...initMetadata,
1257
1376
  ...logExecutionId !== void 0 ? { executionId: logExecutionId } : {},
1258
1377
  migratedFrom
1259
1378
  });
1260
1379
  }
1261
1380
  } else if (init.snapshot !== void 0) {
1262
1381
  logExecutionId = crypto.randomUUID();
1263
- seedInitEntry = () => appendInitEntry(snapshotInitCandidates(), { executionId: logExecutionId });
1382
+ seedInitEntry = () => appendInitEntry(snapshotInitCandidates(), {
1383
+ ...initMetadata,
1384
+ executionId: logExecutionId
1385
+ });
1264
1386
  } else {
1265
1387
  logExecutionId = crypto.randomUUID();
1266
- seedInitEntry = () => appendInitEntry([resolvedInput !== void 0 ? { input: resolvedInput } : {}], { executionId: logExecutionId });
1388
+ seedInitEntry = () => appendInitEntry([resolvedInput !== void 0 ? { input: resolvedInput } : {}], {
1389
+ ...initMetadata,
1390
+ executionId: logExecutionId
1391
+ });
1267
1392
  }
1268
1393
  const resumedHistory = [...logEntries];
1269
1394
  const siteCallCounts = /* @__PURE__ */ new Map();
@@ -1286,11 +1411,13 @@ function createAgentRuntime(machine, options = {}) {
1286
1411
  ...effectiveSnapshot !== void 0 ? { snapshot: effectiveSnapshot } : {},
1287
1412
  ...resumeEvent !== void 0 ? { event: resumeEvent } : {}
1288
1413
  });
1289
- if (options.signal) if (options.signal.aborted) stopReason = {
1290
- cause: "aborted",
1291
- error: options.signal.reason ?? /* @__PURE__ */ new Error("Aborted")
1292
- };
1293
- else options.signal.addEventListener("abort", onAbort);
1414
+ if (options.signal) {
1415
+ if (options.signal.aborted) stopReason = {
1416
+ cause: "aborted",
1417
+ error: options.signal.reason ?? /* @__PURE__ */ new Error("Aborted")
1418
+ };
1419
+ else options.signal.addEventListener("abort", onAbort);
1420
+ }
1294
1421
  let snapshot;
1295
1422
  let effects = [];
1296
1423
  const initEvent = {
@@ -1322,12 +1449,15 @@ function createAgentRuntime(machine, options = {}) {
1322
1449
  commit(snapshot, initEvent);
1323
1450
  return [snapshot, effects];
1324
1451
  },
1325
- transition(state, event) {
1452
+ transition(state, event, transitionOptions) {
1326
1453
  if (finished) throw new AgentError("runtime-finished", "createAgentRuntime: the run has finished; start a new runtime to continue.");
1327
1454
  if (stopReason !== void 0) return [state, []];
1455
+ event = toTimerInput(event);
1456
+ const attempts = transitionOptions?.attempts ?? attemptsByEvent.get(event);
1457
+ if (transitionOptions?.attempts !== void 0) assertJsonSerializable(transitionOptions.attempts, "attempts");
1328
1458
  const [next, effects] = execution.transition(state, event);
1329
1459
  if (!fromMailbox.has(event) && next === state && effects.length === 0) ignoredEvent = event;
1330
- appendLogEntry(event, next);
1460
+ appendLogEntry(event, attempts);
1331
1461
  commit(next, event);
1332
1462
  return [next, effects];
1333
1463
  },
@@ -1459,7 +1589,8 @@ function inspectTransitions(handler) {
1459
1589
  * ```
1460
1590
  *
1461
1591
  * Only ROOT-actor transitions are traced (matching the runtime's
1462
- * `machine.transition`); child-actor transitions are ignored. Attribute the
1592
+ * `machine.transition`); child-actor transitions are ignored. Each event's
1593
+ * `from.value` is the root's previous state value, tracked per root actor. Attribute the
1463
1594
  * event via its envelope `runId`.
1464
1595
  *
1465
1596
  * By design this path has NO `run.start`/`run.end` events: `createActor` has no
@@ -1470,13 +1601,19 @@ function inspectTransitions(handler) {
1470
1601
  * with `actor.on('*', ...)` if you need them.
1471
1602
  */
1472
1603
  function traceTransitions(onTrace) {
1604
+ const lastValue = /* @__PURE__ */ new WeakMap();
1473
1605
  return (inspectionEvent) => {
1474
1606
  if (inspectionEvent.type !== "@xstate.transition") return;
1475
1607
  const actorRef = inspectionEvent.actorRef;
1476
1608
  if (actorRef?._parent) return;
1477
- onTrace(stampRootTrace(actorRef, {
1609
+ const root = actorRef;
1610
+ const snapshot = inspectionEvent.snapshot;
1611
+ const from = { value: lastValue.get(root) ?? snapshot.value };
1612
+ lastValue.set(root, snapshot.value);
1613
+ onTrace(stampRootTrace(root, {
1478
1614
  type: "machine.transition",
1479
- snapshot: inspectionEvent.snapshot,
1615
+ from,
1616
+ snapshot,
1480
1617
  event: inspectionEvent.event
1481
1618
  }));
1482
1619
  };
@@ -1498,4 +1635,4 @@ function isAgentIdle(snapshot) {
1498
1635
  }) || getAcceptedEvents(snapshot).length > 0;
1499
1636
  }
1500
1637
  //#endregion
1501
- export { bindDecisionForProvide as a, getConfiguredInvokeSrcs as c, isStateMachineLogic as d, runToQuiescence as f, bindChildMachineForProvide as i, inspectTransitions as l, traceTransitions as m, AgentMaxModelCallsExceededError as n, bindTextForProvide as o, serializeTraceEvent as p, AgentSnapshotDivergedError as r, createAgentRuntime as s, AGENT_TRACE_SCHEMA_VERSION as t, isAgentIdle as u };
1638
+ export { bindDecisionForProvide as a, getConfiguredInvokeSrcs as c, isStateMachineLogic as d, runAgent as f, traceTransitions as h, bindChildMachineForProvide as i, inspectTransitions as l, serializeTraceEvent as m, AgentMaxModelCallsExceededError as n, bindTextForProvide as o, runToQuiescence as p, AgentSnapshotDivergedError as r, createAgentRuntime as s, AGENT_TRACE_SCHEMA_VERSION as t, isAgentIdle as u };
@@ -1,23 +1,9 @@
1
- import { _ as StandardSchemaV1, m as InferInput, s as AgentTools, w as WithAgentInputSchema } from "./types-BgNbNKnJ.mjs";
2
- import { K as AgentRequestSource, M as AgentDecisionRequest, U as AgentEventDescriptor, Z as AgentError, d as AgentRequestMode, f as AgentTextRequest, m as AgentUsage, r as AgentFinishReason, t as AgentCallUsage, u as AgentRequestExecutors } from "./text-logic-D-czVPYp.mjs";
3
- import { c as AgentLogEntry, n as AgentEventLogStore } from "./event-log-store-BIPOz-di.mjs";
4
- import { AnyActorLogic, AnyActorRef, AnyMachineSnapshot, AnyStateMachine, AsyncActorLogic, EmittedFrom, EventFromLogic, EventObject, InputFrom, InspectionEvent, OutputFrom, Snapshot, SnapshotFrom } from "xstate";
1
+ import { _ as StandardSchemaV1, m as InferInput, s as AgentTools, w as WithAgentInputSchema } from "./types-Dp5_Ru4R.mjs";
2
+ import { I as DecisionAttempt, N as AgentDecisionRequest, Q as AgentError, W as AgentEventDescriptor, d as AgentRequestMode, f as AgentTextRequest, m as AgentUsage, q as AgentRequestSource, r as AgentFinishReason, t as AgentCallUsage, u as AgentRequestExecutors } from "./text-logic-BRYOPWvY.mjs";
3
+ import { n as AgentUsageEvent } from "./usage-BkM3z02Y.mjs";
4
+ import { c as AgentLogEntry, h as JsonValue$1, n as AgentEventLogStore } from "./event-log-store-CIIJohjj.mjs";
5
+ import { AnyActorLogic, AnyActorRef, AnyMachineSnapshot, AnyStateMachine, AsyncActorLogic, EmittedFrom, EventFromLogic, EventObject, InputFrom, InspectionEvent, OutputFrom, Snapshot, SnapshotFrom, StateValue } from "xstate";
5
6
  import { DurableExecution } from "xstate/durable";
6
-
7
- //#region src/usage.d.ts
8
- /** Reserved event delivered after a model call reports token usage. */
9
- declare const AGENT_USAGE_EVENT_TYPE: "@agent.usage";
10
- /** Machine-owned usage signal. Handle it with an ordinary XState transition. */
11
- interface AgentUsageEvent extends EventObject {
12
- type: typeof AGENT_USAGE_EVENT_TYPE;
13
- usage: AgentCallUsage;
14
- kind?: "text" | "decision";
15
- id?: string;
16
- src?: string;
17
- model?: string;
18
- name?: string;
19
- }
20
- //#endregion
21
7
  //#region src/steps.d.ts
22
8
  /**
23
9
  * A pending text request surfaced by step discovery ({@link getAgentRequests}
@@ -81,11 +67,13 @@ type AgentTransitionHandler<TMachine extends AnyStateMachine> = (snapshot: Snaps
81
67
  */
82
68
  declare const AGENT_TRACE_SCHEMA_VERSION = 1;
83
69
  type AgentTraceEvent<TMachine extends AnyStateMachine = AnyStateMachine> = {
84
- /** The {@link AGENT_TRACE_SCHEMA_VERSION} the event was produced with. */schemaVersion: typeof AGENT_TRACE_SCHEMA_VERSION;
70
+ /** The {@link AGENT_TRACE_SCHEMA_VERSION} the event was produced with. */
71
+ schemaVersion: typeof AGENT_TRACE_SCHEMA_VERSION;
85
72
  runId: string;
86
73
  seq: number;
87
74
  timestamp: string;
88
- machineId: string; /** The machine's own `version`, else its structural hash. */
75
+ machineId: string;
76
+ /** The machine's own `version`, else its structural hash. */
89
77
  machineVersion: string;
90
78
  } & ({
91
79
  type: "run.start";
@@ -122,6 +110,15 @@ type AgentTraceEvent<TMachine extends AnyStateMachine = AnyStateMachine> = {
122
110
  chunk: string;
123
111
  } | {
124
112
  type: "machine.transition";
113
+ /**
114
+ * Where the event arrived: the state value before this transition. The
115
+ * first transition of a stream (the init event, or the restore on
116
+ * resume) has no earlier state, so its `from.value` is its own
117
+ * `snapshot.value`. An object so more of the prior snapshot can join it.
118
+ */
119
+ from: {
120
+ value: StateValue;
121
+ };
125
122
  snapshot: SnapshotFrom<TMachine>;
126
123
  event: EventFromLogic<TMachine>;
127
124
  } | {
@@ -132,7 +129,8 @@ type AgentTraceEvent<TMachine extends AnyStateMachine = AnyStateMachine> = {
132
129
  * tokens still fold into {@link AgentRunResult.usage}; only the machine
133
130
  * event is dropped. */
134
131
  type: "usage.dropped";
135
- event: AgentUsageEvent; /** `'settled'`: the call settled after the run's cycle had resolved. */
132
+ event: AgentUsageEvent;
133
+ /** `'settled'`: the call settled after the run's cycle had resolved. */
136
134
  reason: "settled";
137
135
  } | ({
138
136
  type: "run.end";
@@ -159,7 +157,7 @@ type AgentTraceEvent<TMachine extends AnyStateMachine = AnyStateMachine> = {
159
157
  */
160
158
  type TraceVerbatimKey = (typeof TRACE_ENVELOPE_KEYS)[number] | "reason";
161
159
  /** One trace variant's JSON projection. Homomorphic, so `?` modifiers survive. @internal */
162
- type JsonProjectedTraceVariant<TEvent> = { [K in keyof TEvent]: K extends TraceVerbatimKey ? TEvent[K] : JsonValue };
160
+ type JsonProjectedTraceVariant<TEvent> = { [K in keyof TEvent]: K extends TraceVerbatimKey ? TEvent[K] : JsonValue; };
163
161
  /**
164
162
  * `raw` is written only when `includeRaw` was set, so it is optional on the
165
163
  * JSON side even though the live trace always carries it. @internal
@@ -178,7 +176,7 @@ type WithOptionalRaw<T> = "raw" extends keyof T ? Omit<T, "raw"> & {
178
176
  * miss the JSON side. `src/serialize-trace-event.test.ts` pins the result to
179
177
  * the shape this type had when it was hand-maintained.
180
178
  */
181
- type JsonSerializableTraceEvent = AgentTraceEvent extends infer TEvent ? TEvent extends unknown ? WithOptionalRaw<JsonProjectedTraceVariant<TEvent>> : never : never;
179
+ type JsonSerializableTraceEvent = AgentTraceEvent extends (infer TEvent) ? TEvent extends unknown ? WithOptionalRaw<JsonProjectedTraceVariant<TEvent>> : never : never;
182
180
  declare const TRACE_ENVELOPE_KEYS: readonly ["schemaVersion", "runId", "seq", "timestamp", "machineId", "machineVersion", "type", "status", "cause", "reasoning", "finishReason", "chunk"];
183
181
  /**
184
182
  * Projects an {@link AgentTraceEvent} into a guaranteed JSON-safe envelope —
@@ -253,6 +251,14 @@ interface AgentRuntimeOptions<TMachine extends AnyStateMachine> {
253
251
  * the same state. Set `false` for a smaller, unverifiable log.
254
252
  */
255
253
  verification?: boolean;
254
+ /**
255
+ * Host-owned JSON stored on the log's `@agent.init` entry when this run
256
+ * starts a log: what produced the run, such as a policy version, the model
257
+ * ids, or the scenario. A resume keeps the stamp of the run that started
258
+ * the log; a version bridge, which opens a new log segment, takes this
259
+ * run's. `executionId` and `migratedFrom` are reserved and cannot be set here.
260
+ */
261
+ metadata?: Record<string, JsonValue$1>;
256
262
  /** Actor source implementations, merged onto the machine before binding — sugar for `machine.provide({ actors })` ahead of the run. */
257
263
  actors?: Record<string, AnyActorLogic>;
258
264
  /**
@@ -292,7 +298,7 @@ interface AgentRuntimeOptions<TMachine extends AnyStateMachine> {
292
298
  */
293
299
  on?: { [TType in EmittedFrom<TMachine>["type"] | "*"]?: (emitted: EmittedFrom<TMachine> & (TType extends "*" ? unknown : {
294
300
  type: TType;
295
- })) => void };
301
+ })) => void; };
296
302
  /**
297
303
  * Raw xstate inspection passthrough: fires for every inspection event in
298
304
  * the whole actor system — root machine, invoked child machines, spawned
@@ -549,8 +555,15 @@ interface AgentRunStart<TMachine extends AnyStateMachine> {
549
555
  interface AgentRuntime<TMachine extends AnyStateMachine> {
550
556
  /** Opens the run: a fresh start from `input`, a resume from `snapshot`, or recovery from a log. */
551
557
  start(init?: AgentRunStart<TMachine>): Promise<[SnapshotFrom<TMachine>, AgentEffects]>;
552
- /** Applies one event: journals it, traces it, and returns the next state plus its effects. */
553
- transition(state: SnapshotFrom<TMachine>, event: EventFromLogic<TMachine> | AgentTimerEvent): [SnapshotFrom<TMachine>, AgentEffects];
558
+ /**
559
+ * Applies one event: journals it, traces it, and returns the next state plus
560
+ * its effects. `options.attempts` records the failed attempts of a decider
561
+ * the host ran itself (e.g. `decideNext`'s `attempts`) on the event's entry
562
+ * as `entry.attempts`. Replay ignores them; an empty list is not journaled.
563
+ */
564
+ transition(state: SnapshotFrom<TMachine>, event: EventFromLogic<TMachine> | AgentTimerEvent, options?: {
565
+ attempts?: DecisionAttempt[];
566
+ }): [SnapshotFrom<TMachine>, AgentEffects];
554
567
  /** Starts the effects' work and returns once it is accepted, not once it finishes. */
555
568
  execute(effects: AgentEffects): Promise<void>;
556
569
  /** The next event that arrived, or `undefined` once the run is quiescent. */
@@ -570,6 +583,12 @@ interface AgentRunInit<TMachine extends AnyStateMachine> extends AgentRunStart<T
570
583
  * due is delivered the same way, as an {@link AgentTimerEvent}.
571
584
  */
572
585
  event?: EventFromLogic<TMachine> | AgentTimerEvent;
586
+ /**
587
+ * The failed attempts of the decider the host ran to choose `event` (e.g.
588
+ * `decideNext`'s `attempts`), journaled on `event`'s entry as
589
+ * `entry.attempts`. Replay ignores them.
590
+ */
591
+ attempts?: DecisionAttempt[];
573
592
  }
574
593
  /**
575
594
  * The blocking host: opens the run, delivers `event` if given, then applies
@@ -578,6 +597,51 @@ interface AgentRunInit<TMachine extends AnyStateMachine> extends AgentRunStart<T
578
597
  * own stop policy; this one is for scripts and tests.
579
598
  */
580
599
  declare function runToQuiescence<TMachine extends AnyStateMachine>(runtime: AgentRuntime<TMachine>, init?: AgentRunInit<TMachine>): Promise<AgentRunResult<TMachine>>;
600
+ /** Everything {@link runAgent} takes: the runtime's options plus how to open the run. */
601
+ interface AgentRunOptions<TMachine extends AnyStateMachine> extends AgentRuntimeOptions<TMachine>, AgentRunInit<TMachine> {
602
+ /**
603
+ * Answers an idle state for a host that can block for it. When given,
604
+ * {@link runAgent} loops: each time the run settles `idle`, it calls
605
+ * `onIdle` with the idle snapshot, persists the run, and resumes from that
606
+ * persisted snapshot with the returned event — until the run is `done` or
607
+ * `error`. Each pass is a fresh {@link createAgentRuntime} over the same
608
+ * options, so nothing of the earlier pass is held across the wait; the log
609
+ * travels with the result (or the store's thread), so the final `events`
610
+ * replays every pass, and `maxModelCalls` bounds the whole call. An answer
611
+ * the idle state does not handle ends the loop: the result is `idle` with
612
+ * {@link AgentRunResult.ignored} set, not another call to `onIdle`.
613
+ *
614
+ * A host that cannot block for the answer (a request handler, a durable
615
+ * object) leaves this out, stores `result.persist()`, and calls
616
+ * {@link runAgent} again later with `{ snapshot, event }`.
617
+ */
618
+ onIdle?: (snapshot: SnapshotFrom<TMachine>) => Promise<EventFromLogic<TMachine>>;
619
+ }
620
+ /**
621
+ * Runs `machine` to quiescence in one call: {@link createAgentRuntime} over
622
+ * `options`, then {@link runToQuiescence} with the same object as its init.
623
+ * One options object carries both halves (`executors`, `store`, callbacks,
624
+ * and `input` | `snapshot` + `event`), and the result is the same
625
+ * {@link AgentRunResult}. With {@link AgentRunOptions.onIdle}, idle states are
626
+ * answered in place and the call returns only `done` or `error`.
627
+ *
628
+ * Reach for {@link createAgentRuntime} directly when the host needs the loop
629
+ * itself: a non-blocking durable host, events pushed mid-run, or a custom stop
630
+ * or checkpoint policy.
631
+ *
632
+ * @example
633
+ * ```ts
634
+ * const result = await runAgent(machine, { input: { topic }, executors });
635
+ * if (result.status === "done") console.log(result.output);
636
+ * ```
637
+ *
638
+ * @example
639
+ * ```ts
640
+ * // Resume a run a request handler left idle.
641
+ * const result = await runAgent(machine, { executors, snapshot, event });
642
+ * ```
643
+ */
644
+ declare function runAgent<TMachine extends AnyStateMachine>(machine: TMachine, options?: AgentRunOptions<TMachine>): Promise<AgentRunResult<TMachine>>;
581
645
  /**
582
646
  * Creates the helpers for one run of `machine`: executors bound to its
583
647
  * requests, the write-ahead log, traces, the budget, and a mailbox over
@@ -601,7 +665,7 @@ declare function runToQuiescence<TMachine extends AnyStateMachine>(runtime: Agen
601
665
  * while (r.status === 'idle') {
602
666
  * const event = await promptUser(getAcceptedEvents(r.snapshot));
603
667
  * r = await runToQuiescence(createAgentRuntime(machine, { executors }), {
604
- * snapshot: r.snapshot,
668
+ * snapshot: r.persist(),
605
669
  * event,
606
670
  * });
607
671
  * }
@@ -647,7 +711,8 @@ declare function inspectTransitions(handler: (snapshot: AnyMachineSnapshot, acto
647
711
  * ```
648
712
  *
649
713
  * Only ROOT-actor transitions are traced (matching the runtime's
650
- * `machine.transition`); child-actor transitions are ignored. Attribute the
714
+ * `machine.transition`); child-actor transitions are ignored. Each event's
715
+ * `from.value` is the root's previous state value, tracked per root actor. Attribute the
651
716
  * event via its envelope `runId`.
652
717
  *
653
718
  * By design this path has NO `run.start`/`run.end` events: `createActor` has no
@@ -669,4 +734,4 @@ declare function traceTransitions<TMachine extends AnyStateMachine = AnyStateMac
669
734
  */
670
735
  declare function isAgentIdle(snapshot: AnyMachineSnapshot): boolean;
671
736
  //#endregion
672
- export { serializeTraceEvent as C, AGENT_USAGE_EVENT_TYPE as D, AgentStepRequest as E, AgentUsageEvent as O, runToQuiescence as S, AgentRequest as T, InspectedActorRef as _, AgentRunErrorCause as a, inspectTransitions as b, AgentRunResult as c, AgentRuntimeOptions as d, AgentSnapshotDivergedError as f, AgentTransitionHandler as g, AgentTraceEvent as h, AgentMaxModelCallsExceededError as i, AgentRunStart as l, AgentTimerScheduler as m, AgentEffects as n, AgentRunInit as o, AgentTimerEvent as p, AgentInputFrom as r, AgentRunMeta as s, AGENT_TRACE_SCHEMA_VERSION as t, AgentRuntime as u, JsonSerializableTraceEvent as v, traceTransitions as w, isAgentIdle as x, createAgentRuntime as y };
737
+ export { runAgent as C, AgentRequest as D, traceTransitions as E, AgentStepRequest as O, isAgentIdle as S, serializeTraceEvent as T, AgentTransitionHandler as _, AgentRunErrorCause as a, createAgentRuntime as b, AgentRunOptions as c, AgentRuntime as d, AgentRuntimeOptions as f, AgentTraceEvent as g, AgentTimerScheduler as h, AgentMaxModelCallsExceededError as i, AgentRunResult as l, AgentTimerEvent as m, AgentEffects as n, AgentRunInit as o, AgentSnapshotDivergedError as p, AgentInputFrom as r, AgentRunMeta as s, AGENT_TRACE_SCHEMA_VERSION as t, AgentRunStart as u, InspectedActorRef as v, runToQuiescence as w, inspectTransitions as x, JsonSerializableTraceEvent as y };