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

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 (54) hide show
  1. package/dist/ai-sdk.cjs +4 -4
  2. package/dist/ai-sdk.d.cts +6 -6
  3. package/dist/ai-sdk.d.mts +6 -6
  4. package/dist/ai-sdk.mjs +4 -4
  5. package/dist/{decision-CM9CYZ6t.cjs → decision-CmM8-HHz.cjs} +10 -9
  6. package/dist/{decision-DzSv1NpD.mjs → decision-RQ0iv0oZ.mjs} +10 -9
  7. package/dist/{event-log-store-Ba2fsc4E.mjs → event-log-store-2pAFiWuc.mjs} +1 -1
  8. package/dist/{event-log-store-DvOcs10J.d.cts → event-log-store-2xzFmgr2.d.cts} +1 -1
  9. package/dist/{event-log-store-DxyVgnas.d.mts → event-log-store-BIPOz-di.d.mts} +1 -1
  10. package/dist/{event-log-store-DQmImLYk.cjs → event-log-store-C-COhIXP.cjs} +1 -1
  11. package/dist/index.cjs +13 -195
  12. package/dist/index.d.cts +25 -105
  13. package/dist/index.d.mts +25 -105
  14. package/dist/index.mjs +12 -189
  15. package/dist/log.cjs +1 -1
  16. package/dist/log.d.cts +1 -1
  17. package/dist/log.d.mts +1 -1
  18. package/dist/log.mjs +1 -1
  19. package/dist/machines.cjs +4 -7
  20. package/dist/machines.d.cts +5 -7
  21. package/dist/machines.d.mts +5 -7
  22. package/dist/machines.mjs +4 -7
  23. package/dist/openai.cjs +3 -3
  24. package/dist/openai.d.cts +5 -5
  25. package/dist/openai.d.mts +5 -5
  26. package/dist/openai.mjs +3 -3
  27. package/dist/otel.cjs +2 -2
  28. package/dist/otel.d.cts +3 -3
  29. package/dist/otel.d.mts +3 -3
  30. package/dist/otel.mjs +2 -2
  31. package/dist/{run-agent-CG343kFs.d.mts → run-agent-ByO-Bxyd.d.cts} +184 -179
  32. package/dist/{run-agent-BOfoJg5B.d.cts → run-agent-COXXc0RW.d.mts} +184 -179
  33. package/dist/{run-agent-Cb1-LS5P.cjs → run-agent-Dmf8GV2d.cjs} +539 -737
  34. package/dist/{run-agent-DvDQd4If.mjs → run-agent-xNTxpt82.mjs} +537 -705
  35. package/dist/{setup-agent-CFW-jPI8.mjs → setup-agent-BuanDXeh.mjs} +6 -28
  36. package/dist/{setup-agent-CPf7MxnG.cjs → setup-agent-DV4cTou-.cjs} +6 -28
  37. package/dist/testing.cjs +276 -27
  38. package/dist/testing.d.cts +17 -15
  39. package/dist/testing.d.mts +17 -15
  40. package/dist/testing.mjs +260 -12
  41. package/dist/{text-logic-Bl_ZRxDi.mjs → text-logic-CIqHAmBi.mjs} +10 -26
  42. package/dist/{text-logic-BFEOxyxv.d.cts → text-logic-D-czVPYp.d.mts} +27 -28
  43. package/dist/{text-logic-hZSiRUo1.d.mts → text-logic-IjfYy9DP.d.cts} +27 -28
  44. package/dist/{text-logic-C8xyr6Ag.cjs → text-logic-f5F5sCdc.cjs} +9 -43
  45. package/dist/{types-B1Qs2q3q.d.cts → types-BgNbNKnJ.d.mts} +3 -3
  46. package/dist/{types-tA3SdczG.d.mts → types-hR5f5YXa.d.cts} +3 -3
  47. package/dist/{utils-C2DPqomn.d.mts → utils-_q7F-AZu.d.mts} +2 -2
  48. package/dist/{utils-ceStNCOh.d.cts → utils-o4YRdHJX.d.cts} +2 -2
  49. package/dist/validate.cjs +0 -8
  50. package/dist/validate.mjs +0 -8
  51. package/package.json +3 -3
  52. package/readme.md +26 -18
  53. package/schemas/agent-workflow.json +0 -8
  54. package/skills/generate-machine/SKILL.md +6 -8
@@ -1,5 +1,5 @@
1
- import { E as setAgentExecutionOptions, T as missingActor, V as validateSchemaSync, b as getAgentExecutionOptions, n as DECIDE_ACTOR, o as builtinTextActors, s as createTextLogic, w as machineIdlePredicates } from "./text-logic-Bl_ZRxDi.mjs";
2
- import { n as createDecideActor } from "./decision-DzSv1NpD.mjs";
1
+ import { C as setAgentExecutionOptions, R as validateSchemaSync, S as missingActor, n as DECIDE_ACTOR, o as builtinTextActors, s as createTextLogic, y as getAgentExecutionOptions } from "./text-logic-CIqHAmBi.mjs";
2
+ import { n as createDecideActor } from "./decision-RQ0iv0oZ.mjs";
3
3
  import { t as AGENT_USAGE_EVENT_TYPE } from "./usage-BdEjFuIi.mjs";
