@statelyai/agent 2.0.0-alpha.10 → 2.0.0-alpha.12

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 (62) hide show
  1. package/dist/ai-sdk.cjs +62 -99
  2. package/dist/ai-sdk.d.cts +10 -117
  3. package/dist/ai-sdk.d.mts +10 -117
  4. package/dist/ai-sdk.mjs +63 -91
  5. package/dist/{decision-CQdrKc8k.mjs → decision-BezSD_YC.mjs} +120 -32
  6. package/dist/{decision-b-lkcs4L.cjs → decision-dWGhBh0P.cjs} +141 -53
  7. package/dist/errors-BQRk9eiZ.d.cts +19 -0
  8. package/dist/errors-C9rxnWbX.d.mts +19 -0
  9. package/dist/errors-CeSXQx0v.mjs +23 -0
  10. package/dist/errors-DUBBzRLP.cjs +28 -0
  11. package/dist/event-log-store-CNT_7F0V.cjs +452 -0
  12. package/dist/event-log-store-CriMgX1D.d.mts +144 -0
  13. package/dist/event-log-store-D7pWtIhb.mjs +411 -0
  14. package/dist/event-log-store-Ruq18mGp.d.cts +144 -0
  15. package/dist/index.cjs +2844 -30
  16. package/dist/index.d.cts +1005 -12
  17. package/dist/index.d.mts +1005 -12
  18. package/dist/index.mjs +2799 -4
  19. package/dist/machines.cjs +752 -0
  20. package/dist/machines.d.cts +372 -0
  21. package/dist/machines.d.mts +372 -0
  22. package/dist/machines.mjs +741 -0
  23. package/dist/otel.cjs +268 -0
  24. package/dist/otel.d.cts +67 -0
  25. package/dist/otel.d.mts +67 -0
  26. package/dist/otel.mjs +267 -0
  27. package/dist/run-agent-B1nBa7aV.d.mts +1111 -0
  28. package/dist/run-agent-qkg0evvW.d.cts +1111 -0
  29. package/dist/setup-agent-DAZZSjDS.mjs +1711 -0
  30. package/dist/setup-agent-DP95MFrI.cjs +1836 -0
  31. package/dist/sqlite.cjs +135 -0
  32. package/dist/sqlite.d.cts +57 -0
  33. package/dist/sqlite.d.mts +57 -0
  34. package/dist/sqlite.mjs +133 -0
  35. package/dist/{text-logic-C7WJpCIc.d.mts → text-logic-CorGzucG.d.cts} +110 -66
  36. package/dist/{text-logic-CZjyACzQ.d.cts → text-logic-DjR5PUVz.d.mts} +110 -66
  37. package/dist/{types-C9QiMjre.d.cts → types-QbEfCVny.d.cts} +1 -1
  38. package/dist/{types-qm00QF91.d.mts → types-_FXoFBGO.d.mts} +1 -1
  39. package/package.json +55 -27
  40. package/readme.md +40 -9
  41. package/schemas/agent-workflow.json +44 -26
  42. package/skills/generate-machine/SKILL.md +267 -0
  43. package/dist/cli.cjs +0 -64
  44. package/dist/cli.d.cts +0 -1
  45. package/dist/cli.d.mts +0 -1
  46. package/dist/cli.mjs +0 -65
  47. package/dist/openai-compat.cjs +0 -319
  48. package/dist/openai-compat.d.cts +0 -98
  49. package/dist/openai-compat.d.mts +0 -98
  50. package/dist/openai-compat.mjs +0 -312
  51. package/dist/run-agent-BFMkuI1F.cjs +0 -1599
  52. package/dist/run-agent-BVMd--1l.d.cts +0 -1103
  53. package/dist/run-agent-BoAOq_0Z.mjs +0 -1540
  54. package/dist/run-agent-DzYJb3CK.d.mts +0 -1103
  55. package/dist/src-D-77Ha5p.cjs +0 -1087
  56. package/dist/src-DUeIFjv-.mjs +0 -1016
  57. package/dist/utils-Dri7aeEG.d.cts +0 -108
  58. package/dist/utils-Y6GDRGGE.d.mts +0 -108
  59. package/dist/zod.cjs +0 -31
  60. package/dist/zod.d.cts +0 -30
  61. package/dist/zod.d.mts +0 -30
  62. package/dist/zod.mjs +0 -30
package/dist/ai-sdk.mjs CHANGED
@@ -1,7 +1,6 @@
1
- import { a as runAgent$1, c as setupAgent } from "./run-agent-BoAOq_0Z.mjs";
2
- import { J as isStandardSchema, L as getRegisteredAgentModels, T as getAgentOutputMode, l as renderDecisionAttempts, x as buildEnvelopeSchema } from "./decision-CQdrKc8k.mjs";
1
+ import { J as isStandardSchema, T as getAgentOutputMode, b as buildEnvelopeSchema, l as renderDecisionAttempts } from "./decision-BezSD_YC.mjs";
3
2
  import { NoObjectGeneratedError, Output, generateText, stepCountIs, streamText, tool } from "ai";
