@statelyai/agent 2.0.0-alpha.11 → 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 (66) hide show
  1. package/dist/ai-sdk.cjs +4 -5
  2. package/dist/ai-sdk.d.cts +7 -4
  3. package/dist/ai-sdk.d.mts +7 -4
  4. package/dist/ai-sdk.mjs +1 -2
  5. package/dist/{events-JiVPYrct.mjs → decision-BezSD_YC.mjs} +327 -20
  6. package/dist/{events-CRQj3VtP.cjs → decision-dWGhBh0P.cjs} +401 -28
  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 +1050 -705
  16. package/dist/index.d.cts +538 -565
  17. package/dist/index.d.mts +538 -565
  18. package/dist/index.mjs +950 -644
  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-CaKqgX4Y.d.mts → text-logic-CorGzucG.d.cts} +103 -59
  36. package/dist/{text-logic-Ckhr2kKC.d.cts → text-logic-DjR5PUVz.d.mts} +103 -59
  37. package/dist/{types-qm00QF91.d.mts → types-QbEfCVny.d.cts} +1 -1
  38. package/dist/{types-C9QiMjre.d.cts → types-_FXoFBGO.d.mts} +1 -1
  39. package/package.json +44 -39
  40. package/readme.md +28 -7
  41. package/schemas/agent-workflow.json +40 -21
  42. package/skills/generate-machine/SKILL.md +267 -0
  43. package/dist/adapter.cjs +0 -15
  44. package/dist/adapter.d.cts +0 -4
  45. package/dist/adapter.d.mts +0 -4
  46. package/dist/adapter.mjs +0 -2
  47. package/dist/decision-C3k4ve51.mjs +0 -227
  48. package/dist/decision-D8wJrM8W.cjs +0 -286
  49. package/dist/openai-compat.cjs +0 -309
  50. package/dist/openai-compat.d.cts +0 -59
  51. package/dist/openai-compat.d.mts +0 -59
  52. package/dist/openai-compat.mjs +0 -308
  53. package/dist/steps-BALp1eZo.d.mts +0 -198
  54. package/dist/steps-CVe54GPP.cjs +0 -420
  55. package/dist/steps-CkyyyuHd.mjs +0 -379
  56. package/dist/steps-MjnQI4aB.d.cts +0 -198
  57. package/dist/steps.cjs +0 -12
  58. package/dist/steps.d.cts +0 -3
  59. package/dist/steps.d.mts +0 -3
  60. package/dist/steps.mjs +0 -3
  61. package/dist/utils-BYqT_Dyv.d.cts +0 -108
  62. package/dist/utils-Do5wIJrh.d.mts +0 -108
  63. package/dist/zod.cjs +0 -31
  64. package/dist/zod.d.cts +0 -30
  65. package/dist/zod.d.mts +0 -30
  66. package/dist/zod.mjs +0 -30
