@statelyai/agent 2.0.0-alpha.18 → 2.0.0-alpha.20

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 (38) hide show
  1. package/dist/ai-sdk.cjs +4 -2
  2. package/dist/ai-sdk.d.cts +1 -1
  3. package/dist/ai-sdk.d.mts +1 -1
  4. package/dist/ai-sdk.mjs +3 -2
  5. package/dist/{decision-C11xuud2.mjs → decision-BfhSgCc6.mjs} +48 -28
  6. package/dist/{decision-DnQCQPew.cjs → decision-DhsKLYAI.cjs} +64 -43
  7. package/dist/{event-log-store-CQJq8_v4.d.cts → event-log-store-Bz7HDBkE.d.cts} +11 -12
  8. package/dist/{event-log-store-B-1fcfkT.mjs → event-log-store-DmIDosD6.mjs} +22 -14
  9. package/dist/{event-log-store-yquOV1TX.cjs → event-log-store-a_TKy1gk.cjs} +22 -14
  10. package/dist/{event-log-store-BrC9Q1xW.d.mts → event-log-store-hrA1vqtN.d.mts} +11 -12
  11. package/dist/index.cjs +458 -109
  12. package/dist/index.d.cts +209 -81
  13. package/dist/index.d.mts +209 -81
  14. package/dist/index.mjs +455 -108
  15. package/dist/machines.cjs +13 -17
  16. package/dist/machines.d.cts +14 -17
  17. package/dist/machines.d.mts +14 -17
  18. package/dist/machines.mjs +13 -17
  19. package/dist/otel.cjs +1 -0
  20. package/dist/otel.d.cts +1 -1
  21. package/dist/otel.d.mts +1 -1
  22. package/dist/{run-agent-r9OD4z8F.d.cts → run-agent--4bbms-D.d.cts} +121 -48
  23. package/dist/{run-agent-DQIDikfd.d.mts → run-agent-CwmzAZwj.d.mts} +121 -48
  24. package/dist/{setup-agent-BrE2zFDy.mjs → setup-agent-BOcSpsIq.mjs} +38 -28
  25. package/dist/{setup-agent-C3ETi_HZ.cjs → setup-agent-gISRLxRe.cjs} +44 -33
  26. package/dist/sqlite.cjs +3 -9
  27. package/dist/sqlite.d.cts +1 -1
  28. package/dist/sqlite.d.mts +1 -1
  29. package/dist/sqlite.mjs +3 -9
  30. package/dist/{text-logic-VcWqO-Cl.d.cts → text-logic-Cavva1W6.d.cts} +24 -8
  31. package/dist/{text-logic-RvnlD-An.d.mts → text-logic-Er5KkTX6.d.mts} +24 -8
  32. package/dist/validate.cjs +436 -0
  33. package/dist/validate.d.cts +31 -0
  34. package/dist/validate.d.mts +31 -0
  35. package/dist/validate.mjs +411 -0
  36. package/package.json +17 -3
  37. package/schemas/agent-workflow.json +2 -2
  38. package/skills/generate-machine/SKILL.md +12 -14
@@ -1,6 +1,6 @@
1
1
  import { t as AgentError } from "./errors-CeSXQx0v.mjs";
2
- import { B as getMachineStructuralHash, F as djb2Hex, M as machineSuspensionPredicates, N as missingActor, T as agentExecutionOptions, d as USER_INPUT_ACTOR, g as executeAgentTextRequest, h as createTextLogic, j as machineStaticTransitionTargets, k as getRegisteredAgentExecutionOptions, l as DECIDE_ACTOR, m as builtinTextActors, n as createDecideActor, o as getAcceptedEvents, q as validateSchemaSync, r as isDecisionLogic, w as userInputActor, y as isTextLogic } from "./decision-C11xuud2.mjs";
3
- import { a as assertJsonSerializable, i as assertAgentLogEntry } from "./event-log-store-B-1fcfkT.mjs";
2
+ import { F as djb2Hex, M as machineStaticTransitionTargets, N as missingActor, T as agentExecutionOptions, U as resolveMachineVersion, d as USER_INPUT_ACTOR, g as executeAgentTextRequest, h as createTextLogic, j as machineIdlePredicates, k as getRegisteredAgentExecutionOptions, l as DECIDE_ACTOR, m as builtinTextActors, n as createDecideActor, o as getAcceptedEvents, q as validateSchemaSync, r as isDecisionLogic, w as userInputActor, y as isTextLogic } from "./decision-BfhSgCc6.mjs";
3
+ import { a as assertJsonSerializable, i as assertAgentLogEntry } from "./event-log-store-DmIDosD6.mjs";
4
4
  import { createMachineFromConfig, initialTransition, setup, transition } from "xstate";
5
5
  //#region src/messages.ts
