@statelyai/agent 2.0.0-alpha.23 → 2.0.0-alpha.25

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 (53) hide show
  1. package/dist/ai-sdk.cjs +30 -34
  2. package/dist/ai-sdk.d.cts +27 -31
  3. package/dist/ai-sdk.d.mts +27 -31
  4. package/dist/ai-sdk.mjs +27 -31
  5. package/dist/decision-CM9CYZ6t.cjs +519 -0
  6. package/dist/decision-DzSv1NpD.mjs +453 -0
  7. package/dist/event-log-store-Ba2fsc4E.mjs +576 -0
  8. package/dist/event-log-store-DQmImLYk.cjs +702 -0
  9. package/dist/event-log-store-DvOcs10J.d.cts +338 -0
  10. package/dist/event-log-store-DxyVgnas.d.mts +338 -0
  11. package/dist/index.cjs +429 -4272
  12. package/dist/index.d.cts +104 -1005
  13. package/dist/index.d.mts +104 -1005
  14. package/dist/index.mjs +389 -4202
  15. package/dist/log.cjs +392 -0
  16. package/dist/log.d.cts +32 -0
  17. package/dist/log.d.mts +32 -0
  18. package/dist/log.mjs +371 -0
  19. package/dist/machines.cjs +27 -16
  20. package/dist/machines.d.cts +1 -1
  21. package/dist/machines.d.mts +1 -1
  22. package/dist/machines.mjs +27 -16
  23. package/dist/openai.cjs +16 -15
  24. package/dist/openai.d.cts +9 -9
  25. package/dist/openai.d.mts +9 -9
  26. package/dist/openai.mjs +10 -9
  27. package/dist/otel.d.cts +1 -1
  28. package/dist/otel.d.mts +1 -1
  29. package/dist/{run-agent-Ck7Sa3Tb.d.mts → run-agent-BOfoJg5B.d.cts} +86 -387
  30. package/dist/{run-agent-DWqA8KiI.d.cts → run-agent-CG343kFs.d.mts} +86 -387
  31. package/dist/run-agent-Cb1-LS5P.cjs +1783 -0
  32. package/dist/run-agent-DvDQd4If.mjs +1669 -0
  33. package/dist/{setup-agent-CeO2fARv.mjs → setup-agent-CFW-jPI8.mjs} +9 -20
  34. package/dist/{setup-agent-Dl2VELLi.cjs → setup-agent-CPf7MxnG.cjs} +20 -37
  35. package/dist/testing.cjs +1222 -0
  36. package/dist/testing.d.cts +602 -0
  37. package/dist/testing.d.mts +602 -0
  38. package/dist/testing.mjs +1212 -0
  39. package/dist/{text-logic-DJBK3LbG.d.mts → text-logic-BFEOxyxv.d.cts} +71 -147
  40. package/dist/text-logic-Bl_ZRxDi.mjs +833 -0
  41. package/dist/text-logic-C8xyr6Ag.cjs +1091 -0
  42. package/dist/{text-logic-C7bSnH_B.d.cts → text-logic-hZSiRUo1.d.mts} +71 -147
  43. package/dist/{types-CjHk5OdH.d.cts → types-B1Qs2q3q.d.cts} +2 -1
  44. package/dist/{types-DWA6X9R-.d.mts → types-tA3SdczG.d.mts} +2 -1
  45. package/dist/usage-BdEjFuIi.mjs +5 -0
  46. package/dist/usage-efOQPdf_.cjs +10 -0
  47. package/dist/utils-C1p37X_c.d.mts +209 -0
  48. package/dist/utils-RalRn9sk.d.cts +209 -0
  49. package/package.json +24 -4
  50. package/readme.md +2 -2
  51. package/skills/generate-machine/SKILL.md +4 -6
  52. package/dist/decision-BBZ2jMO1.mjs +0 -1490
  53. package/dist/decision-Cv6SfNWl.cjs +0 -1856