@@ -1,3 +1,4 @@
1
+ const require_errors = require("./errors-DUBBzRLP.cjs");
1
2
  let xstate = require("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;
@@ -236,6 +236,24 @@ function getMachineSuspensionPredicate(machine) {
236
236
  const config = machine.config;
237
237
  return config ? machineSuspensionPredicates.get(config) : void 0;
238
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
+ }
239
257
  const unboundPlaceholderLogics = /* @__PURE__ */ new WeakSet();
240
258
  /** Text/decision logics created WITH their own executor (withExecutor or the
241
259
  * factory's second arg) — these are runnable as-is, so runAgent's bind check
@@ -243,7 +261,7 @@ const unboundPlaceholderLogics = /* @__PURE__ */ new WeakSet();
243
261
  const executorBoundLogics = /* @__PURE__ */ new WeakSet();
244
262
  function missingActor(src) {
245
263
  const logic = (0, xstate.createAsyncLogic)({ run: async () => {
246
- 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}': ... } }).`);
247
265
  } });
248
266
  unboundPlaceholderLogics.add(logic);
249
267
  return logic;
@@ -287,6 +305,33 @@ function parseModelRef(modelRef) {
287
305
  modelId: modelRef.slice(slash + 1)
288
306
  };
289
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
+ }
290
335
  const agentTextInputSchema = { "~standard": {
291
336
  version: 1,
292
337
  vendor: "statelyai-agent",
@@ -314,9 +359,16 @@ const stringOutputSchema = { "~standard": {
314
359
  return typeof value === "string" ? { value } : { issues: [{ message: "Expected string output" }] };
315
360
  }
316
361
  } };
362
+ const noInputSchema = { "~standard": {
363
+ version: 1,
364
+ vendor: "statelyai-agent",
365
+ validate(value) {
366
+ return { value };
367
+ }
368
+ } };
317
369
  function createBuiltinTextActor(src, mode, outputSchema) {
318
370
  const logic = (0, xstate.createAsyncLogic)({ run: async () => {
319
- 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(...).`);
320
372
  } });
321
373
  return Object.assign(logic, {
322
374
  kind: "statelyai.textLogic",
@@ -365,7 +417,7 @@ const builtinTextActors = {
365
417
  };
366
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 */
367
419
  const userInputActor = (0, xstate.createAsyncLogic)({ run: async () => {
368
- 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}': ... } }).`);
369
421
  } });
370
422
  unboundPlaceholderLogics.add(userInputActor);
371
423
  /**
@@ -384,7 +436,7 @@ function resolveTextLogicValue(value, args) {
384
436
  /**
385
437
  * Creates reusable, standalone {@link TextLogic}: an actor that, when run,
386
438
  * resolves typed input to typed output via a model call. Register the
387
- * result under `actorSources:` and invoke it by name (equivalent to what
439
+ * result under `actors:` and invoke it by name (equivalent to what
388
440
  * `setupAgent({ requests })` builds internally for each request entry). Pass
389
441
  * `execute` here, or bind it later with `.withExecutor(...)`, a runtime
390
442
  * adapter's `machine.provide(...)`, or `runAgent`'s `generateText`/
@@ -402,8 +454,12 @@ function resolveTextLogicValue(value, args) {
402
454
  * ```
403
455
  */
404
456
  function createTextLogic(config, execute) {
457
+ const schemas = {
458
+ input: config.schemas?.input ?? noInputSchema,
459
+ output: config.schemas?.output ?? stringOutputSchema
460
+ };
405
461
  const request = (input) => {
406
- const args = { input: validateSchemaSync(config.schemas.input, input) };
462
+ const args = { input: validateSchemaSync(schemas.input, input) };
407
463
  return {
408
464
  name: resolveTextLogicValue(config.name, args),
409
465
  model: resolveTextLogicValue(config.model, args),
@@ -412,7 +468,7 @@ function createTextLogic(config, execute) {
412
468
  messages: resolveTextLogicValue(config.messages, args),
413
469
  tools: resolveTextLogicValue(config.tools, args),
414
470
  toolChoice: resolveTextLogicValue(config.toolChoice, args),
415
- outputSchema: config.schemas.output,
471
+ outputSchema: schemas.output,
416
472
  reasoning: resolveTextLogicValue(config.reasoning, args),
417
473
  temperature: resolveTextLogicValue(config.temperature, args),
418
474
  maxOutputTokens: resolveTextLogicValue(config.maxOutputTokens, args),
@@ -425,7 +481,7 @@ function createTextLogic(config, execute) {
425
481
  };
426
482
  const logic = (0, xstate.createAsyncLogic)({ run: async ({ input, signal, system, self }, enq) => {
427
483
  const resolvedRequest = request(input);
428
- 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 }).");
429
485
  const result = await execute({
430
486
  input,
431
487
  request: resolvedRequest,
@@ -436,16 +492,16 @@ function createTextLogic(config, execute) {
436
492
  });
437
493
  const selfId = self?.id;
438
494
  const output = await normalizeGeneratorResult(result, typeof selfId === "string" ? selfId : "text logic", { request: resolvedRequest });
439
- return validateSchemaSync(config.schemas.output, output);
495
+ return validateSchemaSync(schemas.output, output);
440
496
  } });
441
497
  const textLogic = Object.assign(logic, {
442
498
  kind: "statelyai.textLogic",
443
499
  mode: config.mode ?? "generate",
444
- schemas: config.schemas,
500
+ schemas,
445
501
  request,
446
502
  async execute(input, executors) {
447
503
  const { output } = await executeAgentTextRequest(config.mode ?? "generate", "textLogic", request(input), executors);
448
- return validateSchemaSync(config.schemas.output, output);
504
+ return validateSchemaSync(schemas.output, output);
449
505
  },
450
506
  withExecutor(nextExecute) {
451
507
  return createTextLogic(config, nextExecute);
@@ -465,7 +521,7 @@ function createTextLogic(config, execute) {
465
521
  * @example
466
522
  * ```ts
467
523
  * childMachine.provide({
468
- * actorSources: {
524
+ * actors: {
469
525
  * researchTopic: bindRequestExecutor(setup.requests.researchTopic, generateText),
470
526
  * },
471
527
  * });
@@ -503,10 +559,6 @@ function getAgentOutputMode(schema) {
503
559
  if (jsonSchema.type === void 0 && ("anyOf" in jsonSchema || "oneOf" in jsonSchema || "allOf" in jsonSchema)) return "structured";
504
560
  return "text";
505
561
  }
506
- /** True when {@link getAgentOutputMode} classifies `schema` as `'structured'`. */
507
- function isStructuredOutputSchema(schema) {
508
- return getAgentOutputMode(schema) === "structured";
509
- }
510
562
  /**
511
563
  * Builds the uniform structured-output envelope schema every structured request
512
564
  * is sent to the provider as: a root object `{ result: <inner> }`, plus — when
@@ -692,6 +744,18 @@ function matchesEventPattern(eventType, pattern) {
692
744
  if (pattern.endsWith(".*")) return eventType.startsWith(`${pattern.slice(0, -1)}`);
693
745
  return eventType === pattern;
694
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.";
695
759
  /** True when an `allowedEvents` entry is a wildcard pattern rather than a concrete event type. @internal */
696
760
  function isEventPattern(entry) {
697
761
  return entry === "*" || entry.endsWith(".*");
@@ -734,13 +798,29 @@ function parseAgentEvent(snapshot, event, options = {}) {
734
798
  }
735
799
  return event;
736
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
+ */
737
817
  function getAcceptedEvents(snapshot, options = {}) {
738
818
  const eventTypes = options.eventTypes;
739
819
  const seen = /* @__PURE__ */ new Set();
740
820
  const usedToolNames = /* @__PURE__ */ new Set();
741
821
  return (0, xstate.getNextTransitions)(snapshot).flatMap((transitionDefinition) => {
742
822
  const eventType = transitionDefinition.eventType;
743
- 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 [];
744
824
  seen.add(eventType);
745
825
  const defaultToolName = sanitizeEventToolName(eventType);
746
826
  const toolName = options.eventToolName ? options.eventToolName({
@@ -756,6 +836,245 @@ function getAcceptedEvents(snapshot, options = {}) {
756
836
  });
757
837
  }
758
838
  //#endregion
839
+ //#region src/decision.ts
840
+ function decideRequestFromInput(input) {
841
+ const allowedEventTypes = resolveAllowedEventTypes(input.allowedEvents, input) ?? [];
842
+ return {
843
+ kind: "decision",
844
+ id: "",
845
+ model: input.model,
846
+ system: input.system,
847
+ prompt: input.prompt,
848
+ messages: input.messages,
849
+ events: allowedEventTypes.filter((type) => !isEventPattern(type)).map((type) => ({
850
+ type,
851
+ toolName: sanitizeEventToolName(type)
852
+ })),
853
+ attempts: [],
854
+ temperature: input.temperature,
855
+ maxOutputTokens: input.maxOutputTokens,
856
+ topP: input.topP,
857
+ topK: input.topK,
858
+ seed: input.seed,
859
+ stopSequences: input.stopSequences,
860
+ metadata: input.metadata
861
+ };
862
+ }
863
+ function decideActorWithExecutor(execute) {
864
+ const logic = (0, xstate.createAsyncLogic)({ run: async ({ input, signal }) => {
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(...).`);
866
+ const resolvedEventTypes = resolveAllowedEventTypes(input.allowedEvents, input);
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.`);
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.`);
869
+ return resolveDecision(decideRequestFromInput(input), execute, {
870
+ maxRetries: input.maxRetries ?? 2,
871
+ signal
872
+ });
873
+ } });
874
+ return Object.assign(logic, {
875
+ kind: "statelyai.decisionLogic",
876
+ maxRetries: 2,
877
+ request: decideRequestFromInput,
878
+ allowedEventTypes: (input) => resolveAllowedEventTypes(input.allowedEvents, input),
879
+ withExecutor: (nextExecute) => decideActorWithExecutor(nextExecute)
880
+ });
881
+ }
882
+ function createDecideActor() {
883
+ return decideActorWithExecutor();
884
+ }
885
+ /**
886
+ * Reserved event type the `agent.plan` builtin adds to every step's
887
+ * candidates as the explicit "no further action needed" move. Choosing it
888
+ * ends the plan (`stopped: 'done'`); it is never sent to the machine, so
889
+ * machines need no no-op sentinel event of their own.
890
+ */
891
+ const PLAN_DONE_EVENT_TYPE = "agent.plan.done";
892
+ function createPlanActor() {
893
+ const logic = (0, xstate.createLogic)({
894
+ context: ({ input }) => ({
895
+ applied: [],
896
+ stepsRemaining: input.maxSteps ?? 8,
897
+ stopped: null
898
+ }),
899
+ run: ({ context, event }) => event.type === "plan.applied" ? { context: {
900
+ ...context,
901
+ applied: [...context.applied, event.event],
902
+ stepsRemaining: context.stepsRemaining - 1
903
+ } } : event.type === "plan.ended" ? {
904
+ context: {
905
+ ...context,
906
+ stopped: event.stopped
907
+ },
908
+ status: "done",
909
+ output: {
910
+ steps: context.applied,
911
+ stopped: event.stopped
912
+ }
913
+ } : void 0
914
+ });
915
+ return Object.assign(logic, {
916
+ kind: "statelyai.planLogic",
917
+ maxRetries: 2,
918
+ request: decideRequestFromInput,
919
+ allowedEventTypes: (input) => resolveAllowedEventTypes(input.allowedEvents, input)
920
+ });
921
+ }
922
+ const PLAN_LEDGER_SCOPE = {
923
+ emit: () => {},
924
+ self: { id: "agent.plan.ledger" }
925
+ };
926
+ /**
927
+ * Builds a fresh plan ledger snapshot from resolved plan input — the shared
928
+ * starting point for BOTH hosts (the step path reads the invoke child's own
929
+ * initial snapshot; runAgent seeds a local ledger with this). @internal
930
+ */
931
+ function initialPlanLedger(logic, input) {
932
+ return logic.getInitialSnapshot(PLAN_LEDGER_SCOPE, input);
933
+ }
934
+ /**
935
+ * Advances a plan ledger by one {@link PlanLedgerEvent}, returning the next
936
+ * snapshot (unwrapping `createLogic`'s `[snapshot, effects]` tuple). Pure — no
937
+ * mutation of the input snapshot. @internal
938
+ */
939
+ function advancePlanLedger(logic, snapshot, event) {
940
+ const result = logic.transition(snapshot, event, PLAN_LEDGER_SCOPE);
941
+ return Array.isArray(result) ? result[0] : result;
942
+ }
943
+ /** Type guard: true for the `agent.plan` builtin logic (checks the `kind` marker). @internal */
944
+ function isPlanLogic(logic) {
945
+ return !!logic && logic.kind === "statelyai.planLogic";
946
+ }
947
+ function resolveAllowedEventTypes(allowedEvents, input) {
948
+ if (allowedEvents === void 0) return;
949
+ const resolved = typeof allowedEvents === "function" ? allowedEvents({ input }) : allowedEvents;
950
+ return typeof resolved === "string" ? [resolved] : resolved;
951
+ }
952
+ /** Type guard: true for any actor logic built by createDecisionLogic/createDecideActor (checks the `kind` marker). @internal */
953
+ function isDecisionLogic(value) {
954
+ return !!value && typeof value === "object" && value.kind === "statelyai.decisionLogic" && typeof value.request === "function";
955
+ }
956
+ /**
957
+ * Thrown by {@link resolveDecision} when every attempt (up to
958
+ * `maxRetries + 1` of them) fails one of the three checks recorded in
959
+ * {@link DecisionAttempt.failure}. Carries the full `attempts` list for
960
+ * diagnostics; a machine typically routes this via the decision invoke's
961
+ * `onError`.
962
+ */
963
+ var AgentDecisionExhaustedError = class extends require_errors.AgentError {
964
+ attempts;
965
+ constructor(attempts) {
966
+ super("decision-exhausted", `Decision exhausted after ${attempts.length} attempt${attempts.length === 1 ? "" : "s"}: ` + attempts.map((attempt) => attempt.reason).join("; "));
967
+ this.name = "AgentDecisionExhaustedError";
968
+ this.attempts = attempts;
969
+ }
970
+ };
971
+ /**
972
+ * Renders a decision request's prior failed `attempts` into feedback messages
973
+ * a host appends to the model call so retries converge — the transport-agnostic
974
+ * "your last choice failed because X, choose again from Y" logic every adapter
975
+ * and raw-SDK host repeats. Returns one `user`-role {@link AgentMessage} per
976
+ * attempt (empty when there are none); adapters map each onto their wire
977
+ * message shape (`attempt.content` is always a string). Core never rewrites the
978
+ * request itself — this only turns the recorded attempts into messages.
979
+ *
980
+ * @example
981
+ * ```ts
982
+ * const messages = [...baseMessages, ...renderDecisionAttempts(request)];
983
+ * ```
984
+ */
985
+ function renderDecisionAttempts(request) {
986
+ const types = request.events.map((event) => event.type).join(", ") || "(none)";
987
+ return request.attempts.map((attempt) => userMessage(`Your previous choice failed: ${attempt.reason}. Choose again from: ${types}`));
988
+ }
989
+ /**
990
+ * Validation + retry core for decisions. No provider mechanics — the
991
+ * `executor` is responsible for making the model choose an event; this
992
+ * function only validates the choice and retries on failure, up to
993
+ * `options.maxRetries` (default 2, i.e. up to 3 attempts total).
994
+ *
995
+ * Each attempt is checked in order and can fail one of three ways (recorded
996
+ * as a {@link DecisionAttempt}): `'unknown-event'` (the chosen `type` is not
997
+ * among `request.events`), `'invalid-payload'` (the payload fails that
998
+ * event's schema), or `'rejected-by-guard'` (passes both checks but
999
+ * `options.canTake` returns `false` — a type/payload-legal event the
1000
+ * machine's guard rejects right now; omit `canTake` to skip this check).
1001
+ * Every prior failed attempt for this call is fed back to the executor on
1002
+ * the next attempt via `request.attempts`, so an adapter can render "your
1003
+ * last choice failed because X — try again" into the next model call; core
1004
+ * never rewrites the request itself. Exhausting all attempts throws
1005
+ * {@link AgentDecisionExhaustedError} with the full attempts list.
1006
+ *
1007
+ * @example
1008
+ * ```ts
1009
+ * const event = await resolveDecision(request, decide, {
1010
+ * canTake: (e) => snapshot.can(e),
1011
+ * });
1012
+ * ```
1013
+ */
1014
+ async function resolveDecision(request, executor, options = {}) {
1015
+ const maxRetries = options.maxRetries ?? 2;
1016
+ const attempts = [];
1017
+ const eventsByType = new Map(request.events.map((event) => [event.type, event]));
1018
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
1019
+ options.signal?.throwIfAborted();
1020
+ const result = await executor({
1021
+ ...request,
1022
+ attempts: [...attempts],
1023
+ signal: options.signal
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;
1027
+ const descriptor = eventsByType.get(event.type);
1028
+ if (!descriptor) {
1029
+ attempts.push({
1030
+ event,
1031
+ failure: "unknown-event",
1032
+ reason: `'${event.type}' is not among the currently allowed events: ${request.events.map((candidate) => candidate.type).join(", ") || "(none)"}.`
1033
+ });
1034
+ continue;
1035
+ }
1036
+ let validatedEvent = event;
1037
+ if (descriptor.inputSchema) {
1038
+ const { type, ...payload } = event;
1039
+ try {
1040
+ validatedEvent = {
1041
+ ...validateSchemaSync(descriptor.inputSchema, payload),
1042
+ type
1043
+ };
1044
+ } catch (error) {
1045
+ attempts.push({
1046
+ event,
1047
+ failure: "invalid-payload",
1048
+ reason: `'${event.type}' payload failed validation: ${error instanceof Error ? error.message : String(error)}`
1049
+ });
1050
+ continue;
1051
+ }
1052
+ }
1053
+ if (options.canTake?.(validatedEvent) === false) {
1054
+ attempts.push({
1055
+ event: validatedEvent,
1056
+ failure: "rejected-by-guard",
1057
+ reason: `'${validatedEvent.type}' is not currently takeable (guard rejected it).`
1058
+ });
1059
+ continue;
1060
+ }
1061
+ return validatedEvent;
1062
+ }
1063
+ throw new AgentDecisionExhaustedError(attempts);
1064
+ }
1065
+ //#endregion
1066
+ Object.defineProperty(exports, "AGENT_USAGE_TOKEN_FIELDS", {
1067
+ enumerable: true,
1068
+ get: function() {
1069
+ return AGENT_USAGE_TOKEN_FIELDS;
1070
+ }
1071
+ });
1072
+ Object.defineProperty(exports, "AgentDecisionExhaustedError", {
1073
+ enumerable: true,
1074
+ get: function() {
1075
+ return AgentDecisionExhaustedError;
1076
+ }
1077
+ });
759
1078
  Object.defineProperty(exports, "DECIDE_ACTOR", {
760
1079
  enumerable: true,
761
1080
  get: function() {
@@ -774,12 +1093,24 @@ Object.defineProperty(exports, "PLAN_ACTOR", {
774
1093
  return PLAN_ACTOR;
775
1094
  }
776
1095
  });
1096
+ Object.defineProperty(exports, "PLAN_DONE_EVENT_TYPE", {
1097
+ enumerable: true,
1098
+ get: function() {
1099
+ return PLAN_DONE_EVENT_TYPE;
1100
+ }
1101
+ });
777
1102
  Object.defineProperty(exports, "USER_INPUT_ACTOR", {
778
1103
  enumerable: true,
779
1104
  get: function() {
780
1105
  return USER_INPUT_ACTOR;
781
1106
  }
782
1107
  });
1108
+ Object.defineProperty(exports, "advancePlanLedger", {
1109
+ enumerable: true,
1110
+ get: function() {
1111
+ return advancePlanLedger;
1112
+ }
1113
+ });
783
1114
  Object.defineProperty(exports, "agentExecutionOptions", {
784
1115
  enumerable: true,
785
1116
  get: function() {
@@ -810,6 +1141,18 @@ Object.defineProperty(exports, "builtinTextActors", {
810
1141
  return builtinTextActors;
811
1142
  }
812
1143
  });
1144
+ Object.defineProperty(exports, "createDecideActor", {
1145
+ enumerable: true,
1146
+ get: function() {
1147
+ return createDecideActor;
1148
+ }
1149
+ });
1150
+ Object.defineProperty(exports, "createPlanActor", {
1151
+ enumerable: true,
1152
+ get: function() {
1153
+ return createPlanActor;
1154
+ }
1155
+ });
813
1156
  Object.defineProperty(exports, "createTextLogic", {
814
1157
  enumerable: true,
815
1158
  get: function() {
@@ -828,6 +1171,12 @@ Object.defineProperty(exports, "executorBoundLogics", {
828
1171
  return executorBoundLogics;
829
1172
  }
830
1173
  });
1174
+ Object.defineProperty(exports, "extractCallUsage", {
1175
+ enumerable: true,
1176
+ get: function() {
1177
+ return extractCallUsage;
1178
+ }
1179
+ });
831
1180
  Object.defineProperty(exports, "findNonSerializableContextPaths", {
832
1181
  enumerable: true,
833
1182
  get: function() {
@@ -864,6 +1213,12 @@ Object.defineProperty(exports, "getJsonSchemaSync", {
864
1213
  return getJsonSchemaSync;
865
1214
  }
866
1215
  });
1216
+ Object.defineProperty(exports, "getMachineStaticTransitionTargets", {
1217
+ enumerable: true,
1218
+ get: function() {
1219
+ return getMachineStaticTransitionTargets;
1220
+ }
1221
+ });
867
1222
  Object.defineProperty(exports, "getMachineStructuralHash", {
868
1223
  enumerable: true,
869
1224
  get: function() {
@@ -888,22 +1243,28 @@ Object.defineProperty(exports, "getStateMeta", {
888
1243
  return getStateMeta;
889
1244
  }
890
1245
  });
891
- Object.defineProperty(exports, "isEventPattern", {
1246
+ Object.defineProperty(exports, "initialPlanLedger", {
892
1247
  enumerable: true,
893
1248
  get: function() {
894
- return isEventPattern;
1249
+ return initialPlanLedger;
895
1250
  }
896
1251
  });
897
- Object.defineProperty(exports, "isStandardSchema", {
1252
+ Object.defineProperty(exports, "isDecisionLogic", {
898
1253
  enumerable: true,
899
1254
  get: function() {
900
- return isStandardSchema;
1255
+ return isDecisionLogic;
901
1256
  }
902
1257
  });
903
- Object.defineProperty(exports, "isStructuredOutputSchema", {
1258
+ Object.defineProperty(exports, "isPlanLogic", {
904
1259
  enumerable: true,
905
1260
  get: function() {
906
- return isStructuredOutputSchema;
1261
+ return isPlanLogic;
1262
+ }
1263
+ });
1264
+ Object.defineProperty(exports, "isStandardSchema", {
1265
+ enumerable: true,
1266
+ get: function() {
1267
+ return isStandardSchema;
907
1268
  }
908
1269
  });
909
1270
  Object.defineProperty(exports, "isTextLogic", {
@@ -918,16 +1279,16 @@ Object.defineProperty(exports, "isUnboundPlaceholder", {
918
1279
  return isUnboundPlaceholder;
919
1280
  }
920
1281
  });
921
- Object.defineProperty(exports, "machineSuspensionPredicates", {
1282
+ Object.defineProperty(exports, "machineStaticTransitionTargets", {
922
1283
  enumerable: true,
923
1284
  get: function() {
924
- return machineSuspensionPredicates;
1285
+ return machineStaticTransitionTargets;
925
1286
  }
926
1287
  });
927
- Object.defineProperty(exports, "matchesEventPattern", {
1288
+ Object.defineProperty(exports, "machineSuspensionPredicates", {
928
1289
  enumerable: true,
929
1290
  get: function() {
930
- return matchesEventPattern;
1291
+ return machineSuspensionPredicates;
931
1292
  }
932
1293
  });
933
1294
  Object.defineProperty(exports, "missingActor", {
@@ -972,6 +1333,18 @@ Object.defineProperty(exports, "persistSnapshot", {
972
1333
  return persistSnapshot;
973
1334
  }
974
1335
  });
1336
+ Object.defineProperty(exports, "renderDecisionAttempts", {
1337
+ enumerable: true,
1338
+ get: function() {
1339
+ return renderDecisionAttempts;
1340
+ }
1341
+ });
1342
+ Object.defineProperty(exports, "resolveDecision", {
1343
+ enumerable: true,
1344
+ get: function() {
1345
+ return resolveDecision;
1346
+ }
1347
+ });
975
1348
  Object.defineProperty(exports, "sanitizeEventToolName", {
976
1349
  enumerable: true,
977
1350
  get: function() {
@@ -0,0 +1,19 @@
1
+ //#region src/errors.d.ts
2
+ /**
3
+ * Base class for every error this package throws. Carries a stable, kebab-case
4
+ * `code` so hosts can branch on the failure without `instanceof` (useful across
5
+ * bundle/realm boundaries and after serialization).
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * catch (error) {
10
+ * if (error instanceof AgentError && error.code === 'agent-idle') { ... }
11
+ * }
12
+ * ```
13
+ */
14
+ declare class AgentError extends Error {
15
+ readonly code: string;
16
+ constructor(code: string, message: string, options?: ErrorOptions);
17
+ }
18
+ //#endregion
19
+ export { AgentError as t };
@@ -0,0 +1,19 @@
1
+ //#region src/errors.d.ts
2
+ /**
3
+ * Base class for every error this package throws. Carries a stable, kebab-case
4
+ * `code` so hosts can branch on the failure without `instanceof` (useful across
5
+ * bundle/realm boundaries and after serialization).
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * catch (error) {
10
+ * if (error instanceof AgentError && error.code === 'agent-idle') { ... }
11
+ * }
12
+ * ```
13
+ */
14
+ declare class AgentError extends Error {
15
+ readonly code: string;
16
+ constructor(code: string, message: string, options?: ErrorOptions);
17
+ }
18
+ //#endregion
19
+ export { AgentError as t };
@@ -0,0 +1,23 @@
1
+ //#region src/errors.ts
2
+ /**
3
+ * Base class for every error this package throws. Carries a stable, kebab-case
4
+ * `code` so hosts can branch on the failure without `instanceof` (useful across
5
+ * bundle/realm boundaries and after serialization).
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * catch (error) {
10
+ * if (error instanceof AgentError && error.code === 'agent-idle') { ... }
11
+ * }
12
+ * ```
13
+ */
14
+ var AgentError = class extends Error {
15
+ code;
16
+ constructor(code, message, options) {
17
+ super(message, options);
18
+ this.name = "AgentError";
19
+ this.code = code;
20
+ }
21
+ };
22
+ //#endregion
23
+ export { AgentError as t };