@statelyai/agent 1.1.6 → 2.0.0-alpha.10

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 (88) hide show
  1. package/LICENSE +21 -0
  2. package/dist/ai-sdk.cjs +342 -0
  3. package/dist/ai-sdk.d.cts +206 -0
  4. package/dist/ai-sdk.d.mts +206 -0
  5. package/dist/ai-sdk.mjs +331 -0
  6. package/dist/cli.cjs +64 -0
  7. package/dist/cli.d.cts +1 -0
  8. package/dist/cli.d.mts +1 -0
  9. package/dist/cli.mjs +65 -0
  10. package/dist/decision-CQdrKc8k.mjs +978 -0
  11. package/dist/decision-b-lkcs4L.cjs +1295 -0
  12. package/dist/index.cjs +59 -0
  13. package/dist/index.d.cts +212 -0
  14. package/dist/index.d.mts +201 -417
  15. package/dist/index.mjs +4 -588
  16. package/dist/openai-compat.cjs +319 -0
  17. package/dist/openai-compat.d.cts +98 -0
  18. package/dist/openai-compat.d.mts +98 -0
  19. package/dist/openai-compat.mjs +312 -0
  20. package/dist/run-agent-BFMkuI1F.cjs +1599 -0
  21. package/dist/run-agent-BVMd--1l.d.cts +1103 -0
  22. package/dist/run-agent-BoAOq_0Z.mjs +1540 -0
  23. package/dist/run-agent-DzYJb3CK.d.mts +1103 -0
  24. package/dist/src-D-77Ha5p.cjs +1087 -0
  25. package/dist/src-DUeIFjv-.mjs +1016 -0
  26. package/dist/text-logic-C7WJpCIc.d.mts +710 -0
  27. package/dist/text-logic-CZjyACzQ.d.cts +710 -0
  28. package/dist/types-C9QiMjre.d.cts +219 -0
  29. package/dist/types-qm00QF91.d.mts +219 -0
  30. package/dist/utils-Dri7aeEG.d.cts +108 -0
  31. package/dist/utils-Y6GDRGGE.d.mts +108 -0
  32. package/dist/zod.cjs +31 -0
  33. package/dist/zod.d.cts +30 -0
  34. package/dist/zod.d.mts +30 -0
  35. package/dist/zod.mjs +30 -0
  36. package/package.json +109 -28
  37. package/readme.md +143 -6
  38. package/schemas/agent-workflow.json +527 -0
  39. package/.changeset/README.md +0 -8
  40. package/.changeset/config.json +0 -11
  41. package/.env.template +0 -3
  42. package/.github/actions/ci-setup/action.yml +0 -24
  43. package/.github/workflows/release.yml +0 -46
  44. package/.vscode/launch.json +0 -28
  45. package/CHANGELOG.md +0 -222
  46. package/dist/index.d.ts +0 -428
  47. package/dist/index.js +0 -621
  48. package/examples/chatbot.ts +0 -71
  49. package/examples/cot.ts +0 -89
  50. package/examples/email.ts +0 -118
  51. package/examples/example.ts +0 -81
  52. package/examples/goal.ts +0 -94
  53. package/examples/helpers/helpers.ts +0 -17
  54. package/examples/helpers/loader.ts +0 -32
  55. package/examples/helpers/runner.ts +0 -27
  56. package/examples/joke.ts +0 -225
  57. package/examples/multi.ts +0 -103
  58. package/examples/newspaper.ts +0 -324
  59. package/examples/number.ts +0 -102
  60. package/examples/raffle.ts +0 -105
  61. package/examples/sandbox.ts +0 -28
  62. package/examples/simple.ts +0 -39
  63. package/examples/support.ts +0 -147
  64. package/examples/ticTacToe.ts +0 -224
  65. package/examples/todo.ts +0 -137
  66. package/examples/tutor.ts +0 -100
  67. package/examples/verify.ts +0 -120
  68. package/examples/weather.ts +0 -178
  69. package/examples/wiki.ts +0 -30
  70. package/examples/word.ts +0 -171
  71. package/src/adapters/vercel.ts +0 -7
  72. package/src/agent-experimental.ts +0 -221
  73. package/src/agent.test.ts +0 -506
  74. package/src/agent.ts +0 -300
  75. package/src/decision.test.ts +0 -179
  76. package/src/decision.ts +0 -84
  77. package/src/index.ts +0 -4
  78. package/src/memory.ts +0 -25
  79. package/src/planners/shortestPathPlanner.ts +0 -22
  80. package/src/planners/simplePlanner.ts +0 -139
  81. package/src/schemas.ts +0 -11
  82. package/src/strategies/chain-of-note.ts +0 -155
  83. package/src/templates/defaultText.ts +0 -18
  84. package/src/text.ts +0 -241
  85. package/src/types.ts +0 -499
  86. package/src/utils.ts +0 -72
  87. package/tsconfig.json +0 -109
  88. package/vitest.config.ts +0 -9