4
- //#region src/ai-sdk/index.ts
3
+ //#region src/ai-sdk/mappers.ts
5
4
  /**
6
5
  * Maps an {@link AgentTools} map onto AI SDK `tool()` definitions. A tool that
7
6
  * already carries its own Standard Schema `inputSchema` — an AI SDK
@@ -10,8 +9,7 @@ import { NoObjectGeneratedError, Output, generateText, stepCountIs, streamText,
10
9
  * every extra property (`providerOptions`, `toModelOutput`, …) survives. A bare
11
10
  * `AgentToolExecute` function becomes a tool with an unconstrained input schema;
12
11
  * a minimal descriptor with no readable schema is converted with a permissive
13
- * fallback. Used internally by {@link toAiSdkCallSettings}; exported for callers
14
- * building AI SDK calls by hand outside `createAiSdkExecutors`.
12
+ * fallback. Used by {@link toAiSdkCallSettings}.
15
13
  */
16
14
  function toAiSdkTools(tools) {
17
15
  const entries = [];
@@ -44,9 +42,6 @@ function toAiSdkTools(tools) {
44
42
  }
45
43
  return Object.fromEntries(entries);
46
44
  }
47
- function maxStepsSetting(request) {
48
- return typeof request.metadata?.maxSteps === "number" ? { stopWhen: stepCountIs(request.metadata.maxSteps) } : {};
49
- }
50
45
  const unknownSchema = { "~standard": {
51
46
  version: 1,
52
47
  vendor: "statelyai-agent",
@@ -54,35 +49,6 @@ const unknownSchema = { "~standard": {
54
49
  jsonSchema: { input: () => ({}) }
55
50
  } };
56
51
  /**
57
- * Identity helper for a `models` map whose value is exported. Returns the map
58
- * unchanged, but types it as {@link AiSdkModelMap}`<keyof T & string>` — a
59
- * portable, nameable type — so an exported `const models = defineModels({...})`
60
- * needs no `Record<'a' | 'b', LanguageModel>` annotation and never triggers
61
- * TS2742 ("inferred type cannot be named without a reference to …"). The exact
62
- * ref keys survive, so `createAiSdkExecutors({ models })` and
63
- * `setupAgent({ models })` still infer/autocomplete them.
64
- *
65
- * @example
66
- * ```ts
67
- * export const models = defineModels({
68
- * quick: openai('gpt-5.4-mini'),
69
- * deep: openai('gpt-5.4'),
70
- * });
71
- * // typeof models === AiSdkModelMap<'quick' | 'deep'>
72
- * ```
73
- */
74
- function defineModels(models) {
75
- return models;
76
- }
77
- function resolveAiSdkModel(options, modelRef) {
78
- if (options.resolveModel) return options.resolveModel(modelRef);
79
- const models = options.models;
80
- if (!models) throw new Error(`createAiSdkExecutors: no model resolver configured for '${modelRef}'.`);
81
- const model = models[modelRef];
82
- if (!model) throw new Error(`createAiSdkExecutors: unknown model '${modelRef}'.`);
83
- return model;
84
- }
85
- /**
86
52
  * AI SDK request-mapping settings shared by `generateText`/`streamText`.
87
53
  * `AgentTextRequest.messages` (`AgentMessage[]`) and AI SDK's `ModelMessage[]`
88
54
  * are structurally compatible by design (§1 of .scratch/p0-design.md) — the cast
@@ -147,6 +113,65 @@ function extractFirstJsonValue(text) {
147
113
  }
148
114
  }
149
115
  }
116
+ /** One AI SDK `tool()` per candidate event — the "tool-per-event +
117
+ * toolChoice: 'required'" recipe from .scratch/p0-design.md §2.6. */
118
+ function toAiSdkEventTools(events) {
119
+ return Object.fromEntries(events.map((event) => [event.toolName, tool({
120
+ description: `Choose the '${event.type}' move.`,
121
+ inputSchema: event.inputSchema ? event.inputSchema : unknownSchema
122
+ })]));
123
+ }
124
+ /**
125
+ * Messages for a decision request, with prior failed `attempts` (§2.6)
126
+ * rendered as appended user messages (via core's {@link renderDecisionAttempts})
127
+ * so retries converge. Core never rewrites prompts — this is adapter business.
128
+ */
129
+ function toDecisionMessages(request) {
130
+ if (!request.messages && request.attempts.length === 0) return;
131
+ const messages = [...request.messages ?? (request.prompt !== void 0 ? [{
132
+ role: "user",
133
+ content: request.prompt
134
+ }] : [])];
135
+ for (const attempt of renderDecisionAttempts(request)) messages.push({
136
+ role: "user",
137
+ content: attempt.content
138
+ });
139
+ return messages;
140
+ }
141
+ //#endregion
142
+ //#region src/ai-sdk/index.ts
143
+ function maxStepsSetting(request) {
144
+ return typeof request.metadata?.maxSteps === "number" ? { stopWhen: stepCountIs(request.metadata.maxSteps) } : {};
145
+ }
146
+ /**
147
+ * Identity helper for a `models` map whose value is exported. Returns the map
148
+ * unchanged, but types it as {@link AiSdkModelMap}`<keyof T & string>` — a
149
+ * portable, nameable type — so an exported `const models = defineModels({...})`
150
+ * needs no `Record<'a' | 'b', LanguageModel>` annotation and never triggers
151
+ * TS2742 ("inferred type cannot be named without a reference to …"). The exact
152
+ * ref keys survive, so `createAiSdkExecutors({ models })` and
153
+ * `setupAgent({ models })` still infer/autocomplete them.
154
+ *
155
+ * @example
156
+ * ```ts
157
+ * export const models = defineModels({
158
+ * quick: openai('gpt-5.4-mini'),
159
+ * deep: openai('gpt-5.4'),
160
+ * });
161
+ * // typeof models === AiSdkModelMap<'quick' | 'deep'>
162
+ * ```
163
+ */
164
+ function defineModels(models) {
165
+ return models;
166
+ }
167
+ function resolveAiSdkModel(options, modelRef) {
168
+ if (options.resolveModel) return options.resolveModel(modelRef);
169
+ const models = options.models;
170
+ if (!models) throw new Error(`createAiSdkExecutors: no model resolver configured for '${modelRef}'.`);
171
+ const model = models[modelRef];
172
+ if (!model) throw new Error(`createAiSdkExecutors: unknown model '${modelRef}'.`);
173
+ return model;
174
+ }
150
175
  function withJsonRepair(output) {
151
176
  return {
152
177
  ...output,
@@ -274,58 +299,5 @@ function createAiSdkExecutors(options) {
274
299
  decide
275
300
  };
276
301
  }
277
- /** AI SDK host for a machine authored with `setupAgent({ models })`. */
278
- function runAgent(machine, options) {
279
- const models = getRegisteredAgentModels(machine);
280
- if (!models || Object.keys(models).length === 0) throw new Error("AI SDK runAgent: machine has no models. Pass `models` to setupAgent, or use core runAgent with explicit executors.");
281
- return runAgent$1(machine, {
282
- ...options,
283
- executors: createAiSdkExecutors({ models })
284
- });
285
- }
286
- function createAgent(config) {
287
- const { model, models: configuredModels, schemas, ...machineConfig } = config;
288
- const models = configuredModels ?? { default: model };
289
- const executors = createAiSdkExecutors({ models });
290
- const machine = setupAgent({
291
- ...schemas,
292
- models
293
- }).createMachine(machineConfig);
294
- return {
295
- machine,
296
- run(runInput, options = {}) {
297
- return runAgent$1(machine, {
298
- ...options,
299
- input: runInput,
300
- executors
301
- });
302
- }
303
- };
304
- }
305
- /** One AI SDK `tool()` per candidate event — the "tool-per-event +
306
- * toolChoice: 'required'" recipe from .scratch/p0-design.md §2.6. */
307
- function toAiSdkEventTools(events) {
308
- return Object.fromEntries(events.map((event) => [event.toolName, tool({
309
- description: `Choose the '${event.type}' move.`,
310
- inputSchema: event.inputSchema ? event.inputSchema : unknownSchema
311
- })]));
312
- }
313
- /**
314
- * Messages for a decision request, with prior failed `attempts` (§2.6)
315
- * rendered as appended user messages (via core's {@link renderDecisionAttempts})
316
- * so retries converge. Core never rewrites prompts — this is adapter business.
317
- */
318
- function toDecisionMessages(request) {
319
- if (!request.messages && request.attempts.length === 0) return;
320
- const messages = [...request.messages ?? (request.prompt !== void 0 ? [{
321
- role: "user",
322
- content: request.prompt
323
- }] : [])];
324
- for (const attempt of renderDecisionAttempts(request)) messages.push({
325
- role: "user",
326
- content: attempt.content
327
- });
328
- return messages;
329
- }
330
302
  //#endregion
331
- export { createAgent, createAiSdkExecutors, defineModels, extractFirstJsonValue, isStructuredOutputRequest, runAgent, toAiSdkCallSettings, toAiSdkEventTools, toAiSdkToolChoice, toAiSdkTools, toDecisionMessages };
303
+ export { createAiSdkExecutors, defineModels };
@@ -1,3 +1,4 @@
1
+ import { t as AgentError } from "./errors-CeSXQx0v.mjs";
1
2
  import { createAsyncLogic, createLogic, getNextTransitions } from "xstate";
2
3
  //#region src/utils.ts
3
4
  /**
@@ -174,8 +175,7 @@ function getAgentMessages(snapshot) {
174
175
  * Structural guard for a {@link StandardSchemaV1}: `true` when `value` carries
175
176
  * the `~standard` marker. Used to tell an already-schema'd tool `inputSchema`
176
177
  * (a Zod/Valibot/… schema) apart from an SDK-specific schema wrapper that core
177
- * can't read directly — see the `ai-sdk` tool pass-through and `openai-compat`
178
- * tool serialization.
178
+ * can't read directly — see the `ai-sdk` tool pass-through.
179
179
  */
180
180
  function isStandardSchema(value) {
181
181
  return typeof value === "object" && value !== null && "~standard" in value;
@@ -221,9 +221,6 @@ function validateSchemaSync(schema, value) {
221
221
  //#endregion
222
222
  //#region src/internal/registry.ts
223
223
  const agentExecutionOptions = /* @__PURE__ */ new WeakMap();
224
- function getRegisteredAgentModels(machine) {
225
- return agentExecutionOptions.get(machine)?.models;
226
- }
227
224
  /**
228
225
  * Machine-carried wait-state predicates, keyed on the machine's root `config`
229
226
  * object. `config` is shared by reference across `machine.provide(...)` (unlike
@@ -239,6 +236,24 @@ function getMachineSuspensionPredicate(machine) {
239
236
  const config = machine.config;
240
237
  return config ? machineSuspensionPredicates.get(config) : void 0;
241
238
  }
239
+ /**
240
+ * Lint-reachability sidecar for `fromConfig` machines.
241
+ *
242
+ * Static transition targets declared by the source config of a
243
+ * `setupAgent.fromConfig` machine, as `dotted state path → declared target
244
+ * strings` (every `on`/`always`/`after`/`onDone`/`choice` target plus each
245
+ * invoke's `onDone`/`onError`). The JSON layer folds a transition that carries a
246
+ * context patch into an opaque resolver function, erasing its target from
247
+ * `machine.config` — so `lintAgentMachine`'s reachability walk reads the
248
+ * targets from here instead. Keyed on the machine's root `config` object (like
249
+ * {@link machineSuspensionPredicates}) so it survives `machine.provide(...)`.
250
+ */
251
+ const machineStaticTransitionTargets = /* @__PURE__ */ new WeakMap();
252
+ /** Reads the {@link machineStaticTransitionTargets} map carried by `machine` (via its root `config`), if any. */
253
+ function getMachineStaticTransitionTargets(machine) {
254
+ const config = machine.config;
255
+ return config ? machineStaticTransitionTargets.get(config) : void 0;
256
+ }
242
257
  const unboundPlaceholderLogics = /* @__PURE__ */ new WeakSet();
243
258
  /** Text/decision logics created WITH their own executor (withExecutor or the
244
259
  * factory's second arg) — these are runnable as-is, so runAgent's bind check
@@ -246,7 +261,7 @@ const unboundPlaceholderLogics = /* @__PURE__ */ new WeakSet();
246
261
  const executorBoundLogics = /* @__PURE__ */ new WeakSet();
247
262
  function missingActor(src) {
248
263
  const logic = createAsyncLogic({ run: async () => {
249
- throw new Error(`'${src}' has no host execution. Provide an implementation with machine.provide({ actorSources: { '${src}': ... } }).`);
264
+ throw new Error(`'${src}' has no host execution. Provide an implementation with machine.provide({ actors: { '${src}': ... } }).`);
250
265
  } });
251
266
  unboundPlaceholderLogics.add(logic);
252
267
  return logic;
@@ -290,11 +305,44 @@ function parseModelRef(modelRef) {
290
305
  modelId: modelRef.slice(slash + 1)
291
306
  };
292
307
  }
308
+ /** The token fields {@link AgentUsage} aggregates. @internal */
309
+ const AGENT_USAGE_TOKEN_FIELDS = [
310
+ "inputTokens",
311
+ "outputTokens",
312
+ "totalTokens",
313
+ "reasoningTokens",
314
+ "cachedInputTokens"
315
+ ];
316
+ /**
317
+ * Reads a per-call {@link AgentCallUsage} off a raw executor result's `usage`
318
+ * field, keeping only finite numbers. Returns `undefined` when the result
319
+ * reports no usage at all. Works for our `{ output, usage }` envelope, for a
320
+ * raw Vercel AI SDK result (its `LanguageModelUsage` carries the same flat
321
+ * field names), and for any custom executor that follows the shape.
322
+ *
323
+ * @internal
324
+ */
325
+ function extractCallUsage(raw) {
326
+ const usage = raw?.usage;
327
+ if (!usage || typeof usage !== "object") return;
328
+ let out;
329
+ for (const field of AGENT_USAGE_TOKEN_FIELDS) {
330
+ const value = usage[field];
331
+ if (typeof value === "number" && Number.isFinite(value)) (out ??= {})[field] = value;
332
+ }
333
+ return out;
334
+ }
293
335
  const agentTextInputSchema = { "~standard": {
294
336
  version: 1,
295
337
  vendor: "statelyai-agent",
296
338
  validate(value) {
297
- return !!value && typeof value === "object" && typeof value.model === "string" ? { value } : { issues: [{ message: "Expected agent text input with a model" }] };
339
+ if (!value || typeof value !== "object") return { issues: [{ message: "Expected agent text input object" }] };
340
+ const request = value;
341
+ if (typeof request.model !== "string") return { issues: [{ message: "Expected agent text input with a string `model`" }] };
342
+ const hasPrompt = typeof request.prompt === "string" && request.prompt.length > 0;
343
+ const hasMessages = Array.isArray(request.messages) && request.messages.length > 0;
344
+ if (!hasPrompt && !hasMessages) return { issues: [{ message: `Agent text request${request.name ? ` '${request.name}'` : ""} has neither a non-empty \`prompt\` nor \`messages\` — provide at least one so the model has something to respond to.` }] };
345
+ return { value: request };
298
346
  }
299
347
  } };
300
348
  const unknownOutputSchema = { "~standard": {
@@ -311,9 +359,16 @@ const stringOutputSchema = { "~standard": {
311
359
  return typeof value === "string" ? { value } : { issues: [{ message: "Expected string output" }] };
312
360
  }
313
361
  } };
362
+ const noInputSchema = { "~standard": {
363
+ version: 1,
364
+ vendor: "statelyai-agent",
365
+ validate(value) {
366
+ return { value };
367
+ }
368
+ } };
314
369
  function createBuiltinTextActor(src, mode, outputSchema) {
315
370
  const logic = createAsyncLogic({ run: async () => {
316
- throw new Error(`'${src}' has no host execution. Provide an implementation with machine.provide({ actorSources: { '${src}': ... } }) or execute the returned agent request with executeAgentRequest(...).`);
371
+ throw new Error(`'${src}' has no host execution. Provide an implementation with machine.provide({ actors: { '${src}': ... } }) or execute the returned agent request with executeAgentRequest(...).`);
317
372
  } });
318
373
  return Object.assign(logic, {
319
374
  kind: "statelyai.textLogic",
@@ -362,7 +417,7 @@ const builtinTextActors = {
362
417
  };
363
418
  /** The unbound `agent.userInput` builtin registered by setupAgent (an unbound-placeholder logic — see internal/registry.ts). Output is `string` — what the human typed. @internal */
364
419
  const userInputActor = createAsyncLogic({ run: async () => {
365
- throw new Error(`'${USER_INPUT_ACTOR}' has no host execution. Provide an implementation with machine.provide({ actorSources: { '${USER_INPUT_ACTOR}': ... } }).`);
420
+ throw new Error(`'${USER_INPUT_ACTOR}' has no host execution. Provide an implementation with machine.provide({ actors: { '${USER_INPUT_ACTOR}': ... } }).`);
366
421
  } });
367
422
  unboundPlaceholderLogics.add(userInputActor);
368
423
  /**
@@ -381,7 +436,7 @@ function resolveTextLogicValue(value, args) {
381
436
  /**
382
437
  * Creates reusable, standalone {@link TextLogic}: an actor that, when run,
383
438
  * resolves typed input to typed output via a model call. Register the
384
- * result under `actorSources:` and invoke it by name (equivalent to what
439
+ * result under `actors:` and invoke it by name (equivalent to what
385
440
  * `setupAgent({ requests })` builds internally for each request entry). Pass
386
441
  * `execute` here, or bind it later with `.withExecutor(...)`, a runtime
387
442
  * adapter's `machine.provide(...)`, or `runAgent`'s `generateText`/
@@ -399,8 +454,12 @@ function resolveTextLogicValue(value, args) {
399
454
  * ```
400
455
  */
401
456
  function createTextLogic(config, execute) {
457
+ const schemas = {
458
+ input: config.schemas?.input ?? noInputSchema,
459
+ output: config.schemas?.output ?? stringOutputSchema
460
+ };
402
461
  const request = (input) => {
403
- const args = { input: validateSchemaSync(config.schemas.input, input) };
462
+ const args = { input: validateSchemaSync(schemas.input, input) };
404
463
  return {
405
464
  name: resolveTextLogicValue(config.name, args),
406
465
  model: resolveTextLogicValue(config.model, args),
@@ -409,7 +468,7 @@ function createTextLogic(config, execute) {
409
468
  messages: resolveTextLogicValue(config.messages, args),
410
469
  tools: resolveTextLogicValue(config.tools, args),
411
470
  toolChoice: resolveTextLogicValue(config.toolChoice, args),
412
- outputSchema: config.schemas.output,
471
+ outputSchema: schemas.output,
413
472
  reasoning: resolveTextLogicValue(config.reasoning, args),
414
473
  temperature: resolveTextLogicValue(config.temperature, args),
415
474
  maxOutputTokens: resolveTextLogicValue(config.maxOutputTokens, args),
@@ -422,7 +481,7 @@ function createTextLogic(config, execute) {
422
481
  };
423
482
  const logic = createAsyncLogic({ run: async ({ input, signal, system, self }, enq) => {
424
483
  const resolvedRequest = request(input);
425
- 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 extract it with getAgentRequests(..., { actorSources }).");
484
+ 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 extract it with getAgentEffects(..., { actors }).");
426
485
  const result = await execute({
427
486
  input,
428
487
  request: resolvedRequest,
@@ -433,16 +492,16 @@ function createTextLogic(config, execute) {
433
492
  });
434
493
  const selfId = self?.id;
435
494
  const output = await normalizeGeneratorResult(result, typeof selfId === "string" ? selfId : "text logic", { request: resolvedRequest });
436
- return validateSchemaSync(config.schemas.output, output);
495
+ return validateSchemaSync(schemas.output, output);
437
496
  } });
438
497
  const textLogic = Object.assign(logic, {
439
498
  kind: "statelyai.textLogic",
440
499
  mode: config.mode ?? "generate",
441
- schemas: config.schemas,
500
+ schemas,
442
501
  request,
443
502
  async execute(input, executors) {
444
503
  const { output } = await executeAgentTextRequest(config.mode ?? "generate", "textLogic", request(input), executors);
445
- return validateSchemaSync(config.schemas.output, output);
504
+ return validateSchemaSync(schemas.output, output);
446
505
  },
447
506
  withExecutor(nextExecute) {
448
507
  return createTextLogic(config, nextExecute);
@@ -462,7 +521,7 @@ function createTextLogic(config, execute) {
462
521
  * @example
463
522
  * ```ts
464
523
  * childMachine.provide({
465
- * actorSources: {
524
+ * actors: {
466
525
  * researchTopic: bindRequestExecutor(setup.requests.researchTopic, generateText),
467
526
  * },
468
527
  * });
@@ -500,10 +559,6 @@ function getAgentOutputMode(schema) {
500
559
  if (jsonSchema.type === void 0 && ("anyOf" in jsonSchema || "oneOf" in jsonSchema || "allOf" in jsonSchema)) return "structured";
501
560
  return "text";
502
561
  }
503
- /** True when {@link getAgentOutputMode} classifies `schema` as `'structured'`. */
504
- function isStructuredOutputSchema(schema) {
505
- return getAgentOutputMode(schema) === "structured";
506
- }
507
562
  /**
508
563
  * Builds the uniform structured-output envelope schema every structured request
509
564
  * is sent to the provider as: a root object `{ result: <inner> }`, plus — when
@@ -654,7 +709,7 @@ function invalidGeneratorResult(id) {
654
709
  }
655
710
  //#endregion
656
711
  //#region src/events.ts
657
- /** Default prefix for the synthetic tool name generated per candidate event (e.g. `send_event_ASK`). Override per-request with {@link AgentEventToolNameResolver}. */
712
+ /** Default prefix for the synthetic tool name generated per candidate event (e.g. `send_event_ASK`). Override per-request with {@link AgentEventToolNameResolver}. @internal */
658
713
  const EVENT_TOOL_PREFIX = "send_event_";
659
714
  function hashString(value) {
660
715
  let hash = 5381;
@@ -689,6 +744,18 @@ function matchesEventPattern(eventType, pattern) {
689
744
  if (pattern.endsWith(".*")) return eventType.startsWith(`${pattern.slice(0, -1)}`);
690
745
  return eventType === pattern;
691
746
  }
747
+ /**
748
+ * The namespace reserved for events the library itself delivers to a machine
749
+ * (`@agent.init`, `@agent.usage`). A machine may declare transitions on them,
750
+ * but they are never model-facing: {@link getAcceptedEvents} drops them before
751
+ * any `allowedEvents` matching, so they cannot be offered as a decision
752
+ * candidate (not even under a `'*'` wildcard) and {@link parseAgentEvent}
753
+ * rejects them — a model or a wire message must not be able to forge one.
754
+ * Matched as a prefix rather than a list so this module stays free of an import
755
+ * cycle back to `effects.ts`, where the constants live.
756
+ * @internal
757
+ */
758
+ const RESERVED_AGENT_EVENT_PREFIX = "@agent.";
692
759
  /** True when an `allowedEvents` entry is a wildcard pattern rather than a concrete event type. @internal */
693
760
  function isEventPattern(entry) {
694
761
  return entry === "*" || entry.endsWith(".*");
@@ -731,13 +798,29 @@ function parseAgentEvent(snapshot, event, options = {}) {
731
798
  }
732
799
  return event;
733
800
  }
801
+ /**
802
+ * Lists the events a snapshot can currently accept, as {@link AgentEventDescriptor}s
803
+ * a model can be offered (via `resolveDecision`/an adapter's tool-per-event
804
+ * mapping). **Filters by event TYPE only** — it does not evaluate guards, so
805
+ * a type-legal-but-guard-rejected event can still appear here. Guard
806
+ * legality is checked separately, at decision-resolution time, via
807
+ * `snapshot.can(event)` (the `canTake` option of {@link resolveDecision} /
808
+ * {@link ResolveDecisionOptions}). Pass `eventTypes` to further narrow to a
809
+ * declared `allowedEvents` set — entries may be exact types or wildcard
810
+ * patterns (`'*'`, `'todo.*'`; see {@link matchesEventPattern}).
811
+ *
812
+ * XState-internal (`xstate.*`) and library-reserved
813
+ * ({@link RESERVED_AGENT_EVENT_PREFIX}) event types are always excluded, before
814
+ * any `allowedEvents` matching — a machine that handles `'@agent.usage'` still
815
+ * never offers it to a model.
816
+ */
734
817
  function getAcceptedEvents(snapshot, options = {}) {
735
818
  const eventTypes = options.eventTypes;
736
819
  const seen = /* @__PURE__ */ new Set();
737
820
  const usedToolNames = /* @__PURE__ */ new Set();
738
821
  return getNextTransitions(snapshot).flatMap((transitionDefinition) => {
739
822
  const eventType = transitionDefinition.eventType;
740
- if (!eventType || eventType === "*" || eventType.startsWith("xstate.") || eventTypes && !eventTypes.some((pattern) => matchesEventPattern(eventType, pattern)) || seen.has(eventType)) return [];
823
+ if (!eventType || eventType === "*" || eventType.startsWith("xstate.") || eventType.startsWith(RESERVED_AGENT_EVENT_PREFIX) || eventTypes && !eventTypes.some((pattern) => matchesEventPattern(eventType, pattern)) || seen.has(eventType)) return [];
741
824
  seen.add(eventType);
742
825
  const defaultToolName = sanitizeEventToolName(eventType);
743
826
  const toolName = options.eventToolName ? options.eventToolName({
@@ -779,7 +862,7 @@ function decideRequestFromInput(input) {
779
862
  }
780
863
  function decideActorWithExecutor(execute) {
781
864
  const logic = createAsyncLogic({ run: async ({ input, signal }) => {
782
- if (!execute) throw new Error(`'${DECIDE_ACTOR}' has no host execution. Provide an implementation with machine.provide({ actorSources: { '${DECIDE_ACTOR}': ... } }) or resolve the returned agent request with resolveDecision(...).`);
865
+ if (!execute) throw new Error(`'${DECIDE_ACTOR}' has no host execution. Provide an implementation with machine.provide({ actors: { '${DECIDE_ACTOR}': ... } }) or resolve the returned agent request with resolveDecision(...).`);
783
866
  const resolvedEventTypes = resolveAllowedEventTypes(input.allowedEvents, input);
784
867
  if (resolvedEventTypes === void 0) throw new Error(`'${DECIDE_ACTOR}' input has omitted \`allowedEvents\`, which means "all currently-legal events" — but that requires a snapshot-aware host (runAgent or the step path) to resolve. Under a bare createActor(...), declare \`allowedEvents\` explicitly to use this actor here.`);
785
868
  if (resolvedEventTypes.some(isEventPattern)) throw new Error(`'${DECIDE_ACTOR}' input uses wildcard \`allowedEvents\` patterns, which expand against the live snapshot — that requires a snapshot-aware host (runAgent or the step path). Under a bare createActor(...), list event types explicitly.`);
@@ -836,7 +919,10 @@ function createPlanActor() {
836
919
  allowedEventTypes: (input) => resolveAllowedEventTypes(input.allowedEvents, input)
837
920
  });
838
921
  }
839
- const PLAN_LEDGER_SCOPE = { emit: () => {} };
922
+ const PLAN_LEDGER_SCOPE = {
923
+ emit: () => {},
924
+ self: { id: "agent.plan.ledger" }
925
+ };
840
926
  /**
841
927
  * Builds a fresh plan ledger snapshot from resolved plan input — the shared
842
928
  * starting point for BOTH hosts (the step path reads the invoke child's own
@@ -874,11 +960,11 @@ function isDecisionLogic(value) {
874
960
  * diagnostics; a machine typically routes this via the decision invoke's
875
961
  * `onError`.
876
962
  */
877
- var DecisionExhaustedError = class extends Error {
963
+ var AgentDecisionExhaustedError = class extends AgentError {
878
964
  attempts;
879
965
  constructor(attempts) {
880
- super(`Decision exhausted after ${attempts.length} attempt${attempts.length === 1 ? "" : "s"}: ` + attempts.map((attempt) => attempt.reason).join("; "));
881
- this.name = "DecisionExhaustedError";
966
+ super("decision-exhausted", `Decision exhausted after ${attempts.length} attempt${attempts.length === 1 ? "" : "s"}: ` + attempts.map((attempt) => attempt.reason).join("; "));
967
+ this.name = "AgentDecisionExhaustedError";
882
968
  this.attempts = attempts;
883
969
  }
884
970
  };
@@ -916,7 +1002,7 @@ function renderDecisionAttempts(request) {
916
1002
  * the next attempt via `request.attempts`, so an adapter can render "your
917
1003
  * last choice failed because X — try again" into the next model call; core
918
1004
  * never rewrites the request itself. Exhausting all attempts throws
919
- * {@link DecisionExhaustedError} with the full attempts list.
1005
+ * {@link AgentDecisionExhaustedError} with the full attempts list.
920
1006
  *
921
1007
  * @example
922
1008
  * ```ts
@@ -931,11 +1017,13 @@ async function resolveDecision(request, executor, options = {}) {
931
1017
  const eventsByType = new Map(request.events.map((event) => [event.type, event]));
932
1018
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
933
1019
  options.signal?.throwIfAborted();
934
- const { event } = await executor({
1020
+ const result = await executor({
935
1021
  ...request,
936
1022
  attempts: [...attempts],
937
1023
  signal: options.signal
938
1024
  });
1025
+ if (!result || typeof result !== "object" || typeof result.event !== "object" || result.event === null || typeof result.event.type !== "string") throw new Error(`decide executor must return { event: { type: string, ... } }; got ${JSON.stringify(result)}. Wrap the chosen event: return { event: { type: 'SAFE' } }.`);
1026
+ const { event } = result;
939
1027
  const descriptor = eventsByType.get(event.type);
940
1028
  if (!descriptor) {
941
1029
  attempts.push({
@@ -972,7 +1060,7 @@ async function resolveDecision(request, executor, options = {}) {
972
1060
  }
973
1061
  return validatedEvent;
974
1062
  }
975
- throw new DecisionExhaustedError(attempts);
1063
+ throw new AgentDecisionExhaustedError(attempts);
976
1064
  }
977
1065
  //#endregion
978
- export { validateSchemaSync as $, parseOutput as A, missingActor as B, createTextLogic as C, isTextLogic as D, isStructuredOutputSchema as E, getMachineSuspensionPredicate as F, getJsonSchemaSync as G, findNonSerializableContextPaths as H, getRegisteredAgentExecutionOptions as I, isStandardSchema as J, getMachineStructuralHash as K, getRegisteredAgentModels as L, userInputActor as M, agentExecutionOptions as N, normalizeGeneratorResult as O, executorBoundLogics as P, userMessage as Q, isUnboundPlaceholder as R, builtinTextActors as S, getAgentOutputMode as T, getAgentMessages as U, assistantMessage as V, getJsonSchema as W, systemMessage as X, persistSnapshot as Y, toolMessage as Z, INTERPRET_SOURCE as _, createPlanActor as a, bindRequestExecutor as b, isPlanLogic as c, EVENT_TOOL_PREFIX as d, getAcceptedEvents as f, DECIDE_ACTOR as g, sanitizeEventToolName as h, createDecideActor as i, parseStructuredEnvelope as j, parseModelRef as k, renderDecisionAttempts as l, parseAgentEvent as m, PLAN_DONE_EVENT_TYPE as n, initialPlanLedger as o, matchesEventPattern as p, getStateMeta as q, advancePlanLedger as r, isDecisionLogic as s, DecisionExhaustedError as t, resolveDecision as u, PLAN_ACTOR as v, executeAgentTextRequest as w, buildEnvelopeSchema as x, USER_INPUT_ACTOR as y, machineSuspensionPredicates as z };
1066
+ export { validateSchemaSync as $, parseStructuredEnvelope as A, missingActor as B, executeAgentTextRequest as C, normalizeGeneratorResult as D, isTextLogic as E, getMachineSuspensionPredicate as F, getJsonSchemaSync as G, findNonSerializableContextPaths as H, getRegisteredAgentExecutionOptions as I, isStandardSchema as J, getMachineStructuralHash as K, isUnboundPlaceholder as L, agentExecutionOptions as M, executorBoundLogics as N, parseModelRef as O, getMachineStaticTransitionTargets as P, userMessage as Q, machineStaticTransitionTargets as R, createTextLogic as S, getAgentOutputMode as T, getAgentMessages as U, assistantMessage as V, getJsonSchema as W, systemMessage as X, persistSnapshot as Y, toolMessage as Z, PLAN_ACTOR as _, createPlanActor as a, buildEnvelopeSchema as b, isPlanLogic as c, getAcceptedEvents as d, parseAgentEvent as f, INTERPRET_SOURCE as g, DECIDE_ACTOR as h, createDecideActor as i, userInputActor as j, parseOutput as k, renderDecisionAttempts as l, AGENT_USAGE_TOKEN_FIELDS as m, PLAN_DONE_EVENT_TYPE as n, initialPlanLedger as o, sanitizeEventToolName as p, getStateMeta as q, advancePlanLedger as r, isDecisionLogic as s, AgentDecisionExhaustedError as t, resolveDecision as u, USER_INPUT_ACTOR as v, extractCallUsage as w, builtinTextActors as x, bindRequestExecutor as y, machineSuspensionPredicates as z };