6
6
  function addMessages(resolve) {
@@ -221,7 +221,7 @@ function resolveAgentStep(machine, step, request, output, options) {
221
221
  return createAgentStep(machine, snapshot, actions, getRegisteredAgentExecutionOptions(machine, options));
222
222
  }
223
223
  async function executeAgentRequest(requestOrEffect, executors) {
224
- if (requestOrEffect.kind === "decision") throw new Error("executeAgentRequest(...) is text-only. Resolve a 'decision' request with resolveDecision(request, executors.decide, ...) instead.");
224
+ if (requestOrEffect.kind === "decision") throw new Error("executeAgentRequest(...) is text-only. Resolve a 'decision' request with resolveDecision(request, executors, ...) instead.");
225
225
  const request = "requestId" in requestOrEffect ? {
226
226
  kind: "text",
227
227
  id: requestOrEffect.requestId,
@@ -335,7 +335,7 @@ const AGENT_USAGE_EVENT_TYPE = "@agent.usage";
335
335
  function createReplayEntry(machine, entries, event, options = {}) {
336
336
  const index = entries.length;
337
337
  const machineId = machine.config.id ?? machine.id ?? "(machine)";
338
- const machineVersion = options.machineVersion ?? getMachineStructuralHash(machine);
338
+ const machineVersion = options.machineVersion ?? resolveMachineVersion(machine);
339
339
  const entry = {
340
340
  schemaVersion: 1,
341
341
  id: options.id ?? `evt_${String(index).padStart(8, "0")}`,
@@ -373,6 +373,13 @@ function toEvents(history) {
373
373
  return candidate && typeof candidate === "object" && "event" in candidate && candidate.event ? candidate.event : entry;
374
374
  });
375
375
  }
376
+ /**
377
+ * Rewrites a journaled actor event's per-incarnation `sessionId` to the
378
+ * current snapshot's child for the same stable `actorId`, so replayed
379
+ * completions match freshly restored children.
380
+ *
381
+ * @internal
382
+ */
376
383
  function rebindActorSession(event, snapshot, sessions) {
377
384
  const actorEvent = event;
378
385
  if (typeof actorEvent.actorId !== "string" || typeof actorEvent.sessionId !== "string") return event;
@@ -631,7 +638,7 @@ function validateReplayEntries(entries, expected, label) {
631
638
  function replay(machine, entries, options = {}) {
632
639
  validateReplayEntries(entries, {
633
640
  machineId: machine.config.id ?? machine.id ?? "(machine)",
634
- machineVersion: options.machineVersion ?? getMachineStructuralHash(machine)
641
+ machineVersion: options.machineVersion ?? resolveMachineVersion(machine)
635
642
  }, "Replay entries");
636
643
  const events = toEvents(entries);
637
644
  const initOffset = events[0]?.type === "@agent.init" ? 1 : 0;
@@ -661,13 +668,6 @@ function replay(machine, entries, options = {}) {
661
668
  effects
662
669
  };
663
670
  }
664
- /** Requires and checks every entry's recorded state/effect hashes. */
665
- function verifyReplay(machine, entries, options = {}) {
666
- return replay(machine, entries, {
667
- ...options,
668
- verify: "strict"
669
- });
670
- }
671
671
  /** Structural event-tail, logical-state, and owed-effect comparison. */
672
672
  function diffEventLogs(machine, parentEntries, forkEntries, options = {}) {
673
673
  let commonLength = 0;
@@ -1135,14 +1135,14 @@ function collectDeclaredStateTags(states, tags = /* @__PURE__ */ new Set()) {
1135
1135
  }
1136
1136
  return tags;
1137
1137
  }
1138
- function resolveSuspensionPredicate(config, options) {
1139
- if (options.isSuspended) return options.isSuspended;
1140
- const suspendedTags = config.suspendedTags ?? [];
1141
- if (!suspendedTags.length) return;
1138
+ function resolveIdlePredicate(config, options) {
1139
+ if (options.isIdle) return options.isIdle;
1140
+ const idleTags = config.idleTags ?? [];
1141
+ if (!idleTags.length) return;
1142
1142
  const declaredTags = collectDeclaredStateTags(config.states);
1143
- const unknown = suspendedTags.filter((tag) => !declaredTags.has(tag));
1144
- if (unknown.length) throw new Error(`setupAgent.fromConfig: 'suspendedTags' lists ${unknown.map((tag) => `'${tag}'`).join(", ")}, which no state declares in its 'tags'. Tag the waiting state(s) — e.g. "tags": ["${unknown[0]}"] — or remove the entry.`);
1145
- return (snapshot) => suspendedTags.some((tag) => snapshot.hasTag(tag));
1143
+ const unknown = idleTags.filter((tag) => !declaredTags.has(tag));
1144
+ if (unknown.length) throw new Error(`setupAgent.fromConfig: 'idleTags' lists ${unknown.map((tag) => `'${tag}'`).join(", ")}, which no state declares in its 'tags'. Tag the waiting state(s) — e.g. "tags": ["${unknown[0]}"] — or remove the entry.`);
1145
+ return (snapshot) => idleTags.some((tag) => snapshot.hasTag(tag));
1146
1146
  }
1147
1147
  function setupAgentFromConfig(config, options) {
1148
1148
  if (!options || typeof options.compileSchema !== "function") throw new Error("setupAgent.fromConfig(...) requires a 'compileSchema' option: { compileSchema: (jsonSchema, name) => StandardSchemaV1 }. Bring your own JSON Schema engine (Ajv, @cfworker/json-schema, a compiled-Zod-from-JSON-Schema pipeline, ...). Core intentionally ships no JSON Schema engine.");
@@ -1174,8 +1174,8 @@ function setupAgentFromConfig(config, options) {
1174
1174
  models: {}
1175
1175
  });
1176
1176
  if (machine.config) machineStaticTransitionTargets.set(machine.config, translation.transitionTargets);
1177
- const isSuspended = resolveSuspensionPredicate(config, options);
1178
- if (isSuspended && machine.config) machineSuspensionPredicates.set(machine.config, isSuspended);
1177
+ const isIdle = resolveIdlePredicate(config, options);
1178
+ if (isIdle && machine.config) machineIdlePredicates.set(machine.config, isIdle);
1179
1179
  return {
1180
1180
  machine,
1181
1181
  schemas
@@ -1389,9 +1389,9 @@ function setupAgent(config) {
1389
1389
  assertStateSchemaKeysExist(config.states, machineConfig?.states);
1390
1390
  const machine = createBaseMachine(withRootOutputFromSingleFinal(machineConfig));
1391
1391
  agentExecutionOptions.set(machine, machineOptions);
1392
- if (config.isSuspended) {
1392
+ if (config.isIdle) {
1393
1393
  const rootConfig = machine.config;
1394
- if (rootConfig) machineSuspensionPredicates.set(rootConfig, config.isSuspended);
1394
+ if (rootConfig) machineIdlePredicates.set(rootConfig, config.isIdle);
1395
1395
  }
1396
1396
  return machine;
1397
1397
  },
@@ -1482,13 +1482,22 @@ const RESERVED_AGENT_ACTOR_KEYS = [
1482
1482
  DECIDE_ACTOR
1483
1483
  ];
1484
1484
  /**
1485
+ * The whole `agent.` actor-source namespace is reserved for the library, not
1486
+ * just the shipped builtins: a key starting with this prefix is rejected at
1487
+ * setup time so a future builtin can never collide with (or be shadowed by) a
1488
+ * user source. Name your own sources without it.
1489
+ */
1490
+ const RESERVED_AGENT_KEY_PREFIX = "agent.";
1491
+ /**
1485
1492
  * Runtime guards over the user-supplied `actors`/`requests` keys, in one walk
1486
1493
  * of both groups:
1487
1494
  *
1488
- * 1. A key in the reserved `agent.*` builtin namespace is rejected. Without
1489
- * this, the builtins-first spread in {@link createAgentActors} lets such a
1490
- * key overwrite the builtin (`agent.decide`, …) silently. Deliberate
1491
- * override of a builtin is still possible after the machine is created, via
1495
+ * 1. A key in the reserved `agent.` namespace is rejected — every key with
1496
+ * that prefix, not only today's builtins. Without this, the builtins-first
1497
+ * spread in {@link createAgentActors} lets such a key overwrite the builtin
1498
+ * (`agent.decide`, …) silently, and a builtin added later would start
1499
+ * colliding with user code. Deliberate override of a builtin is still
1500
+ * possible after the machine is created, via
1492
1501
  * `machine.provide({ actors: { 'agent.decide': ... } })`.
1493
1502
  * 2. A key appearing in BOTH groups is almost certainly a mistake (whichever
1494
1503
  * spread applies last would silently win) — fail fast with a clear message
@@ -1499,6 +1508,7 @@ function assertActorKeys(actors, requests) {
1499
1508
  const groups = [["actors", actors], ["requests", requests]];
1500
1509
  for (const [groupName, group] of groups) for (const key of Object.keys(group ?? {})) {
1501
1510
  if (RESERVED_AGENT_ACTOR_KEYS.some((reserved) => reserved === key)) throw new Error(`setupAgent: '${groupName}' key '${key}' is a reserved builtin agent actor and cannot be redefined here (it would silently clobber the builtin). Reserved keys: ${RESERVED_AGENT_ACTOR_KEYS.join(", ")}. To deliberately override a builtin, do it on the created machine instead: machine.provide({ actors: { '${key}': ... } }).`);
1511
+ if (key.startsWith(RESERVED_AGENT_KEY_PREFIX)) throw new Error(`setupAgent: '${groupName}' key '${key}' uses the reserved '${RESERVED_AGENT_KEY_PREFIX}' namespace, which belongs to the library (${RESERVED_AGENT_ACTOR_KEYS.join(", ")}, and anything added later). Rename it without the '${RESERVED_AGENT_KEY_PREFIX}' prefix.`);
1502
1512
  const existingGroup = seenIn.get(key);
1503
1513
  if (existingGroup) throw new Error(`setupAgent: key '${key}' is defined in both '${existingGroup}' and '${groupName}'. Each actor source key must be unique across 'actors' and 'requests'.`);
1504
1514
  seenIn.set(key, groupName);
@@ -1515,4 +1525,4 @@ function createAgentActors(actors, requestActors) {
1515
1525
  };
1516
1526
  }
1517
1527
  //#endregion
1518
- export { initialAgentStep as _, AGENT_USAGE_EVENT_TYPE as a, appendMessages as b, createReplayEntry as c, initEntry as d, replay as f, getInvokeEffectMetadata as g, executeAgentRequest as h, AGENT_INIT_EVENT_TYPE as i, diffEventLogs as l, verifyReplay as m, getAgentSchemas as n, AgentReplayDivergenceError as o, validateReplayEntries as p, setupAgent as r, AgentReplayMachineMismatchError as s, createAgentSchemas as t, getAgentEffects as u, resolveAgentStep as v, messagesSchema as x, transitionAgentStep as y };
1528
+ export { initialAgentStep as _, AGENT_USAGE_EVENT_TYPE as a, appendMessages as b, createReplayEntry as c, initEntry as d, rebindActorSession as f, getInvokeEffectMetadata as g, executeAgentRequest as h, AGENT_INIT_EVENT_TYPE as i, diffEventLogs as l, validateReplayEntries as m, getAgentSchemas as n, AgentReplayDivergenceError as o, replay as p, setupAgent as r, AgentReplayMachineMismatchError as s, createAgentSchemas as t, getAgentEffects as u, resolveAgentStep as v, messagesSchema as x, transitionAgentStep as y };
@@ -1,6 +1,7 @@
1
1
  const require_errors = require("./errors-DUBBzRLP.cjs");
2
- const require_decision = require("./decision-DnQCQPew.cjs");
3
- const require_event_log_store = require("./event-log-store-yquOV1TX.cjs");
2
+ const require_decision = require("./decision-DhsKLYAI.cjs");
3
+ const require_event_log_store = require("./event-log-store-a_TKy1gk.cjs");
4
+ require("./validate.cjs");
4
5
  let xstate = require("xstate");
5
6
  //#region src/messages.ts
6
7
  function addMessages(resolve) {
@@ -221,7 +222,7 @@ function resolveAgentStep(machine, step, request, output, options) {
221
222
  return createAgentStep(machine, snapshot, actions, require_decision.getRegisteredAgentExecutionOptions(machine, options));
222
223
  }
223
224
  async function executeAgentRequest(requestOrEffect, executors) {
224
- if (requestOrEffect.kind === "decision") throw new Error("executeAgentRequest(...) is text-only. Resolve a 'decision' request with resolveDecision(request, executors.decide, ...) instead.");
225
+ if (requestOrEffect.kind === "decision") throw new Error("executeAgentRequest(...) is text-only. Resolve a 'decision' request with resolveDecision(request, executors, ...) instead.");
225
226
  const request = "requestId" in requestOrEffect ? {
226
227
  kind: "text",
227
228
  id: requestOrEffect.requestId,
@@ -335,7 +336,7 @@ const AGENT_USAGE_EVENT_TYPE = "@agent.usage";
335
336
  function createReplayEntry(machine, entries, event, options = {}) {
336
337
  const index = entries.length;
337
338
  const machineId = machine.config.id ?? machine.id ?? "(machine)";
338
- const machineVersion = options.machineVersion ?? require_decision.getMachineStructuralHash(machine);
339
+ const machineVersion = options.machineVersion ?? require_decision.resolveMachineVersion(machine);
339
340
  const entry = {
340
341
  schemaVersion: 1,
341
342
  id: options.id ?? `evt_${String(index).padStart(8, "0")}`,
@@ -373,6 +374,13 @@ function toEvents(history) {
373
374
  return candidate && typeof candidate === "object" && "event" in candidate && candidate.event ? candidate.event : entry;
374
375
  });
375
376
  }
377
+ /**
378
+ * Rewrites a journaled actor event's per-incarnation `sessionId` to the
379
+ * current snapshot's child for the same stable `actorId`, so replayed
380
+ * completions match freshly restored children.
381
+ *
382
+ * @internal
383
+ */
376
384
  function rebindActorSession(event, snapshot, sessions) {
377
385
  const actorEvent = event;
378
386
  if (typeof actorEvent.actorId !== "string" || typeof actorEvent.sessionId !== "string") return event;
@@ -631,7 +639,7 @@ function validateReplayEntries(entries, expected, label) {
631
639
  function replay(machine, entries, options = {}) {
632
640
  validateReplayEntries(entries, {
633
641
  machineId: machine.config.id ?? machine.id ?? "(machine)",
634
- machineVersion: options.machineVersion ?? require_decision.getMachineStructuralHash(machine)
642
+ machineVersion: options.machineVersion ?? require_decision.resolveMachineVersion(machine)
635
643
  }, "Replay entries");
636
644
  const events = toEvents(entries);
637
645
  const initOffset = events[0]?.type === "@agent.init" ? 1 : 0;
@@ -661,13 +669,6 @@ function replay(machine, entries, options = {}) {
661
669
  effects
662
670
  };
663
671
  }
664
- /** Requires and checks every entry's recorded state/effect hashes. */
665
- function verifyReplay(machine, entries, options = {}) {
666
- return replay(machine, entries, {
667
- ...options,
668
- verify: "strict"
669
- });
670
- }
671
672
  /** Structural event-tail, logical-state, and owed-effect comparison. */
672
673
  function diffEventLogs(machine, parentEntries, forkEntries, options = {}) {
673
674
  let commonLength = 0;
@@ -1135,14 +1136,14 @@ function collectDeclaredStateTags(states, tags = /* @__PURE__ */ new Set()) {
1135
1136
  }
1136
1137
  return tags;
1137
1138
  }
1138
- function resolveSuspensionPredicate(config, options) {
1139
- if (options.isSuspended) return options.isSuspended;
1140
- const suspendedTags = config.suspendedTags ?? [];
1141
- if (!suspendedTags.length) return;
1139
+ function resolveIdlePredicate(config, options) {
1140
+ if (options.isIdle) return options.isIdle;
1141
+ const idleTags = config.idleTags ?? [];
1142
+ if (!idleTags.length) return;
1142
1143
  const declaredTags = collectDeclaredStateTags(config.states);
1143
- const unknown = suspendedTags.filter((tag) => !declaredTags.has(tag));
1144
- if (unknown.length) throw new Error(`setupAgent.fromConfig: 'suspendedTags' lists ${unknown.map((tag) => `'${tag}'`).join(", ")}, which no state declares in its 'tags'. Tag the waiting state(s) — e.g. "tags": ["${unknown[0]}"] — or remove the entry.`);
1145
- return (snapshot) => suspendedTags.some((tag) => snapshot.hasTag(tag));
1144
+ const unknown = idleTags.filter((tag) => !declaredTags.has(tag));
1145
+ if (unknown.length) throw new Error(`setupAgent.fromConfig: 'idleTags' lists ${unknown.map((tag) => `'${tag}'`).join(", ")}, which no state declares in its 'tags'. Tag the waiting state(s) — e.g. "tags": ["${unknown[0]}"] — or remove the entry.`);
1146
+ return (snapshot) => idleTags.some((tag) => snapshot.hasTag(tag));
1146
1147
  }
1147
1148
  function setupAgentFromConfig(config, options) {
1148
1149
  if (!options || typeof options.compileSchema !== "function") throw new Error("setupAgent.fromConfig(...) requires a 'compileSchema' option: { compileSchema: (jsonSchema, name) => StandardSchemaV1 }. Bring your own JSON Schema engine (Ajv, @cfworker/json-schema, a compiled-Zod-from-JSON-Schema pipeline, ...). Core intentionally ships no JSON Schema engine.");
@@ -1174,8 +1175,8 @@ function setupAgentFromConfig(config, options) {
1174
1175
  models: {}
1175
1176
  });
1176
1177
  if (machine.config) require_decision.machineStaticTransitionTargets.set(machine.config, translation.transitionTargets);
1177
- const isSuspended = resolveSuspensionPredicate(config, options);
1178
- if (isSuspended && machine.config) require_decision.machineSuspensionPredicates.set(machine.config, isSuspended);
1178
+ const isIdle = resolveIdlePredicate(config, options);
1179
+ if (isIdle && machine.config) require_decision.machineIdlePredicates.set(machine.config, isIdle);
1179
1180
  return {
1180
1181
  machine,
1181
1182
  schemas
@@ -1389,9 +1390,9 @@ function setupAgent(config) {
1389
1390
  assertStateSchemaKeysExist(config.states, machineConfig?.states);
1390
1391
  const machine = createBaseMachine(withRootOutputFromSingleFinal(machineConfig));
1391
1392
  require_decision.agentExecutionOptions.set(machine, machineOptions);
1392
- if (config.isSuspended) {
1393
+ if (config.isIdle) {
1393
1394
  const rootConfig = machine.config;
1394
- if (rootConfig) require_decision.machineSuspensionPredicates.set(rootConfig, config.isSuspended);
1395
+ if (rootConfig) require_decision.machineIdlePredicates.set(rootConfig, config.isIdle);
1395
1396
  }
1396
1397
  return machine;
1397
1398
  },
@@ -1482,13 +1483,22 @@ const RESERVED_AGENT_ACTOR_KEYS = [
1482
1483
  require_decision.DECIDE_ACTOR
1483
1484
  ];
1484
1485
  /**
1486
+ * The whole `agent.` actor-source namespace is reserved for the library, not
1487
+ * just the shipped builtins: a key starting with this prefix is rejected at
1488
+ * setup time so a future builtin can never collide with (or be shadowed by) a
1489
+ * user source. Name your own sources without it.
1490
+ */
1491
+ const RESERVED_AGENT_KEY_PREFIX = "agent.";
1492
+ /**
1485
1493
  * Runtime guards over the user-supplied `actors`/`requests` keys, in one walk
1486
1494
  * of both groups:
1487
1495
  *
1488
- * 1. A key in the reserved `agent.*` builtin namespace is rejected. Without
1489
- * this, the builtins-first spread in {@link createAgentActors} lets such a
1490
- * key overwrite the builtin (`agent.decide`, …) silently. Deliberate
1491
- * override of a builtin is still possible after the machine is created, via
1496
+ * 1. A key in the reserved `agent.` namespace is rejected — every key with
1497
+ * that prefix, not only today's builtins. Without this, the builtins-first
1498
+ * spread in {@link createAgentActors} lets such a key overwrite the builtin
1499
+ * (`agent.decide`, …) silently, and a builtin added later would start
1500
+ * colliding with user code. Deliberate override of a builtin is still
1501
+ * possible after the machine is created, via
1492
1502
  * `machine.provide({ actors: { 'agent.decide': ... } })`.
1493
1503
  * 2. A key appearing in BOTH groups is almost certainly a mistake (whichever
1494
1504
  * spread applies last would silently win) — fail fast with a clear message
@@ -1499,6 +1509,7 @@ function assertActorKeys(actors, requests) {
1499
1509
  const groups = [["actors", actors], ["requests", requests]];
1500
1510
  for (const [groupName, group] of groups) for (const key of Object.keys(group ?? {})) {
1501
1511
  if (RESERVED_AGENT_ACTOR_KEYS.some((reserved) => reserved === key)) throw new Error(`setupAgent: '${groupName}' key '${key}' is a reserved builtin agent actor and cannot be redefined here (it would silently clobber the builtin). Reserved keys: ${RESERVED_AGENT_ACTOR_KEYS.join(", ")}. To deliberately override a builtin, do it on the created machine instead: machine.provide({ actors: { '${key}': ... } }).`);
1512
+ if (key.startsWith(RESERVED_AGENT_KEY_PREFIX)) throw new Error(`setupAgent: '${groupName}' key '${key}' uses the reserved '${RESERVED_AGENT_KEY_PREFIX}' namespace, which belongs to the library (${RESERVED_AGENT_ACTOR_KEYS.join(", ")}, and anything added later). Rename it without the '${RESERVED_AGENT_KEY_PREFIX}' prefix.`);
1502
1513
  const existingGroup = seenIn.get(key);
1503
1514
  if (existingGroup) throw new Error(`setupAgent: key '${key}' is defined in both '${existingGroup}' and '${groupName}'. Each actor source key must be unique across 'actors' and 'requests'.`);
1504
1515
  seenIn.set(key, groupName);
@@ -1605,6 +1616,12 @@ Object.defineProperty(exports, "messagesSchema", {
1605
1616
  return messagesSchema;
1606
1617
  }
1607
1618
  });
1619
+ Object.defineProperty(exports, "rebindActorSession", {
1620
+ enumerable: true,
1621
+ get: function() {
1622
+ return rebindActorSession;
1623
+ }
1624
+ });
1608
1625
  Object.defineProperty(exports, "replay", {
1609
1626
  enumerable: true,
1610
1627
  get: function() {
@@ -1635,9 +1652,3 @@ Object.defineProperty(exports, "validateReplayEntries", {
1635
1652
  return validateReplayEntries;
1636
1653
  }
1637
1654
  });
1638
- Object.defineProperty(exports, "verifyReplay", {
1639
- enumerable: true,
1640
- get: function() {
1641
- return verifyReplay;
1642
- }
1643
- });
package/dist/sqlite.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_event_log_store = require("./event-log-store-yquOV1TX.cjs");
2
+ const require_event_log_store = require("./event-log-store-a_TKy1gk.cjs");
3
3
  //#region src/sqlite/index.ts
4
4
  function openDatabase(path) {
5
5
  const sqlite = process.getBuiltinModule?.("node:sqlite");
@@ -80,18 +80,12 @@ function createSqliteEventLogStore(options) {
80
80
  async length(threadId) {
81
81
  return lengthOf(threadId);
82
82
  },
83
- async fork({ threadId, newThreadId, upToIndex, atEventId }) {
84
- if (upToIndex !== void 0 && atEventId !== void 0) throw new Error("AgentEventLogStore.fork: pass either upToIndex or atEventId, not both.");
83
+ async fork({ threadId, newThreadId, upToIndex }) {
85
84
  transact(() => {
86
85
  if (lengthOf(newThreadId) > 0) throw new Error(`AgentEventLogStore.fork: newThreadId "${newThreadId}" already has entries.`);
87
86
  const sourceLength = lengthOf(threadId);
88
87
  if (sourceLength === 0) throw new Error(`AgentEventLogStore.fork: unknown source thread "${threadId}".`);
89
- let upTo = upToIndex ?? sourceLength;
90
- if (atEventId !== void 0) {
91
- const row = db.prepare(`SELECT idx FROM ${table} WHERE thread_id = ? AND entry_id = ?`).get(threadId, atEventId);
92
- if (!row) throw new Error(`AgentEventLogStore.fork: thread "${threadId}" has no event id "${atEventId}".`);
93
- upTo = Number(row.idx) + 1;
94
- }
88
+ const upTo = upToIndex ?? sourceLength;
95
89
  if (upTo < 0 || upTo > sourceLength) throw new Error(`AgentEventLogStore.fork: thread "${threadId}" (length ${sourceLength}) has no index ${upTo} to fork up to.`);
96
90
  db.prepare(`INSERT INTO ${table} (thread_id, idx, entry_id, entry)
97
91
  SELECT ?, idx, entry_id, entry FROM ${table} WHERE thread_id = ? AND idx < ?`).run(newThreadId, threadId, upTo);
package/dist/sqlite.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { r as AgentSnapshotStore } from "./types-pJ5Hn8fv.cjs";
2
- import { r as AgentEventLogStore } from "./event-log-store-CQJq8_v4.cjs";
2
+ import { r as AgentEventLogStore } from "./event-log-store-Bz7HDBkE.cjs";
3
3
 
4
4
  //#region src/sqlite/index.d.ts
5
5
  /** A prepared statement, structurally compatible with `node:sqlite`'s `StatementSync`. */
package/dist/sqlite.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { r as AgentSnapshotStore } from "./types-DYpK3QF4.mjs";
2
- import { r as AgentEventLogStore } from "./event-log-store-BrC9Q1xW.mjs";
2
+ import { r as AgentEventLogStore } from "./event-log-store-hrA1vqtN.mjs";
3
3
 
4
4
  //#region src/sqlite/index.d.ts
5
5
  /** A prepared statement, structurally compatible with `node:sqlite`'s `StatementSync`. */
package/dist/sqlite.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { i as assertAgentLogEntry, n as AgentEventLogConflictError } from "./event-log-store-B-1fcfkT.mjs";
1
+ import { i as assertAgentLogEntry, n as AgentEventLogConflictError } from "./event-log-store-DmIDosD6.mjs";
2
2
  //#region src/sqlite/index.ts
3
3
  function openDatabase(path) {
4
4
  const sqlite = process.getBuiltinModule?.("node:sqlite");
@@ -79,18 +79,12 @@ function createSqliteEventLogStore(options) {
79
79
  async length(threadId) {
80
80
  return lengthOf(threadId);
81
81
  },
82
- async fork({ threadId, newThreadId, upToIndex, atEventId }) {
83
- if (upToIndex !== void 0 && atEventId !== void 0) throw new Error("AgentEventLogStore.fork: pass either upToIndex or atEventId, not both.");
82
+ async fork({ threadId, newThreadId, upToIndex }) {
84
83
  transact(() => {
85
84
  if (lengthOf(newThreadId) > 0) throw new Error(`AgentEventLogStore.fork: newThreadId "${newThreadId}" already has entries.`);
86
85
  const sourceLength = lengthOf(threadId);
87
86
  if (sourceLength === 0) throw new Error(`AgentEventLogStore.fork: unknown source thread "${threadId}".`);
88
- let upTo = upToIndex ?? sourceLength;
89
- if (atEventId !== void 0) {
90
- const row = db.prepare(`SELECT idx FROM ${table} WHERE thread_id = ? AND entry_id = ?`).get(threadId, atEventId);
91
- if (!row) throw new Error(`AgentEventLogStore.fork: thread "${threadId}" has no event id "${atEventId}".`);
92
- upTo = Number(row.idx) + 1;
93
- }
87
+ const upTo = upToIndex ?? sourceLength;
94
88
  if (upTo < 0 || upTo > sourceLength) throw new Error(`AgentEventLogStore.fork: thread "${threadId}" (length ${sourceLength}) has no index ${upTo} to fork up to.`);
95
89
  db.prepare(`INSERT INTO ${table} (thread_id, idx, entry_id, entry)
96
90
  SELECT ?, idx, entry_id, entry FROM ${table} WHERE thread_id = ? AND idx < ?`).run(newThreadId, threadId, upTo);
@@ -214,14 +214,17 @@ declare function renderDecisionAttempts(request: Pick<AgentDecisionRequest, "eve
214
214
  * `generateText`/`streamText` — how the model is coerced into choosing
215
215
  * (tool-per-event + forced tool choice, structured output, …) is entirely
216
216
  * adapter business; core only validates and retries the returned choice (see
217
- * {@link resolveDecision}). The optional `reason` is carried through to
217
+ * {@link resolveDecision}). It takes the same `(request, info)` pair as
218
+ * `generateText`/`streamText` — `info` carries the host seams (`signal`,
219
+ * `runId`, `requestId`); `onChunk` is never set for a decision.
220
+ * The optional `reason` is carried through to
218
221
  * `onResult`/event-sourcing but never affects validation. Like text
219
222
  * executors' `{ output, ...extras }` envelope, any extra keys (finish reason,
220
223
  * …) flow untouched to `onResult`'s `raw`; `usage` is the one core reads —
221
224
  * report this attempt's tokens there and `runAgent` folds them into the run's
222
225
  * aggregated {@link AgentUsage}.
223
226
  */
224
- type AgentDecisionExecutor = (request: AgentDecisionRequest) => PromiseLike<{
227
+ type AgentDecisionExecutor = (request: AgentDecisionRequest, info?: AgentRequestExecutorInfo) => PromiseLike<{
225
228
  event: ChosenEvent;
226
229
  reason?: string; /** This attempt's token usage, aggregated into the run result's {@link AgentUsage}. */
227
230
  usage?: AgentCallUsage;
@@ -252,7 +255,7 @@ interface ResolveDecisionOptions<TEvent extends ChosenEvent = ChosenEvent> {
252
255
  }
253
256
  /**
254
257
  * Validation + retry core for decisions. No provider mechanics — the
255
- * `executor` is responsible for making the model choose an event; this
258
+ * `executors.decide` is responsible for making the model choose an event; this
256
259
  * function only validates the choice and retries on failure, up to
257
260
  * `options.maxRetries` (default 2, i.e. up to 3 attempts total).
258
261
  *
@@ -270,12 +273,12 @@ interface ResolveDecisionOptions<TEvent extends ChosenEvent = ChosenEvent> {
270
273
  *
271
274
  * @example
272
275
  * ```ts
273
- * const event = await resolveDecision(request, decide, {
276
+ * const event = await resolveDecision(request, executors, {
274
277
  * canTake: (e) => snapshot.can(e),
275
278
  * });
276
279
  * ```
277
280
  */
278
- declare function resolveDecision<TEvent extends ChosenEvent = ChosenEvent>(request: AgentDecisionRequest, executor: AgentDecisionExecutor, options?: ResolveDecisionOptions<TEvent>): Promise<TEvent>;
281
+ declare function resolveDecision<TEvent extends ChosenEvent = ChosenEvent>(request: AgentDecisionRequest, executors: Pick<Partial<AgentRequestExecutors>, "decide">, options?: ResolveDecisionOptions<TEvent>): Promise<TEvent>;
279
282
  //#endregion
280
283
  //#region src/text-logic.d.ts
281
284
  declare const USER_INPUT_ACTOR: "agent.userInput";
@@ -352,12 +355,23 @@ interface AgentTextRequest<TMetadata = Record<string, unknown>> {
352
355
  topK?: number;
353
356
  seed?: number;
354
357
  stopSequences?: string[];
358
+ /**
359
+ * Bounds the HOST-side tool-call loop for this one request: the maximum
360
+ * number of model steps the executor may run before it must return. Omitted
361
+ * means single-step (one model call, tool results not fed back). Named and
362
+ * typed to match the AI SDK — the shipped adapter lowers it to
363
+ * `stopWhen: stepCountIs(maxSteps)`.
364
+ *
365
+ * This is a REQUEST budget, distinct from the machine-level `maxTurns` a
366
+ * preset uses for its own turn budget, and from `runAgent`'s run-wide
367
+ * `maxModelCalls`.
368
+ */
369
+ maxSteps?: number;
355
370
  /**
356
371
  * Host-owned per-call options. Use this for provider/runtime details such
357
372
  * as Cloudflare bindings, tracing IDs, SDK provider options, or transport
358
- * hints. The machine carries it; the host decides what it means e.g.
359
- * the AI SDK adapter (`createAiSdkExecutors`) reads `metadata.maxSteps` to
360
- * bound its multi-step tool-call loop for that request.
373
+ * hints. The machine carries it; the host decides what it means. Not the
374
+ * place for `maxSteps` any more — that is a typed field above.
361
375
  */
362
376
  metadata?: TMetadata;
363
377
  }
@@ -473,6 +487,8 @@ interface TextLogicConfig<TInputSchema extends StandardSchemaV1 = StandardSchema
473
487
  topK?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
474
488
  seed?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
475
489
  stopSequences?: ResolveTextLogicValue<string[] | undefined, InferOutput<TInputSchema>>;
490
+ /** Bounds this request's host-side tool loop (see {@link AgentTextRequest.maxSteps}). */
491
+ maxSteps?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
476
492
  metadata?: ResolveTextLogicValue<TMetadata | undefined, InferOutput<TInputSchema>>;
477
493
  }
478
494
  /** Arguments passed to a {@link TextLogicExecutor}: the typed input, the lowered {@link AgentTextRequest}, and the actor's own `signal`/`system`/`self`/`emit`. */
@@ -214,14 +214,17 @@ declare function renderDecisionAttempts(request: Pick<AgentDecisionRequest, "eve
214
214
  * `generateText`/`streamText` — how the model is coerced into choosing
215
215
  * (tool-per-event + forced tool choice, structured output, …) is entirely
216
216
  * adapter business; core only validates and retries the returned choice (see
217
- * {@link resolveDecision}). The optional `reason` is carried through to
217
+ * {@link resolveDecision}). It takes the same `(request, info)` pair as
218
+ * `generateText`/`streamText` — `info` carries the host seams (`signal`,
219
+ * `runId`, `requestId`); `onChunk` is never set for a decision.
220
+ * The optional `reason` is carried through to
218
221
  * `onResult`/event-sourcing but never affects validation. Like text
219
222
  * executors' `{ output, ...extras }` envelope, any extra keys (finish reason,
220
223
  * …) flow untouched to `onResult`'s `raw`; `usage` is the one core reads —
221
224
  * report this attempt's tokens there and `runAgent` folds them into the run's
222
225
  * aggregated {@link AgentUsage}.
223
226
  */
224
- type AgentDecisionExecutor = (request: AgentDecisionRequest) => PromiseLike<{
227
+ type AgentDecisionExecutor = (request: AgentDecisionRequest, info?: AgentRequestExecutorInfo) => PromiseLike<{
225
228
  event: ChosenEvent;
226
229
  reason?: string; /** This attempt's token usage, aggregated into the run result's {@link AgentUsage}. */
227
230
  usage?: AgentCallUsage;
@@ -252,7 +255,7 @@ interface ResolveDecisionOptions<TEvent extends ChosenEvent = ChosenEvent> {
252
255
  }
253
256
  /**
254
257
  * Validation + retry core for decisions. No provider mechanics — the
255
- * `executor` is responsible for making the model choose an event; this
258
+ * `executors.decide` is responsible for making the model choose an event; this
256
259
  * function only validates the choice and retries on failure, up to
257
260
  * `options.maxRetries` (default 2, i.e. up to 3 attempts total).
258
261
  *
@@ -270,12 +273,12 @@ interface ResolveDecisionOptions<TEvent extends ChosenEvent = ChosenEvent> {
270
273
  *
271
274
  * @example
272
275
  * ```ts
273
- * const event = await resolveDecision(request, decide, {
276
+ * const event = await resolveDecision(request, executors, {
274
277
  * canTake: (e) => snapshot.can(e),
275
278
  * });
276
279
  * ```
277
280
  */
278
- declare function resolveDecision<TEvent extends ChosenEvent = ChosenEvent>(request: AgentDecisionRequest, executor: AgentDecisionExecutor, options?: ResolveDecisionOptions<TEvent>): Promise<TEvent>;
281
+ declare function resolveDecision<TEvent extends ChosenEvent = ChosenEvent>(request: AgentDecisionRequest, executors: Pick<Partial<AgentRequestExecutors>, "decide">, options?: ResolveDecisionOptions<TEvent>): Promise<TEvent>;
279
282
  //#endregion
280
283
  //#region src/text-logic.d.ts
281
284
  declare const USER_INPUT_ACTOR: "agent.userInput";
@@ -352,12 +355,23 @@ interface AgentTextRequest<TMetadata = Record<string, unknown>> {
352
355
  topK?: number;
353
356
  seed?: number;
354
357
  stopSequences?: string[];
358
+ /**
359
+ * Bounds the HOST-side tool-call loop for this one request: the maximum
360
+ * number of model steps the executor may run before it must return. Omitted
361
+ * means single-step (one model call, tool results not fed back). Named and
362
+ * typed to match the AI SDK — the shipped adapter lowers it to
363
+ * `stopWhen: stepCountIs(maxSteps)`.
364
+ *
365
+ * This is a REQUEST budget, distinct from the machine-level `maxTurns` a
366
+ * preset uses for its own turn budget, and from `runAgent`'s run-wide
367
+ * `maxModelCalls`.
368
+ */
369
+ maxSteps?: number;
355
370
  /**
356
371
  * Host-owned per-call options. Use this for provider/runtime details such
357
372
  * as Cloudflare bindings, tracing IDs, SDK provider options, or transport
358
- * hints. The machine carries it; the host decides what it means e.g.
359
- * the AI SDK adapter (`createAiSdkExecutors`) reads `metadata.maxSteps` to
360
- * bound its multi-step tool-call loop for that request.
373
+ * hints. The machine carries it; the host decides what it means. Not the
374
+ * place for `maxSteps` any more — that is a typed field above.
361
375
  */
362
376
  metadata?: TMetadata;
363
377
  }
@@ -473,6 +487,8 @@ interface TextLogicConfig<TInputSchema extends StandardSchemaV1 = StandardSchema
473
487
  topK?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
474
488
  seed?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
475
489
  stopSequences?: ResolveTextLogicValue<string[] | undefined, InferOutput<TInputSchema>>;
490
+ /** Bounds this request's host-side tool loop (see {@link AgentTextRequest.maxSteps}). */
491
+ maxSteps?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
476
492
  metadata?: ResolveTextLogicValue<TMetadata | undefined, InferOutput<TInputSchema>>;
477
493
  }
478
494
  /** Arguments passed to a {@link TextLogicExecutor}: the typed input, the lowered {@link AgentTextRequest}, and the actor's own `signal`/`system`/`self`/`emit`. */