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

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 +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 +285 -170
  38. package/dist/testing.d.cts +39 -22
  39. package/dist/testing.d.mts +39 -22
  40. package/dist/testing.mjs +270 -155
  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-C1p37X_c.d.mts → utils-_q7F-AZu.d.mts} +3 -103
  48. package/dist/{utils-RalRn9sk.d.cts → utils-o4YRdHJX.d.cts} +3 -103
  49. package/dist/validate.cjs +0 -8
  50. package/dist/validate.mjs +0 -8
  51. package/package.json +5 -4
  52. package/readme.md +8 -4
  53. package/schemas/agent-workflow.json +0 -8
package/dist/testing.mjs CHANGED
@@ -1,6 +1,251 @@
1
- import { H as AgentError, P as getStateMeta, S as getRegisteredAgentExecutionOptions, d as getCallUsage, f as isTextLogic, p as normalizeGeneratorResult, y as executorBoundLogics } from "./text-logic-Bl_ZRxDi.mjs";
2
- import { a as isDecisionLogic, d as isRecord, l as getAcceptedEvents, s as resolveDecision, t as AgentDecisionExhaustedError } from "./decision-DzSv1NpD.mjs";
3
- import { _ as rejectAgentStep, d as runAgent, g as initialAgentStep, h as getPendingInvokes, v as resolveAgentStep, y as transitionAgentStep } from "./run-agent-DvDQd4If.mjs";
1
+ import { b as getRegisteredAgentExecutionOptions, d as isTextLogic, f as normalizeGeneratorResult, j as getStateMeta, u as getCallUsage, v as executorBoundLogics, z as AgentError } from "./text-logic-CIqHAmBi.mjs";
2
+ import { a as isDecisionLogic, d as isRecord, l as getAcceptedEvents, s as resolveDecision, t as AgentDecisionExhaustedError } from "./decision-RQ0iv0oZ.mjs";
3
+ import { f as runToQuiescence, s as createAgentRuntime } from "./run-agent-xNTxpt82.mjs";
4
+ import { initialTransition, transition } from "xstate";
5
+ //#region src/steps.ts
6
+ /**
7
+ * Internal: the pure `(state, event) => (nextState, requests)` view of an
8
+ * agent machine, used by model-free simulation (`simulateAgent`) and tests.
9
+ * An {@link AgentStep} is a snapshot plus the model requests the machine is
10
+ * now waiting on; nothing here executes anything. Hosts use
11
+ * `createAgentRuntime`.
12
+ * @module
13
+ */
14
+ /** @internal Normalizes current and legacy XState invoke effect shapes. */
15
+ function getInvokeEffectMetadata(action) {
16
+ if (action.type === "@xstate.spawn") return action;
17
+ if (action.type === "xstate.spawnChild") {
18
+ const params = action.params;
19
+ return params ? {
20
+ ...params,
21
+ logic: action.logic
22
+ } : void 0;
23
+ }
24
+ if (action.type === "@xstate.start" && typeof action.src === "string") return action;
25
+ }
26
+ /**
27
+ * The invokes a snapshot is still waiting on, lowered to the same spawn-effect
28
+ * shape {@link getAgentRequests} reads. Derived from the snapshot's live
29
+ * children rather than the last transition's actions, so a state that invokes
30
+ * several actors at once (an `invoke: [...]` array, or parallel regions each
31
+ * invoking) keeps reporting the siblings after the first one settles —
32
+ * including when the settled invoke's `onDone` is targetless and starts
33
+ * nothing new.
34
+ *
35
+ * Entries are ordered by invoke id, so a walker that resolves one invoke per
36
+ * step is deterministic.
37
+ *
38
+ * @internal
39
+ */
40
+ function getPendingInvokes(snapshot) {
41
+ const children = snapshot.children ?? {};
42
+ return Object.keys(children).sort().flatMap((id) => {
43
+ const child = children[id];
44
+ const childSnapshot = child?.getSnapshot?.();
45
+ if (!child || childSnapshot?.status !== "active") return [];
46
+ return [{
47
+ type: "@xstate.spawn",
48
+ id,
49
+ src: child.src,
50
+ input: childSnapshot.input,
51
+ logic: child.logic
52
+ }];
53
+ });
54
+ }
55
+ /**
56
+ * Scans a set of executable actions (as returned by xstate's `transition`/
57
+ * `initialTransition`) for spawned `TextLogic`/`DecisionLogic` invokes and
58
+ * lowers each into an {@link AgentStepRequest}. Pass `options.machine` to
59
+ * pre-fill `schemas`/`actors` from the machine's registered `setupAgent`
60
+ * options instead of passing them by hand.
61
+ * `options.snapshot` is required to resolve a decision's candidate events
62
+ * (intersecting declared `allowedEvents` with what's currently legal) — omit
63
+ * it and decision requests report an empty `events` list.
64
+ *
65
+ * @internal
66
+ */
67
+ function getAgentRequests(actions, { machine, ...options } = {}) {
68
+ if (machine) options = {
69
+ ...getRegisteredAgentExecutionOptions(machine),
70
+ ...options
71
+ };
72
+ return actions.flatMap((action) => {
73
+ const params = getInvokeEffectMetadata(action);
74
+ if (!params || typeof params.src !== "string") return [];
75
+ if (typeof params.id !== "string" || params.id.length === 0) throw new Error(`Agent invoke '${params.src}' must define a durable string id.`);
76
+ const registeredLogic = isTextLogic(params.logic) || isDecisionLogic(params.logic) ? params.logic : options.actors?.[params.src];
77
+ if (isDecisionLogic(registeredLogic)) {
78
+ const decisionRequest = registeredLogic.request(params.input);
79
+ const allowedEventTypes = registeredLogic.allowedEventTypes?.(params.input);
80
+ const events = options.snapshot ? getAcceptedEvents(options.snapshot, {
81
+ events: options.events,
82
+ schemas: options.schemas,
83
+ eventTypes: allowedEventTypes
84
+ }) : [];
85
+ return [{
86
+ ...decisionRequest,
87
+ id: params.id,
88
+ events
89
+ }];
90
+ }
91
+ const textLogic = isTextLogic(registeredLogic) ? registeredLogic : void 0;
92
+ const input = textLogic ? textLogic.request(params.input) : void 0;
93
+ if (!input) return [];
94
+ return [{
95
+ kind: "text",
96
+ id: params.id,
97
+ src: params.src,
98
+ ...textLogic ? { mode: textLogic.mode } : {},
99
+ input,
100
+ tools: input.tools ?? {},
101
+ events: []
102
+ }];
103
+ });
104
+ }
105
+ /**
106
+ * Builds the canonical `xstate.done.actor` event xstate's `transition()`
107
+ * expects to resolve a spawned invoke — including the child session identity
108
+ * that rejects a stale completion from an earlier incarnation.
109
+ *
110
+ * @internal
111
+ */
112
+ function doneEvent(snapshot, request, output) {
113
+ const id = typeof request === "string" ? request : request.id;
114
+ const child = snapshot.children[id];
115
+ return {
116
+ type: "xstate.done.actor",
117
+ actorId: id,
118
+ ...typeof child?.sessionId === "string" ? { sessionId: child.sessionId } : {},
119
+ output
120
+ };
121
+ }
122
+ /**
123
+ * The `xstate.error.actor` counterpart of {@link doneEvent} — the event a
124
+ * failed invoke delivers, which `onError` transitions observe. Carries the
125
+ * same child session identity, so xstate does not discard it as stale.
126
+ *
127
+ * @internal
128
+ */
129
+ function errorEvent(snapshot, request, error) {
130
+ const id = typeof request === "string" ? request : request.id;
131
+ const child = snapshot.children[id];
132
+ return {
133
+ type: "xstate.error.actor",
134
+ actorId: id,
135
+ ...typeof child?.sessionId === "string" ? { sessionId: child.sessionId } : {},
136
+ error
137
+ };
138
+ }
139
+ /**
140
+ * Applies a request's `output` as a done event (or, with `outcome: 'error'`,
141
+ * its `output` as the invoke's error) via `transition(...)`, returning the raw
142
+ * `[snapshot, actions]` tuple. Lower-level than {@link resolveAgentStep} /
143
+ * {@link rejectAgentStep} — those helpers wrap this and also run
144
+ * {@link getAgentRequests} to produce the next {@link AgentStep}.
145
+ *
146
+ * @internal
147
+ */
148
+ function transitionResult(logic, snapshot, request, output, outcome = "output") {
149
+ const event = outcome === "error" ? errorEvent(snapshot, request, output) : doneEvent(snapshot, request, output);
150
+ const result = transition(logic, snapshot, event);
151
+ applyFinalStateOutput(logic, result[0], event);
152
+ return result;
153
+ }
154
+ /**
155
+ * Starts a machine and returns its first {@link AgentStep} — the step-path
156
+ * equivalent of `initialTransition` plus request discovery. Begins the
157
+ * durable/per-model-call-checkpoint loop: resolve each `step.requests` entry
158
+ * (via {@link executeAgentRequest} for `kind: 'text'`, or
159
+ * {@link resolveDecision} for `kind: 'decision'`), then advance with
160
+ * {@link resolveAgentStep} or {@link transitionAgentStep}.
161
+ */
162
+ function initialAgentStep(machine, input, options) {
163
+ const [snapshot, actions] = initialTransition(machine, input);
164
+ return createAgentStep(machine, snapshot, actions, getRegisteredAgentExecutionOptions(machine, options));
165
+ }
166
+ /**
167
+ * Applies an externally-sent event (e.g. a decision's chosen event, or a
168
+ * human's reply) and returns the next {@link AgentStep}. Accepts **either**
169
+ * a raw snapshot **or** a prior `AgentStep` as the second argument —
170
+ * `.snapshot` is unwrapped automatically, so callers can thread the whole
171
+ * step object through without manually plucking the snapshot out.
172
+ */
173
+ function transitionAgentStep(machine, snapshotOrStep, event, options) {
174
+ const [nextSnapshot, actions] = transition(machine, isAgentStep(snapshotOrStep) ? snapshotOrStep.snapshot : snapshotOrStep, event);
175
+ return createAgentStep(machine, nextSnapshot, actions, getRegisteredAgentExecutionOptions(machine, options));
176
+ }
177
+ /**
178
+ * Applies a resolved text request's output (a `kind: 'text'`
179
+ * {@link AgentRequest} — not a decision) as a done event and returns the
180
+ * next {@link AgentStep}. For decisions, resolve with `resolveDecision`
181
+ * (which returns a {@link ChosenEvent}) and apply it with
182
+ * {@link transitionAgentStep} instead — a decision has no output value of
183
+ * its own to feed here.
184
+ */
185
+ function resolveAgentStep(machine, step, request, output, options) {
186
+ const [snapshot, actions] = transitionResult(machine, step.snapshot, request, output);
187
+ return createAgentStep(machine, snapshot, actions, getRegisteredAgentExecutionOptions(machine, options));
188
+ }
189
+ /**
190
+ * Rejects a pending invoke — the failure counterpart of
191
+ * {@link resolveAgentStep}. Delivers `error` as the invoke's
192
+ * `xstate.error.actor` event, so the machine takes that invoke's `onError`
193
+ * transition and returns the next {@link AgentStep}. With no `onError` in
194
+ * scope the returned step's snapshot has `status: 'error'`, exactly as a live
195
+ * run's failed invoke does.
196
+ *
197
+ * A durable host replays a failed call with this: the log says the call
198
+ * failed, so the replay rejects the invoke instead of resolving it. Scripted
199
+ * playthroughs use it too — see `simulateAgent`'s `script.errors`.
200
+ *
201
+ * `error` can be any value. An `Error` instance is the usual one, but a plain
202
+ * object (`{ code: 'truncated' }`) reaches the `onError` transition as
203
+ * `event.error` untouched, so a machine that branches on a failure code is
204
+ * testable without constructing a provider's error class.
205
+ */
206
+ function rejectAgentStep(machine, step, request, error, options) {
207
+ const [snapshot, actions] = transitionResult(machine, step.snapshot, request, error, "error");
208
+ return createAgentStep(machine, snapshot, actions, getRegisteredAgentExecutionOptions(machine, options));
209
+ }
210
+ function createAgentStep(machine, snapshot, actions, options) {
211
+ applyFinalStateOutput(machine, snapshot);
212
+ return {
213
+ snapshot,
214
+ actions,
215
+ requests: getAgentRequests(getPendingInvokes(snapshot), {
216
+ ...options,
217
+ snapshot
218
+ }),
219
+ done: snapshot.status === "done"
220
+ };
221
+ }
222
+ function resolveStateValueConfig(config, value) {
223
+ if (typeof value === "string") return config.states?.[value];
224
+ if (!value || typeof value !== "object") return;
225
+ for (const [key, childValue] of Object.entries(value)) {
226
+ const childConfig = config.states?.[key];
227
+ if (!childConfig) continue;
228
+ if (childConfig.type === "final") return childConfig;
229
+ const nested = resolveStateValueConfig(childConfig, childValue);
230
+ if (nested) return nested;
231
+ }
232
+ }
233
+ function applyFinalStateOutput(logic, snapshot, event) {
234
+ const machineSnapshot = snapshot;
235
+ if (machineSnapshot.status !== "done" || machineSnapshot.output !== void 0 || !("config" in logic)) return;
236
+ const config = logic.config;
237
+ if (!config) return;
238
+ const output = resolveStateValueConfig(config, machineSnapshot.value)?.output;
239
+ if (output === void 0) return;
240
+ machineSnapshot.output = typeof output === "function" ? output({
241
+ context: machineSnapshot.context,
242
+ event
243
+ }) : output;
244
+ }
245
+ function isAgentStep(value) {
246
+ return !!value && typeof value === "object" && "snapshot" in value && "actions" in value && "requests" in value;
247
+ }
248
+ //#endregion
4
249
  //#region src/verify.ts