4
4
  import { createMachineFromConfig, setup } from "xstate";
5
5
  //#region src/workflow-config.ts
@@ -273,22 +273,6 @@ function translateWorkflowConfig(config, translation) {
273
273
  if (json.output === void 0 && finalOutputs.length === 1) json.output = finalOutputs[0];
274
274
  return json;
275
275
  }
276
- function collectDeclaredStateTags(states, tags = /* @__PURE__ */ new Set()) {
277
- for (const state of Object.values(states ?? {})) {
278
- for (const tag of state.tags ?? []) tags.add(tag);
279
- collectDeclaredStateTags(state.states, tags);
280
- }
281
- return tags;
282
- }
283
- function resolveIdlePredicate(config, options) {
284
- if (options.isIdle) return options.isIdle;
285
- const idleTags = config.idleTags ?? [];
286
- if (!idleTags.length) return;
287
- const declaredTags = collectDeclaredStateTags(config.states);
288
- const unknown = idleTags.filter((tag) => !declaredTags.has(tag));
289
- 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.`);
290
- return (snapshot) => idleTags.some((tag) => snapshot.hasTag(tag));
291
- }
292
276
  function setupAgentFromConfig(config, options) {
293
277
  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.");
294
278
  const { compileSchema } = options;
@@ -310,16 +294,14 @@ function setupAgentFromConfig(config, options) {
310
294
  event: args.event
311
295
  }))])),
312
296
  ...options.actions ? { actions: options.actions } : {},
313
- actors: Object.fromEntries(Object.keys(actors).map((key) => [key, key])),
297
+ actors,
314
298
  evaluators: { [AGENT_EXPRESSION_LANG]: createWorkflowConfigEvaluator(schemas.context) }
315
- }).provide({ actors });
299
+ });
316
300
  setAgentExecutionOptions(machine, {
317
301
  schemas,
318
302
  actors,
319
303
  models: {}
320
304
  });
321
- const isIdle = resolveIdlePredicate(config, options);
322
- if (isIdle && machine.config) machineIdlePredicates.set(machine.config, isIdle);
323
305
  return {
324
306
  machine,
325
307
  schemas
@@ -388,7 +370,7 @@ const agentUsageEventSchema = { "~standard": {
388
370
  * Adds the reserved `'@agent.usage'` schema to an authored event map. A
389
371
  * user-declared entry under that key is rejected: the `@agent.*` namespace
390
372
  * belongs to the library (same rule as the reserved `agent.*` actor keys), and
391
- * a custom payload schema would silently disagree with what `runAgent`
373
+ * a custom payload schema would silently disagree with what the runtime
392
374
  * delivers.
393
375
  */
394
376
  function withAgentUsageEventSchema(events) {
@@ -423,7 +405,7 @@ function createAgentSchemas(schemas) {
423
405
  /**
424
406
  * Schema-first `setup(...)` for agent machines — the standard entry point
425
407
  * for authoring a machine (the blueprint) that this library then runs (via
426
- * {@link runAgent} or the step helpers) against host-supplied model/decision
408
+ * {@link createAgentRuntime}) against host-supplied model/decision
427
409
  * executors. Context, events, machine input, machine output, and
428
410
  * state/transition meta are all standard schemas — no `{} as Type` casts —
429
411
  * and are retained on `result.schemas` for runtime validation. Also
@@ -496,10 +478,6 @@ function setupAgent(config) {
496
478
  assertStateSchemaKeysExist(config.states, machineConfig?.states);
497
479
  const machine = createBaseMachine(withRootOutputFromSingleFinal(machineConfig));
498
480
  setAgentExecutionOptions(machine, machineOptions);
499
- if (config.isIdle) {
500
- const rootConfig = machine.config;
501
- if (rootConfig) machineIdlePredicates.set(rootConfig, config.isIdle);
502
- }
503
481
  return machine;
504
482
  },
505
483
  schemas,
@@ -1,5 +1,5 @@
1
- const require_text_logic = require("./text-logic-C8xyr6Ag.cjs");
2
- const require_decision = require("./decision-CM9CYZ6t.cjs");
1
+ const require_text_logic = require("./text-logic-f5F5sCdc.cjs");
2
+ const require_decision = require("./decision-CmM8-HHz.cjs");
3
3
  const require_usage = require("./usage-efOQPdf_.cjs");
4
4
  require("./validate.cjs");
5
5
  let xstate = require("xstate");
@@ -274,22 +274,6 @@ function translateWorkflowConfig(config, translation) {
274
274
  if (json.output === void 0 && finalOutputs.length === 1) json.output = finalOutputs[0];
275
275
  return json;
276
276
  }
277
- function collectDeclaredStateTags(states, tags = /* @__PURE__ */ new Set()) {
278
- for (const state of Object.values(states ?? {})) {
279
- for (const tag of state.tags ?? []) tags.add(tag);
280
- collectDeclaredStateTags(state.states, tags);
281
- }
282
- return tags;
283
- }
284
- function resolveIdlePredicate(config, options) {
285
- if (options.isIdle) return options.isIdle;
286
- const idleTags = config.idleTags ?? [];
287
- if (!idleTags.length) return;
288
- const declaredTags = collectDeclaredStateTags(config.states);
289
- const unknown = idleTags.filter((tag) => !declaredTags.has(tag));
290
- 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.`);
291
- return (snapshot) => idleTags.some((tag) => snapshot.hasTag(tag));
292
- }
293
277
  function setupAgentFromConfig(config, options) {
294
278
  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.");
295
279
  const { compileSchema } = options;
@@ -311,16 +295,14 @@ function setupAgentFromConfig(config, options) {
311
295
  event: args.event
312
296
  }))])),
