@statelyai/agent 2.0.0-alpha.15 → 2.0.0-alpha.17

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 (35) hide show
  1. package/dist/ai-sdk.cjs +1 -1
  2. package/dist/ai-sdk.d.cts +2 -2
  3. package/dist/ai-sdk.d.mts +2 -2
  4. package/dist/ai-sdk.mjs +1 -1
  5. package/dist/{decision-D9Zi7Xi5.mjs → decision-C11xuud2.mjs} +35 -26
  6. package/dist/{decision-C0cUKvNt.cjs → decision-DnQCQPew.cjs} +46 -31
  7. package/dist/{event-log-store-D7pWtIhb.mjs → event-log-store-B-1fcfkT.mjs} +149 -141
  8. package/dist/{event-log-store-BkUNtyOF.d.mts → event-log-store-BrC9Q1xW.d.mts} +14 -12
  9. package/dist/{event-log-store-CVd2eyRy.d.cts → event-log-store-CQJq8_v4.d.cts} +14 -12
  10. package/dist/{event-log-store-CNT_7F0V.cjs → event-log-store-yquOV1TX.cjs} +148 -140
  11. package/dist/index.cjs +498 -520
  12. package/dist/index.d.cts +130 -104
  13. package/dist/index.d.mts +130 -104
  14. package/dist/index.mjs +497 -519
  15. package/dist/machines.cjs +1 -1
  16. package/dist/machines.d.cts +1 -1
  17. package/dist/machines.d.mts +1 -1
  18. package/dist/machines.mjs +1 -1
  19. package/dist/otel.d.cts +1 -1
  20. package/dist/otel.d.mts +1 -1
  21. package/dist/{run-agent-B_n4Qxye.d.cts → run-agent-BxjGaVpL.d.cts} +49 -109
  22. package/dist/{run-agent-BWzo4FLv.d.mts → run-agent-COHoCgQd.d.mts} +49 -109
  23. package/dist/{setup-agent-DeHRW-qX.mjs → setup-agent-CTg57Pa4.mjs} +154 -167
  24. package/dist/{setup-agent-CpK0ZRWV.cjs → setup-agent-D_EyJ0Ik.cjs} +159 -172
  25. package/dist/sqlite.cjs +1 -1
  26. package/dist/sqlite.d.cts +2 -2
  27. package/dist/sqlite.d.mts +2 -2
  28. package/dist/sqlite.mjs +1 -1
  29. package/dist/{text-logic-DZW7XWy9.d.cts → text-logic-BFX5q7fM.d.cts} +23 -2
  30. package/dist/{text-logic-C7anC7qX.d.mts → text-logic-DQW8_DWW.d.mts} +23 -2
  31. package/dist/{types-DFD28AWe.d.cts → types-DYpK3QF4.d.mts} +7 -6
  32. package/dist/{types-CTBhMnFu.d.mts → types-pJ5Hn8fv.d.cts} +7 -6
  33. package/package.json +28 -28
  34. package/readme.md +6 -19
  35. package/schemas/agent-workflow.json +9 -4
@@ -1,6 +1,6 @@
1
1
  import { t as AgentError } from "./errors-CeSXQx0v.mjs";
2
- import { K as validateSchemaSync, M as machineSuspensionPredicates, N as missingActor, T as agentExecutionOptions, _ as extractCallUsage, 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, r as isDecisionLogic, w as userInputActor, y as isTextLogic, z as getMachineStructuralHash } from "./decision-D9Zi7Xi5.mjs";
3
- import { i as assertAgentLogEntry, o as assertJsonSerializable } from "./event-log-store-D7pWtIhb.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";
4
4
  import { createMachineFromConfig, initialTransition, setup, transition } from "xstate";
5
5
  //#region src/messages.ts