@@ -0,0 +1,206 @@
1
+ import { C as StandardSchemaV1, m as ChosenEvent, n as AgentEventSchemaInputMap, u as AgentTools } from "./types-qm00QF91.mjs";
2
+ import { H as AgentEventDescriptor, i as AgentRequestExecutor, j as AgentDecisionRequest, k as AgentDecisionExecutor, l as AgentTextRequest, s as AgentRequestExecutors } from "./text-logic-C7WJpCIc.mjs";
3
+ import { D as AgentMachine, O as AgentMachineConfig, l as RunAgentOptions, u as RunAgentResult } from "./run-agent-DzYJb3CK.mjs";
4
+ import * as _$xstate from "xstate";
5
+ import { FinishReason, LanguageModel, LanguageModelUsage, ModelMessage, Tool, ToolSet, TypedToolCall, TypedToolResult } from "ai";
6
+
7
+ //#region src/ai-sdk/index.d.ts
8
+ /**
9
+ * Maps an {@link AgentTools} map onto AI SDK `tool()` definitions. A tool that
10
+ * already carries its own Standard Schema `inputSchema` — an AI SDK
11
+ * `tool({...})`, or any equivalent descriptor — is passed through **unchanged**,
12
+ * so the SDK applies its own validation, calls `execute(input, options)`, and
13
+ * every extra property (`providerOptions`, `toModelOutput`, …) survives. A bare
14
+ * `AgentToolExecute` function becomes a tool with an unconstrained input schema;
15
+ * a minimal descriptor with no readable schema is converted with a permissive
16
+ * fallback. Used internally by {@link toAiSdkCallSettings}; exported for callers
17
+ * building AI SDK calls by hand outside `createAiSdkExecutors`.
18
+ */
19
+ declare function toAiSdkTools(tools: AgentTools): {
20
+ [k: string]: Tool<unknown, unknown> | Tool<unknown, never>;
21
+ };
22
+ /** AI SDK model registry: maps model refs (as used in `setupAgent({ models })`/`AgentTextRequest.model`) to AI SDK `LanguageModel` values. The optional `TKey` parameter pins the ref keys (see {@link defineModels}); it defaults to `string`, so bare `AiSdkModelMap` stays `Record<string, LanguageModel>`. */
23
+ type AiSdkModelMap<TKey extends string = string> = Record<TKey, LanguageModel>;
24
+ /**
25
+ * Identity helper for a `models` map whose value is exported. Returns the map
26
+ * unchanged, but types it as {@link AiSdkModelMap}`<keyof T & string>` — a
27
+ * portable, nameable type — so an exported `const models = defineModels({...})`
28
+ * needs no `Record<'a' | 'b', LanguageModel>` annotation and never triggers
29
+ * TS2742 ("inferred type cannot be named without a reference to …"). The exact
30
+ * ref keys survive, so `createAiSdkExecutors({ models })` and
31
+ * `setupAgent({ models })` still infer/autocomplete them.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * export const models = defineModels({
36
+ * quick: openai('gpt-5.4-mini'),
37
+ * deep: openai('gpt-5.4'),
38
+ * });
39
+ * // typeof models === AiSdkModelMap<'quick' | 'deep'>
40
+ * ```
41
+ */
42
+ declare function defineModels<T extends Record<string, LanguageModel>>(models: T): AiSdkModelMap<keyof T & string>;
43
+ /**
44
+ * Options for {@link createAiSdkExecutors}: either a static `models` map
45
+ * (model refs resolved by lookup), a `resolveModel` function (refs resolved
46
+ * dynamically, e.g. `"openai/gpt-5.4-mini"` → `openai('gpt-5.4-mini')`), or
47
+ * both — `resolveModel` takes precedence when both are supplied.
48
+ */
49
+ type CreateAiSdkExecutorsOptions<TModels extends AiSdkModelMap = AiSdkModelMap> = {
50
+ models: TModels;
51
+ resolveModel?: (modelRef: keyof TModels & string) => LanguageModel;
52
+ } | {
53
+ models?: TModels;
54
+ resolveModel: (modelRef: string) => LanguageModel;
55
+ };
56
+ /**
57
+ * AI SDK request-mapping settings shared by `generateText`/`streamText`.
58
+ * `AgentTextRequest.messages` (`AgentMessage[]`) and AI SDK's `ModelMessage[]`
59
+ * are structurally compatible by design (§1 of .scratch/p0-design.md) — the cast
60
+ * below is a typed identity mapping, not a semantic conversion.
61
+ */
62
+ declare function toAiSdkCallSettings(request: AgentTextRequest & {
63
+ tools?: AgentTools;
64
+ }): {
65
+ temperature: number | undefined;
66
+ maxOutputTokens: number | undefined;
67
+ topP: number | undefined;
68
+ topK: number | undefined;
69
+ seed: number | undefined;
70
+ stopSequences: string[] | undefined;
71
+ tools: {
72
+ [k: string]: Tool<unknown, unknown> | Tool<unknown, never>;
73
+ } | undefined;
74
+ toolChoice: "auto" | "none" | "required" | {
75
+ type: "tool";
76
+ toolName: string;
77
+ } | undefined;
78
+ messages: ModelMessage[];
79
+ system: string | undefined;
80
+ } | {
81
+ temperature: number | undefined;
82
+ maxOutputTokens: number | undefined;
83
+ topP: number | undefined;
84
+ topK: number | undefined;
85
+ seed: number | undefined;
86
+ stopSequences: string[] | undefined;
87
+ tools: {
88
+ [k: string]: Tool<unknown, unknown> | Tool<unknown, never>;
89
+ } | undefined;
90
+ toolChoice: "auto" | "none" | "required" | {
91
+ type: "tool";
92
+ toolName: string;
93
+ } | undefined;
94
+ prompt: string;
95
+ system: string | undefined;
96
+ };
97
+ /** Maps an {@link AgentToolChoice} to AI SDK's tool-choice shape — `{ type: 'tool'; name }` becomes `{ type: 'tool'; toolName }`; `'auto'`/`'none'`/`'required'`/`undefined` pass through unchanged. */
98
+ declare function toAiSdkToolChoice(toolChoice: AgentTextRequest["toolChoice"]): "auto" | "none" | "required" | {
99
+ type: "tool";
100
+ toolName: string;
101
+ } | undefined;
102
+ /** `true` when the request should use AI SDK structured `Output.object`. */
103
+ declare function isStructuredOutputRequest(request: Pick<AgentTextRequest, "outputSchema">): boolean;
104
+ /**
105
+ * Extracts the first complete top-level JSON value from `text`, or returns
106
+ * `undefined` when there is nothing to repair (no complete value, or the value
107
+ * already spans the whole text). Models occasionally emit two structured-output
108
+ * envelopes back to back (`{"result":{…}}{"result":{…}}`), which fails JSON
109
+ * parsing wholesale; the balanced scan below recovers the first value and
110
+ * drops the rest.
111
+ */
112
+ declare function extractFirstJsonValue(text: string): string | undefined;
113
+ /**
114
+ * Raw result shape from {@link AiSdkExecutors.generateText} — the `{ output }`
115
+ * envelope (the validated structured object for structured-output requests,
116
+ * or the accumulated text string otherwise; unwrapped by
117
+ * `normalizeGeneratorResult`) plus the AI SDK call metadata. Core only reads
118
+ * `output`; everything else flows verbatim to `runAgent`'s
119
+ * `onResult(request, { raw })`, so `raw as AiSdkGenerateResult` is the
120
+ * supported cast for token accounting and tracing.
121
+ */
122
+ type AiSdkGenerateResult = {
123
+ output: unknown;
124
+ /** The model's reasoning, present only when the request opted in via
125
+ * `reasoning: true` and the model produced it (see the structured-output
126
+ * envelope in {@link buildEnvelopeSchema}). Never enters machine context/output. */
127
+ reasoning?: string;
128
+ usage: LanguageModelUsage;
129
+ finishReason: FinishReason;
130
+ toolCalls: TypedToolCall<ToolSet>[];
131
+ toolResults: TypedToolResult<ToolSet>[];
132
+ };
133
+ /** Raw result shape from {@link AiSdkExecutors.streamText} — the `{ output }` envelope carrying the fully-accumulated text once the stream finishes (chunks are delivered separately via `onChunk`), plus the stream's final usage/finish metadata for `onResult`. */
134
+ type AiSdkStreamResult = {
135
+ output: string;
136
+ usage: LanguageModelUsage;
137
+ finishReason: FinishReason;
138
+ };
139
+ /** Raw result shape from {@link AiSdkExecutors.decide} — the chosen event plus the AI SDK call metadata, delivered per decision attempt to `onResult`. */
140
+ type AiSdkDecideResult = {
141
+ event: ChosenEvent;
142
+ usage: LanguageModelUsage;
143
+ finishReason: FinishReason;
144
+ };
145
+ /** `createAiSdkExecutors` always populates all three slots (unlike the
146
+ * general `AgentRequestExecutors`, where `streamText`/`decide` are optional),
147
+ * and its `generateText`/`streamText` results are concretely typed. */
148
+ interface AiSdkExecutors extends AgentRequestExecutors<AiSdkGenerateResult, AiSdkStreamResult> {
149
+ streamText: AgentRequestExecutor<AiSdkStreamResult>;
150
+ decide: AgentDecisionExecutor;
151
+ }
152
+ /**
153
+ * The canonical Vercel AI SDK adapter: builds the `{ generateText, streamText,
154
+ * decide }` executor set consumed by `runAgent`/`executeAgentRequest`. `ai`
155
+ * must not become a dependency of core `src/` files — this subpath is the one
156
+ * place it's imported, and callers must supply their own model resolver so no
157
+ * concrete provider package (e.g. `@ai-sdk/openai`) becomes a dependency here
158
+ * either.
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * const executors = createAiSdkExecutors({ models: { quick: openai('gpt-5.4-mini') } });
163
+ * const result = await runAgent(machine, { input, executors });
164
+ * ```
165
+ */
166
+ declare function createAiSdkExecutors<TModels extends AiSdkModelMap>(options: CreateAiSdkExecutorsOptions<TModels>): AiSdkExecutors;
167
+ /** AI SDK host for a machine authored with `setupAgent({ models })`. */
168
+ declare function runAgent<TMachine extends _$xstate.AnyStateMachine>(machine: TMachine, options: Omit<RunAgentOptions<TMachine>, "executors">): Promise<RunAgentResult<TMachine>>;
169
+ type CreateAgentMachineConfig<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TInputSchema extends StandardSchemaV1, TEventSchemas extends AgentEventSchemaInputMap, TOutputSchema extends StandardSchemaV1, TModels extends AiSdkModelMap> = Omit<AgentMachineConfig<TContextSchema, TInputSchema, TEventSchemas, TOutputSchema, TModels>, "schemas">;
170
+ type CreateAgentBaseConfig<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TInputSchema extends StandardSchemaV1, TEventSchemas extends AgentEventSchemaInputMap, TOutputSchema extends StandardSchemaV1, TModels extends AiSdkModelMap> = CreateAgentMachineConfig<TContextSchema, TInputSchema, TEventSchemas, TOutputSchema, TModels> & {
171
+ schemas: {
172
+ context: TContextSchema;
173
+ input: TInputSchema;
174
+ events?: TEventSchemas;
175
+ output?: TOutputSchema;
176
+ };
177
+ };
178
+ interface CreatedAgent<TMachine extends _$xstate.AnyStateMachine> {
179
+ machine: TMachine;
180
+ run(input: _$xstate.InputFrom<TMachine>, options?: Omit<RunAgentOptions<TMachine>, "input" | "executors">): Promise<RunAgentResult<TMachine>>;
181
+ }
182
+ /**
183
+ * One-call AI SDK entry point for the common case: creates a typed machine and
184
+ * a `run(input)` method with model executors already wired.
185
+ */
186
+ declare function createAgent<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TInputSchema extends StandardSchemaV1, TEventSchemas extends AgentEventSchemaInputMap = {}, TOutputSchema extends StandardSchemaV1 = StandardSchemaV1>(config: CreateAgentBaseConfig<TContextSchema, TInputSchema, TEventSchemas, TOutputSchema, AiSdkModelMap<"default">> & {
187
+ model: LanguageModel;
188
+ models?: never;
189
+ }): CreatedAgent<AgentMachine<TContextSchema, TInputSchema, TEventSchemas, TOutputSchema, AiSdkModelMap<"default">>>;
190
+ declare function createAgent<TModels extends AiSdkModelMap, TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TInputSchema extends StandardSchemaV1, TEventSchemas extends AgentEventSchemaInputMap = {}, TOutputSchema extends StandardSchemaV1 = StandardSchemaV1>(config: CreateAgentBaseConfig<TContextSchema, TInputSchema, TEventSchemas, TOutputSchema, TModels> & {
191
+ models: TModels;
192
+ model?: never;
193
+ }): CreatedAgent<AgentMachine<TContextSchema, TInputSchema, TEventSchemas, TOutputSchema, TModels>>;
194
+ /** One AI SDK `tool()` per candidate event — the "tool-per-event +
195
+ * toolChoice: 'required'" recipe from .scratch/p0-design.md §2.6. */
196
+ declare function toAiSdkEventTools(events: AgentEventDescriptor[]): {
197
+ [k: string]: Tool<unknown, never>;
198
+ };
199
+ /**
200
+ * Messages for a decision request, with prior failed `attempts` (§2.6)
201
+ * rendered as appended user messages (via core's {@link renderDecisionAttempts})
202
+ * so retries converge. Core never rewrites prompts — this is adapter business.
203
+ */
204
+ declare function toDecisionMessages(request: Pick<AgentDecisionRequest, "messages" | "prompt" | "events" | "attempts">): ModelMessage[] | undefined;
205
+ //#endregion
206
+ export { AiSdkDecideResult, AiSdkExecutors, AiSdkGenerateResult, AiSdkModelMap, AiSdkStreamResult, CreateAiSdkExecutorsOptions, CreatedAgent, createAgent, createAiSdkExecutors, defineModels, extractFirstJsonValue, isStructuredOutputRequest, runAgent, toAiSdkCallSettings, toAiSdkEventTools, toAiSdkToolChoice, toAiSdkTools, toDecisionMessages };
@@ -0,0 +1,331 @@
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";
3
+ import { NoObjectGeneratedError, Output, generateText, stepCountIs, streamText, tool } from "ai";
4
+ //#region src/ai-sdk/index.ts
5
+ /**
6
+ * Maps an {@link AgentTools} map onto AI SDK `tool()` definitions. A tool that
7
+ * already carries its own Standard Schema `inputSchema` — an AI SDK
8
+ * `tool({...})`, or any equivalent descriptor — is passed through **unchanged**,
9
+ * so the SDK applies its own validation, calls `execute(input, options)`, and
10
+ * every extra property (`providerOptions`, `toModelOutput`, …) survives. A bare
11
+ * `AgentToolExecute` function becomes a tool with an unconstrained input schema;
12
+ * 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`.
15
+ */
16
+ function toAiSdkTools(tools) {
17
+ const entries = [];
18
+ for (const [name, descriptor] of Object.entries(tools)) {
19
+ if (!descriptor) continue;
20
+ if (typeof descriptor === "function") {
21
+ entries.push([name, tool({
22
+ inputSchema: unknownSchema,
23
+ execute: (input) => descriptor(input)
24
+ })]);
25
+ continue;
26
+ }
27
+ if (isStandardSchema(descriptor.inputSchema)) {
28
+ entries.push([name, descriptor]);
29
+ continue;
30
+ }
31
+ const inputSchema = descriptor.inputSchema ?? descriptor.schemas?.input;
32
+ const toolOptions = {
33
+ description: descriptor.description,
34
+ inputSchema: inputSchema ? inputSchema : unknownSchema
35
+ };
36
+ if (descriptor.execute) {
37
+ entries.push([name, tool({
38
+ ...toolOptions,
39
+ execute: (input) => descriptor.execute?.(input)
40
+ })]);
41
+ continue;
42
+ }
43
+ entries.push([name, tool(toolOptions)]);
44
+ }
45
+ return Object.fromEntries(entries);
46
+ }
47
+ function maxStepsSetting(request) {
48
+ return typeof request.metadata?.maxSteps === "number" ? { stopWhen: stepCountIs(request.metadata.maxSteps) } : {};
49
+ }
50
+ const unknownSchema = { "~standard": {
51
+ version: 1,
52
+ vendor: "statelyai-agent",
53
+ validate: (value) => ({ value }),
54
+ jsonSchema: { input: () => ({}) }
55
+ } };
56
+ /**
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
+ * AI SDK request-mapping settings shared by `generateText`/`streamText`.
87
+ * `AgentTextRequest.messages` (`AgentMessage[]`) and AI SDK's `ModelMessage[]`
88
+ * are structurally compatible by design (§1 of .scratch/p0-design.md) — the cast
89
+ * below is a typed identity mapping, not a semantic conversion.
90
+ */
91
+ function toAiSdkCallSettings(request) {
92
+ const messages = request.messages;
93
+ return {
94
+ system: request.system,
95
+ ...messages ? { messages } : { prompt: request.prompt ?? "" },
96
+ temperature: request.temperature,
97
+ maxOutputTokens: request.maxOutputTokens,
98
+ topP: request.topP,
99
+ topK: request.topK,
100
+ seed: request.seed,
101
+ stopSequences: request.stopSequences,
102
+ tools: request.tools ? toAiSdkTools(request.tools) : void 0,
103
+ toolChoice: toAiSdkToolChoice(request.toolChoice)
104
+ };
105
+ }
106
+ /** Maps an {@link AgentToolChoice} to AI SDK's tool-choice shape — `{ type: 'tool'; name }` becomes `{ type: 'tool'; toolName }`; `'auto'`/`'none'`/`'required'`/`undefined` pass through unchanged. */
107
+ function toAiSdkToolChoice(toolChoice) {
108
+ return typeof toolChoice === "object" ? {
109
+ type: "tool",
110
+ toolName: toolChoice.name
111
+ } : toolChoice;
112
+ }
113
+ /** `true` when the request should use AI SDK structured `Output.object`. */
114
+ function isStructuredOutputRequest(request) {
115
+ return getAgentOutputMode(request.outputSchema) === "structured";
116
+ }
117
+ /**
118
+ * Extracts the first complete top-level JSON value from `text`, or returns
119
+ * `undefined` when there is nothing to repair (no complete value, or the value
120
+ * already spans the whole text). Models occasionally emit two structured-output
121
+ * envelopes back to back (`{"result":{…}}{"result":{…}}`), which fails JSON
122
+ * parsing wholesale; the balanced scan below recovers the first value and
123
+ * drops the rest.
124
+ */
125
+ function extractFirstJsonValue(text) {
126
+ const start = text.search(/[{[]/);
127
+ if (start === -1) return;
128
+ let depth = 0;
129
+ let inString = false;
130
+ let escaped = false;
131
+ for (let i = start; i < text.length; i++) {
132
+ const char = text[i];
133
+ if (inString) {
134
+ if (escaped) escaped = false;
135
+ else if (char === "\\") escaped = true;
136
+ else if (char === "\"") inString = false;
137
+ continue;
138
+ }
139
+ if (char === "\"") inString = true;
140
+ else if (char === "{" || char === "[") depth++;
141
+ else if (char === "}" || char === "]") {
142
+ depth--;
143
+ if (depth === 0) {
144
+ const value = text.slice(start, i + 1);
145
+ return value === text.trim() ? void 0 : value;
146
+ }
147
+ }
148
+ }
149
+ }
150
+ function withJsonRepair(output) {
151
+ return {
152
+ ...output,
153
+ parseCompleteOutput: async (options, context) => {
154
+ try {
155
+ return await output.parseCompleteOutput(options, context);
156
+ } catch (error) {
157
+ const repaired = extractFirstJsonValue(options.text);
158
+ if (repaired === void 0) throw error;
159
+ return await output.parseCompleteOutput({
160
+ ...options,
161
+ text: repaired
162
+ }, context);
163
+ }
164
+ }
165
+ };
166
+ }
167
+ /**
168
+ * The canonical Vercel AI SDK adapter: builds the `{ generateText, streamText,
169
+ * decide }` executor set consumed by `runAgent`/`executeAgentRequest`. `ai`
170
+ * must not become a dependency of core `src/` files — this subpath is the one
171
+ * place it's imported, and callers must supply their own model resolver so no
172
+ * concrete provider package (e.g. `@ai-sdk/openai`) becomes a dependency here
173
+ * either.
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * const executors = createAiSdkExecutors({ models: { quick: openai('gpt-5.4-mini') } });
178
+ * const result = await runAgent(machine, { input, executors });
179
+ * ```
180
+ */
181
+ function createAiSdkExecutors(options) {
182
+ const generateText$1 = async (request, info) => {
183
+ const common = {
184
+ model: resolveAiSdkModel(options, request.model),
185
+ abortSignal: info?.signal,
186
+ ...toAiSdkCallSettings(request),
187
+ ...maxStepsSetting(request)
188
+ };
189
+ if (isStructuredOutputRequest(request)) {
190
+ const envelope = buildEnvelopeSchema(request.outputSchema, { reasoning: request.reasoning });
191
+ const structuredOutput = withJsonRepair(Output.object({ schema: envelope }));
192
+ const canRetry = !request.tools || Object.keys(request.tools).length === 0;
193
+ let result;
194
+ try {
195
+ result = await generateText({
196
+ ...common,
197
+ output: structuredOutput
198
+ });
199
+ } catch (error) {
200
+ if (!canRetry || !NoObjectGeneratedError.isInstance(error) || info?.signal?.aborted) throw error;
201
+ result = await generateText({
202
+ ...common,
203
+ output: structuredOutput
204
+ });
205
+ }
206
+ const { result: output, reasoning } = result.output;
207
+ return {
208
+ output,
209
+ ...reasoning !== void 0 ? { reasoning } : {},
210
+ usage: result.usage,
211
+ finishReason: result.finishReason,
212
+ toolCalls: result.toolCalls,
213
+ toolResults: result.toolResults
214
+ };
215
+ }
216
+ const result = await generateText(common);
217
+ return {
218
+ output: result.text,
219
+ usage: result.usage,
220
+ finishReason: result.finishReason,
221
+ toolCalls: result.toolCalls,
222
+ toolResults: result.toolResults
223
+ };
224
+ };
225
+ const streamText$1 = async (request, info) => {
226
+ const result = streamText({
227
+ model: resolveAiSdkModel(options, request.model),
228
+ abortSignal: info?.signal,
229
+ ...toAiSdkCallSettings(request),
230
+ ...maxStepsSetting(request)
231
+ });
232
+ for await (const chunk of result.textStream) info?.onChunk?.(chunk);
233
+ return {
234
+ output: await result.text,
235
+ usage: await result.usage,
236
+ finishReason: await result.finishReason
237
+ };
238
+ };
239
+ const decide = async (request) => {
240
+ const model = resolveAiSdkModel(options, request.model);
241
+ const tools = toAiSdkEventTools(request.events);
242
+ const messages = toDecisionMessages(request);
243
+ const result = await generateText({
244
+ model,
245
+ abortSignal: request.signal,
246
+ system: request.system,
247
+ ...messages ? { messages } : { prompt: request.prompt ?? "" },
248
+ tools,
249
+ toolChoice: "required",
250
+ stopWhen: stepCountIs(1),
251
+ temperature: request.temperature,
252
+ maxOutputTokens: request.maxOutputTokens,
253
+ topP: request.topP,
254
+ topK: request.topK,
255
+ seed: request.seed,
256
+ stopSequences: request.stopSequences
257
+ });
258
+ const toolCall = result.toolCalls[0];
259
+ if (!toolCall) throw new Error("createAiSdkExecutors: decide — model did not call an event tool.");
260
+ const chosenEvent = request.events.find((event) => event.toolName === toolCall.toolName);
261
+ if (!chosenEvent) throw new Error(`createAiSdkExecutors: decide — model called unknown tool '${toolCall.toolName}'.`);
262
+ return {
263
+ event: {
264
+ ...toolCall.input && typeof toolCall.input === "object" ? toolCall.input : {},
265
+ type: chosenEvent.type
266
+ },
267
+ usage: result.usage,
268
+ finishReason: result.finishReason
269
+ };
270
+ };
271
+ return {
272
+ generateText: generateText$1,
273
+ streamText: streamText$1,
274
+ decide
275
+ };
276
+ }
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
+ //#endregion
331
+ export { createAgent, createAiSdkExecutors, defineModels, extractFirstJsonValue, isStructuredOutputRequest, runAgent, toAiSdkCallSettings, toAiSdkEventTools, toAiSdkToolChoice, toAiSdkTools, toDecisionMessages };
package/dist/cli.cjs ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ const require_run_agent = require("./run-agent-BFMkuI1F.cjs");
3
+ const require_src = require("./src-D-77Ha5p.cjs");
4
+ let node_fs = require("node:fs");
5
+ //#region src/cli.ts
6
+ /**
7
+ * `statelyai-agent lint <workflow.json>` — keyless static verification for an
8
+ * agent machine authored as data (an {@link AgentWorkflowConfig} JSON file).
9
+ *
10
+ * The library bundles no JSON Schema engine, so the CLI lints STRUCTURE ONLY:
11
+ * it compiles the config with a permissive pass-through schema compiler (each
12
+ * JSON Schema is kept as-is for structural checks, validation is a no-op) and
13
+ * runs {@link lintAgentMachine}. Exits `1` on any error-severity finding.
14
+ *
15
+ * For full schema-aware linting, import the API and compile with a real engine:
16
+ * `lintAgentMachine(setupAgent.fromConfig(config, { compileSchema }))`.
17
+ *
18
+ * @module
19
+ */
20
+ function stubCompileSchema(jsonSchema) {
21
+ return { "~standard": {
22
+ version: 1,
23
+ vendor: "statelyai-agent-cli",
24
+ validate: (value) => ({ value }),
25
+ jsonSchema: { input: () => jsonSchema }
26
+ } };
27
+ }
28
+ function printUsage() {
29
+ process.stderr.write("Usage: statelyai-agent lint <workflow.json> [--no-schemas]\n\n Statically verifies an agent-machine JSON config (structure-only).\n Exits 1 on any error-severity finding.\n");
30
+ }
31
+ function main(argv) {
32
+ const args = argv.slice(2);
33
+ const command = args[0];
34
+ const file = args.find((arg, index) => index > 0 && !arg.startsWith("-"));
35
+ if (command !== "lint" || !file) {
36
+ printUsage();
37
+ return 2;
38
+ }
39
+ let config;
40
+ try {
41
+ config = JSON.parse((0, node_fs.readFileSync)(file, "utf8"));
42
+ } catch (error) {
43
+ process.stderr.write(`statelyai-agent: could not read/parse '${file}': ${error instanceof Error ? error.message : String(error)}\n`);
44
+ return 2;
45
+ }
46
+ let machine;
47
+ try {
48
+ machine = require_run_agent.setupAgent.fromConfig(config, { compileSchema: stubCompileSchema });
49
+ } catch (error) {
50
+ process.stderr.write(`statelyai-agent: '${file}' is not a valid agent-machine config: ${error instanceof Error ? error.message : String(error)}\n`);
51
+ return 2;
52
+ }
53
+ const diagnostics = require_src.lintAgentMachine(machine);
54
+ const errors = diagnostics.filter((d) => d.severity === "error");
55
+ const warnings = diagnostics.filter((d) => d.severity === "warning");
56
+ for (const d of diagnostics) {
57
+ const label = d.severity === "error" ? "error" : "warn ";
58
+ process.stdout.write(` ${label} ${d.code} ${d.path}\n ${d.message}\n`);
59
+ }
60
+ process.stdout.write(`\n${file}: ${errors.length} error(s), ${warnings.length} warning(s) (structure-only; schemas not compiled).\n`);
61
+ return errors.length > 0 ? 1 : 0;
62
+ }
63
+ process.exit(main(process.argv));
64
+ //#endregion
package/dist/cli.d.cts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/cli.d.mts ADDED
@@ -0,0 +1 @@
1
+ export { };
package/dist/cli.mjs ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ import { c as setupAgent } from "./run-agent-BoAOq_0Z.mjs";
3
+ import { a as lintAgentMachine } from "./src-DUeIFjv-.mjs";
4
+ import { readFileSync } from "node:fs";
5
+ //#region src/cli.ts
6
+ /**
7
+ * `statelyai-agent lint <workflow.json>` — keyless static verification for an
8
+ * agent machine authored as data (an {@link AgentWorkflowConfig} JSON file).
9
+ *
10
+ * The library bundles no JSON Schema engine, so the CLI lints STRUCTURE ONLY:
11
+ * it compiles the config with a permissive pass-through schema compiler (each
12
+ * JSON Schema is kept as-is for structural checks, validation is a no-op) and
13
+ * runs {@link lintAgentMachine}. Exits `1` on any error-severity finding.
14
+ *
15
+ * For full schema-aware linting, import the API and compile with a real engine:
16
+ * `lintAgentMachine(setupAgent.fromConfig(config, { compileSchema }))`.
17
+ *
18
+ * @module
19
+ */
20
+ function stubCompileSchema(jsonSchema) {
21
+ return { "~standard": {
22
+ version: 1,
23
+ vendor: "statelyai-agent-cli",
24
+ validate: (value) => ({ value }),
25
+ jsonSchema: { input: () => jsonSchema }
26
+ } };
27
+ }
28
+ function printUsage() {
29
+ process.stderr.write("Usage: statelyai-agent lint <workflow.json> [--no-schemas]\n\n Statically verifies an agent-machine JSON config (structure-only).\n Exits 1 on any error-severity finding.\n");
30
+ }
31
+ function main(argv) {
32
+ const args = argv.slice(2);
33
+ const command = args[0];
34
+ const file = args.find((arg, index) => index > 0 && !arg.startsWith("-"));
35
+ if (command !== "lint" || !file) {
36
+ printUsage();
37
+ return 2;
38
+ }
39
+ let config;
40
+ try {
41
+ config = JSON.parse(readFileSync(file, "utf8"));
42
+ } catch (error) {
43
+ process.stderr.write(`statelyai-agent: could not read/parse '${file}': ${error instanceof Error ? error.message : String(error)}\n`);
44
+ return 2;
45
+ }
46
+ let machine;
47
+ try {
48
+ machine = setupAgent.fromConfig(config, { compileSchema: stubCompileSchema });
49
+ } catch (error) {
50
+ process.stderr.write(`statelyai-agent: '${file}' is not a valid agent-machine config: ${error instanceof Error ? error.message : String(error)}\n`);
51
+ return 2;
52
+ }
53
+ const diagnostics = lintAgentMachine(machine);
54
+ const errors = diagnostics.filter((d) => d.severity === "error");
55
+ const warnings = diagnostics.filter((d) => d.severity === "warning");
56
+ for (const d of diagnostics) {
57
+ const label = d.severity === "error" ? "error" : "warn ";
58
+ process.stdout.write(` ${label} ${d.code} ${d.path}\n ${d.message}\n`);
59
+ }
60
+ process.stdout.write(`\n${file}: ${errors.length} error(s), ${warnings.length} warning(s) (structure-only; schemas not compiled).\n`);
61
+ return errors.length > 0 ? 1 : 0;
62
+ }
63
+ process.exit(main(process.argv));
64
+ //#endregion
65
+ export {};