313
297
  ...options.actions ? { actions: options.actions } : {},
314
- actors: Object.fromEntries(Object.keys(actors).map((key) => [key, key])),
298
+ actors,
315
299
  evaluators: { [AGENT_EXPRESSION_LANG]: createWorkflowConfigEvaluator(schemas.context) }
316
- }).provide({ actors });
300
+ });
317
301
  require_text_logic.setAgentExecutionOptions(machine, {
318
302
  schemas,
319
303
  actors,
320
304
  models: {}
321
305
  });
322
- const isIdle = resolveIdlePredicate(config, options);
323
- if (isIdle && machine.config) require_text_logic.machineIdlePredicates.set(machine.config, isIdle);
324
306
  return {
325
307
  machine,
326
308
  schemas
@@ -389,7 +371,7 @@ const agentUsageEventSchema = { "~standard": {
389
371
  * Adds the reserved `'@agent.usage'` schema to an authored event map. A
390
372
  * user-declared entry under that key is rejected: the `@agent.*` namespace
391
373
  * belongs to the library (same rule as the reserved `agent.*` actor keys), and
392
- * a custom payload schema would silently disagree with what `runAgent`
374
+ * a custom payload schema would silently disagree with what the runtime
393
375
  * delivers.
394
376
  */
395
377
  function withAgentUsageEventSchema(events) {
@@ -424,7 +406,7 @@ function createAgentSchemas(schemas) {
424
406
  /**
425
407
  * Schema-first `setup(...)` for agent machines — the standard entry point
426
408
  * for authoring a machine (the blueprint) that this library then runs (via
427
- * {@link runAgent} or the step helpers) against host-supplied model/decision
409
+ * {@link createAgentRuntime}) against host-supplied model/decision
428
410
  * executors. Context, events, machine input, machine output, and
429
411
  * state/transition meta are all standard schemas — no `{} as Type` casts —
430
412
  * and are retained on `result.schemas` for runtime validation. Also
@@ -497,10 +479,6 @@ function setupAgent(config) {
497
479
  assertStateSchemaKeysExist(config.states, machineConfig?.states);
498
480
  const machine = createBaseMachine(withRootOutputFromSingleFinal(machineConfig));
499
481
  require_text_logic.setAgentExecutionOptions(machine, machineOptions);
500
- if (config.isIdle) {
501
- const rootConfig = machine.config;
502
- if (rootConfig) require_text_logic.machineIdlePredicates.set(rootConfig, config.isIdle);
503
- }
504
482
  return machine;
505
483
  },
506
484
  schemas,
package/dist/testing.cjs CHANGED
@@ -1,7 +1,253 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_text_logic = require("./text-logic-C8xyr6Ag.cjs");
3
- const require_decision = require("./decision-CM9CYZ6t.cjs");
4
- const require_run_agent = require("./run-agent-Cb1-LS5P.cjs");
2
+ const require_text_logic = require("./text-logic-f5F5sCdc.cjs");
3
+ const require_decision = require("./decision-CmM8-HHz.cjs");
4
+ const require_run_agent = require("./run-agent-Dmf8GV2d.cjs");
5
+ require("./validate.cjs");
6
+ let xstate = require("xstate");
7
+ //#region src/steps.ts
8
+ /**
9
+ * Internal: the pure `(state, event) => (nextState, requests)` view of an
10
+ * agent machine, used by model-free simulation (`simulateAgent`) and tests.
11
+ * An {@link AgentStep} is a snapshot plus the model requests the machine is
12
+ * now waiting on; nothing here executes anything. Hosts use
13
+ * `createAgentRuntime`.
14
+ * @module
15
+ */
16
+ /** @internal Normalizes current and legacy XState invoke effect shapes. */
17
+ function getInvokeEffectMetadata(action) {
18
+ if (action.type === "@xstate.spawn") return action;
19
+ if (action.type === "xstate.spawnChild") {
20
+ const params = action.params;
21
+ return params ? {
22
+ ...params,
23
+ logic: action.logic
24
+ } : void 0;
25
+ }
26
+ if (action.type === "@xstate.start" && typeof action.src === "string") return action;
27
+ }
28
+ /**
29
+ * The invokes a snapshot is still waiting on, lowered to the same spawn-effect
30
+ * shape {@link getAgentRequests} reads. Derived from the snapshot's live
31
+ * children rather than the last transition's actions, so a state that invokes
32
+ * several actors at once (an `invoke: [...]` array, or parallel regions each
33
+ * invoking) keeps reporting the siblings after the first one settles —
34
+ * including when the settled invoke's `onDone` is targetless and starts
35
+ * nothing new.
36
+ *
37
+ * Entries are ordered by invoke id, so a walker that resolves one invoke per
38
+ * step is deterministic.
39
+ *
40
+ * @internal
41
+ */
42
+ function getPendingInvokes(snapshot) {
43
+ const children = snapshot.children ?? {};
44
+ return Object.keys(children).sort().flatMap((id) => {
45
+ const child = children[id];
46
+ const childSnapshot = child?.getSnapshot?.();
47
+ if (!child || childSnapshot?.status !== "active") return [];
48
+ return [{
49
+ type: "@xstate.spawn",
50
+ id,
51
+ src: child.src,
52
+ input: childSnapshot.input,
53
+ logic: child.logic
54
+ }];
55
+ });
56
+ }
57
+ /**
58
+ * Scans a set of executable actions (as returned by xstate's `transition`/
59
+ * `initialTransition`) for spawned `TextLogic`/`DecisionLogic` invokes and
60
+ * lowers each into an {@link AgentStepRequest}. Pass `options.machine` to
61
+ * pre-fill `schemas`/`actors` from the machine's registered `setupAgent`
62
+ * options instead of passing them by hand.
63
+ * `options.snapshot` is required to resolve a decision's candidate events
64
+ * (intersecting declared `allowedEvents` with what's currently legal) — omit
65
+ * it and decision requests report an empty `events` list.
66
+ *
67
+ * @internal
68
+ */
69
+ function getAgentRequests(actions, { machine, ...options } = {}) {
70
+ if (machine) options = {
71
+ ...require_text_logic.getRegisteredAgentExecutionOptions(machine),
72
+ ...options
73
+ };
74
+ return actions.flatMap((action) => {
75
+ const params = getInvokeEffectMetadata(action);
76
+ if (!params || typeof params.src !== "string") return [];
77
+ if (typeof params.id !== "string" || params.id.length === 0) throw new Error(`Agent invoke '${params.src}' must define a durable string id.`);
78
+ const registeredLogic = require_text_logic.isTextLogic(params.logic) || require_decision.isDecisionLogic(params.logic) ? params.logic : options.actors?.[params.src];
79
+ if (require_decision.isDecisionLogic(registeredLogic)) {
80
+ const decisionRequest = registeredLogic.request(params.input);
81
+ const allowedEventTypes = registeredLogic.allowedEventTypes?.(params.input);
82
+ const events = options.snapshot ? require_decision.getAcceptedEvents(options.snapshot, {
83
+ events: options.events,
84
+ schemas: options.schemas,
85
+ eventTypes: allowedEventTypes
86
+ }) : [];
87
+ return [{
88
+ ...decisionRequest,
89
+ id: params.id,
90
+ events
91
+ }];
92
+ }
93
+ const textLogic = require_text_logic.isTextLogic(registeredLogic) ? registeredLogic : void 0;
94
+ const input = textLogic ? textLogic.request(params.input) : void 0;
95
+ if (!input) return [];
96
+ return [{
97
+ kind: "text",
98
+ id: params.id,
99
+ src: params.src,
100
+ ...textLogic ? { mode: textLogic.mode } : {},
101
+ input,
102
+ tools: input.tools ?? {},
103
+ events: []
104
+ }];
105
+ });
106
+ }
107
+ /**
108
+ * Builds the canonical `xstate.done.actor` event xstate's `transition()`
109
+ * expects to resolve a spawned invoke — including the child session identity
110
+ * that rejects a stale completion from an earlier incarnation.
111
+ *
112
+ * @internal
113
+ */
114
+ function doneEvent(snapshot, request, output) {
115
+ const id = typeof request === "string" ? request : request.id;
116
+ const child = snapshot.children[id];
117
+ return {
118
+ type: "xstate.done.actor",
119
+ actorId: id,
120
+ ...typeof child?.sessionId === "string" ? { sessionId: child.sessionId } : {},
121
+ output
122
+ };
123
+ }
124
+ /**
125
+ * The `xstate.error.actor` counterpart of {@link doneEvent} — the event a
126
+ * failed invoke delivers, which `onError` transitions observe. Carries the
127
+ * same child session identity, so xstate does not discard it as stale.
128
+ *
129
+ * @internal
130
+ */
131
+ function errorEvent(snapshot, request, error) {
132
+ const id = typeof request === "string" ? request : request.id;
133
+ const child = snapshot.children[id];
134
+ return {
135
+ type: "xstate.error.actor",
136
+ actorId: id,
137
+ ...typeof child?.sessionId === "string" ? { sessionId: child.sessionId } : {},
138
+ error
139
+ };
140
+ }
141
+ /**
142
+ * Applies a request's `output` as a done event (or, with `outcome: 'error'`,
143
+ * its `output` as the invoke's error) via `transition(...)`, returning the raw
144
+ * `[snapshot, actions]` tuple. Lower-level than {@link resolveAgentStep} /
145
+ * {@link rejectAgentStep} — those helpers wrap this and also run
146
+ * {@link getAgentRequests} to produce the next {@link AgentStep}.
147
+ *
148
+ * @internal
149
+ */
150
+ function transitionResult(logic, snapshot, request, output, outcome = "output") {
151
+ const event = outcome === "error" ? errorEvent(snapshot, request, output) : doneEvent(snapshot, request, output);
152
+ const result = (0, xstate.transition)(logic, snapshot, event);
153
+ applyFinalStateOutput(logic, result[0], event);
154
+ return result;
155
+ }
156
+ /**
157
+ * Starts a machine and returns its first {@link AgentStep} — the step-path
158
+ * equivalent of `initialTransition` plus request discovery. Begins the
159
+ * durable/per-model-call-checkpoint loop: resolve each `step.requests` entry
160
+ * (via {@link executeAgentRequest} for `kind: 'text'`, or
161
+ * {@link resolveDecision} for `kind: 'decision'`), then advance with
162
+ * {@link resolveAgentStep} or {@link transitionAgentStep}.
163
+ */
164
+ function initialAgentStep(machine, input, options) {
165
+ const [snapshot, actions] = (0, xstate.initialTransition)(machine, input);
166
+ return createAgentStep(machine, snapshot, actions, require_text_logic.getRegisteredAgentExecutionOptions(machine, options));
167
+ }
168
+ /**
169
+ * Applies an externally-sent event (e.g. a decision's chosen event, or a
170
+ * human's reply) and returns the next {@link AgentStep}. Accepts **either**
171
+ * a raw snapshot **or** a prior `AgentStep` as the second argument —
172
+ * `.snapshot` is unwrapped automatically, so callers can thread the whole
173
+ * step object through without manually plucking the snapshot out.
174
+ */
175
+ function transitionAgentStep(machine, snapshotOrStep, event, options) {
176
+ const [nextSnapshot, actions] = (0, xstate.transition)(machine, isAgentStep(snapshotOrStep) ? snapshotOrStep.snapshot : snapshotOrStep, event);
177
+ return createAgentStep(machine, nextSnapshot, actions, require_text_logic.getRegisteredAgentExecutionOptions(machine, options));
178
+ }
179
+ /**
180
+ * Applies a resolved text request's output (a `kind: 'text'`
181
+ * {@link AgentRequest} — not a decision) as a done event and returns the
182
+ * next {@link AgentStep}. For decisions, resolve with `resolveDecision`
183
+ * (which returns a {@link ChosenEvent}) and apply it with
184
+ * {@link transitionAgentStep} instead — a decision has no output value of
185
+ * its own to feed here.
186
+ */
187
+ function resolveAgentStep(machine, step, request, output, options) {
188
+ const [snapshot, actions] = transitionResult(machine, step.snapshot, request, output);
189
+ return createAgentStep(machine, snapshot, actions, require_text_logic.getRegisteredAgentExecutionOptions(machine, options));
190
+ }
191
+ /**
192
+ * Rejects a pending invoke — the failure counterpart of
193
+ * {@link resolveAgentStep}. Delivers `error` as the invoke's
194
+ * `xstate.error.actor` event, so the machine takes that invoke's `onError`
195
+ * transition and returns the next {@link AgentStep}. With no `onError` in
196
+ * scope the returned step's snapshot has `status: 'error'`, exactly as a live
197
+ * run's failed invoke does.
198
+ *
199
+ * A durable host replays a failed call with this: the log says the call
200
+ * failed, so the replay rejects the invoke instead of resolving it. Scripted
201
+ * playthroughs use it too — see `simulateAgent`'s `script.errors`.
202
+ *
203
+ * `error` can be any value. An `Error` instance is the usual one, but a plain
204
+ * object (`{ code: 'truncated' }`) reaches the `onError` transition as
205
+ * `event.error` untouched, so a machine that branches on a failure code is
206
+ * testable without constructing a provider's error class.
207
+ */
208
+ function rejectAgentStep(machine, step, request, error, options) {
209
+ const [snapshot, actions] = transitionResult(machine, step.snapshot, request, error, "error");
210
+ return createAgentStep(machine, snapshot, actions, require_text_logic.getRegisteredAgentExecutionOptions(machine, options));
211
+ }
212
+ function createAgentStep(machine, snapshot, actions, options) {
213
+ applyFinalStateOutput(machine, snapshot);
214
+ return {
215
+ snapshot,
216
+ actions,
217
+ requests: getAgentRequests(getPendingInvokes(snapshot), {
218
+ ...options,
219
+ snapshot
220
+ }),
221
+ done: snapshot.status === "done"
222
+ };
223
+ }
224
+ function resolveStateValueConfig(config, value) {
225
+ if (typeof value === "string") return config.states?.[value];
226
+ if (!value || typeof value !== "object") return;
227
+ for (const [key, childValue] of Object.entries(value)) {
228
+ const childConfig = config.states?.[key];
229
+ if (!childConfig) continue;
230
+ if (childConfig.type === "final") return childConfig;
231
+ const nested = resolveStateValueConfig(childConfig, childValue);
232
+ if (nested) return nested;
233
+ }
234
+ }
235
+ function applyFinalStateOutput(logic, snapshot, event) {
236
+ const machineSnapshot = snapshot;
237
+ if (machineSnapshot.status !== "done" || machineSnapshot.output !== void 0 || !("config" in logic)) return;
238
+ const config = logic.config;
239
+ if (!config) return;
240
+ const output = resolveStateValueConfig(config, machineSnapshot.value)?.output;
241
+ if (output === void 0) return;
242
+ machineSnapshot.output = typeof output === "function" ? output({
243
+ context: machineSnapshot.context,
244
+ event
245
+ }) : output;
246
+ }
247
+ function isAgentStep(value) {
248
+ return !!value && typeof value === "object" && "snapshot" in value && "actions" in value && "requests" in value;
249
+ }
250
+ //#endregion
5
251
  //#region src/verify.ts
6
252
  const DECIDE_SRC = "agent.decide";
7
253
  function normalizeInvokes(invoke) {
@@ -78,7 +324,7 @@ function checkDirectObjectSrc(ctx) {
78
324
  code: "direct-object-src",
79
325
  severity: "warning",
80
326
  path: node.path,
81
- message: `State '${node.path}' invokes a direct-object agent logic. Direct-object invoke srcs cannot be rebound by runAgent, so they inherit no host executors — call '.withExecutor(...)' on the logic, or register it as a string-keyed actor source (machine.provide({ actors: { name: logic } })) and invoke it by name.`
327
+ message: `State '${node.path}' invokes a direct-object agent logic. Direct-object invoke srcs cannot be rebound by the agent runtime, so they inherit no host executors — call '.withExecutor(...)' on the logic, or register it as a string-keyed actor source (machine.provide({ actors: { name: logic } })) and invoke it by name.`
82
328
  });
83
329
  }
84
330
  return out;
@@ -192,7 +438,7 @@ function assertAgentMachine(machine, options = {}) {
192
438
  }
193
439
  function pendingInvokes(step) {
194
440
  const out = [];
195
- for (const metadata of require_run_agent.getPendingInvokes(step.snapshot)) if (typeof metadata.src === "string") out.push({
441
+ for (const metadata of getPendingInvokes(step.snapshot)) if (typeof metadata.src === "string") out.push({
196
442
  id: metadata.id,
197
443
  src: metadata.src
198
444
  });
@@ -252,7 +498,7 @@ async function simulateAgent(machine, options) {
252
498
  errors: mapValues(options.script.errors ?? {}, (arr) => [...arr]),
253
499
  events: [...options.script.events ?? []]
254
500
  };
255
- let step = require_run_agent.initialAgentStep(machine, options.input);
501
+ let step = initialAgentStep(machine, options.input);
256
502
  const trail = [{ state: step.snapshot.value }];
257
503
  for (let i = 0; i < maxSteps; i++) {
258
504
  if (step.done) return {
@@ -290,7 +536,7 @@ async function simulateAgent(machine, options) {
290
536
  }
291
537
  const taken = takeFromQueue(script.text, request.src);
292
538
  if (!taken.found) throw scriptDryError("text", request.src, request.id);
293
- step = require_run_agent.resolveAgentStep(machine, step, request, asTextResult(taken.value));
539
+ step = resolveAgentStep(machine, step, request, asTextResult(taken.value));
294
540
  trail.push({
295
541
  state: step.snapshot.value,
296
542
  resolvedRequest: {
@@ -315,7 +561,7 @@ async function simulateAgent(machine, options) {
315
561
  }
316
562
  const taken = takeFromQueue(script.invokes, invoke.src);
317
563
  if (!taken.found) throw scriptDryError("invoke", invoke.src, invoke.id);
318
- step = require_run_agent.resolveAgentStep(machine, step, invoke.id, taken.value);
564
+ step = resolveAgentStep(machine, step, invoke.id, taken.value);
319
565
  trail.push({
320
566
  state: step.snapshot.value,
321
567
  resolvedRequest: {
@@ -331,7 +577,7 @@ async function simulateAgent(machine, options) {
331
577
  if (external.length > 0) {
332
578
  const event = external.shift();
333
579
  if (!step.snapshot.can(event)) throw new Error(`simulateAgent: scripted external event '${event.type}' cannot be taken in state ${JSON.stringify(step.snapshot.value)} (no handler, or its guard rejected it). A live run's send would be silently dropped here; fix the script's \`events\` queue.`);
334
- step = require_run_agent.transitionAgentStep(machine, step, event);
580
+ step = transitionAgentStep(machine, step, event);
335
581
  trail.push({
336
582
  state: step.snapshot.value,
337
583
  appliedEvent: event,
@@ -356,7 +602,7 @@ function queueKey(channel, src, id) {
356
602
  }
357
603
  function rejectScriptedRequest(machine, step, request, error, entry) {
358
604
  const id = typeof request === "string" ? request : request.id;
359
- const next = require_run_agent.rejectAgentStep(machine, step, request, error);
605
+ const next = rejectAgentStep(machine, step, request, error);
360
606
  if (next.snapshot.status === "error") throw unhandledScriptedError(error, entry.kind, entry.src, id);
361
607
  entry.trail.push({
362
608
  state: next.snapshot.value,
@@ -394,7 +640,7 @@ async function applyScriptedDecision(machine, step, request, decisionSrc, invoke
394
640
  });
395
641
  } catch (error) {
396
642
  if (!(error instanceof require_decision.AgentDecisionExhaustedError)) throw error;
397
- const next = require_run_agent.rejectAgentStep(machine, step, request.id, error);
643
+ const next = rejectAgentStep(machine, step, request.id, error);
398
644
  if (next.snapshot.status === "error") throw error;
399
645
  trail.push({
400
646
  state: next.snapshot.value,
@@ -402,7 +648,7 @@ async function applyScriptedDecision(machine, step, request, decisionSrc, invoke
402
648
  });
403
649
  return next;
404
650
  }
405
- const next = require_run_agent.transitionAgentStep(machine, step, chosen);
651
+ const next = transitionAgentStep(machine, step, chosen);
406
652
  const rejected = dequeued.slice(0, -1);
407
653
  trail.push({
408
654
  state: next.snapshot.value,
@@ -412,7 +658,7 @@ async function applyScriptedDecision(machine, step, request, decisionSrc, invoke
412
658
  return next;
413
659
  }
414
660
  function findInvokeMetadata(step, id) {
415
- for (const metadata of require_run_agent.getPendingInvokes(step.snapshot)) {
661
+ for (const metadata of getPendingInvokes(step.snapshot)) {
416
662
  if (metadata.id !== id) continue;
417
663
  return {
418
664
  ...typeof metadata.src === "string" ? { src: metadata.src } : {},
@@ -472,7 +718,7 @@ async function explore(machine, options, stopWhen) {
472
718
  reachedValues.push(snapshot.value);
473
719
  }
474
720
  };
475
- const initial = require_run_agent.initialAgentStep(machine, options.input);
721
+ const initial = initialAgentStep(machine, options.input);
476
722
  recordState(initial.snapshot);
477
723
  if (stopWhen?.(initial.snapshot)) witness = [];
478
724
  const advance = (step) => {
@@ -493,7 +739,7 @@ async function explore(machine, options, stopWhen) {
493
739
  step: current,
494
740
  blockedSrc: request.src
495
741
  };
496
- current = require_run_agent.resolveAgentStep(machine, current, request, asTextResult(textScript[request.src]));
742
+ current = resolveAgentStep(machine, current, request, asTextResult(textScript[request.src]));
497
743
  recordState(current.snapshot);
498
744
  continue;
499
745
  }
@@ -520,7 +766,7 @@ async function explore(machine, options, stopWhen) {
520
766
  step: current,
521
767
  blockedSrc: invoke.src
522
768
  };
523
- current = require_run_agent.resolveAgentStep(machine, current, invoke.id, invokeOutputs[invoke.src]);
769
+ current = resolveAgentStep(machine, current, invoke.id, invokeOutputs[invoke.src]);
524
770
  recordState(current.snapshot);
525
771
  continue;
526
772
  }
@@ -551,12 +797,12 @@ async function explore(machine, options, stopWhen) {
551
797
  unexplored.push(`max-depth: stopped at path [${path.map((e) => e.type).join(", ")}]`);
552
798
  return;
553
799
  }
554
- const failed = require_run_agent.rejectAgentStep(machine, settled, fork.id, errorScript[fork.src]);
800
+ const failed = rejectAgentStep(machine, settled, fork.id, errorScript[fork.src]);
555
801
  recordState(failed.snapshot);
556
802
  await visit(failed, [...path, { type: `xstate.error.actor.${fork.id}` }], depth + 1);
557
803
  if (!fork.isDecision) {
558
804
  if (fork.hasOutput) {
559
- const resolved = require_run_agent.resolveAgentStep(machine, settled, fork.id, fork.output);
805
+ const resolved = resolveAgentStep(machine, settled, fork.id, fork.output);
560
806
  recordState(resolved.snapshot);
561
807
  await visit(resolved, path, depth + 1);
562
808
  }
@@ -625,7 +871,7 @@ async function explore(machine, options, stopWhen) {
625
871
  prunedByGuard++;
626
872
  continue;
627
873
  }
628
- const next = require_run_agent.transitionAgentStep(machine, settled, event);
874
+ const next = transitionAgentStep(machine, settled, event);
629
875
  recordState(next.snapshot);
630
876
  await visit(next, [...path, event], depth + 1);
631
877
  }
@@ -812,11 +1058,13 @@ function matcherFor(expected) {
812
1058
  * @example Trajectory assertions in a test
813
1059
  * ```ts
814
1060
  * const statePath: unknown[] = [];
815
- * const result = await runAgent(machine, {
816
- * input,
817
- * executors,
818
- * onTransition: (snapshot) => statePath.push(snapshot.value),
819
- * });
1061
+ * const result = await runToQuiescence(
1062
+ * createAgentRuntime(machine, {
1063
+ * executors,
1064
+ * onTransition: (snapshot) => statePath.push(snapshot.value),
1065
+ * }),
1066
+ * { input },
1067
+ * );
820
1068
  *
821
1069
  * const path = matchesTrajectory(statePath, ['prompting', 'drafting', 'sent']);
822
1070
  * expect(path.matched, JSON.stringify(path.firstMiss)).toBe(true);
@@ -1024,9 +1272,7 @@ async function runSeam(machine, options) {
1024
1272
  let result;
1025
1273
  const maxTurns = options.maxTurns ?? 12;
1026
1274
  for (let turn = 0; turn <= maxTurns; turn++) {
1027
- result = await require_run_agent.runAgent(machine, {
1028
- ...snapshot ? { snapshot } : { input: options.input },
1029
- ...event ? { event } : {},
1275
+ result = await require_run_agent.runToQuiescence(require_run_agent.createAgentRuntime(machine, {
1030
1276
  ...options.actors ? { actors: options.actors } : {},
1031
1277
  executors,
1032
1278
  onTransition: (next, causedBy) => {
@@ -1035,6 +1281,9 @@ async function runSeam(machine, options) {
1035
1281
  liveEvents = events.length;
1036
1282
  statePath.push(next.value);
1037
1283
  }
1284
+ }), {
1285
+ ...snapshot ? { snapshot } : { input: options.input },
1286
+ ...event ? { event } : {}
1038
1287
  });
1039
1288
  if (result.status !== "idle" || turn === maxTurns) break;
1040
1289
  const next = options.respond?.({
@@ -1,7 +1,7 @@
1
- import { u as ChosenEvent } from "./types-B1Qs2q3q.cjs";
2
- import { Z as AgentError, c as AgentRequestExecutorInfo, f as AgentTextRequest, s as AgentRequestExecutor, t as AgentCallUsage, u as AgentRequestExecutors } from "./text-logic-BFEOxyxv.cjs";
3
- import { d as RunAgentOptions, f as RunAgentResult } from "./run-agent-BOfoJg5B.cjs";
4
- import { t as MetaOfSnapshot } from "./utils-ceStNCOh.cjs";
1
+ import { u as ChosenEvent } from "./types-hR5f5YXa.cjs";
2
+ import { Z as AgentError, c as AgentRequestExecutorInfo, f as AgentTextRequest, s as AgentRequestExecutor, t as AgentCallUsage, u as AgentRequestExecutors } from "./text-logic-IjfYy9DP.cjs";
3
+ import { c as AgentRunResult, d as AgentRuntimeOptions, o as AgentRunInit } from "./run-agent-ByO-Bxyd.cjs";
4
+ import { t as MetaOfSnapshot } from "./utils-o4YRdHJX.cjs";
5
5
  import { AnyMachineSnapshot, AnyStateMachine, EventFromLogic, InputFrom, SnapshotFrom, StateValue } from "xstate";
6
6
 
7
7
  //#region src/verify.d.ts
@@ -415,11 +415,13 @@ interface TrajectoryMatch {
415
415
  * @example Trajectory assertions in a test
416
416
  * ```ts
417
417
  * const statePath: unknown[] = [];
418
- * const result = await runAgent(machine, {
419
- * input,
420
- * executors,
421
- * onTransition: (snapshot) => statePath.push(snapshot.value),
422
- * });
418
+ * const result = await runToQuiescence(
419
+ * createAgentRuntime(machine, {
420
+ * executors,
421
+ * onTransition: (snapshot) => statePath.push(snapshot.value),
422
+ * }),
423
+ * { input },
424
+ * );
423
425
  *
424
426
  * const path = matchesTrajectory(statePath, ['prompting', 'drafting', 'sent']);
425
427
  * expect(path.matched, JSON.stringify(path.firstMiss)).toBe(true);
@@ -480,7 +482,7 @@ interface SeamTurn<TMachine extends AnyStateMachine> {
480
482
  /** 0-based index of this pause within the run. */
481
483
  turn: number;
482
484
  /** The `idle` result that produced the pause. */
483
- result: RunAgentResult<TMachine>;
485
+ result: AgentRunResult<TMachine>;
484
486
  }
485
487
  /**
486
488
  * One text call in a {@link runSeam} run's ledger, in call order — the receipt
@@ -511,7 +513,7 @@ interface SeamSlice {
511
513
  }
512
514
  /** Options for {@link runSeam}. */
513
515
  interface RunSeamOptions<TMachine extends AnyStateMachine> {
514
- /** Machine input, passed straight through to `runAgent`. */
516
+ /** Machine input, passed straight through to `runToQuiescence`. */
515
517
  input?: InputFrom<TMachine>;
516
518
  /**
517
519
  * The call plan: scripted answers per key, consumed in order. A key is a
@@ -554,15 +556,15 @@ interface RunSeamOptions<TMachine extends AnyStateMachine> {
554
556
  * Text slots are always owned by the routing.
555
557
  */
556
558
  executors?: Partial<AgentRequestExecutors>;
557
- /** Passed through to `runAgent`: actor implementations merged onto the machine. */
558
- actors?: RunAgentOptions<TMachine>["actors"];
559
+ /** Passed through to `createAgentRuntime`: actor implementations merged onto the machine. */
560
+ actors?: (AgentRuntimeOptions<TMachine> & AgentRunInit<TMachine>)["actors"];
559
561
  }
560
562
  /** What {@link runSeam} returns: the seam's own answer, plus the run it caused. */
561
563
  interface RunSeamResult<TMachine extends AnyStateMachine> {
562
564
  /**
563
- * The final `runAgent` result. `usage` accounts for the last leg.
565
+ * The final `runToQuiescence` result. `usage` accounts for the last leg.
564
566
  */
565
- result: RunAgentResult<TMachine>;
567
+ result: AgentRunResult<TMachine>;
566
568
  /** What the seam call returned, or `undefined` when the run never reached it. */
567
569
  seamOutput: unknown;
568
570
  /**