6
6
  function addMessages(resolve) {
@@ -85,7 +85,7 @@ const messagesSchema = { "~standard": {
85
85
  * The step envelope: an INTERNAL, per-model-call-checkpoint view of an agent
86
86
  * machine (`AgentStep` = snapshot + actions + discovered requests + done). It
87
87
  * once backed a public step API; the public step path is now the thin
88
- * effect/replay loop in `./effects.ts` (re-exported from `@statelyai/agent/steps`).
88
+ * effect/replay loop in `./effects.ts` (re-exported from `@statelyai/agent`).
89
89
  * These helpers survive as internals that `runAgent`, `verify.ts`, and the
90
90
  * effect path build on — the only symbol still on the public surface is
91
91
  * {@link executeAgentRequest} (the `text`-effect resolver).
@@ -106,17 +106,20 @@ function getInvokeEffectMetadata(action) {
106
106
  /**
107
107
  * Scans a set of executable actions (as returned by xstate's `transition`/
108
108
  * `initialTransition`) for spawned `TextLogic`/`DecisionLogic` invokes and
109
- * lowers each into an {@link AgentStepRequest}. The hand-passed-schemas
110
- * implementation detail behind the public {@link getAgentRequests} — it needs
111
- * `schemas`/`actors` passed explicitly, whereas `getAgentRequests`
112
- * pre-fills them from the machine's registered `setupAgent` options.
109
+ * lowers each into an {@link AgentStepRequest}. Pass `options.machine` to
110
+ * pre-fill `schemas`/`actors` from the machine's registered `setupAgent`
111
+ * options instead of passing them by hand.
113
112
  * `options.snapshot` is required to resolve a decision's candidate events
114
113
  * (intersecting declared `allowedEvents` with what's currently legal) — omit
115
114
  * it and decision requests report an empty `events` list.
116
115
  *
117
116
  * @internal
118
117
  */
119
- function getAgentRequestsWith(actions, options = {}) {
118
+ function getAgentRequests(actions, { machine, ...options } = {}) {
119
+ if (machine) options = {
120
+ ...getRegisteredAgentExecutionOptions(machine),
121
+ ...options
122
+ };
120
123
  return actions.flatMap((action) => {
121
124
  const params = getInvokeEffectMetadata(action);
122
125
  if (!params || typeof params.src !== "string") return [];
@@ -217,7 +220,7 @@ function resolveAgentStep(machine, step, request, output, options) {
217
220
  const [snapshot, actions] = transitionResult(machine, step.snapshot, request, output);
218
221
  return createAgentStep(machine, snapshot, actions, getRegisteredAgentExecutionOptions(machine, options));
219
222
  }
220
- async function executeAgentRequest(requestOrEffect, executors, options) {
223
+ async function executeAgentRequest(requestOrEffect, executors) {
221
224
  if (requestOrEffect.kind === "decision") throw new Error("executeAgentRequest(...) is text-only. Resolve a 'decision' request with resolveDecision(request, executors.decide, ...) instead.");
222
225
  const request = "requestId" in requestOrEffect ? {
223
226
  kind: "text",
@@ -230,11 +233,10 @@ async function executeAgentRequest(requestOrEffect, executors, options) {
230
233
  } : requestOrEffect;
231
234
  assertTextExecutor(request, executors);
232
235
  const { output, raw } = await executeAgentTextRequest(request.mode ?? "generate", request.id, request.input, executors, request.tools);
233
- const normalizedOutput = request.input.outputSchema ? validateSchemaSync(request.input.outputSchema, output) : output;
234
- return options?.verbose ? {
235
- output: normalizedOutput,
236
+ return {
237
+ output: request.input.outputSchema ? validateSchemaSync(request.input.outputSchema, output) : output,
236
238
  raw
237
- } : normalizedOutput;
239
+ };
238
240
  }
239
241
  function assertTextExecutor(request, executors) {
240
242
  const mode = request.mode ?? "generate";
@@ -246,7 +248,7 @@ function createAgentStep(machine, snapshot, actions, options) {
246
248
  return {
247
249
  snapshot,
248
250
  actions,
249
- requests: getAgentRequestsWith(actions, {
251
+ requests: getAgentRequests(actions, {
250
252
  ...options,
251
253
  snapshot
252
254
  }),
@@ -327,26 +329,6 @@ const AGENT_INIT_EVENT_TYPE = "@agent.init";
327
329
  */
328
330
  const AGENT_USAGE_EVENT_TYPE = "@agent.usage";
329
331
  /**
330
- * Reads a settled call's token usage off a RAW executor result — the same
331
- * normalization `runAgent` applies before it delivers
332
- * {@link AGENT_USAGE_EVENT_TYPE}. Returns `undefined` when the executor
333
- * reported none.
334
- *
335
- * The seam for the step-loop path, where the host holds the raw result itself:
336
- *
337
- * ```ts
338
- * const { output, raw } = await executeAgentRequest(effect, executors, { verbose: true });
339
- * const usage = getCallUsage(raw);
340
- * if (usage) append({ type: AGENT_USAGE_EVENT_TYPE, usage }); // journal + transition, like any event
341
- * append(effect.toDoneEvent(output));
342
- * ```
343
- *
344
- * See "Token usage on this path" in docs/steps.md for the full loop.
345
- */
346
- function getCallUsage(raw) {
347
- return extractCallUsage(raw);
348
- }
349
- /**
350
332
  * Creates a JSON-safe, self-describing entry and records the state/effect
351
333
  * hashes produced after replaying it. `entries` must be the complete prefix.
352
334
  */
@@ -374,7 +356,6 @@ function createReplayEntry(machine, entries, event, options = {}) {
374
356
  });
375
357
  entry.verification = replayVerification(result.snapshot, result.effects);
376
358
  }
377
- assertAgentLogEntry(entry);
378
359
  return entry;
379
360
  }
380
361
  /** Reserved first replay entry carrying machine input and verification hashes. */
@@ -527,14 +508,15 @@ function buildInvokeEffect(meta, mapped, events, snapshot, options) {
527
508
  function getAgentEffects(machine, snapshot, actions, options = {}) {
528
509
  const resolved = getRegisteredAgentExecutionOptions(machine, options);
529
510
  const events = toEvents(options.history);
530
- const requests = getAgentRequestsWith(actions, {
511
+ const rawActions = actions;
512
+ const requests = getAgentRequests(rawActions, {
531
513
  ...resolved,
532
514
  snapshot
533
515
  });
534
516
  const requestById = new Map(requests.map((request) => [request.id, request]));
535
517
  const effects = [];
536
518
  const emitted = /* @__PURE__ */ new Set();
537
- for (const rawAction of actions) {
519
+ for (const rawAction of rawActions) {
538
520
  const meta = getInvokeEffectMetadata(rawAction);
539
521
  if (meta) {
540
522
  const effect = buildInvokeEffect(meta, typeof meta.id === "string" ? requestById.get(meta.id) : void 0, events, snapshot, resolved);
@@ -626,45 +608,48 @@ var AgentReplayDivergenceError = class extends AgentError {
626
608
  * Raised/internal events are never in the journal — replay re-derives them
627
609
  * deterministically from the machine's own logic.
628
610
  */
629
- function replay(machine, entries, options = {}) {
630
- const machineId = machine.config.id ?? machine.id ?? "(machine)";
631
- const machineVersion = options.machineVersion ?? getMachineStructuralHash(machine);
611
+ /**
612
+ * Validates a replay entry sequence: envelope shape, contiguity from index 0,
613
+ * unique event ids, and machine identity.
614
+ *
615
+ * @internal
616
+ */
617
+ function validateReplayEntries(entries, expected, label) {
632
618
  const eventIds = /* @__PURE__ */ new Set();
633
619
  for (let index = 0; index < entries.length; index++) {
634
620
  const entry = entries[index];
635
621
  assertAgentLogEntry(entry);
636
- if (entry.index !== index) throw new Error(`Replay entries must be contiguous from index 0; found entry.index ${entry.index} at position ${index}.`);
637
- if (eventIds.has(entry.id)) throw new Error(`Replay entries contain duplicate event id '${entry.id}'.`);
622
+ if (entry.index !== index) throw new Error(`${label} must be contiguous from index 0; found entry.index ${entry.index} at position ${index}.`);
623
+ if (eventIds.has(entry.id)) throw new Error(`${label} contain duplicate event id '${entry.id}'.`);
638
624
  eventIds.add(entry.id);
639
- if (entry.machineId !== machineId || entry.machineVersion !== machineVersion) throw new AgentReplayMachineMismatchError(entry.id, entry.index, {
640
- machineId,
641
- machineVersion
642
- }, {
625
+ if (entry.machineId !== expected.machineId || entry.machineVersion !== expected.machineVersion) throw new AgentReplayMachineMismatchError(entry.id, entry.index, expected, {
643
626
  machineId: entry.machineId,
644
627
  machineVersion: entry.machineVersion
645
628
  });
646
629
  }
630
+ }
631
+ function replay(machine, entries, options = {}) {
632
+ validateReplayEntries(entries, {
633
+ machineId: machine.config.id ?? machine.id ?? "(machine)",
634
+ machineVersion: options.machineVersion ?? getMachineStructuralHash(machine)
635
+ }, "Replay entries");
647
636
  const events = toEvents(entries);
648
- let input = options.input;
649
- let journal = events;
650
- let journalEntries = entries;
651
- if (events[0]?.type === "@agent.init") {
652
- input = events[0].input;
653
- journal = events.slice(1);
654
- journalEntries = entries.slice(1);
655
- }
637
+ const initOffset = events[0]?.type === "@agent.init" ? 1 : 0;
638
+ const input = initOffset ? events[0].input : options.input;
639
+ const journal = events.slice(initOffset);
640
+ const journalEntries = entries.slice(initOffset);
656
641
  let [snapshot, actions] = initialTransition(machine, input);
657
642
  let effects = getAgentEffects(machine, snapshot, actions, {
658
643
  ...options,
659
- history: entries.slice(0, events[0]?.type === "@agent.init" ? 1 : 0)
644
+ history: entries.slice(0, initOffset)
660
645
  });
661
- if (events[0]?.type === "@agent.init") verifyEntry(entries[0], snapshot, effects, options.verify);
646
+ if (initOffset) verifyEntry(entries[0], snapshot, effects, options.verify);
662
647
  const sessions = /* @__PURE__ */ new Map();
663
648
  for (let index = 0; index < journal.length; index++) {
664
649
  const event = journal[index];
665
650
  const reboundEvent = rebindActorSession(event, snapshot, sessions);
666
651
  [snapshot, actions] = transition(machine, snapshot, reboundEvent);
667
- const consumed = entries.slice(0, entries.length - journalEntries.length + index + 1);
652
+ const consumed = entries.slice(0, initOffset + index + 1);
668
653
  effects = getAgentEffects(machine, snapshot, actions, {
669
654
  ...options,
670
655
  history: consumed
@@ -816,10 +801,7 @@ function sortJson(value) {
816
801
  return value;
817
802
  }
818
803
  function hashStableJson(value) {
819
- const input = stableJson(value);
820
- let hash = 5381;
821
- for (let index = 0; index < input.length; index++) hash = (hash << 5) + hash + input.charCodeAt(index) | 0;
822
- return (hash >>> 0).toString(16).padStart(8, "0");
804
+ return djb2Hex(stableJson(value));
823
805
  }
824
806
  function diffJson(before, after, path = "") {
825
807
  if (stableJson(before) === stableJson(after)) return [];
@@ -893,6 +875,9 @@ const DECIDE_SRC = "agent.decide";
893
875
  const workflowConfigWholeExpressionPattern = /^\{\{\s*([\s\S]*?)\s*\}\}$/;
894
876
  const workflowConfigTemplateExpressionPattern = /\{\{\s*([\s\S]*?)\s*\}\}/g;
895
877
  const workflowConfigHasTemplatePattern = /\{\{[\s\S]*?\}\}/;
878
+ function toArray(value) {
879
+ return Array.isArray(value) ? value : [value];
880
+ }
896
881
  function evaluateWorkflowConfigPath(expression, scope) {
897
882
  const parts = expression.trim().split(".").filter(Boolean);
898
883
  let current = scope;
@@ -926,6 +911,7 @@ function createSchemasFromWorkflowConfig(config, compileSchema) {
926
911
  });
927
912
  }
928
913
  function createRequestsFromWorkflowConfig(config, compileSchema) {
914
+ const resolver = (value) => value === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(value, { input });
929
915
  return Object.fromEntries(Object.entries(config.requests ?? {}).map(([key, request]) => [key, {
930
916
  mode: request.mode,
931
917
  description: request.description,
@@ -934,19 +920,19 @@ function createRequestsFromWorkflowConfig(config, compileSchema) {
934
920
  output: compileSchema(request.output, `${key}.output`)
935
921
  },
936
922
  model: ({ input }) => String(evaluateWorkflowConfigValue(request.model, { input }) ?? ""),
937
- system: request.system === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.system, { input }),
938
- prompt: request.prompt === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.prompt, { input }),
939
- messages: request.messages === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.messages, { input }),
923
+ system: resolver(request.system),
924
+ prompt: resolver(request.prompt),
925
+ messages: resolver(request.messages),
940
926
  tools: request.tools,
941
927
  toolChoice: request.toolChoice,
942
928
  reasoning: request.reasoning,
943
- temperature: request.temperature === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.temperature, { input }),
944
- maxOutputTokens: request.maxOutputTokens === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.maxOutputTokens, { input }),
945
- topP: request.topP === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.topP, { input }),
946
- topK: request.topK === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.topK, { input }),
947
- seed: request.seed === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.seed, { input }),
948
- stopSequences: request.stopSequences === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.stopSequences, { input }),
949
- metadata: request.metadata === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(request.metadata, { input })
929
+ temperature: resolver(request.temperature),
930
+ maxOutputTokens: resolver(request.maxOutputTokens),
931
+ topP: resolver(request.topP),
932
+ topK: resolver(request.topK),
933
+ seed: resolver(request.seed),
934
+ stopSequences: resolver(request.stopSequences),
935
+ metadata: resolver(request.metadata)
950
936
  }]));
951
937
  }
952
938
  function createActorPlaceholdersFromWorkflowConfig(config) {
@@ -1012,7 +998,7 @@ function translateWorkflowAction(action, translation, location) {
1012
998
  throw new Error(`setupAgent.fromConfig: ${location} action must declare 'assign', 'emit', or 'type'.`);
1013
999
  }
1014
1000
  function translateWorkflowTransition(transitionConfig, translation, location) {
1015
- const actionConfigs = transitionConfig.actions ? Array.isArray(transitionConfig.actions) ? transitionConfig.actions : [transitionConfig.actions] : [];
1001
+ const actionConfigs = transitionConfig.actions ? toArray(transitionConfig.actions) : [];
1016
1002
  const assignConfigs = [...transitionConfig.assign !== void 0 ? [transitionConfig.assign] : [], ...actionConfigs.filter((action) => action.assign !== void 0).map((action) => action.assign)];
1017
1003
  const contextPatch = assignConfigs.length ? toWorkflowExpression(Object.assign({}, ...assignConfigs)) : void 0;
1018
1004
  const actions = actionConfigs.filter((action) => action.assign === void 0).map((action) => translateWorkflowAction(action, translation, location));
@@ -1054,9 +1040,8 @@ function translateWorkflowInvoke(invokeConfig, translation, stateKey) {
1054
1040
  }
1055
1041
  function assertValidTransitionTargets(stateKey, location, transitionConfig, siblingKeys, declaredTargets) {
1056
1042
  if (!transitionConfig) return;
1057
- const transitions = Array.isArray(transitionConfig) ? transitionConfig : [transitionConfig];
1058
- for (const transition of transitions) {
1059
- const targets = transition.target === void 0 ? [] : Array.isArray(transition.target) ? transition.target : [transition.target];
1043
+ for (const transition of toArray(transitionConfig)) {
1044
+ const targets = transition.target === void 0 ? [] : toArray(transition.target);
1060
1045
  for (const target of targets) {
1061
1046
  if (typeof target !== "string") continue;
1062
1047
  declaredTargets.push(target);
@@ -1068,16 +1053,16 @@ function assertValidTransitionTargets(stateKey, location, transitionConfig, sibl
1068
1053
  }
1069
1054
  function assertStateTransitionTargets(stateKey, stateConfig, siblingKeys) {
1070
1055
  const declaredTargets = [];
1071
- for (const [eventType, transition] of Object.entries(stateConfig.on ?? {})) assertValidTransitionTargets(stateKey, `'on.${eventType}'`, transition, siblingKeys, declaredTargets);
1072
- for (const [delay, transition] of Object.entries(stateConfig.after ?? {})) assertValidTransitionTargets(stateKey, `'after.${delay}'`, transition, siblingKeys, declaredTargets);
1073
- assertValidTransitionTargets(stateKey, "'always'", stateConfig.always, siblingKeys, declaredTargets);
1074
- assertValidTransitionTargets(stateKey, "'onDone'", stateConfig.onDone, siblingKeys, declaredTargets);
1075
- assertValidTransitionTargets(stateKey, "'choice'", stateConfig.choice, siblingKeys, declaredTargets);
1076
- const invokes = stateConfig.invoke ? Array.isArray(stateConfig.invoke) ? stateConfig.invoke : [stateConfig.invoke] : [];
1077
- for (const invoke of invokes) {
1078
- assertValidTransitionTargets(stateKey, "invoke 'onDone'", invoke.onDone, siblingKeys, declaredTargets);
1079
- assertValidTransitionTargets(stateKey, "invoke 'onError'", invoke.onError, siblingKeys, declaredTargets);
1080
- }
1056
+ const invokes = stateConfig.invoke ? toArray(stateConfig.invoke) : [];
1057
+ const sources = [
1058
+ ...Object.entries(stateConfig.on ?? {}).map(([eventType, transition]) => [`'on.${eventType}'`, transition]),
1059
+ ...Object.entries(stateConfig.after ?? {}).map(([delay, transition]) => [`'after.${delay}'`, transition]),
1060
+ ["'always'", stateConfig.always],
1061
+ ["'onDone'", stateConfig.onDone],
1062
+ ["'choice'", stateConfig.choice],
1063
+ ...invokes.flatMap((invoke) => [["invoke 'onDone'", invoke.onDone], ["invoke 'onError'", invoke.onError]])
1064
+ ];
1065
+ for (const [location, transition] of sources) assertValidTransitionTargets(stateKey, location, transition, siblingKeys, declaredTargets);
1081
1066
  return declaredTargets;
1082
1067
  }
1083
1068
  function translateWorkflowState(stateKey, stateConfig, siblingKeys, path, translation) {
@@ -1097,7 +1082,7 @@ function translateWorkflowState(stateKey, stateConfig, siblingKeys, path, transl
1097
1082
  ...doneStateId ? { id: doneStateId } : {},
1098
1083
  ...stateConfig.initial !== void 0 ? { initial: stateConfig.initial } : {},
1099
1084
  ...stateConfig.states !== void 0 ? { states: Object.fromEntries(Object.entries(stateConfig.states).map(([key, child]) => [key, translateWorkflowState(key, child, childKeys, childPath, translation)])) } : {},
1100
- ...stateConfig.choice !== void 0 ? { choice: (Array.isArray(stateConfig.choice) ? stateConfig.choice : [stateConfig.choice]).map((branch) => {
1085
+ ...stateConfig.choice !== void 0 ? { choice: toArray(stateConfig.choice).map((branch) => {
1101
1086
  if (branch.actions !== void 0) throw new Error(`setupAgent.fromConfig: state '${stateKey}' has a 'choice' branch with 'actions', which is not supported. Use 'assign' on the branch, or move the actions to the target state's 'entry'.`);
1102
1087
  const when = translateWorkflowGuard(branch.guard, translation, location);
1103
1088
  return {
@@ -1113,8 +1098,8 @@ function translateWorkflowState(stateKey, stateConfig, siblingKeys, path, transl
1113
1098
  ...Object.keys(translatedOn).length ? { on: translatedOn } : {},
1114
1099
  ...stateConfig.always !== void 0 ? { always: translateWorkflowTransitions(stateConfig.always, translation, location) } : {},
1115
1100
  ...stateConfig.after !== void 0 ? { after: Object.fromEntries(Object.entries(stateConfig.after).map(([delay, transitionConfig]) => [delay, translateWorkflowTransitions(transitionConfig, translation, location)])) } : {},
1116
- ...stateConfig.entry !== void 0 ? { entry: (Array.isArray(stateConfig.entry) ? stateConfig.entry : [stateConfig.entry]).map((action) => translateWorkflowAction(action, translation, location)) } : {},
1117
- ...stateConfig.exit !== void 0 ? { exit: (Array.isArray(stateConfig.exit) ? stateConfig.exit : [stateConfig.exit]).map((action) => translateWorkflowAction(action, translation, location)) } : {},
1101
+ ...stateConfig.entry !== void 0 ? { entry: toArray(stateConfig.entry).map((action) => translateWorkflowAction(action, translation, location)) } : {},
1102
+ ...stateConfig.exit !== void 0 ? { exit: toArray(stateConfig.exit).map((action) => translateWorkflowAction(action, translation, location)) } : {},
1118
1103
  ...stateConfig.tags !== void 0 ? { tags: stateConfig.tags } : {},
1119
1104
  ...stateConfig.output !== void 0 ? { output: toWorkflowExpression(stateConfig.output) } : {},
1120
1105
  ...stateConfig.meta !== void 0 ? { meta: stateConfig.meta } : {}
@@ -1143,6 +1128,22 @@ function translateWorkflowConfig(config, translation) {
1143
1128
  if (json.output === void 0 && finalOutputs.length === 1) json.output = finalOutputs[0];
1144
1129
  return json;
1145
1130
  }
1131
+ function collectDeclaredStateTags(states, tags = /* @__PURE__ */ new Set()) {
1132
+ for (const state of Object.values(states ?? {})) {
1133
+ for (const tag of state.tags ?? []) tags.add(tag);
1134
+ collectDeclaredStateTags(state.states, tags);
1135
+ }
1136
+ return tags;
1137
+ }
1138
+ function resolveSuspensionPredicate(config, options) {
1139
+ if (options.isSuspended) return options.isSuspended;
1140
+ const suspendedTags = config.suspendedTags ?? [];
1141
+ if (!suspendedTags.length) return;
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));
1146
+ }
1146
1147
  function setupAgentFromConfig(config, options) {
1147
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.");
1148
1149
  const { compileSchema } = options;
@@ -1173,6 +1174,8 @@ function setupAgentFromConfig(config, options) {
1173
1174
  models: {}
1174
1175
  });
1175
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);
1176
1179
  return {
1177
1180
  machine,
1178
1181
  schemas
@@ -1226,7 +1229,7 @@ const agentUsageEventSchema = { "~standard": {
1226
1229
  path: ["usage", field]
1227
1230
  });
1228
1231
  }
1229
- if (event.kind !== void 0 && !USAGE_KINDS.includes(event.kind)) issues.push({
1232
+ if (event.kind !== void 0 && !USAGE_KINDS.some((kind) => kind === event.kind)) issues.push({
1230
1233
  message: `Expected one of ${USAGE_KINDS.join(", ")}`,
1231
1234
  path: ["kind"]
1232
1235
  });
@@ -1356,7 +1359,47 @@ function resolveAgentStateSchemas(contextSchema, states) {
1356
1359
  * ```
1357
1360
  */
1358
1361
  function setupAgent(config) {
1359
- return createSetupAgent(config);
1362
+ const schemas = normalizeAgentSchemas(config);
1363
+ const requestActors = createRequestActors(config.requests ?? {});
1364
+ const actors = createAgentActors(config.actors, requestActors);
1365
+ const base = setup({
1366
+ schemas: {
1367
+ context: schemas.context,
1368
+ events: schemas.events,
1369
+ input: schemas.input,
1370
+ output: schemas.output,
1371
+ meta: schemas.meta,
1372
+ ...schemas.emitted && Object.keys(schemas.emitted).length > 0 ? { emitted: schemas.emitted } : {}
1373
+ },
1374
+ ...config.states ? { states: resolveAgentStateSchemas(schemas.context, config.states) } : {},
1375
+ actors,
1376
+ actions: config.actions,
1377
+ guards: config.guards,
1378
+ delays: config.delays
1379
+ });
1380
+ const createBaseMachine = base.createMachine.bind(base);
1381
+ const models = config.models ?? {};
1382
+ const machineOptions = {
1383
+ schemas,
1384
+ actors,
1385
+ models
1386
+ };
1387
+ return Object.assign(base, {
1388
+ createMachine(machineConfig) {
1389
+ assertStateSchemaKeysExist(config.states, machineConfig?.states);
1390
+ const machine = createBaseMachine(withRootOutputFromSingleFinal(machineConfig));
1391
+ agentExecutionOptions.set(machine, machineOptions);
1392
+ if (config.isSuspended) {
1393
+ const rootConfig = machine.config;
1394
+ if (rootConfig) machineSuspensionPredicates.set(rootConfig, config.isSuspended);
1395
+ }
1396
+ return machine;
1397
+ },
1398
+ schemas,
1399
+ models,
1400
+ requests: requestActors,
1401
+ appendMessages
1402
+ });
1360
1403
  }
1361
1404
  function collectFinalStateOutputs(states, outputs = []) {
1362
1405
  for (const state of Object.values(states ?? {})) {
@@ -1400,24 +1443,6 @@ function normalizeAgentSchemas(config) {
1400
1443
  context: loose.context
1401
1444
  });
1402
1445
  }
1403
- function normalizeAgentRequestInput(requests) {
1404
- return requests ?? {};
1405
- }
1406
- /**
1407
- * Runtime guard: a key appearing in both `actors`/`requests` is almost
1408
- * certainly a mistake (whichever spread applies last would silently win) —
1409
- * fail fast with a clear message rather than let one implementation shadow
1410
- * another.
1411
- */
1412
- function assertNoActorKeyCollisions(actors, requests) {
1413
- const seenIn = /* @__PURE__ */ new Map();
1414
- const groups = [["actors", actors], ["requests", requests]];
1415
- for (const [groupName, group] of groups) for (const key of Object.keys(group ?? {})) {
1416
- const existingGroup = seenIn.get(key);
1417
- 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'.`);
1418
- seenIn.set(key, groupName);
1419
- }
1420
- }
1421
1446
  /**
1422
1447
  * Runtime guard: every key of the `setupAgent({ states })` narrowing map must
1423
1448
  * name a real state node in the machine config. A typo'd key is otherwise a
@@ -1443,20 +1468,30 @@ const RESERVED_AGENT_ACTOR_KEYS = [
1443
1468
  DECIDE_ACTOR
1444
1469
  ];
1445
1470
  /**
1446
- * Rejects a user-supplied `actors`/`requests` key in the reserved
1447
- * `agent.*` builtin namespace. Without this, the builtins-first spread in
1448
- * {@link createAgentActors} lets such a key overwrite the builtin
1449
- * (`agent.decide`, …) silently. Deliberate override of a builtin
1450
- * is still possible after the machine is created, via
1451
- * `machine.provide({ actors: { 'agent.decide': ... } })`.
1471
+ * Runtime guards over the user-supplied `actors`/`requests` keys, in one walk
1472
+ * of both groups:
1473
+ *
1474
+ * 1. A key in the reserved `agent.*` builtin namespace is rejected. Without
1475
+ * this, the builtins-first spread in {@link createAgentActors} lets such a
1476
+ * key overwrite the builtin (`agent.decide`, …) silently. Deliberate
1477
+ * override of a builtin is still possible after the machine is created, via
1478
+ * `machine.provide({ actors: { 'agent.decide': ... } })`.
1479
+ * 2. A key appearing in BOTH groups is almost certainly a mistake (whichever
1480
+ * spread applies last would silently win) — fail fast with a clear message
1481
+ * rather than let one implementation shadow another.
1452
1482
  */
1453
- function assertNoReservedAgentKeys(actors, requests) {
1483
+ function assertActorKeys(actors, requests) {
1484
+ const seenIn = /* @__PURE__ */ new Map();
1454
1485
  const groups = [["actors", actors], ["requests", requests]];
1455
- for (const [groupName, group] of groups) for (const key of Object.keys(group ?? {})) if (RESERVED_AGENT_ACTOR_KEYS.includes(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}': ... } }).`);
1486
+ for (const [groupName, group] of groups) for (const key of Object.keys(group ?? {})) {
1487
+ 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}': ... } }).`);
1488
+ const existingGroup = seenIn.get(key);
1489
+ 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'.`);
1490
+ seenIn.set(key, groupName);
1491
+ }
1456
1492
  }
1457
1493
  function createAgentActors(actors, requestActors) {
1458
- assertNoActorKeyCollisions(actors, requestActors);
1459
- assertNoReservedAgentKeys(actors, requestActors);
1494
+ assertActorKeys(actors, requestActors);
1460
1495
  return {
1461
1496
  ...builtinTextActors,
1462
1497
  [USER_INPUT_ACTOR]: userInputActor,
@@ -1465,53 +1500,5 @@ function createAgentActors(actors, requestActors) {
1465
1500
  ...requestActors
1466
1501
  };
1467
1502
  }
1468
- function createAgentSetupConfig(schemas, actors, config) {
1469
- return {
1470
- schemas: {
1471
- context: schemas.context,
1472
- events: schemas.events,
1473
- input: schemas.input,
1474
- output: schemas.output,
1475
- meta: schemas.meta,
1476
- ...schemas.emitted && Object.keys(schemas.emitted).length > 0 ? { emitted: schemas.emitted } : {}
1477
- },
1478
- ...config.states ? { states: resolveAgentStateSchemas(schemas.context, config.states) } : {},
1479
- actors,
1480
- actions: config.actions,
1481
- guards: config.guards,
1482
- delays: config.delays
1483
- };
1484
- }
1485
- function createSetupAgent(config) {
1486
- const schemas = normalizeAgentSchemas(config);
1487
- const requestActors = createRequestActors(normalizeAgentRequestInput(config.requests));
1488
- const actors = createAgentActors(config.actors, requestActors);
1489
- const base = setup(createAgentSetupConfig(schemas, actors, config));
1490
- const createBaseMachine = base.createMachine.bind(base);
1491
- const models = config.models ?? {};
1492
- const machineOptions = {
1493
- schemas,
1494
- actors,
1495
- models
1496
- };
1497
- return Object.assign(base, {
1498
- createMachine(machineConfig) {
1499
- assertStateSchemaKeysExist(config.states, machineConfig?.states);
1500
- const machine = createBaseMachine(withRootOutputFromSingleFinal(machineConfig));
1501
- agentExecutionOptions.set(machine, machineOptions);
1502
- if (config.isSuspended) {
1503
- const rootConfig = machine.config;
1504
- if (rootConfig) machineSuspensionPredicates.set(rootConfig, config.isSuspended);
1505
- }
1506
- return machine;
1507
- },
1508
- schemas,
1509
- models,
1510
- requests: requestActors,
1511
- appendMessages(resolve) {
1512
- return appendMessages(resolve);
1513
- }
1514
- });
1515
- }
1516
1503
  //#endregion
1517
- export { resolveAgentStep as _, AgentReplayDivergenceError as a, messagesSchema as b, diffEventLogs as c, initEntry as d, replay as f, initialAgentStep as g, getInvokeEffectMetadata as h, AGENT_USAGE_EVENT_TYPE as i, getAgentEffects as l, executeAgentRequest as m, setupAgent as n, AgentReplayMachineMismatchError as o, verifyReplay as p, AGENT_INIT_EVENT_TYPE as r, createReplayEntry as s, createAgentSchemas as t, getCallUsage as u, transitionAgentStep as v, appendMessages as y };
1504
+ export { resolveAgentStep as _, AgentReplayDivergenceError as a, messagesSchema as b, diffEventLogs as c, replay as d, validateReplayEntries as f, initialAgentStep as g, getInvokeEffectMetadata as h, AGENT_USAGE_EVENT_TYPE as i, getAgentEffects as l, executeAgentRequest as m, setupAgent as n, AgentReplayMachineMismatchError as o, verifyReplay as p, AGENT_INIT_EVENT_TYPE as r, createReplayEntry as s, createAgentSchemas as t, initEntry as u, transitionAgentStep as v, appendMessages as y };