@@ -0,0 +1,1783 @@
1
+ const require_text_logic = require("./text-logic-C8xyr6Ag.cjs");
2
+ const require_decision = require("./decision-CM9CYZ6t.cjs");
3
+ const require_usage = require("./usage-efOQPdf_.cjs");
4
+ const require_event_log_store = require("./event-log-store-DQmImLYk.cjs");
5
+ require("./validate.cjs");
6
+ let xstate = require("xstate");
7
+ //#region src/steps.ts
8
+ /**
9
+ * The step API: the pure `(state, event) => (nextState, requests)` view of an
10
+ * agent machine. An {@link AgentStep} is a snapshot plus the model requests
11
+ * the machine is now waiting on; nothing here executes anything. A host
12
+ * resolves each request however it likes ({@link executeAgentRequest},
13
+ * `resolveDecision`, a queue, a durable workflow, a replayed log) and feeds
14
+ * the result back with {@link resolveAgentStep} or {@link rejectAgentStep}.
15
+ * `runAgent` is the in-process host built for the common case.
16
+ * @module
17
+ */
18
+ /** @internal Normalizes current and legacy XState invoke effect shapes. */
19
+ function getInvokeEffectMetadata(action) {
20
+ if (action.type === "@xstate.spawn") return action;
21
+ if (action.type === "xstate.spawnChild") {
22
+ const params = action.params;
23
+ return params ? {
24
+ ...params,
25
+ logic: action.logic
26
+ } : void 0;
27
+ }
28
+ if (action.type === "@xstate.start" && typeof action.src === "string") return action;
29
+ }
30
+ /**
31
+ * The invokes a snapshot is still waiting on, lowered to the same spawn-effect
32
+ * shape {@link getAgentRequests} reads. Derived from the snapshot's live
33
+ * children rather than the last transition's actions, so a state that invokes
34
+ * several actors at once (an `invoke: [...]` array, or parallel regions each
35
+ * invoking) keeps reporting the siblings after the first one settles —
36
+ * including when the settled invoke's `onDone` is targetless and starts
37
+ * nothing new.
38
+ *
39
+ * Entries are ordered by invoke id, so a walker that resolves one invoke per
40
+ * step is deterministic.
41
+ *
42
+ * @internal
43
+ */
44
+ function getPendingInvokes(snapshot) {
45
+ const children = snapshot.children ?? {};
46
+ return Object.keys(children).sort().flatMap((id) => {
47
+ const child = children[id];
48
+ const childSnapshot = child?.getSnapshot?.();
49
+ if (!child || childSnapshot?.status !== "active") return [];
50
+ return [{
51
+ type: "@xstate.spawn",
52
+ id,
53
+ src: child.src,
54
+ input: childSnapshot.input,
55
+ logic: child.logic
56
+ }];
57
+ });
58
+ }
59
+ /**
60
+ * Scans a set of executable actions (as returned by xstate's `transition`/
61
+ * `initialTransition`) for spawned `TextLogic`/`DecisionLogic` invokes and
62
+ * lowers each into an {@link AgentStepRequest}. Pass `options.machine` to
63
+ * pre-fill `schemas`/`actors` from the machine's registered `setupAgent`
64
+ * options instead of passing them by hand.
65
+ * `options.snapshot` is required to resolve a decision's candidate events
66
+ * (intersecting declared `allowedEvents` with what's currently legal) — omit
67
+ * it and decision requests report an empty `events` list.
68
+ *
69
+ * @internal
70
+ */
71
+ function getAgentRequests(actions, { machine, ...options } = {}) {
72
+ if (machine) options = {
73
+ ...require_text_logic.getRegisteredAgentExecutionOptions(machine),
74
+ ...options
75
+ };
76
+ return actions.flatMap((action) => {
77
+ const params = getInvokeEffectMetadata(action);
78
+ if (!params || typeof params.src !== "string") return [];
79
+ if (typeof params.id !== "string" || params.id.length === 0) throw new Error(`Agent invoke '${params.src}' must define a durable string id.`);
80
+ const registeredLogic = require_text_logic.isTextLogic(params.logic) || require_decision.isDecisionLogic(params.logic) ? params.logic : options.actors?.[params.src];
81
+ if (require_decision.isDecisionLogic(registeredLogic)) {
82
+ const decisionRequest = registeredLogic.request(params.input);
83
+ const allowedEventTypes = registeredLogic.allowedEventTypes?.(params.input);
84
+ const events = options.snapshot ? require_decision.getAcceptedEvents(options.snapshot, {
85
+ events: options.events,
86
+ schemas: options.schemas,
87
+ eventTypes: allowedEventTypes
88
+ }) : [];
89
+ return [{
90
+ ...decisionRequest,
91
+ id: params.id,
92
+ events
93
+ }];
94
+ }
95
+ const textLogic = require_text_logic.isTextLogic(registeredLogic) ? registeredLogic : void 0;
96
+ const input = textLogic ? textLogic.request(params.input) : void 0;
97
+ if (!input) return [];
98
+ return [{
99
+ kind: "text",
100
+ id: params.id,
101
+ src: params.src,
102
+ ...textLogic ? { mode: textLogic.mode } : {},
103
+ input,
104
+ tools: input.tools ?? {},
105
+ events: []
106
+ }];
107
+ });
108
+ }
109
+ /**
110
+ * Builds the canonical `xstate.done.actor` event xstate's `transition()`
111
+ * expects to resolve a spawned invoke — including the child session identity
112
+ * that rejects a stale completion from an earlier incarnation.
113
+ *
114
+ * @internal
115
+ */
116
+ function doneEvent(snapshot, request, output) {
117
+ const id = typeof request === "string" ? request : request.id;
118
+ const child = snapshot.children[id];
119
+ return {
120
+ type: "xstate.done.actor",
121
+ actorId: id,
122
+ ...typeof child?.sessionId === "string" ? { sessionId: child.sessionId } : {},
123
+ output
124
+ };
125
+ }
126
+ /**
127
+ * The `xstate.error.actor` counterpart of {@link doneEvent} — the event a
128
+ * failed invoke delivers, which `onError` transitions observe. Carries the
129
+ * same child session identity, so xstate does not discard it as stale.
130
+ *
131
+ * @internal
132
+ */
133
+ function errorEvent(snapshot, request, error) {
134
+ const id = typeof request === "string" ? request : request.id;
135
+ const child = snapshot.children[id];
136
+ return {
137
+ type: "xstate.error.actor",
138
+ actorId: id,
139
+ ...typeof child?.sessionId === "string" ? { sessionId: child.sessionId } : {},
140
+ error
141
+ };
142
+ }
143
+ /**
144
+ * Applies a request's `output` as a done event (or, with `outcome: 'error'`,
145
+ * its `output` as the invoke's error) via `transition(...)`, returning the raw
146
+ * `[snapshot, actions]` tuple. Lower-level than {@link resolveAgentStep} /
147
+ * {@link rejectAgentStep} — those helpers wrap this and also run
148
+ * {@link getAgentRequests} to produce the next {@link AgentStep}.
149
+ *
150
+ * @internal
151
+ */
152
+ function transitionResult(logic, snapshot, request, output, outcome = "output") {
153
+ const event = outcome === "error" ? errorEvent(snapshot, request, output) : doneEvent(snapshot, request, output);
154
+ const result = (0, xstate.transition)(logic, snapshot, event);
155
+ applyFinalStateOutput(logic, result[0], event);
156
+ return result;
157
+ }
158
+ /**
159
+ * Starts a machine and returns its first {@link AgentStep} — the step-path
160
+ * equivalent of `initialTransition` plus request discovery. Begins the
161
+ * durable/per-model-call-checkpoint loop: resolve each `step.requests` entry
162
+ * (via {@link executeAgentRequest} for `kind: 'text'`, or
163
+ * {@link resolveDecision} for `kind: 'decision'`), then advance with
164
+ * {@link resolveAgentStep} or {@link transitionAgentStep}.
165
+ */
166
+ function initialAgentStep(machine, input, options) {
167
+ const [snapshot, actions] = (0, xstate.initialTransition)(machine, input);
168
+ return createAgentStep(machine, snapshot, actions, require_text_logic.getRegisteredAgentExecutionOptions(machine, options));
169
+ }
170
+ /**
171
+ * Applies an externally-sent event (e.g. a decision's chosen event, or a
172
+ * human's reply) and returns the next {@link AgentStep}. Accepts **either**
173
+ * a raw snapshot **or** a prior `AgentStep` as the second argument —
174
+ * `.snapshot` is unwrapped automatically, so callers can thread the whole
175
+ * step object through without manually plucking the snapshot out.
176
+ */
177
+ function transitionAgentStep(machine, snapshotOrStep, event, options) {
178
+ const [nextSnapshot, actions] = (0, xstate.transition)(machine, isAgentStep(snapshotOrStep) ? snapshotOrStep.snapshot : snapshotOrStep, event);
179
+ return createAgentStep(machine, nextSnapshot, actions, require_text_logic.getRegisteredAgentExecutionOptions(machine, options));
180
+ }
181
+ /**
182
+ * Applies a resolved text request's output (a `kind: 'text'`
183
+ * {@link AgentRequest} — not a decision) as a done event and returns the
184
+ * next {@link AgentStep}. For decisions, resolve with `resolveDecision`
185
+ * (which returns a {@link ChosenEvent}) and apply it with
186
+ * {@link transitionAgentStep} instead — a decision has no output value of
187
+ * its own to feed here.
188
+ */
189
+ function resolveAgentStep(machine, step, request, output, options) {
190
+ const [snapshot, actions] = transitionResult(machine, step.snapshot, request, output);
191
+ return createAgentStep(machine, snapshot, actions, require_text_logic.getRegisteredAgentExecutionOptions(machine, options));
192
+ }
193
+ /**
194
+ * Rejects a pending invoke — the failure counterpart of
195
+ * {@link resolveAgentStep}. Delivers `error` as the invoke's
196
+ * `xstate.error.actor` event, so the machine takes that invoke's `onError`
197
+ * transition and returns the next {@link AgentStep}. With no `onError` in
198
+ * scope the returned step's snapshot has `status: 'error'`, exactly as a live
199
+ * run's failed invoke does.
200
+ *
201
+ * A durable host replays a failed call with this: the log says the call
202
+ * failed, so the replay rejects the invoke instead of resolving it. Scripted
203
+ * playthroughs use it too — see `simulateAgent`'s `script.errors`.
204
+ *
205
+ * `error` can be any value. An `Error` instance is the usual one, but a plain
206
+ * object (`{ code: 'truncated' }`) reaches the `onError` transition as
207
+ * `event.error` untouched, so a machine that branches on a failure code is
208
+ * testable without constructing a provider's error class.
209
+ */
210
+ function rejectAgentStep(machine, step, request, error, options) {
211
+ const [snapshot, actions] = transitionResult(machine, step.snapshot, request, error, "error");
212
+ return createAgentStep(machine, snapshot, actions, require_text_logic.getRegisteredAgentExecutionOptions(machine, options));
213
+ }
214
+ /**
215
+ * Resolves one **text** request ({@link AgentRequest}, from
216
+ * {@link AgentStep.requests}) against a host's {@link AgentRequestExecutors}
217
+ * — merges the request's tools, dispatches to `generateText`/`streamText`
218
+ * per `mode`, and validates the result against the request's
219
+ * `outputSchema` if present. **Text-only**: passing a `kind: 'decision'`
220
+ * request throws, directing the caller to `resolveDecision(request,
221
+ * executors, ...)` instead. Returns the invoke's output — `{ result,
222
+ * messages }`, ready for {@link resolveAgentStep} — plus the `raw` executor
223
+ * result (tool calls, usage, finish reason).
224
+ */
225
+ async function executeAgentRequest(request, executors) {
226
+ if (request.kind === "decision") throw new Error("executeAgentRequest(...) is text-only. Resolve a 'decision' request with resolveDecision(request, executors, ...) instead.");
227
+ assertTextExecutor(request, executors);
228
+ const { result, raw } = await require_text_logic.executeAgentTextRequest(request.mode ?? "generate", request.id, request.input, executors, request.tools);
229
+ return {
230
+ result: request.input.outputSchema ? require_text_logic.validateSchemaSync(request.input.outputSchema, result) : result,
231
+ messages: require_text_logic.responseMessagesOf(raw),
232
+ raw
233
+ };
234
+ }
235
+ function assertTextExecutor(request, executors) {
236
+ const mode = request.mode ?? "generate";
237
+ const kind = mode === "stream" ? "streamText" : "generateText";
238
+ if (!(mode === "stream" ? executors.streamText : executors.generateText)) throw new Error(`this step's text request '${request.src}' needs a '${kind}' executor but none was provided.`);
239
+ }
240
+ function createAgentStep(machine, snapshot, actions, options) {
241
+ applyFinalStateOutput(machine, snapshot);
242
+ return {
243
+ snapshot,
244
+ actions,
245
+ requests: getAgentRequests(getPendingInvokes(snapshot), {
246
+ ...options,
247
+ snapshot
248
+ }),
249
+ done: snapshot.status === "done"
250
+ };
251
+ }
252
+ function resolveStateValueConfig(config, value) {
253
+ if (typeof value === "string") return config.states?.[value];
254
+ if (!value || typeof value !== "object") return;
255
+ for (const [key, childValue] of Object.entries(value)) {
256
+ const childConfig = config.states?.[key];
257
+ if (!childConfig) continue;
258
+ if (childConfig.type === "final") return childConfig;
259
+ const nested = resolveStateValueConfig(childConfig, childValue);
260
+ if (nested) return nested;
261
+ }
262
+ }
263
+ function applyFinalStateOutput(logic, snapshot, event) {
264
+ const machineSnapshot = snapshot;
265
+ if (machineSnapshot.status !== "done" || machineSnapshot.output !== void 0 || !("config" in logic)) return;
266
+ const config = logic.config;
267
+ if (!config) return;
268
+ const output = resolveStateValueConfig(config, machineSnapshot.value)?.output;
269
+ if (output === void 0) return;
270
+ machineSnapshot.output = typeof output === "function" ? output({
271
+ context: machineSnapshot.context,
272
+ event
273
+ }) : output;
274
+ }
275
+ function isAgentStep(value) {
276
+ return !!value && typeof value === "object" && "snapshot" in value && "actions" in value && "requests" in value;
277
+ }
278
+ //#endregion
279
+ //#region src/run-agent.ts
280
+ /**
281
+ * Thrown by {@link runAgent} when a resume is given BOTH an `events` log and a
282
+ * `snapshot` that claims a position in that log (`agentMeta.logIndex`), and the
283
+ * two disagree about the state at that position. The log is the source of
284
+ * truth, so this is a host bug (a snapshot cached from a different lineage, or
285
+ * a snapshot mutated out of band), not a recoverable resume: pass the log
286
+ * alone, or the matching snapshot.
287
+ */
288
+ var AgentSnapshotDivergedError = class extends require_text_logic.AgentError {
289
+ constructor(expected, actual, logIndex) {
290
+ super("snapshot-diverged", `runAgent: the resume snapshot disagrees with the event log at index ${logIndex}: the log replays to state hash '${expected}', the snapshot hashes '${actual}'.`);
291
+ this.expected = expected;
292
+ this.actual = actual;
293
+ this.logIndex = logIndex;
294
+ this.name = "AgentSnapshotDivergedError";
295
+ }
296
+ };
297
+ function hashResumeSnapshot(snapshot) {
298
+ if (snapshot !== null && typeof snapshot === "object" && "agentMeta" in snapshot) {
299
+ const rest = {};
300
+ for (const [key, value] of Object.entries(snapshot)) if (key !== "agentMeta") rest[key] = value;
301
+ return require_event_log_store.getSnapshotStateHash(rest);
302
+ }
303
+ return require_event_log_store.getSnapshotStateHash(snapshot);
304
+ }
305
+ function readAgentMeta(snapshot) {
306
+ const meta = snapshot?.agentMeta;
307
+ return meta !== null && typeof meta === "object" ? meta : void 0;
308
+ }
309
+ /**
310
+ * The version of the {@link AgentTraceEvent} envelope every trace event carries
311
+ * as `schemaVersion`. Bumped only on a breaking change to the envelope or any
312
+ * payload shape, so a consumer can gate on it. Emitted identically by
313
+ * {@link runAgent}, {@link provideExecutors}' `onTrace`, and
314
+ * {@link traceTransitions}.
315
+ */
316
+ const AGENT_TRACE_SCHEMA_VERSION = 1;
317
+ const TRACE_ENVELOPE_KEYS = [
318
+ "schemaVersion",
319
+ "runId",
320
+ "seq",
321
+ "timestamp",
322
+ "machineId",
323
+ "machineVersion",
324
+ "type",
325
+ "status",
326
+ "cause",
327
+ "reasoning",
328
+ "finishReason",
329
+ "chunk"
330
+ ];
331
+ /**
332
+ * Best-effort JSON projection of an arbitrary value. Never throws: functions,
333
+ * symbols, `undefined`, and cyclic back-references are DROPPED (array holes
334
+ * become `null`), non-finite numbers become `null`, `bigint`s become strings,
335
+ * `Error`s become `{ name, message, stack?, code? }`, and anything with a
336
+ * `toJSON()` (e.g. `Date`) is projected through it — the same losses a
337
+ * `JSON.parse(JSON.stringify(...))` round-trip incurs, minus the throws.
338
+ */
339
+ function toJsonValue(value, ancestors) {
340
+ if (value === null) return null;
341
+ const type = typeof value;
342
+ if (type === "string" || type === "boolean") return value;
343
+ if (type === "number") return Number.isFinite(value) ? value : null;
344
+ if (type === "bigint") return value.toString();
345
+ if (type !== "object") return;
346
+ const object = value;
347
+ if (ancestors.includes(object)) return;
348
+ const nextAncestors = [...ancestors, object];
349
+ if (object instanceof Error) {
350
+ const serialized = {
351
+ name: object.name,
352
+ message: object.message
353
+ };
354
+ if (typeof object.stack === "string") serialized.stack = object.stack;
355
+ const code = object.code;
356
+ if (typeof code === "string") serialized.code = code;
357
+ const cause = toJsonValue(object.cause, nextAncestors);
358
+ if (cause !== void 0) serialized.cause = cause;
359
+ return serialized;
360
+ }
361
+ const toJSON = object.toJSON;
362
+ if (typeof toJSON === "function") return toJsonValue(toJSON.call(object), nextAncestors);
363
+ if (Array.isArray(object)) return object.map((item) => toJsonValue(item, nextAncestors) ?? null);
364
+ const out = {};
365
+ for (const [key, item] of Object.entries(object)) {
366
+ const serializedItem = toJsonValue(item, nextAncestors);
367
+ if (serializedItem !== void 0) out[key] = serializedItem;
368
+ }
369
+ return out;
370
+ }
371
+ /**
372
+ * Projects an {@link AgentTraceEvent} into a guaranteed JSON-safe envelope —
373
+ * the form the trace stream is actually sold for (one `JSON.stringify` per line
374
+ * in a JSONL file). Live values are sanitized rather than trusted:
375
+ *
376
+ * - Snapshots (`run.start`, `machine.transition`, `run.end`) go through the
377
+ * same JSON round-trip as `machine.getPersistedSnapshot(...)`, so what lands on disk is
378
+ * what a resume would see.
379
+ * - `request.end`'s `raw` (a provider SDK object, frequently cyclic) is DROPPED
380
+ * unless `includeRaw` is set, in which case it is sanitized like everything
381
+ * else.
382
+ * - Non-serializable values anywhere (functions, symbols, `undefined`, cyclic
383
+ * back-references) are dropped; `Error`s become `{ name, message, stack?,
384
+ * code? }` instead of `{}`. Nothing throws.
385
+ *
386
+ * @example
387
+ * ```ts
388
+ * await appendFile('trace.jsonl', JSON.stringify(serializeTraceEvent(event)) + '\n');
389
+ * ```
390
+ */
391
+ function serializeTraceEvent(event, options = {}) {
392
+ const out = {};
393
+ for (const [key, value] of Object.entries(event)) {
394
+ if (key === "raw" && !options.includeRaw) continue;
395
+ if (TRACE_ENVELOPE_KEYS.includes(key)) {
396
+ if (value !== void 0) out[key] = value;
397
+ continue;
398
+ }
399
+ const serialized = toJsonValue(value, []);
400
+ if (serialized !== void 0) out[key] = serialized;
401
+ }
402
+ return out;
403
+ }
404
+ let nextRunAgentTraceId = 1;
405
+ /**
406
+ * Thrown into the invoke that would have made the call once
407
+ * {@link RunAgentOptions.maxModelCalls} is spent. It reaches the machine
408
+ * through the normal error channel, so an invoke's `onError` can branch on it
409
+ * (`error.code === 'max-model-calls'`, the same string the settled result's
410
+ * `cause` uses) and route to a degraded/finish state instead of failing the
411
+ * run. Unhandled, it settles `{ status: 'error', cause: 'max-model-calls' }`.
412
+ *
413
+ * ```ts
414
+ * onError: [
415
+ * { guard: ({ event }) => event.error?.code === 'max-model-calls', target: 'budgetSpent' },
416
+ * { target: 'failed' },
417
+ * ]
418
+ * ```
419
+ */
420
+ var AgentMaxModelCallsExceededError = class extends require_text_logic.AgentError {
421
+ /** The budget that was exceeded (`options.maxModelCalls`). */
422
+ maxModelCalls;
423
+ constructor(maxModelCalls) {
424
+ super("max-model-calls", `runAgent exceeded maxModelCalls (${maxModelCalls}). Raise the budget, or handle it in the invoke's onError (error.code === 'max-model-calls').`);
425
+ this.name = "AgentMaxModelCallsExceededError";
426
+ this.maxModelCalls = maxModelCalls;
427
+ }
428
+ };
429
+ function wrapsDecisionExhausted(error) {
430
+ let current = error;
431
+ for (let depth = 0; depth < 10 && current != null; depth++) {
432
+ if (current instanceof require_decision.AgentDecisionExhaustedError) return true;
433
+ current = current.cause;
434
+ }
435
+ return false;
436
+ }
437
+ /**
438
+ * Recursively collects every invoke's `src` from raw machine config (spike
439
+ * S6: `machine.config` preserves authored srcs; the built `machine.root`
440
+ * normalizes object srcs to synthetic string ids and loses the distinction
441
+ * this walk needs). Function-valued `src` resolvers are dynamic and are not
442
+ * statically analyzable, so they are skipped (pass-through, like any other
443
+ * non-agent actor).
444
+ */
445
+ function collectConfiguredInvokeSrcs(stateConfig, stateName, out) {
446
+ if (!stateConfig) return;
447
+ const invokes = stateConfig.invoke === void 0 ? [] : Array.isArray(stateConfig.invoke) ? stateConfig.invoke : [stateConfig.invoke];
448
+ for (const invokeConfig of invokes) {
449
+ const src = invokeConfig?.src;
450
+ if (typeof src === "string" || src && typeof src === "object") out.push({
451
+ stateName,
452
+ src
453
+ });
454
+ }
455
+ for (const [childName, childConfig] of Object.entries(stateConfig.states ?? {})) collectConfiguredInvokeSrcs(childConfig, `${stateName}.${childName}`, out);
456
+ }
457
+ /**
458
+ * Duck-types a state machine actor logic (an invoked child machine) vs. any
459
+ * other actor logic. xstate's `StateMachine` carries `.config`, `.root`, and
460
+ * a `.provide(...)` method plus a `sources.actors` map — this
461
+ * combination is unique to machines and survives the dual-package/version
462
+ * boundary an `instanceof` check would not. Used to descend the bind-time
463
+ * walk into invoked child machines (their internal agent requests are opaque
464
+ * to the parent-level source walk otherwise).
465
+ */
466
+ function isStateMachineLogic(logic) {
467
+ return !!logic && typeof logic === "object" && "config" in logic && "root" in logic && typeof logic.provide === "function" && typeof logic.sources === "object" && !!logic.sources?.actors;
468
+ }
469
+ /**
470
+ * Fails fast (throws) at bind time — before any actor runs — when the
471
+ * machine invokes an agent actor `runAgent` cannot execute. See §3.2 point 2.
472
+ *
473
+ * Recurses into invoked child state machines (arbitrarily deep). A child
474
+ * machine's agent requests reached through string-keyed invoke srcs DO inherit
475
+ * the parent runAgent's `generateText`/`streamText`/`decide` executors —
476
+ * runAgent rebinds them with the same host-backed wrappers (see
477
+ * {@link rebindChildMachine}) — so the only remaining bind-time errors are: a
478
+ * required executor kind missing entirely (naming the invoke chain and src),
479
+ * and an unbound request reached through a direct-object invoke src that can't
480
+ * be rebound ({@link unrebindableChildRequestError}). A request that carries
481
+ * its own executor (`.withExecutor(...)`, tracked in `executorBoundLogics`)
482
+ * always runs itself; explicit binding shadows inheritance.
483
+ */
484
+ function assertBindable(machine, effectiveSources, executors) {
485
+ assertMachineBindable(machine, effectiveSources, executors, {
486
+ isChild: false,
487
+ childPath: "",
488
+ rebindable: true,
489
+ visited: new Set([machine])
490
+ });
491
+ }
492
+ function assertMachineBindable(machine, effectiveSources, executors, ctx) {
493
+ const invokes = [];
494
+ collectConfiguredInvokeSrcs(machine.config, machine.config.id ?? "(root)", invokes);
495
+ const where = ctx.isChild ? `child machine '${ctx.childPath}' state` : "state";
496
+ for (const { stateName, src } of invokes) {
497
+ if (typeof src !== "string") {
498
+ if (isStateMachineLogic(src)) {
499
+ assertChildMachineBindable(src, src, stateName, executors, ctx);
500
+ continue;
501
+ }
502
+ if ((require_text_logic.isTextLogic(src) || require_decision.isDecisionLogic(src)) && !require_text_logic.executorBoundLogics.has(src)) throw new Error(`runAgent: ${where} '${stateName}' invokes a direct-object actor logic (kind: '${src.kind}'). Direct-object invoke srcs cannot be rebound by runAgent — either call '.withExecutor(...)' on the logic before invoking it, or register it as a string-keyed actor source instead (machine.provide({ actors: { name: logic } })) and invoke it by name.`);
503
+ continue;
504
+ }
505
+ const logic = effectiveSources[src];
506
+ if (logic === void 0) throw new Error(`runAgent: ${where} '${stateName}' invokes unregistered actor source '${src}'. Provide it via machine.provide({ actors: { '${src}': ... } }) or runAgent(machine, { actors: { '${src}': ... } }).`);
507
+ if (isStateMachineLogic(logic)) {
508
+ assertChildMachineBindable(logic, src, stateName, executors, ctx);
509
+ continue;
510
+ }
511
+ if (require_decision.isDecisionLogic(logic)) {
512
+ if (require_text_logic.executorBoundLogics.has(logic)) continue;
513
+ if (!ctx.rebindable) throw unrebindableChildRequestError(ctx.childPath, stateName, src, "decision");
514
+ if (!executors.decide) throw new Error(`runAgent: ${where} '${stateName}' invokes decision source '${src}' but no 'decide' executor was provided to runAgent(...).`);
515
+ continue;
516
+ }
517
+ if (require_text_logic.isTextLogic(logic)) {
518
+ if (require_text_logic.executorBoundLogics.has(logic)) continue;
519
+ if (!ctx.rebindable) throw unrebindableChildRequestError(ctx.childPath, stateName, src, logic.mode === "stream" ? "streaming text" : "text");
520
+ if (logic.mode === "stream" && !executors.streamText) throw new Error(`runAgent: ${where} '${stateName}' invokes streaming text source '${src}' but no 'streamText' executor was provided to runAgent(...).`);
521
+ if (logic.mode !== "stream" && !executors.generateText) throw new Error(`runAgent: ${where} '${stateName}' invokes text source '${src}' but no 'generateText' executor was provided to runAgent(...).`);
522
+ continue;
523
+ }
524
+ if (require_text_logic.isUnboundPlaceholder(logic)) throw new Error(`runAgent: ${where} '${stateName}' invokes actor source '${src}', which has no host execution. Provide it via machine.provide({ actors: { '${src}': ... } }) or runAgent(machine, { actors: { '${src}': ... } }).`);
525
+ }
526
+ }
527
+ /** Descends the bind-time walk into an invoked child state machine, guarding
528
+ * against a machine that (transitively) invokes itself. */
529
+ function assertChildMachineBindable(childMachine, childSrc, stateName, executors, ctx) {
530
+ if (ctx.visited.has(childMachine)) return;
531
+ const childName = typeof childSrc === "string" ? childSrc : childMachine.config.id ?? "(child machine)";
532
+ const childPath = ctx.childPath ? `${ctx.childPath} > ${childName}` : childName;
533
+ const childSources = childMachine.sources.actors;
534
+ assertMachineBindable(childMachine, childSources, executors, {
535
+ isChild: true,
536
+ childPath,
537
+ rebindable: ctx.rebindable && typeof childSrc === "string",
538
+ visited: new Set([...ctx.visited, childMachine])
539
+ });
540
+ }
541
+ /** The loud bind-time error for an unbound agent request reached under a
542
+ * direct-object invoke src, which runAgent cannot rebind (only string-keyed
543
+ * sources can be swapped via `.provide`). Names the invoke chain AND the
544
+ * request src, and spells out the `.withExecutor`/string-keyed remedy. Note:
545
+ * requests reachable through string-keyed srcs at any depth DO inherit
546
+ * runAgent's executors — this error is only for the unrebindable direct-object
547
+ * case. */
548
+ function unrebindableChildRequestError(childPath, stateName, requestSrc, kind) {
549
+ return /* @__PURE__ */ new Error(`runAgent: child machine '${childPath}' (state '${stateName}') invokes ${kind} source '${requestSrc}', which has no host execution and is reached through a direct-object invoke src that runAgent cannot rebind. Requests reached through string-keyed actor sources inherit runAgent's generateText/streamText/decide executors automatically; a direct-object child machine does not. Either bind the request with its own executor (requestLogic.withExecutor(...)), or register the child as a string-keyed actor source (machine.provide({ actors: { <child>: childMachine } })) and invoke it by name.`);
550
+ }
551
+ /**
552
+ * True when the snapshot's active states declare a transition that would
553
+ * receive the reserved `'@agent.usage'` type — an explicit `on: { '@agent.usage'
554
+ * }` OR a catch-all `on: { '*': … }`. Plain XState semantics apply unmodified:
555
+ * a wildcard matches every event delivered to the machine, reserved ones
556
+ * included. (The MODEL-facing side stays closed: `getAcceptedEvents` drops
557
+ * `@agent.*` before any `allowedEvents` matching, so a wildcard never offers
558
+ * the reserved event as a decision candidate.) @internal
559
+ */
560
+ function declaresUsageTransition(snapshot) {
561
+ return (0, xstate.getNextTransitions)(snapshot).some((transition) => transition.eventType === "@agent.usage" || transition.eventType === "*");
562
+ }
563
+ /**
564
+ * Builds the ONE place a trace payload is emitted: it hands the payload to the
565
+ * envelope-stamping trace sink and, from that same payload, invokes the sugar
566
+ * callbacks that are projections of it — {@link RunAgentOptions.onChunk},
567
+ * {@link RunAgentOptions.onResult}, {@link RunAgentOptions.onTransition}. Each
568
+ * keeps its historical position relative to the trace: `onResult` fires just
569
+ * BEFORE its `request.end`, `onChunk`/`onTransition` just AFTER their
570
+ * `stream.chunk`/`machine.transition`. Sugar dispatch never depends on whether
571
+ * a trace sink is present, and the trace sink is never called when it is
572
+ * absent — so an `onTrace`-less run still mints no envelope (and advances no
573
+ * `seq`). @internal
574
+ */
575
+ function createTraceDispatch(sinks) {
576
+ return (payload, self) => {
577
+ switch (payload.type) {
578
+ case "stream.chunk":
579
+ sinks.onTrace?.(payload, self);
580
+ sinks.onChunk?.(payload.chunk, { request: payload.request });
581
+ return;
582
+ case "request.end":
583
+ sinks.onResult?.(payload.request, {
584
+ result: payload.output,
585
+ raw: payload.raw
586
+ });
587
+ sinks.onTrace?.(payload, self);
588
+ return;
589
+ case "machine.transition":
590
+ sinks.onTrace?.(payload, self);
591
+ sinks.onTransition?.(payload.snapshot, payload.event);
592
+ return;
593
+ default: sinks.onTrace?.(payload, self);
594
+ }
595
+ };
596
+ }
597
+ /** Reads the durable invoke id/src off the async actor's own ref (`self`). */
598
+ function selfIdAndSrc(self) {
599
+ return {
600
+ id: typeof self?.id === "string" ? self.id : "",
601
+ src: typeof self?.src === "string" ? self.src : ""
602
+ };
603
+ }
604
+ /**
605
+ * The machine actor that INVOKED a decision request — the actor whose
606
+ * live snapshot supplies the candidate events and drives `canTake`/`send`.
607
+ * For a top-level request this is the root actor (identity-equal to
608
+ * `runCtx.actorHolder.actorRef`); for a request inside an invoked child
609
+ * machine it is that child's actor, so a child decision reads and drives
610
+ * the CHILD's snapshot — not the root's. Read off `self._parent`, with the
611
+ * root actor as a fallback.
612
+ */
613
+ function invokingActorOf(self, runCtx) {
614
+ return self?._parent ?? runCtx.actorHolder.actorRef;
615
+ }
616
+ /**
617
+ * The shared text/stream emission helper: binds a {@link TextLogic} to
618
+ * `runCtx`'s executor and constructs the `request.start` / `stream.chunk` /
619
+ * `request.end` (incl. the lifted `reasoning`) / `request.error` trace payloads.
620
+ * Used by both `runAgent` and `provideExecutors` so the two paths produce
621
+ * identical event shapes by construction. @internal
622
+ */
623
+ function bindTextLogic(logic, runCtx) {
624
+ return logic.withExecutor(async ({ request: rawRequest, self: selfArg, signal }) => {
625
+ const self = selfArg;
626
+ const { id, src } = selfIdAndSrc(self);
627
+ const request = {
628
+ ...rawRequest,
629
+ name: rawRequest.name ?? (src !== "" && src !== "agent.generateText" && src !== "agent.streamText" ? src : id || src)
630
+ };
631
+ const executor = logic.mode === "stream" ? runCtx.streamText : runCtx.generateText;
632
+ if (!executor) throw new Error(`No '${logic.mode === "stream" ? "streamText" : "generateText"}' executor provided.`);
633
+ const requestWithTools = {
634
+ ...request,
635
+ tools: request.tools ?? {}
636
+ };
637
+ const agentRequest = {
638
+ kind: "text",
639
+ id,
640
+ src,
641
+ mode: logic.mode,
642
+ input: request,
643
+ tools: requestWithTools.tools,
644
+ events: []
645
+ };
646
+ runCtx.consumeModelCall();
647
+ runCtx.emitTrace?.({
648
+ type: "request.start",
649
+ request: agentRequest
650
+ }, self);
651
+ try {
652
+ const callKey = id !== "" ? runCtx.callKey?.(id, self) : void 0;
653
+ await runCtx.awaitJournal?.();
654
+ const raw = await executor(requestWithTools, {
655
+ onChunk: (chunk) => {
656
+ runCtx.emitTrace?.({
657
+ type: "stream.chunk",
658
+ request: agentRequest,
659
+ chunk
660
+ }, self);
661
+ },
662
+ signal,
663
+ ...runCtx.runId !== void 0 ? { runId: runCtx.runId } : {},
664
+ ...id !== "" ? { requestId: id } : {},
665
+ ...callKey !== void 0 ? { callKey } : {}
666
+ });
667
+ const output = await require_text_logic.normalizeGeneratorResult(raw, id);
668
+ const rawReasoning = raw?.reasoning;
669
+ const reasoning = typeof rawReasoning === "string" ? rawReasoning : void 0;
670
+ const usage = require_text_logic.getCallUsage(raw);
671
+ const finishReason = require_text_logic.getCallFinishReason(raw);
672
+ if (usage) runCtx.recordUsage?.(usage, {
673
+ kind: "text",
674
+ ...id !== "" ? { id } : {},
675
+ ...src !== "" ? { src } : {},
676
+ model: request.model,
677
+ ...request.name !== void 0 ? { name: request.name } : {}
678
+ }, self);
679
+ runCtx.emitTrace?.({
680
+ type: "request.end",
681
+ request: agentRequest,
682
+ output,
683
+ raw,
684
+ ...reasoning !== void 0 ? { reasoning } : {},
685
+ ...usage !== void 0 ? { usage } : {},
686
+ ...finishReason !== void 0 ? { finishReason } : {}
687
+ }, self);
688
+ return {
689
+ result: output,
690
+ messages: require_text_logic.responseMessagesOf(raw)
691
+ };
692
+ } catch (error) {
693
+ runCtx.emitTrace?.({
694
+ type: "request.error",
695
+ request: agentRequest,
696
+ error
697
+ }, self);
698
+ throw error;
699
+ }
700
+ });
701
+ }
702
+ function createCountingDecide(runCtx, self) {
703
+ return async (attemptRequest, info) => {
704
+ runCtx.consumeModelCall();
705
+ runCtx.emitTrace?.({
706
+ type: "request.start",
707
+ request: attemptRequest
708
+ }, self);
709
+ try {
710
+ const { id } = selfIdAndSrc(self);
711
+ const invokeCallKey = id !== "" ? runCtx.callKey?.(id, self) : void 0;
712
+ const callKey = invokeCallKey === void 0 ? void 0 : `${invokeCallKey}.${attemptRequest.attempts?.length ?? 0}`;
713
+ await runCtx.awaitJournal?.();
714
+ const result = await runCtx.decide(runCtx.runId !== void 0 ? {
715
+ ...attemptRequest,
716
+ runId: runCtx.runId
717
+ } : attemptRequest, {
718
+ ...info,
719
+ ...runCtx.runId !== void 0 ? { runId: runCtx.runId } : {},
720
+ ...info?.requestId === void 0 && id !== "" ? { requestId: id } : {},
721
+ ...info?.callKey === void 0 && callKey !== void 0 ? { callKey } : {}
722
+ });
723
+ const usage = require_text_logic.getCallUsage(result);
724
+ const finishReason = require_text_logic.getCallFinishReason(result);
725
+ if (usage) {
726
+ const { src } = selfIdAndSrc(self);
727
+ runCtx.recordUsage?.(usage, {
728
+ kind: "decision",
729
+ ...attemptRequest.id ? { id: attemptRequest.id } : {},
730
+ ...src !== "" ? { src } : {},
731
+ model: attemptRequest.model
732
+ }, self);
733
+ }
734
+ runCtx.emitTrace?.({
735
+ type: "request.end",
736
+ request: attemptRequest,
737
+ output: result.event,
738
+ raw: result,
739
+ ...usage !== void 0 ? { usage } : {},
740
+ ...finishReason !== void 0 ? { finishReason } : {}
741
+ }, self);
742
+ return result;
743
+ } catch (error) {
744
+ runCtx.emitTrace?.({
745
+ type: "request.error",
746
+ request: attemptRequest,
747
+ error
748
+ }, self);
749
+ throw error;
750
+ }
751
+ };
752
+ }
753
+ /**
754
+ * Builds the decision actor logic runAgent installs in place of a
755
+ * `DecisionLogic`/`agent.decide` source. `DecisionLogic.withExecutor(...)`
756
+ * can only swap the innermost per-attempt executor — the `resolveDecision(...)`
757
+ * call (and its `canTake`) is hardwired inside the original logic's `run`.
758
+ * To supply `canTake` (mode-3, §2.6), runAgent instead builds a fresh async
759
+ * logic here that calls `resolveDecision` itself, reusing `logic.request(...)`
760
+ * to build the request the same way the original logic would have.
761
+ *
762
+ * On success it SENDS the chosen event to the invoking actor (auto-delivery)
763
+ * and then completes with that event
764
+ * as its output — so callers never wire an `onDone` to deliver it. See the
765
+ * send-then-complete note inside `run` for how exit-cancels-invoke interacts
766
+ * with `onDone`.
767
+ */
768
+ function bindDecisionLogic(logic, runCtx) {
769
+ const decisionLogic = (0, xstate.createAsyncLogic)({ run: async ({ input, signal, self: selfArg }) => {
770
+ if (!runCtx.decide) throw new Error("No 'decide' executor provided.");
771
+ const self = selfArg;
772
+ const { id } = selfIdAndSrc(self);
773
+ const declaredEventTypes = logic.allowedEventTypes?.(input);
774
+ await Promise.resolve();
775
+ const actorRef = invokingActorOf(self, runCtx);
776
+ const events = actorRef ? require_decision.getAcceptedEvents(actorRef.getSnapshot(), {
777
+ schemas: runCtx.schemas,
778
+ eventTypes: declaredEventTypes
779
+ }) : [];
780
+ const lowered = logic.request(input);
781
+ const chosen = await require_decision.resolveDecision({
782
+ ...lowered,
783
+ id,
784
+ name: lowered.name ?? id,
785
+ input,
786
+ events
787
+ }, { decide: createCountingDecide(runCtx, self) }, {
788
+ maxRetries: logic.maxRetries,
789
+ signal,
790
+ canTake: (event) => actorRef ? actorRef.getSnapshot().can(event) : true
791
+ });
792
+ actorRef?.send(chosen);
793
+ await Promise.resolve();
794
+ return chosen;
795
+ } });
796
+ return Object.assign(decisionLogic, {
797
+ kind: "statelyai.decisionLogic",
798
+ maxRetries: logic.maxRetries,
799
+ request: logic.request,
800
+ withExecutor: (nextExecute) => bindDecisionLogic(logic.withExecutor(nextExecute), runCtx)
801
+ });
802
+ }
803
+ /**
804
+ * The set of string-keyed actor `src`s the machine's own config invokes
805
+ * (top-level, recursing into child STATES but not into invoked child
806
+ * machines). {@link provideExecutors} uses it to require an executor only for a
807
+ * source the machine actually invokes — the always-registered `agent.*`
808
+ * builtins that go unused must not force their executors to be supplied.
809
+ * @internal
810
+ */
811
+ function getConfiguredInvokeSrcs(machine) {
812
+ const invokes = [];
813
+ collectConfiguredInvokeSrcs(machine.config, machine.config.id ?? "(root)", invokes);
814
+ const srcs = /* @__PURE__ */ new Set();
815
+ for (const { src } of invokes) if (typeof src === "string") srcs.add(src);
816
+ return srcs;
817
+ }
818
+ const rootTraceRegistry = /* @__PURE__ */ new WeakMap();
819
+ let nextProvideRunId = 1;
820
+ /** Walks `self._parent` from an invoked async leaf actor up to its root actor. */
821
+ function rootActorOf(self) {
822
+ let ref = self;
823
+ while (ref?._parent) ref = ref._parent;
824
+ return ref;
825
+ }
826
+ /** The per-root envelope state, minted on first use (runId `run_<n>`, matching runAgent). */
827
+ function rootTraceState(root) {
828
+ let state = rootTraceRegistry.get(root);
829
+ if (!state) {
830
+ const logic = root.logic;
831
+ const machineId = (logic?.config)?.id ?? logic?.id ?? "(machine)";
832
+ const machineVersion = logic ? require_text_logic.resolveMachineVersion(logic) : "";
833
+ state = {
834
+ runId: `run_${nextProvideRunId++}`,
835
+ seq: 0,
836
+ machineId,
837
+ machineVersion
838
+ };
839
+ rootTraceRegistry.set(root, state);
840
+ }
841
+ return state;
842
+ }
843
+ /** Stamps a per-root-actor envelope onto a bare trace payload. */
844
+ function stampRootTrace(root, payload) {
845
+ const state = rootTraceState(root);
846
+ return {
847
+ schemaVersion: 1,
848
+ runId: state.runId,
849
+ seq: ++state.seq,
850
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
851
+ machineId: state.machineId,
852
+ machineVersion: state.machineVersion,
853
+ ...payload
854
+ };
855
+ }
856
+ /** Adapts a public `onTrace` into the payload-level trace sink a {@link TraceDispatch} fans out to. */
857
+ function provideTraceSink(onTrace) {
858
+ if (!onTrace) return;
859
+ return (payload, self) => {
860
+ const root = rootActorOf(self);
861
+ if (root) onTrace(stampRootTrace(root, payload));
862
+ };
863
+ }
864
+ /**
865
+ * A minimal {@link RunAgentBindContext} for `provideExecutors` (uncontrolled
866
+ * `createActor`): the same wrappers runAgent installs, MINUS the run-scoped
867
+ * model-call counter. `consumeModelCall` is a no-op (no budget), and
868
+ * `actorHolder.actorRef` is left undefined — the wrappers read the invoking
869
+ * actor off `self._parent`, always present under a live `createActor` tree.
870
+ * `onTrace` (when given) mints a per-root-actor envelope. `schemas` come from
871
+ * the machine's registered `setupAgent` execution options.
872
+ *
873
+ * `recordUsage` has no run-level aggregate to fold into here (there is no
874
+ * run), so it does one thing: deliver the reserved `@agent.usage` event, gated
875
+ * exactly like runAgent's — see {@link deliverUsageEvent}.
876
+ */
877
+ function provideBindContext(machine, executors, options) {
878
+ const traceSink = provideTraceSink(options.onTrace);
879
+ const onChunk = options.onChunk;
880
+ return {
881
+ generateText: executors.generateText,
882
+ streamText: executors.streamText,
883
+ decide: executors.decide,
884
+ emitTrace: traceSink || onChunk ? createTraceDispatch({
885
+ onTrace: traceSink,
886
+ onChunk: onChunk ? (chunk) => onChunk(chunk) : void 0
887
+ }) : void 0,
888
+ consumeModelCall: () => {},
889
+ recordUsage: (usage, source, self) => {
890
+ deliverUsageEvent({
891
+ type: require_usage.AGENT_USAGE_EVENT_TYPE,
892
+ ...source,
893
+ usage
894
+ }, () => self?._parent);
895
+ },
896
+ actorHolder: { actorRef: void 0 },
897
+ schemas: require_text_logic.getRegisteredAgentExecutionOptions(machine).schemas
898
+ };
899
+ }
900
+ /**
901
+ * The single reserved-`@agent.usage` DELIVERY seam, shared by both bind paths:
902
+ * after a bound call settles with reported usage, send the prebuilt `event` to
903
+ * the machine actor `resolveActorRef` names — the run's root actor on the `runAgent` path,
904
+ * the settling request actor's `self._parent` (always the invoking machine
905
+ * under a live `createActor` tree) on the `provideExecutors` path.
906
+ *
907
+ * Journaling is separate and unconditional (see `recordUsage`): a call's tokens
908
+ * are recorded in the event log whether or not the machine reacts to them.
909
+ *
910
+ * Gating is identical on both: the target snapshot must be active, must declare
911
+ * an `'@agent.usage'` transition — explicitly, or through a catch-all
912
+ * `on: { '*' }` (see {@link declaresUsageTransition}) — and must be able to
913
+ * take the event. `onDropped` is the run path's straggler gate: it returns `true` for a
914
+ * call that settled after the cycle resolved, which drops the event (traced as
915
+ * `usage.dropped`) rather than delivering it. Uncontrolled mode has no cycle to
916
+ * settle, so it passes no gate and has no dropped stragglers.
917
+ *
918
+ * Delivery follows each path's binding boundary: only sources IT bound report
919
+ * here, so an invoked child machine that was not itself passed through
920
+ * `provideExecutors` reports nothing. @internal
921
+ */
922
+ function deliverUsageEvent(event, resolveActorRef, onDropped) {
923
+ const actorRef = resolveActorRef();
924
+ if (!actorRef) return;
925
+ const snapshot = actorRef.getSnapshot();
926
+ if (snapshot?.status !== "active" || !declaresUsageTransition(snapshot)) return;
927
+ if (onDropped?.(event)) return;
928
+ if (!snapshot.can(event)) return;
929
+ actorRef.send(event);
930
+ }
931
+ /**
932
+ * Host-binds one text/stream source for {@link provideExecutors} using the SAME
933
+ * emission helper as `runAgent` ({@link bindTextLogic}), so a bound
934
+ * text request emits request.start/stream.chunk/request.end/request.error with
935
+ * identical shapes. @internal
936
+ */
937
+ function bindTextForProvide(machine, logic, executors, options) {
938
+ return bindTextLogic(logic, provideBindContext(machine, executors, options));
939
+ }
940
+ /**
941
+ * Host-binds one `DecisionLogic`/`agent.decide` source for
942
+ * {@link provideExecutors}: runAgent's decision wrapper (snapshot-driven
943
+ * candidate events, `canTake`, auto-delivery of the chosen event) with the same
944
+ * request-level tracing runAgent emits, minus run-scoped counting. @internal
945
+ */
946
+ function bindDecisionForProvide(machine, logic, executors, options) {
947
+ return bindDecisionLogic(logic, provideBindContext(machine, executors, options));
948
+ }
949
+ /**
950
+ * Recursively binds an invoked child state machine for {@link provideExecutors},
951
+ * with the same semantics `runAgent` applies ({@link rebindChildMachine}):
952
+ * string-keyed text/decision sources at any depth inherit the host executors,
953
+ * a source that carries its own executor is left alone, and a cycle is
954
+ * returned as-is. Each machine in the tree is bound with its own registered
955
+ * `setupAgent` schemas. Returns the original machine when nothing needed
956
+ * wrapping. @internal
957
+ */
958
+ function bindChildMachineForProvide(childMachine, executors, options, visited) {
959
+ const ctxFor = (target) => provideBindContext(target, executors, options);
960
+ return rebindChildMachine(childMachine, ctxFor(childMachine), visited, ctxFor);
961
+ }
962
+ /**
963
+ * Validates `input` against the machine's registered input schema, returning
964
+ * the schema's output — so defaults are filled and transforms applied before
965
+ * the value reaches `createActor` or the replayable event log.
966
+ *
967
+ * Standard Schema only (no validation library is referenced), so this works for
968
+ * whatever the machine was declared with. Omitted input stays omitted rather
969
+ * than being validated as `{}`: "started with no input" keeps meaning what it
970
+ * has always meant, instead of newly failing schemas with required fields.
971
+ */
972
+ function resolveMachineInput(machine, input) {
973
+ if (input === void 0) return input;
974
+ const schema = require_text_logic.getRegisteredAgentExecutionOptions(machine).schemas?.input;
975
+ if (!require_text_logic.isStandardSchema(schema)) return input;
976
+ try {
977
+ return require_text_logic.validateSchemaSync(schema, input);
978
+ } catch (error) {
979
+ throw new require_text_logic.AgentError("invalid-machine-input", `runAgent: machine input failed validation against the declared input schema: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
980
+ }
981
+ }
982
+ /**
983
+ * Recursively rebinds an invoked child machine's own agent sources with the
984
+ * SAME host-backed wrappers runAgent applies to the top-level machine, so a
985
+ * child's text/stream/decision requests inherit runAgent's executors and
986
+ * participate in maxModelCalls counting, onTrace/onChunk/onResult exactly like
987
+ * parent requests. Returns the child machine to invoke: a `.provide`-rebound
988
+ * copy when any inner source needed wrapping, else the original untouched.
989
+ *
990
+ * Only string-keyed sources are visited — a direct-object invoke src cannot be
991
+ * swapped via `.provide` (assertBindable already rejected an unbound request
992
+ * under one). A source that already carries its own executor
993
+ * (`executorBoundLogics`) is left as-is: explicit binding shadows inheritance.
994
+ * Cycle-safe via `visited` (a machine that invokes itself is returned as-is).
995
+ */
996
+ function rebindChildMachine(childMachine, runCtx, visited, ctxFor) {
997
+ if (visited.has(childMachine)) return childMachine;
998
+ const childVisited = new Set([...visited, childMachine]);
999
+ runCtx = ctxFor ? ctxFor(childMachine) : runCtx;
1000
+ const sources = childMachine.sources.actors;
1001
+ const wrapped = {};
1002
+ for (const [key, logic] of Object.entries(sources)) {
1003
+ if (require_decision.isDecisionLogic(logic)) {
1004
+ if (!require_text_logic.executorBoundLogics.has(logic)) wrapped[key] = bindDecisionLogic(logic, runCtx);
1005
+ continue;
1006
+ }
1007
+ if (require_text_logic.isTextLogic(logic)) {
1008
+ if (!require_text_logic.executorBoundLogics.has(logic)) wrapped[key] = bindTextLogic(logic, runCtx);
1009
+ continue;
1010
+ }
1011
+ if (isStateMachineLogic(logic)) {
1012
+ const rebound = rebindChildMachine(logic, runCtx, childVisited, ctxFor);
1013
+ if (rebound !== logic) wrapped[key] = rebound;
1014
+ continue;
1015
+ }
1016
+ }
1017
+ return Object.keys(wrapped).length > 0 ? childMachine.provide({ actors: wrapped }) : childMachine;
1018
+ }
1019
+ /**
1020
+ * Runs an agent machine to completion or idle: a `createActor` host that
1021
+ * binds `options`' host executors onto the machine's `agent.*`/`TextLogic`/
1022
+ * `DecisionLogic` actor sources, starts (or resumes) the actor, and drives
1023
+ * it until it settles — {@link RunAgentResult} `done | idle | error`. Unlike
1024
+ * the step helpers ({@link initialAgentStep} etc — a pure
1025
+ * transition-at-a-time path for durable hosts), `runAgent` owns a live actor
1026
+ * internally; there is no continuation callback, so **idle always settles**
1027
+ * and the caller resumes explicitly by passing the settled `{ snapshot,
1028
+ * event }` back in. The actor is stopped on every settle path (`done`,
1029
+ * `idle`, and `error` alike) — resume is always by snapshot, never by
1030
+ * holding a reference to a live actor.
1031
+ *
1032
+ * Binding happens **before** the actor starts: every invoke the machine
1033
+ * could reach is walked and checked against the effective actor sources
1034
+ * (`options.actors` merged onto the machine), so a missing
1035
+ * `streamText`/`decide` executor or any other unbound actor source throws
1036
+ * immediately — a bind-time error, not a mid-run failure.
1037
+ *
1038
+ * @example
1039
+ * ```ts
1040
+ * const executors = createAiSdkExecutors({ models });
1041
+ * let r = await runAgent(machine, { input, executors });
1042
+ * while (r.status === 'idle') {
1043
+ * const event = await promptUser(getAcceptedEvents(r.snapshot));
1044
+ * r = await runAgent(machine, { snapshot: r.snapshot, event, executors });
1045
+ * }
1046
+ * if (r.status !== 'done') throw new Error(`Run did not complete: ${r.status}`);
1047
+ * console.log(r.output);
1048
+ * ```
1049
+ *
1050
+ * Each executor is a plain function returning `{ result }` (plus optional `messages`/`usage`), or
1051
+ * an adapter's set: `createAiSdkExecutors` from '@statelyai/agent/ai-sdk' or
1052
+ * `createOpenAiExecutors` from '@statelyai/agent/openai' supply all three.
1053
+ */
1054
+ async function runAgent(machine, options) {
1055
+ const store = options.store;
1056
+ if (store === void 0) return createAgentSession(machine, options).settled();
1057
+ const threadId = options.threadId;
1058
+ if (threadId === void 0 || threadId === "") throw new require_text_logic.AgentError("missing-thread-id", "runAgent: `threadId` is required when `store` is given — it names the log thread to read and append to.");
1059
+ if (options.events !== void 0) {
1060
+ const storedThread = await store.read(threadId);
1061
+ if (storedThread.length !== options.events.length) throw new require_event_log_store.AgentEventLogConflictError(threadId, options.events.length, storedThread.length);
1062
+ assertThreadMatchesEvents(threadId, storedThread, options.events);
1063
+ return createAgentSession(machine, options).settled();
1064
+ }
1065
+ const stored = await store.read(threadId);
1066
+ return createAgentSession(machine, stored.length > 0 ? {
1067
+ ...options,
1068
+ events: stored
1069
+ } : options).settled();
1070
+ }
1071
+ /**
1072
+ * Entry-by-entry check that the caller's `events` IS the store's thread. Equal
1073
+ * lengths prove nothing: a fork, a rolled-back replay, or a concurrent writer
1074
+ * that appended and truncated all produce a divergent log of the same size,
1075
+ * and appending this run's entries onto it would splice two lineages together.
1076
+ */
1077
+ function assertThreadMatchesEvents(threadId, stored, events) {
1078
+ for (let index = 0; index < stored.length; index++) {
1079
+ const storedEntry = stored[index];
1080
+ const givenEntry = events[index];
1081
+ const storedHash = storedEntry.verification?.stateHash;
1082
+ const givenHash = givenEntry.verification?.stateHash;
1083
+ if (!(storedEntry.id === givenEntry.id && storedEntry.index === givenEntry.index && require_event_log_store.canonicalEventJson(storedEntry.event) === require_event_log_store.canonicalEventJson(givenEntry.event) && (storedHash === void 0 || givenHash === void 0 || storedHash === givenHash))) throw new require_text_logic.AgentError("event-log-conflict", `runAgent: the given \`events\` diverge from thread "${threadId}" at index ${index} (stored entry '${storedEntry.id}', given '${givenEntry.id}') — the log passed in is not this thread's log.`);
1084
+ }
1085
+ }
1086
+ function createAgentSession(machine, options) {
1087
+ const maxModelCalls = options.maxModelCalls ?? 100;
1088
+ let modelCallCount = 0;
1089
+ let budgetExceeded = false;
1090
+ let warnedNonSerializable = false;
1091
+ const runId = `run_${nextRunAgentTraceId++}`;
1092
+ let traceSeq = 0;
1093
+ const resolvedInput = resolveMachineInput(machine, options.input);
1094
+ const machineId = machine.config.id ?? machine.id ?? "(machine)";
1095
+ const machineVersion = require_text_logic.resolveMachineVersion(machine);
1096
+ const onTrace = createTraceDispatch({
1097
+ onTrace: (payload) => {
1098
+ options.onTrace?.({
1099
+ schemaVersion: 1,
1100
+ runId,
1101
+ seq: ++traceSeq,
1102
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1103
+ machineId,
1104
+ machineVersion,
1105
+ ...payload
1106
+ });
1107
+ },
1108
+ onChunk: options.onChunk,
1109
+ onResult: options.onResult,
1110
+ onTransition: options.onTransition
1111
+ });
1112
+ const consumeModelCall = () => {
1113
+ if (budgetExceeded) throw new AgentMaxModelCallsExceededError(maxModelCalls);
1114
+ if (modelCallCount + 1 > maxModelCalls) {
1115
+ budgetExceeded = true;
1116
+ throw new AgentMaxModelCallsExceededError(maxModelCalls);
1117
+ }
1118
+ modelCallCount += 1;
1119
+ };
1120
+ const cycleGate = { isResolved: () => false };
1121
+ const logEntries = [];
1122
+ const store = options.store;
1123
+ const threadId = options.threadId;
1124
+ if (store !== void 0 && (threadId === void 0 || threadId === "")) throw new require_text_logic.AgentError("missing-thread-id", "runAgent: `threadId` is required when `store` is given — it names the log thread to read and append to.");
1125
+ let journalChain = Promise.resolve();
1126
+ let journalPending = 0;
1127
+ let journalError;
1128
+ const journalEntry = (entry) => {
1129
+ if (store === void 0) return;
1130
+ journalPending++;
1131
+ journalChain = journalChain.then(async () => {
1132
+ if (journalError !== void 0) return;
1133
+ await store.append({
1134
+ threadId,
1135
+ expectedIndex: entry.index,
1136
+ entries: [entry]
1137
+ });
1138
+ }).catch((error) => {
1139
+ journalError ??= error;
1140
+ failRunOnJournalError(error);
1141
+ }).finally(() => {
1142
+ journalPending--;
1143
+ });
1144
+ };
1145
+ /**
1146
+ * Every journal write ISSUED SO FAR, including the stragglers appended after
1147
+ * the run settled. Re-reads the chain tail until it stops moving, so a write
1148
+ * queued while an earlier one was in flight is covered too. Never rejects: a
1149
+ * failed write already settled the run with `cause: 'journal'`.
1150
+ */
1151
+ const drainJournal = async () => {
1152
+ if (store === void 0) return;
1153
+ let tail = journalChain;
1154
+ for (;;) {
1155
+ await tail;
1156
+ if (journalPending === 0 && journalChain === tail) return;
1157
+ tail = journalChain;
1158
+ }
1159
+ };
1160
+ /** The barrier: settle the pending chain, then surface any failure. */
1161
+ const awaitJournal = async () => {
1162
+ if (store === void 0) return;
1163
+ while (journalPending > 0) await journalChain;
1164
+ if (journalError !== void 0) throw journalError;
1165
+ };
1166
+ const failRunOnJournalError = (error) => {
1167
+ if (settled) return;
1168
+ settle({
1169
+ status: "error",
1170
+ cause: "journal",
1171
+ error,
1172
+ snapshot: actor.getSnapshot()
1173
+ });
1174
+ };
1175
+ let resumedLogLength = 0;
1176
+ let logExecutionId;
1177
+ const verificationEnabled = options.verification !== false;
1178
+ let lastRootSnapshot;
1179
+ let logMachine = machine;
1180
+ let loggingEnabled = true;
1181
+ const appendLogEntry = (event, snapshot) => {
1182
+ if (!loggingEnabled) return;
1183
+ const entry = require_event_log_store.createReplayEntry(logMachine, logEntries, event, {
1184
+ machineVersion,
1185
+ verification: verificationEnabled,
1186
+ ...verificationEnabled && snapshot !== void 0 ? { snapshot } : {}
1187
+ });
1188
+ logEntries.push(entry);
1189
+ journalEntry(entry);
1190
+ options.onEvent?.(entry);
1191
+ return entry;
1192
+ };
1193
+ const usageEntrySnapshot = () => {
1194
+ const current = lastRootSnapshot;
1195
+ if (current && (current.status !== "active" || !declaresUsageTransition(current))) return current;
1196
+ };
1197
+ const recordUsage = (usage, source = {}) => {
1198
+ const event = {
1199
+ type: require_usage.AGENT_USAGE_EVENT_TYPE,
1200
+ ...source,
1201
+ usage
1202
+ };
1203
+ const journal = { event };
1204
+ pendingUsageJournal = journal;
1205
+ try {
1206
+ deliverUsageEvent(event, () => actorHolder.actorRef, (dropped) => {
1207
+ if (!cycleGate.isResolved()) return false;
1208
+ onTrace({
1209
+ type: "usage.dropped",
1210
+ event: dropped,
1211
+ reason: "settled"
1212
+ });
1213
+ return true;
1214
+ });
1215
+ } finally {
1216
+ pendingUsageJournal = void 0;
1217
+ }
1218
+ if (journal.entry === void 0) appendLogEntry(event, usageEntrySnapshot());
1219
+ };
1220
+ let pendingUsageJournal;
1221
+ const runUsage = () => ({
1222
+ ...require_event_log_store.getUsageFromEvents(logEntries.slice(resumedLogLength)),
1223
+ modelCalls: modelCallCount
1224
+ });
1225
+ const warnNonSerializableContext = (snapshot) => {
1226
+ if (warnedNonSerializable || process.env.NODE_ENV === "production") return;
1227
+ let offending = [];
1228
+ try {
1229
+ offending = require_text_logic.findNonSerializableContextPaths(snapshot.context);
1230
+ } catch {
1231
+ return;
1232
+ }
1233
+ if (offending.length === 0) return;
1234
+ warnedNonSerializable = true;
1235
+ console.warn(`runAgent: context holds value(s) that will not survive snapshot persist/resume (JSON round-trip): ${offending.join(", ")}. Persist only JSON-serializable context, or convert these before the run settles.`);
1236
+ };
1237
+ const provided = machine.provide({ actors: options.actors });
1238
+ logMachine = provided;
1239
+ const effectiveSources = provided.sources.actors;
1240
+ const executors = { ...options.executors };
1241
+ assertBindable(provided, effectiveSources, executors);
1242
+ const actorHolder = { actorRef: void 0 };
1243
+ const runCtx = {
1244
+ generateText: executors.generateText,
1245
+ streamText: executors.streamText,
1246
+ decide: executors.decide,
1247
+ emitTrace: onTrace,
1248
+ consumeModelCall,
1249
+ recordUsage,
1250
+ actorHolder,
1251
+ awaitJournal,
1252
+ runId,
1253
+ schemas: require_text_logic.getRegisteredAgentExecutionOptions(machine).schemas
1254
+ };
1255
+ const wrappedSources = {};
1256
+ for (const [key, logic] of Object.entries(effectiveSources)) {
1257
+ if (require_decision.isDecisionLogic(logic)) {
1258
+ wrappedSources[key] = bindDecisionLogic(logic, runCtx);
1259
+ continue;
1260
+ }
1261
+ if (require_text_logic.isTextLogic(logic)) {
1262
+ if (!require_text_logic.executorBoundLogics.has(logic)) wrappedSources[key] = bindTextLogic(logic, runCtx);
1263
+ continue;
1264
+ }
1265
+ if (isStateMachineLogic(logic)) {
1266
+ const rebound = rebindChildMachine(logic, runCtx, new Set([machine]));
1267
+ if (rebound !== logic) wrappedSources[key] = rebound;
1268
+ continue;
1269
+ }
1270
+ }
1271
+ const boundMachine = provided.provide({ actors: wrappedSources });
1272
+ const isIdle = require_text_logic.getMachineIdlePredicate(machine) ?? isAgentIdle;
1273
+ const isIntentionalIdle = (snapshot) => isIdle(snapshot);
1274
+ const resumeEvents = options.events;
1275
+ let effectiveSnapshot = options.snapshot;
1276
+ /** Deferred until after the illegal-resume check, so a rejected resume emits no entries. */
1277
+ let seedInitEntry;
1278
+ const restoredPersistedSnapshot = () => {
1279
+ try {
1280
+ const restored = logMachine.restoreSnapshot(options.snapshot);
1281
+ return logMachine.getPersistedSnapshot(restored);
1282
+ } catch {
1283
+ return;
1284
+ }
1285
+ };
1286
+ /**
1287
+ * Appends the log's reserved first entry, trying each candidate `init` in
1288
+ * turn and, for each, an unverified entry if the hash cannot be computed.
1289
+ * A machine or snapshot that defeats every attempt leaves the run WITHOUT a
1290
+ * log rather than failing it: `runAgent` predates the log, and an exotic
1291
+ * machine that cannot be folded must still run.
1292
+ */
1293
+ const appendInitEntry = (candidates, metadata) => {
1294
+ for (const init of candidates) for (const verification of verificationEnabled ? [true, false] : [false]) try {
1295
+ const entry = require_event_log_store.initEntry(logMachine, init, {
1296
+ machineVersion,
1297
+ verification,
1298
+ metadata
1299
+ });
1300
+ logEntries.push(entry);
1301
+ journalEntry(entry);
1302
+ options.onEvent?.(entry);
1303
+ return;
1304
+ } catch {}
1305
+ loggingEnabled = false;
1306
+ };
1307
+ /** Init forms for a snapshot resume, most faithful first. */
1308
+ const snapshotInitCandidates = () => {
1309
+ const restored = restoredPersistedSnapshot();
1310
+ return [...restored !== void 0 ? [{ snapshot: restored }] : [], { snapshot: options.snapshot }];
1311
+ };
1312
+ if (resumeEvents !== void 0 && resumeEvents.length > 0) {
1313
+ require_event_log_store.validateReplayEntries(resumeEvents);
1314
+ const tail = resumeEvents[resumeEvents.length - 1];
1315
+ const inheritedExecutionId = require_event_log_store.getLogExecutionId(resumeEvents);
1316
+ if (resumeEvents[0].machineId !== machineId) throw new require_event_log_store.AgentMachineVersionMismatchError(tail.id, tail.index, {
1317
+ machineId,
1318
+ machineVersion
1319
+ }, {
1320
+ machineId: resumeEvents[0].machineId,
1321
+ machineVersion: tail.machineVersion
1322
+ });
1323
+ if (tail.machineVersion === machineVersion) {
1324
+ logEntries.push(...resumeEvents);
1325
+ resumedLogLength = logEntries.length;
1326
+ logExecutionId = inheritedExecutionId;
1327
+ const cachedMeta = readAgentMeta(options.snapshot);
1328
+ const tailStateHash = tail.verification?.stateHash;
1329
+ if (!(options.snapshot !== void 0 && inheritedExecutionId !== void 0 && cachedMeta?.logId === inheritedExecutionId && cachedMeta.logIndex === resumeEvents.length && tailStateHash !== void 0 && hashResumeSnapshot(options.snapshot) === tailStateHash)) {
1330
+ const cachedIndex = cachedMeta?.logIndex;
1331
+ if (options.snapshot !== void 0 && typeof cachedIndex === "number" && cachedIndex >= 1 && cachedIndex <= resumeEvents.length && resumeEvents[cachedIndex - 1].verification?.stateHash !== void 0) {
1332
+ const expected = require_event_log_store.getSnapshotStateHash(require_event_log_store.replay(logMachine, resumeEvents.slice(0, cachedIndex), {
1333
+ machineVersion,
1334
+ verify: false
1335
+ }).persistedSnapshot);
1336
+ const actual = hashResumeSnapshot(options.snapshot);
1337
+ if (expected !== actual) throw new AgentSnapshotDivergedError(expected, actual, cachedIndex);
1338
+ }
1339
+ effectiveSnapshot = require_event_log_store.replay(logMachine, resumeEvents, {
1340
+ machineVersion,
1341
+ verify: true
1342
+ }).persistedSnapshot;
1343
+ }
1344
+ } else {
1345
+ if (options.snapshot === void 0) throw new require_event_log_store.AgentMachineVersionMismatchError(tail.id, tail.index, {
1346
+ machineId,
1347
+ machineVersion
1348
+ }, {
1349
+ machineId: tail.machineId,
1350
+ machineVersion: tail.machineVersion
1351
+ });
1352
+ const bridgeMeta = readAgentMeta(options.snapshot);
1353
+ if (inheritedExecutionId === void 0 || bridgeMeta?.logId !== inheritedExecutionId) throw new require_event_log_store.AgentMachineVersionMismatchError(tail.id, tail.index, {
1354
+ machineId,
1355
+ machineVersion
1356
+ }, {
1357
+ machineId: tail.machineId,
1358
+ machineVersion: tail.machineVersion
1359
+ });
1360
+ const bridgeTailHash = tail.verification?.stateHash;
1361
+ const bridgeSnapshotHash = hashResumeSnapshot(options.snapshot);
1362
+ if (bridgeMeta.logIndex !== resumeEvents.length) throw new AgentSnapshotDivergedError(bridgeTailHash ?? "(unrecorded)", bridgeSnapshotHash, resumeEvents.length);
1363
+ if (bridgeTailHash !== void 0 && bridgeSnapshotHash !== bridgeTailHash) throw new AgentSnapshotDivergedError(bridgeTailHash, bridgeSnapshotHash, resumeEvents.length);
1364
+ logExecutionId = inheritedExecutionId;
1365
+ const migratedFrom = {
1366
+ machineVersion: tail.machineVersion,
1367
+ logIndex: resumeEvents.length
1368
+ };
1369
+ seedInitEntry = () => appendInitEntry(snapshotInitCandidates(), {
1370
+ ...logExecutionId !== void 0 ? { executionId: logExecutionId } : {},
1371
+ migratedFrom
1372
+ });
1373
+ }
1374
+ } else if (options.snapshot !== void 0) {
1375
+ logExecutionId = crypto.randomUUID();
1376
+ seedInitEntry = () => appendInitEntry(snapshotInitCandidates(), { executionId: logExecutionId });
1377
+ } else {
1378
+ logExecutionId = crypto.randomUUID();
1379
+ seedInitEntry = () => appendInitEntry([resolvedInput !== void 0 ? { input: resolvedInput } : {}], { executionId: logExecutionId });
1380
+ }
1381
+ const resumedHistory = [...logEntries];
1382
+ const siteCallCounts = /* @__PURE__ */ new Map();
1383
+ const mintedCallKeys = /* @__PURE__ */ new WeakMap();
1384
+ runCtx.callKey = (siteId, self) => {
1385
+ if (logExecutionId === void 0) return;
1386
+ const memoized = self === void 0 ? void 0 : mintedCallKeys.get(self);
1387
+ if (memoized !== void 0) return memoized;
1388
+ const startedHere = siteCallCounts.get(siteId) ?? 0;
1389
+ siteCallCounts.set(siteId, startedHere + 1);
1390
+ const key = `${logExecutionId}:${siteId}#${require_event_log_store.agentCallOccurrence(resumedHistory, siteId) + startedHere}`;
1391
+ if (self !== void 0) mintedCallKeys.set(self, key);
1392
+ return key;
1393
+ };
1394
+ const resumeEventToSend = options.event;
1395
+ let ignoredEvent;
1396
+ seedInitEntry?.();
1397
+ let settled = false;
1398
+ let journalAtSettle;
1399
+ cycleGate.isResolved = () => settled;
1400
+ let lastResult;
1401
+ const waiters = [];
1402
+ let idleTimer;
1403
+ let actor;
1404
+ let actorStarted = false;
1405
+ let deliveringResumeEvent = resumeEventToSend !== void 0;
1406
+ const settle = (outcome) => {
1407
+ if (settled) return;
1408
+ settled = true;
1409
+ let persistedSnapshot;
1410
+ let persistenceError;
1411
+ if (actorStarted && outcome.status !== "done") try {
1412
+ persistedSnapshot = actor.getPersistedSnapshot();
1413
+ } catch (error) {
1414
+ persistenceError = error;
1415
+ }
1416
+ const logIndexAtSettle = logEntries.length;
1417
+ journalAtSettle = journalChain;
1418
+ const persist = () => {
1419
+ if (persistenceError !== void 0) throw persistenceError;
1420
+ persistedSnapshot ??= actor.getPersistedSnapshot();
1421
+ persistedSnapshot.agentMeta = {
1422
+ machineId,
1423
+ version: machineVersion,
1424
+ ...logExecutionId !== void 0 ? { logId: logExecutionId } : {},
1425
+ logIndex: logIndexAtSettle
1426
+ };
1427
+ return persistedSnapshot;
1428
+ };
1429
+ const result = {
1430
+ ...outcome,
1431
+ events: [...logEntries],
1432
+ persist,
1433
+ drain: drainJournal,
1434
+ usage: runUsage(),
1435
+ ...ignoredEvent !== void 0 ? { ignored: ignoredEvent } : {}
1436
+ };
1437
+ if (idleTimer !== void 0) clearTimeout(idleTimer);
1438
+ onTrace({
1439
+ type: "run.end",
1440
+ ...outcome
1441
+ });
1442
+ if (options.signal) options.signal.removeEventListener("abort", onAbort);
1443
+ actor.stop();
1444
+ lastResult = result;
1445
+ for (const resolve of waiters.splice(0)) resolve(result);
1446
+ };
1447
+ const onAbort = () => {
1448
+ settle({
1449
+ status: "error",
1450
+ cause: "aborted",
1451
+ error: options.signal?.reason ?? /* @__PURE__ */ new Error("Aborted"),
1452
+ snapshot: actor.getSnapshot()
1453
+ });
1454
+ };
1455
+ const settleIdle = (current) => {
1456
+ warnNonSerializableContext(current);
1457
+ settle({
1458
+ status: "idle",
1459
+ snapshot: current
1460
+ });
1461
+ };
1462
+ const runErrorCause = (error) => budgetExceeded ? "max-model-calls" : wrapsDecisionExhausted(error) ? "decision-exhausted" : "machine";
1463
+ const scheduleIdleCheck = () => {
1464
+ if (idleTimer !== void 0) clearTimeout(idleTimer);
1465
+ idleTimer = setTimeout(() => {
1466
+ idleTimer = void 0;
1467
+ if (settled) return;
1468
+ const current = actor.getSnapshot();
1469
+ if (isIntentionalIdle(current) && isIdleSnapshot(current)) settleIdle(current);
1470
+ }, 0);
1471
+ };
1472
+ actor = (0, xstate.createActor)(boundMachine, {
1473
+ input: resolvedInput,
1474
+ snapshot: effectiveSnapshot,
1475
+ inspect: (event) => {
1476
+ if (typeof options.inspect === "function") options.inspect(event);
1477
+ else options.inspect?.next?.(event);
1478
+ if (event.type !== "@xstate.transition" || event.actorRef !== actor.ref) return;
1479
+ if (settled) return;
1480
+ const snapshot = event.snapshot;
1481
+ lastRootSnapshot = snapshot;
1482
+ if (resumeEventToSend !== void 0 && event.event === resumeEventToSend && event.microsteps.length === 0 && event.actions.length === 0 && event.sent.length === 0) ignoredEvent = resumeEventToSend;
1483
+ if (pendingUsageJournal !== void 0 && event.event === pendingUsageJournal.event) pendingUsageJournal.entry = appendLogEntry(event.event, snapshot);
1484
+ else if (event.event.type !== "@xstate.init" && (event.sourceRef !== event.actorRef || event.event.type === "xstate.timer")) appendLogEntry(event.event, snapshot);
1485
+ onTrace({
1486
+ type: "machine.transition",
1487
+ snapshot,
1488
+ event: event.event
1489
+ });
1490
+ if (snapshot.status === "done") {
1491
+ settle({
1492
+ status: "done",
1493
+ output: snapshot.output,
1494
+ snapshot
1495
+ });
1496
+ return;
1497
+ }
1498
+ if (snapshot.status === "error") {
1499
+ settle({
1500
+ status: "error",
1501
+ cause: runErrorCause(snapshot.error),
1502
+ error: snapshot.error,
1503
+ snapshot
1504
+ });
1505
+ return;
1506
+ }
1507
+ if (snapshot.status === "stopped") {
1508
+ settle({
1509
+ status: "error",
1510
+ cause: "stopped",
1511
+ error: /* @__PURE__ */ new Error("Actor stopped externally."),
1512
+ snapshot
1513
+ });
1514
+ return;
1515
+ }
1516
+ if (!deliveringResumeEvent && isIntentionalIdle(snapshot) && isIdleSnapshot(snapshot)) {
1517
+ queueMicrotask(() => {
1518
+ if (settled) return;
1519
+ const current = actor.getSnapshot();
1520
+ if (isIntentionalIdle(current) && isIdleSnapshot(current)) settleIdle(current);
1521
+ else scheduleIdleCheck();
1522
+ });
1523
+ return;
1524
+ }
1525
+ scheduleIdleCheck();
1526
+ }
1527
+ });
1528
+ actorHolder.actorRef = actor;
1529
+ actor.subscribe({ error: () => {} });
1530
+ actor.on("*", (event) => {
1531
+ onTrace({
1532
+ type: "emit",
1533
+ event
1534
+ });
1535
+ });
1536
+ for (const [type, handler] of Object.entries(options.on ?? {})) if (typeof handler === "function") actor.on(type, handler);
1537
+ const sessionApi = { settled: async () => {
1538
+ const result = settled && lastResult !== void 0 ? lastResult : await new Promise((resolve) => {
1539
+ waiters.push(resolve);
1540
+ });
1541
+ await journalAtSettle;
1542
+ return result;
1543
+ } };
1544
+ if (options.signal) {
1545
+ if (options.signal.aborted) {
1546
+ settle({
1547
+ status: "error",
1548
+ cause: "aborted",
1549
+ error: options.signal.reason ?? /* @__PURE__ */ new Error("Aborted"),
1550
+ snapshot: actor.getSnapshot()
1551
+ });
1552
+ return sessionApi;
1553
+ }
1554
+ options.signal.addEventListener("abort", onAbort);
1555
+ }
1556
+ onTrace({
1557
+ type: "run.start",
1558
+ ...resolvedInput !== void 0 ? { input: resolvedInput } : {},
1559
+ ...effectiveSnapshot !== void 0 ? { snapshot: effectiveSnapshot } : {},
1560
+ ...resumeEventToSend !== void 0 ? { event: resumeEventToSend } : {}
1561
+ });
1562
+ actorStarted = true;
1563
+ actor.start();
1564
+ if (!settled) {
1565
+ const startedSnapshot = actor.getSnapshot();
1566
+ lastRootSnapshot ??= startedSnapshot;
1567
+ if (startedSnapshot.status === "done") settle({
1568
+ status: "done",
1569
+ output: startedSnapshot.output,
1570
+ snapshot: startedSnapshot
1571
+ });
1572
+ else if (startedSnapshot.status === "error") settle({
1573
+ status: "error",
1574
+ cause: runErrorCause(startedSnapshot.error),
1575
+ error: startedSnapshot.error,
1576
+ snapshot: startedSnapshot
1577
+ });
1578
+ else if (startedSnapshot.status === "stopped") settle({
1579
+ status: "error",
1580
+ cause: "stopped",
1581
+ error: /* @__PURE__ */ new Error("Actor stopped externally."),
1582
+ snapshot: startedSnapshot
1583
+ });
1584
+ }
1585
+ if (resumeEventToSend && !settled) {
1586
+ deliveringResumeEvent = false;
1587
+ actor.send(resumeEventToSend);
1588
+ }
1589
+ return sessionApi;
1590
+ }
1591
+ /**
1592
+ * Wraps a `(snapshot, actorRef) => void` handler into a function usable as
1593
+ * {@link RunAgentOptions.inspect}: it filters the raw inspection stream to
1594
+ * `@xstate.transition` events and hands the handler the typed
1595
+ * {@link AnyMachineSnapshot} and the {@link InspectedActorRef} that
1596
+ * transitioned. Attribute a child actor via `actorRef.id`/`actorRef.src`. Saves
1597
+ * the manual `event.type === '@xstate.transition'` filtering and the snapshot/
1598
+ * actorRef casts.
1599
+ */
1600
+ function inspectTransitions(handler) {
1601
+ return (inspectionEvent) => {
1602
+ if (inspectionEvent.type !== "@xstate.transition") return;
1603
+ handler(inspectionEvent.snapshot, inspectionEvent.actorRef);
1604
+ };
1605
+ }
1606
+ /**
1607
+ * An xstate `inspect` handler that emits `machine.transition` trace events onto
1608
+ * `onTrace`, sharing the SAME versioned envelope and per-root-actor `seq`
1609
+ * registry as {@link provideExecutors}' `onTrace`. Pair the two on one actor to
1610
+ * get a single ordered trace stream (request + transition events) for the
1611
+ * uncontrolled path:
1612
+ *
1613
+ * ```ts
1614
+ * const bound = provideExecutors(machine, executors, { onTrace });
1615
+ * const actor = createActor(bound, { inspect: traceTransitions(onTrace) });
1616
+ * ```
1617
+ *
1618
+ * Only ROOT-actor transitions are traced (matching `runAgent`'s
1619
+ * `machine.transition`); child-actor transitions are ignored. Attribute the
1620
+ * event via its envelope `runId`.
1621
+ *
1622
+ * By design this path has NO `run.start`/`run.end` events: `createActor` has no
1623
+ * run boundary the way `runAgent` does, so the stream starts at the actor's
1624
+ * first transition. It also does NOT emit `emit` trace events: in this xstate
1625
+ * build emitted events are delivered through `actor.on(...)`, not the inspection
1626
+ * protocol, so they are not observable from an `inspect` handler — subscribe
1627
+ * with `actor.on('*', ...)` if you need them.
1628
+ */
1629
+ function traceTransitions(onTrace) {
1630
+ return (inspectionEvent) => {
1631
+ if (inspectionEvent.type !== "@xstate.transition") return;
1632
+ const actorRef = inspectionEvent.actorRef;
1633
+ if (actorRef?._parent) return;
1634
+ onTrace(stampRootTrace(actorRef, {
1635
+ type: "machine.transition",
1636
+ snapshot: inspectionEvent.snapshot,
1637
+ event: inspectionEvent.event
1638
+ }));
1639
+ };
1640
+ }
1641
+ function isIdleSnapshot(snapshot) {
1642
+ if (snapshot.status !== "active") return false;
1643
+ if (Object.values(snapshot.children ?? {}).some((child) => {
1644
+ const childSnapshot = child?.getSnapshot?.();
1645
+ if (childSnapshot?.status !== "active") return false;
1646
+ if ((0, xstate.isMachineSnapshot)(childSnapshot)) return !isIdleSnapshot(childSnapshot);
1647
+ return true;
1648
+ })) return false;
1649
+ return !(0, xstate.getNextTransitions)(snapshot).some((transitionDef) => transitionDef.eventType === "" || transitionDef.eventType.startsWith("xstate.after"));
1650
+ }
1651
+ /**
1652
+ * Default machine-owned idle signal used by {@link runAgent}: an active
1653
+ * snapshot that accepts an external event anywhere in its active hierarchy,
1654
+ * or declares interaction metadata on an active state.
1655
+ *
1656
+ * Compose this in `setupAgent({ isIdle })` when the application has additional
1657
+ * wait states: `isIdle: (snapshot) => isAgentIdle(snapshot) || snapshot.hasTag('waiting')`.
1658
+ * Pending work and active invoked children are checked separately by the
1659
+ * runner, so this function only answers whether the state is an intentional
1660
+ * external wait.
1661
+ */
1662
+ function isAgentIdle(snapshot) {
1663
+ if (snapshot.status !== "active") return false;
1664
+ return snapshot.nodes.some((node) => {
1665
+ const meta = node.meta;
1666
+ return typeof meta === "object" && meta !== null && "interaction" in meta;
1667
+ }) || require_decision.getAcceptedEvents(snapshot).length > 0;
1668
+ }
1669
+ //#endregion
1670
+ Object.defineProperty(exports, "AGENT_TRACE_SCHEMA_VERSION", {
1671
+ enumerable: true,
1672
+ get: function() {
1673
+ return AGENT_TRACE_SCHEMA_VERSION;
1674
+ }
1675
+ });
1676
+ Object.defineProperty(exports, "AgentMaxModelCallsExceededError", {
1677
+ enumerable: true,
1678
+ get: function() {
1679
+ return AgentMaxModelCallsExceededError;
1680
+ }
1681
+ });
1682
+ Object.defineProperty(exports, "AgentSnapshotDivergedError", {
1683
+ enumerable: true,
1684
+ get: function() {
1685
+ return AgentSnapshotDivergedError;
1686
+ }
1687
+ });
1688
+ Object.defineProperty(exports, "bindChildMachineForProvide", {
1689
+ enumerable: true,
1690
+ get: function() {
1691
+ return bindChildMachineForProvide;
1692
+ }
1693
+ });
1694
+ Object.defineProperty(exports, "bindDecisionForProvide", {
1695
+ enumerable: true,
1696
+ get: function() {
1697
+ return bindDecisionForProvide;
1698
+ }
1699
+ });
1700
+ Object.defineProperty(exports, "bindTextForProvide", {
1701
+ enumerable: true,
1702
+ get: function() {
1703
+ return bindTextForProvide;
1704
+ }
1705
+ });
1706
+ Object.defineProperty(exports, "executeAgentRequest", {
1707
+ enumerable: true,
1708
+ get: function() {
1709
+ return executeAgentRequest;
1710
+ }
1711
+ });
1712
+ Object.defineProperty(exports, "getConfiguredInvokeSrcs", {
1713
+ enumerable: true,
1714
+ get: function() {
1715
+ return getConfiguredInvokeSrcs;
1716
+ }
1717
+ });
1718
+ Object.defineProperty(exports, "getPendingInvokes", {
1719
+ enumerable: true,
1720
+ get: function() {
1721
+ return getPendingInvokes;
1722
+ }
1723
+ });
1724
+ Object.defineProperty(exports, "initialAgentStep", {
1725
+ enumerable: true,
1726
+ get: function() {
1727
+ return initialAgentStep;
1728
+ }
1729
+ });
1730
+ Object.defineProperty(exports, "inspectTransitions", {
1731
+ enumerable: true,
1732
+ get: function() {
1733
+ return inspectTransitions;
1734
+ }
1735
+ });
1736
+ Object.defineProperty(exports, "isAgentIdle", {
1737
+ enumerable: true,
1738
+ get: function() {
1739
+ return isAgentIdle;
1740
+ }
1741
+ });
1742
+ Object.defineProperty(exports, "isStateMachineLogic", {
1743
+ enumerable: true,
1744
+ get: function() {
1745
+ return isStateMachineLogic;
1746
+ }
1747
+ });
1748
+ Object.defineProperty(exports, "rejectAgentStep", {
1749
+ enumerable: true,
1750
+ get: function() {
1751
+ return rejectAgentStep;
1752
+ }
1753
+ });
1754
+ Object.defineProperty(exports, "resolveAgentStep", {
1755
+ enumerable: true,
1756
+ get: function() {
1757
+ return resolveAgentStep;
1758
+ }
1759
+ });
1760
+ Object.defineProperty(exports, "runAgent", {
1761
+ enumerable: true,
1762
+ get: function() {
1763
+ return runAgent;
1764
+ }
1765
+ });
1766
+ Object.defineProperty(exports, "serializeTraceEvent", {
1767
+ enumerable: true,
1768
+ get: function() {
1769
+ return serializeTraceEvent;
1770
+ }
1771
+ });
1772
+ Object.defineProperty(exports, "traceTransitions", {
1773
+ enumerable: true,
1774
+ get: function() {
1775
+ return traceTransitions;
1776
+ }
1777
+ });
1778
+ Object.defineProperty(exports, "transitionAgentStep", {
1779
+ enumerable: true,
1780
+ get: function() {
1781
+ return transitionAgentStep;
1782
+ }
1783
+ });