5
250
  const DECIDE_SRC = "agent.decide";
6
251
  function normalizeInvokes(invoke) {
@@ -77,7 +322,7 @@ function checkDirectObjectSrc(ctx) {
77
322
  code: "direct-object-src",
78
323
  severity: "warning",
79
324
  path: node.path,
80
- 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.`
325
+ 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.`
81
326
  });
82
327
  }
83
328
  return out;
@@ -811,11 +1056,13 @@ function matcherFor(expected) {
811
1056
  * @example Trajectory assertions in a test
812
1057
  * ```ts
813
1058
  * const statePath: unknown[] = [];
814
- * const result = await runAgent(machine, {
815
- * input,
816
- * executors,
817
- * onTransition: (snapshot) => statePath.push(snapshot.value),
818
- * });
1059
+ * const result = await runToQuiescence(
1060
+ * createAgentRuntime(machine, {
1061
+ * executors,
1062
+ * onTransition: (snapshot) => statePath.push(snapshot.value),
1063
+ * }),
1064
+ * { input },
1065
+ * );
819
1066
  *
820
1067
  * const path = matchesTrajectory(statePath, ['prompting', 'drafting', 'sent']);
821
1068
  * expect(path.matched, JSON.stringify(path.firstMiss)).toBe(true);
@@ -869,43 +1116,7 @@ function matchesTrajectory(actual, expected, options = {}) {
869
1116
  };
870
1117
  }
871
1118
  //#endregion
872
- //#region src/scripted-executors.ts
873
- /**
874
- * Scripted executors — a deterministic stand-in for a model host.
875
- *
876
- * `createScriptedExecutors` builds a full `{ generateText, streamText, decide }`
877
- * set that plays back canned answers keyed by
878
- * request name, so `runAgent` (or `provideExecutors`, or a bare
879
- * `TextLogic.execute`) runs with no API key and no network.
880
- *
881
- * One rule: entries for a name are consumed in order, and the last entry
882
- * repeats forever.
883
- *
884
- * @module
885
- */
886
- function toQueues(value) {
887
- return new Map(Object.entries(value ?? {}).map(([name, entries]) => [name, {
888
- entries: Array.isArray(entries) ? [...entries] : [entries],
889
- index: 0
890
- }]));
891
- }
892
- /**
893
- * Takes the next entry for `name`, holding on the last entry once the list is
894
- * spent. `undefined` means the script has no route for this name at all.
895
- * @internal
896
- */
897
- function takeEntry(queues, name) {
898
- const queue = queues.get(name) ?? queues.get("*");
899
- if (!queue || queue.entries.length === 0) return;
900
- const entry = queue.entries[Math.min(queue.index, queue.entries.length - 1)];
901
- queue.index++;
902
- return entry;
903
- }
904
- /** @internal */
905
- function noAnswer(name, queues) {
906
- const known = [...queues.keys()].join(", ") || "(none)";
907
- return /* @__PURE__ */ new Error(`No scripted answer for request '${name}'. Known: ${known}`);
908
- }
1119
+ //#region src/seam.ts
909
1120
  /** The only own keys an executor result carries. @internal */
910
1121
  const TEXT_RESULT_KEYS = new Set([
911
1122
  "result",
@@ -924,123 +1135,26 @@ function isTextResult(value) {
924
1135
  return Object.hasOwn(value, "result") && Object.keys(value).every((key) => TEXT_RESULT_KEYS.has(key));
925
1136
  }
926
1137
  /**
927
- * Resolves ONE scripted text entry to an executor result: a function entry is
1138
+ * Resolves ONE scripted entry to an executor result: a function entry is
928
1139
  * called with the request, and the value is taken as the executor result only
929
- * when it is one (see {@link isTextResult}). Shared with `runSeam`, whose routed
930
- * queues follow the same entry conventions. @internal
1140
+ * when it is one (see {@link isTextResult}). @internal
931
1141
  */
932
- async function resolveScriptedTextEntry(entry, request, info) {
1142
+ async function resolveSeamScriptEntry(entry, request, info) {
933
1143
  const value = typeof entry === "function" ? await entry(request, info) : entry;
934
1144
  return isRecord(value) && isTextResult(value) ? value : { result: value };
935
1145
  }
936
- /**
937
- * Names a pending text request in an error message. Shared with `runSeam`.
938
- * @internal
939
- */
1146
+ /** Names a pending text request in an error message. @internal */
940
1147
  function describeText(request) {
941
1148
  return request.name ? `'${request.name}' (model '${request.model}')` : `(model '${request.model}')`;
942
1149
  }
943
1150
  /**
944
- * Stream semantics with no model: the whole text lands as one chunk. Shared
945
- * with `runSeam`, whose scripted answers stream the same way. @internal
1151
+ * Stream semantics with no model: the whole text lands as one chunk. @internal
946
1152
  */
947
1153
  function emitScriptedChunk(result, info) {
948
1154
  const text = isRecord(result) ? result["result"] : void 0;
949
1155
  if (typeof text === "string") info?.onChunk?.(text);
950
1156
  }
951
1157
  /**
952
- * Executors that replay a script instead of calling a model. Every slot is
953
- * provided, so any machine binds.
954
- *
955
- * Answers are keyed by the request's resolved name — its authored `name`, else
956
- * the invoke `id` — and `"*"` serves anything unmatched.
957
- * Entries for a name are consumed in order and the last one repeats forever, so
958
- * a looping machine needs no extra option. A request the script has no route
959
- * for throws an ordinary `Error` from inside the executor, which reaches the
960
- * machine as an actor error.
961
- *
962
- * Queues are copied on creation, so the caller's arrays are never mutated and
963
- * each call builds a fresh, independent playthrough. Entries may be plain
964
- * values or functions of the request.
965
- *
966
- * @example
967
- * ```ts
968
- * const result = await runAgent(moderationMachine, {
969
- * input: { comment: 'honestly this update is terrible', trust: 20 },
970
- * executors: createScriptedExecutors({
971
- * decisions: { moderate: [{ type: 'FLAG', reason: 'Borderline tone.' }] },
972
- * }),
973
- * });
974
- * ```
975
- *
976
- * @example Dynamic entries
977
- * ```ts
978
- * createScriptedExecutors({
979
- * text: { draft: (request) => `Draft about ${request.prompt}` },
980
- * decisions: { route: (request) => ({ type: request.events[0]!.type }) },
981
- * });
982
- * ```
983
- */
984
- function createScriptedExecutors(script = {}) {
985
- const decisions = toQueues(script.decisions);
986
- const text = toQueues(script.text);
987
- const calls = [];
988
- const withDefaultUsage = (result) => result.usage || !script.usage ? result : {
989
- ...result,
990
- usage: script.usage
991
- };
992
- const nextText = async (kind, request, info) => {
993
- const name = request.name ?? "*";
994
- calls.push({
995
- kind,
996
- name,
997
- input: request.input,
998
- request
999
- });
1000
- const entry = takeEntry(text, name);
1001
- if (entry === void 0) throw noAnswer(name, text);
1002
- return withDefaultUsage(await resolveScriptedTextEntry(entry, request, info));
1003
- };
1004
- return {
1005
- calls,
1006
- generateText: (request, info) => nextText("generateText", request, info),
1007
- streamText: async (request, info) => {
1008
- const name = request.name ?? "*";
1009
- const streamEntry = script.stream?.[name] ?? script.stream?.["*"];
1010
- if (streamEntry !== void 0) {
1011
- calls.push({
1012
- kind: "streamText",
1013
- name,
1014
- input: request.input,
1015
- request
1016
- });
1017
- const resolved = typeof streamEntry === "function" ? await streamEntry(request, info) : streamEntry;
1018
- const chunks = typeof resolved === "string" ? [resolved] : [...resolved];
1019
- for (const chunk of chunks) info?.onChunk?.(chunk);
1020
- return withDefaultUsage({ result: chunks.join("") });
1021
- }
1022
- const result = await nextText("streamText", request, info);
1023
- emitScriptedChunk(result, info);
1024
- return result;
1025
- },
1026
- decide: async (request) => {
1027
- const name = request.name ?? request.id;
1028
- calls.push({
1029
- kind: "decide",
1030
- name,
1031
- input: request.input,
1032
- request
1033
- });
1034
- const entry = takeEntry(decisions, name);
1035
- if (entry === void 0) throw noAnswer(name, decisions);
1036
- const value = typeof entry === "function" ? await entry(request) : entry;
1037
- return withDefaultUsage(isRecord(value) && typeof value["type"] !== "string" && "event" in value ? value : { event: value });
1038
- }
1039
- };
1040
- }
1041
- //#endregion
1042
- //#region src/seam.ts
1043
- /**
1044
1158
  * The seam's own answer, for scoring: the executor result's `result`.
1045
1159
  * @internal
1046
1160
  */
@@ -1062,8 +1176,8 @@ async function seamOutputOf(result, request) {
1062
1176
  * @example No API key: the seam is scripted too, so the whole thing runs offline.
1063
1177
  * ```ts
1064
1178
  * const run = await runSeam(emailDrafter, {
1065
- * scripts: { promptEvaluator: [vague, complete], emailDrafter: [draft] },
1066
- * seam: { request: 'evaluatePrompt' },
1179
+ * scripts: { writeFollowUps: [followUps], emailDrafter: [draft] },
1180
+ * seam: { request: 'writeFollowUps' },
1067
1181
  * respond: ({ state }) => (state === 'prompting' ? { type: 'PROMPT_SUBMITTED', prompt } : null),
1068
1182
  * });
1069
1183
  *
@@ -1099,7 +1213,7 @@ async function runSeam(machine, options) {
1099
1213
  const takeScriptedSlot = async (request, info) => {
1100
1214
  const queue = queues.get(queueKeyOf(request));
1101
1215
  if (!queue?.length) return;
1102
- return resolveScriptedTextEntry(options.repeatLast && queue.length === 1 ? queue[0] : queue.shift(), request, info);
1216
+ return resolveSeamScriptEntry(options.repeatLast && queue.length === 1 ? queue[0] : queue.shift(), request, info);
1103
1217
  };
1104
1218
  const scriptedAnswer = async (request, info) => {
1105
1219
  const scripted = await takeScriptedSlot(request, info);
@@ -1156,9 +1270,7 @@ async function runSeam(machine, options) {
1156
1270
  let result;
1157
1271
  const maxTurns = options.maxTurns ?? 12;
1158
1272
  for (let turn = 0; turn <= maxTurns; turn++) {
1159
- result = await runAgent(machine, {
1160
- ...snapshot ? { snapshot } : { input: options.input },
1161
- ...event ? { event } : {},
1273
+ result = await runToQuiescence(createAgentRuntime(machine, {
1162
1274
  ...options.actors ? { actors: options.actors } : {},
1163
1275
  executors,
1164
1276
  onTransition: (next, causedBy) => {
@@ -1167,6 +1279,9 @@ async function runSeam(machine, options) {
1167
1279
  liveEvents = events.length;
1168
1280
  statePath.push(next.value);
1169
1281
  }
1282
+ }), {
1283
+ ...snapshot ? { snapshot } : { input: options.input },
1284
+ ...event ? { event } : {}
1170
1285
  });
1171
1286
  if (result.status !== "idle" || turn === maxTurns) break;
1172
1287
  const next = options.respond?.({
@@ -1209,4 +1324,4 @@ async function runSeam(machine, options) {
1209
1324
  };
1210
1325
  }
1211
1326
  //#endregion
1212
- export { AgentLintError, AgentUnknownStateError, assertAgentMachine, canReach, createScriptedExecutors, explorePaths, lintAgentMachine, matchesTrajectory, runSeam, simulateAgent };
1327
+ export { AgentLintError, AgentUnknownStateError, assertAgentMachine, canReach, explorePaths, lintAgentMachine, matchesTrajectory, runSeam, simulateAgent };
@@ -125,7 +125,7 @@ function findNonSerializableContextPaths(context, limit = 5) {
125
125
  * their prompts or executors hash identically; adding/removing/retargeting a
126
126
  * state or transition changes the hash.
127
127
  *
128
- * Used by {@link runAgent} to stamp settled snapshots with a `version` and to
128
+ * Used by {@link createAgentRuntime} to stamp settled snapshots with a `version` and to
129
129
  * detect a structurally-edited machine on resume. It is a change detector, not
130
130
  * a cryptographic digest — collisions are possible but unlikely for real
131
131
  * configs. Declare `createMachine({ version })` to pin an explicit version instead.
@@ -136,7 +136,7 @@ function getMachineStructuralHash(machine) {
136
136
  /**
137
137
  * The version a machine is stamped with everywhere: an explicitly declared
138
138
  * `createMachine({ version })` when present, else its
139
- * {@link getMachineStructuralHash}. Single source of truth so `runAgent`,
139
+ * {@link getMachineStructuralHash}. Single source of truth so `createAgentRuntime`,
140
140
  * `provideExecutors`/`traceTransitions` trace envelopes agree.
141
141
  * @internal
142
142
  */
@@ -327,7 +327,7 @@ function validateSchemaSync(schema, value) {
327
327
  * Registered execution options, keyed on BOTH the machine object and its root
328
328
  * `config` object. `config` is shared by reference across `machine.provide(...)`
329
329
  * (unlike the machine itself), so the `config` key is what lets a machine
330
- * rebound by `runAgent` — or by any host `.provide(...)` — still resolve the
330
+ * rebound by `createAgentRuntime` — or by any host `.provide(...)` — still resolve the
331
331
  * schemas/actors `setupAgent` registered. Always write through
332
332
  * {@link setAgentExecutionOptions} and read through
333
333
  * {@link getAgentExecutionOptions}.
@@ -347,7 +347,7 @@ function setAgentExecutionOptions(machine, options) {
347
347
  }
348
348
  /**
349
349
  * Reads the options registered for `machine`, falling back to the root `config`
350
- * key so a `.provide(...)`-rebound machine (e.g. the one behind a `runAgent`
350
+ * key so a `.provide(...)`-rebound machine (e.g. the one behind a `runToQuiescence`
351
351
  * result snapshot) resolves the same pack.
352
352
  */
353
353
  function getAgentExecutionOptions(machine) {
@@ -357,24 +357,9 @@ function getAgentExecutionOptions(machine) {
357
357
  const config = machineConfigKey(machine);
358
358
  return config ? agentExecutionOptions.get(config) : void 0;
359
359
  }
360
- /**
361
- * Machine-carried wait-state predicates, keyed on the machine's root `config`
362
- * object. `config` is shared by reference across `machine.provide(...)` (unlike
363
- * the machine object itself), so a predicate registered here travels with the
364
- * machine through `.provide` — which is why it is keyed on `config`, not the
365
- * machine. Set by `setupAgent({ isIdle })` in `createMachine` and by
366
- * `setupAgent.fromConfig` (its `isIdle` option or the config's
367
- * `idleTags`), read by `runAgent` before its structural default.
368
- */
369
- const machineIdlePredicates = /* @__PURE__ */ new WeakMap();
370
- /** Reads the {@link machineIdlePredicates} predicate carried by `machine` (via its root `config`), if any. */
371
- function getMachineIdlePredicate(machine) {
372
- const config = machine.config;
373
- return config ? machineIdlePredicates.get(config) : void 0;
374
- }
375
360
  const unboundPlaceholderLogics = /* @__PURE__ */ new WeakSet();
376
361
  /** Text/decision logics created WITH their own executor (withExecutor or the
377
- * factory's second arg) — these are runnable as-is, so runAgent's bind check
362
+ * factory's second arg) — these are runnable as-is, so the runtime's bind check
378
363
  * must not reject them as direct-object invoke srcs. */
379
364
  const executorBoundLogics = /* @__PURE__ */ new WeakSet();
380
365
  function missingActor(src) {
@@ -408,7 +393,7 @@ const AGENT_FINISH_REASONS = new Set([
408
393
  /**
409
394
  * Reads a settled call's {@link AgentFinishReason} off a RAW executor result's
410
395
  * `finishReason` field — the finish-reason sibling of {@link getCallUsage},
411
- * applied by `runAgent` before it puts the reason on the `request.end` trace.
396
+ * applied by the runtime before it puts the reason on the `request.end` trace.
412
397
  * A provider's `'error'` normalizes to `'other'`; anything else the union does
413
398
  * not name (an un-normalized provider string, a missing field) returns
414
399
  * `undefined`.
@@ -430,7 +415,7 @@ const AGENT_USAGE_TOKEN_FIELDS = [
430
415
  /**
431
416
  * Reads a settled call's per-call {@link AgentCallUsage} off a RAW executor
432
417
  * result's `usage` field, keeping only finite numbers — the same normalization
433
- * `runAgent` applies before it delivers `'@agent.usage'`. Returns `undefined`
418
+ * the runtime applies before it delivers `'@agent.usage'`. Returns `undefined`
434
419
  * when the result reports no usage at all. Works for our `{ result, usage }`
435
420
  * shape, for a raw Vercel AI SDK result (its `LanguageModelUsage` carries
436
421
  * the same flat field names), and for any custom executor that follows the
@@ -585,8 +570,7 @@ function resolveTextLogicValue(value, args) {
585
570
  * result under `actors:` and invoke it by name (equivalent to what
586
571
  * `setupAgent({ requests })` builds internally for each request entry). Pass
587
572
  * `execute` here, or bind it later with `.withExecutor(...)`, a runtime
588
- * adapter's `machine.provide(...)`, or `runAgent`'s `generateText`/
589
- * `streamText` options.
573
+ * adapter's `machine.provide(...)`, or `createAgentRuntime`'s `executors`.
590
574
  *
591
575
  * @example
592
576
  * ```ts
@@ -639,7 +623,7 @@ function createTextLogic(config, execute) {
639
623
  };
640
624
  const logic = createAsyncLogic({ run: async ({ input, signal, system, self }, enq) => {
641
625
  const resolvedRequest = request(input);
642
- if (!execute) throw new Error("Text logic has no host execution. Pass an executor as the second argument to createTextLogic(...), provide a runtime adapter, or bind it through runAgent/provideExecutors, or execute the XState effect in your host.");
626
+ if (!execute) throw new Error("Text logic has no host execution. Pass an executor as the second argument to createTextLogic(...), provide a runtime adapter, or bind it through createAgentRuntime/provideExecutors, or execute the XState effect in your host.");
643
627
  const result = await execute({
644
628
  input,
645
629
  request: resolvedRequest,
@@ -830,4 +814,4 @@ function invalidGeneratorResult(id) {
830
814
  return /* @__PURE__ */ new Error(`Executor for '${id}' returned an invalid result: executors must return { result } (the text string or structured object as \`result\`, plus optional \`messages\`, \`usage\` and other passthrough fields). Wrap a raw SDK result with an adapter such as createAiSdkExecutors.`);
831
815
  }
832
816
  //#endregion
833
- export { getJsonSchema as A, userMessage as B, isUnboundPlaceholder as C, assistantMessage as D, setAgentExecutionOptions as E, getStatePath as F, AgentError as H, isStandardSchema as I, resolveMachineVersion as L, getMachineStructuralHash as M, getMessageText as N, djb2Hex as O, getStateMeta as P, systemMessage as R, getRegisteredAgentExecutionOptions as S, missingActor as T, AgentTruncatedError as U, validateSchemaSync as V, resolveTextLogicValue as _, bindRequestExecutor as a, getAgentExecutionOptions as b, executeAgentTextRequest as c, getCallUsage as d, isTextLogic as f, providerOutputSchema as g, parseProviderOutput as h, STREAM_TEXT_ACTOR as i, getJsonSchemaSync as j, findNonSerializableContextPaths as k, getAgentOutputMode as l, parseOutput as m, DECIDE_ACTOR as n, builtinTextActors as o, normalizeGeneratorResult as p, GENERATE_TEXT_ACTOR as r, createTextLogic as s, AGENT_USAGE_TOKEN_FIELDS as t, getCallFinishReason as u, responseMessagesOf as v, machineIdlePredicates as w, getMachineIdlePredicate as x, executorBoundLogics as y, toolMessage as z };
817
+ export { getMessageText as A, AgentTruncatedError as B, setAgentExecutionOptions as C, getJsonSchema as D, findNonSerializableContextPaths as E, systemMessage as F, toolMessage as I, userMessage as L, getStatePath as M, isStandardSchema as N, getJsonSchemaSync as O, resolveMachineVersion as P, validateSchemaSync as R, missingActor as S, djb2Hex as T, responseMessagesOf as _, bindRequestExecutor as a, getRegisteredAgentExecutionOptions as b, getAgentOutputMode as c, isTextLogic as d, normalizeGeneratorResult as f, resolveTextLogicValue as g, providerOutputSchema as h, STREAM_TEXT_ACTOR as i, getStateMeta as j, getMachineStructuralHash as k, getCallFinishReason as l, parseProviderOutput as m, DECIDE_ACTOR as n, builtinTextActors as o, parseOutput as p, GENERATE_TEXT_ACTOR as r, createTextLogic as s, AGENT_USAGE_TOKEN_FIELDS as t, getCallUsage as u, executorBoundLogics as v, assistantMessage as w, isUnboundPlaceholder as x, getAgentExecutionOptions as y, AgentError as z };