@statelyai/agent 2.0.0-alpha.6 → 2.0.0-alpha.8

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.
package/dist/ai-sdk.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_decision = require("./decision-CX3YdwrO.cjs");
2
+ const require_run_agent = require("./run-agent-BQ3vV7UI.cjs");
3
+ const require_decision = require("./decision-b-lkcs4L.cjs");
3
4
  let ai = require("ai");
4
5
  //#region src/ai-sdk/index.ts
5
6
  /**
@@ -85,7 +86,7 @@ function resolveAiSdkModel(options, modelRef) {
85
86
  /**
86
87
  * AI SDK request-mapping settings shared by `generateText`/`streamText`.
87
88
  * `AgentTextRequest.messages` (`AgentMessage[]`) and AI SDK's `ModelMessage[]`
88
- * are structurally compatible by design (§1 of docs/p0-design.md) — the cast
89
+ * are structurally compatible by design (§1 of .scratch/p0-design.md) — the cast
89
90
  * below is a typed identity mapping, not a semantic conversion.
90
91
  */
91
92
  function toAiSdkCallSettings(request) {
@@ -115,6 +116,56 @@ function isStructuredOutputRequest(request) {
115
116
  return require_decision.getAgentOutputMode(request.outputSchema) === "structured";
116
117
  }
117
118
  /**
119
+ * Extracts the first complete top-level JSON value from `text`, or returns
120
+ * `undefined` when there is nothing to repair (no complete value, or the value
121
+ * already spans the whole text). Models occasionally emit two structured-output
122
+ * envelopes back to back (`{"result":{…}}{"result":{…}}`), which fails JSON
123
+ * parsing wholesale; the balanced scan below recovers the first value and
124
+ * drops the rest.
125
+ */
126
+ function extractFirstJsonValue(text) {
127
+ const start = text.search(/[{[]/);
128
+ if (start === -1) return;
129
+ let depth = 0;
130
+ let inString = false;
131
+ let escaped = false;
132
+ for (let i = start; i < text.length; i++) {
133
+ const char = text[i];
134
+ if (inString) {
135
+ if (escaped) escaped = false;
136
+ else if (char === "\\") escaped = true;
137
+ else if (char === "\"") inString = false;
138
+ continue;
139
+ }
140
+ if (char === "\"") inString = true;
141
+ else if (char === "{" || char === "[") depth++;
142
+ else if (char === "}" || char === "]") {
143
+ depth--;
144
+ if (depth === 0) {
145
+ const value = text.slice(start, i + 1);
146
+ return value === text.trim() ? void 0 : value;
147
+ }
148
+ }
149
+ }
150
+ }
151
+ function withJsonRepair(output) {
152
+ return {
153
+ ...output,
154
+ parseCompleteOutput: async (options, context) => {
155
+ try {
156
+ return await output.parseCompleteOutput(options, context);
157
+ } catch (error) {
158
+ const repaired = extractFirstJsonValue(options.text);
159
+ if (repaired === void 0) throw error;
160
+ return await output.parseCompleteOutput({
161
+ ...options,
162
+ text: repaired
163
+ }, context);
164
+ }
165
+ }
166
+ };
167
+ }
168
+ /**
118
169
  * The canonical Vercel AI SDK adapter: builds the `{ generateText, streamText,
119
170
  * decide }` executor set consumed by `runAgent`/`executeAgentRequest`. `ai`
120
171
  * must not become a dependency of core `src/` files — this subpath is the one
@@ -138,10 +189,21 @@ function createAiSdkExecutors(options) {
138
189
  };
139
190
  if (isStructuredOutputRequest(request)) {
140
191
  const envelope = require_decision.buildEnvelopeSchema(request.outputSchema, { reasoning: request.reasoning });
141
- const result = await (0, ai.generateText)({
142
- ...common,
143
- output: ai.Output.object({ schema: envelope })
144
- });
192
+ const structuredOutput = withJsonRepair(ai.Output.object({ schema: envelope }));
193
+ const canRetry = !request.tools || Object.keys(request.tools).length === 0;
194
+ let result;
195
+ try {
196
+ result = await (0, ai.generateText)({
197
+ ...common,
198
+ output: structuredOutput
199
+ });
200
+ } catch (error) {
201
+ if (!canRetry || !ai.NoObjectGeneratedError.isInstance(error) || info?.signal?.aborted) throw error;
202
+ result = await (0, ai.generateText)({
203
+ ...common,
204
+ output: structuredOutput
205
+ });
206
+ }
145
207
  const { result: output, reasoning } = result.output;
146
208
  return {
147
209
  output,
@@ -213,8 +275,36 @@ function createAiSdkExecutors(options) {
213
275
  decide
214
276
  };
215
277
  }
278
+ /** AI SDK host for a machine authored with `setupAgent({ models })`. */
279
+ function runAgent(machine, options) {
280
+ const models = require_decision.getRegisteredAgentModels(machine);
281
+ 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.");
282
+ return require_run_agent.runAgent(machine, {
283
+ ...options,
284
+ executors: createAiSdkExecutors({ models })
285
+ });
286
+ }
287
+ function createAgent(config) {
288
+ const { model, models: configuredModels, schemas, ...machineConfig } = config;
289
+ const models = configuredModels ?? { default: model };
290
+ const executors = createAiSdkExecutors({ models });
291
+ const machine = require_run_agent.setupAgent({
292
+ ...schemas,
293
+ models
294
+ }).createMachine(machineConfig);
295
+ return {
296
+ machine,
297
+ run(runInput, options = {}) {
298
+ return require_run_agent.runAgent(machine, {
299
+ ...options,
300
+ input: runInput,
301
+ executors
302
+ });
303
+ }
304
+ };
305
+ }
216
306
  /** One AI SDK `tool()` per candidate event — the "tool-per-event +
217
- * toolChoice: 'required'" recipe from docs/p0-design.md §2.6. */
307
+ * toolChoice: 'required'" recipe from .scratch/p0-design.md §2.6. */
218
308
  function toAiSdkEventTools(events) {
219
309
  return Object.fromEntries(events.map((event) => [event.toolName, (0, ai.tool)({
220
310
  description: `Choose the '${event.type}' move.`,
@@ -239,9 +329,12 @@ function toDecisionMessages(request) {
239
329
  return messages;
240
330
  }
241
331
  //#endregion
332
+ exports.createAgent = createAgent;
242
333
  exports.createAiSdkExecutors = createAiSdkExecutors;
243
334
  exports.defineModels = defineModels;
335
+ exports.extractFirstJsonValue = extractFirstJsonValue;
244
336
  exports.isStructuredOutputRequest = isStructuredOutputRequest;
337
+ exports.runAgent = runAgent;
245
338
  exports.toAiSdkCallSettings = toAiSdkCallSettings;
246
339
  exports.toAiSdkEventTools = toAiSdkEventTools;
247
340
  exports.toAiSdkToolChoice = toAiSdkToolChoice;
package/dist/ai-sdk.d.cts CHANGED
@@ -1,5 +1,7 @@
1
- import { c as AgentTools, f as ChosenEvent } from "./types-BHjeDdch.cjs";
2
- import { B as AgentEventDescriptor, D as AgentDecisionExecutor, i as AgentRequestExecutor, k as AgentDecisionRequest, l as AgentTextRequest, s as AgentRequestExecutors } from "./text-logic-1ZQkO3zr.cjs";
1
+ import { C as StandardSchemaV1, m as ChosenEvent, n as AgentEventSchemaInputMap, u as AgentTools } from "./types-C9QiMjre.cjs";
2
+ import { H as AgentEventDescriptor, i as AgentRequestExecutor, j as AgentDecisionRequest, k as AgentDecisionExecutor, l as AgentTextRequest, s as AgentRequestExecutors } from "./text-logic-CZjyACzQ.cjs";
3
+ import { E as AgentMachineConfig, T as AgentMachine, c as RunAgentResult, s as RunAgentOptions } from "./run-agent-BzW4emV_.cjs";
4
+ import * as _$xstate from "xstate";
3
5
  import { FinishReason, LanguageModel, LanguageModelUsage, ModelMessage, Tool, ToolSet, TypedToolCall, TypedToolResult } from "ai";
4
6
 
5
7
  //#region src/ai-sdk/index.d.ts
@@ -54,7 +56,7 @@ type CreateAiSdkExecutorsOptions<TModels extends AiSdkModelMap = AiSdkModelMap>
54
56
  /**
55
57
  * AI SDK request-mapping settings shared by `generateText`/`streamText`.
56
58
  * `AgentTextRequest.messages` (`AgentMessage[]`) and AI SDK's `ModelMessage[]`
57
- * are structurally compatible by design (§1 of docs/p0-design.md) — the cast
59
+ * are structurally compatible by design (§1 of .scratch/p0-design.md) — the cast
58
60
  * below is a typed identity mapping, not a semantic conversion.
59
61
  */
60
62
  declare function toAiSdkCallSettings(request: AgentTextRequest & {
@@ -99,6 +101,15 @@ declare function toAiSdkToolChoice(toolChoice: AgentTextRequest["toolChoice"]):
99
101
  } | undefined;
100
102
  /** `true` when the request should use AI SDK structured `Output.object`. */
101
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;
102
113
  /**
103
114
  * Raw result shape from {@link AiSdkExecutors.generateText} — the `{ output }`
104
115
  * envelope (the validated structured object for structured-output requests,
@@ -153,8 +164,35 @@ interface AiSdkExecutors extends AgentRequestExecutors<AiSdkGenerateResult, AiSd
153
164
  * ```
154
165
  */
155
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>>;
156
194
  /** One AI SDK `tool()` per candidate event — the "tool-per-event +
157
- * toolChoice: 'required'" recipe from docs/p0-design.md §2.6. */
195
+ * toolChoice: 'required'" recipe from .scratch/p0-design.md §2.6. */
158
196
  declare function toAiSdkEventTools(events: AgentEventDescriptor[]): {
159
197
  [k: string]: Tool<unknown, never>;
160
198
  };
@@ -165,4 +203,4 @@ declare function toAiSdkEventTools(events: AgentEventDescriptor[]): {
165
203
  */
166
204
  declare function toDecisionMessages(request: Pick<AgentDecisionRequest, "messages" | "prompt" | "events" | "attempts">): ModelMessage[] | undefined;
167
205
  //#endregion
168
- export { AiSdkDecideResult, AiSdkExecutors, AiSdkGenerateResult, AiSdkModelMap, AiSdkStreamResult, CreateAiSdkExecutorsOptions, createAiSdkExecutors, defineModels, isStructuredOutputRequest, toAiSdkCallSettings, toAiSdkEventTools, toAiSdkToolChoice, toAiSdkTools, toDecisionMessages };
206
+ export { AiSdkDecideResult, AiSdkExecutors, AiSdkGenerateResult, AiSdkModelMap, AiSdkStreamResult, CreateAiSdkExecutorsOptions, CreatedAgent, createAgent, createAiSdkExecutors, defineModels, extractFirstJsonValue, isStructuredOutputRequest, runAgent, toAiSdkCallSettings, toAiSdkEventTools, toAiSdkToolChoice, toAiSdkTools, toDecisionMessages };
package/dist/ai-sdk.d.mts CHANGED
@@ -1,5 +1,7 @@
1
- import { c as AgentTools, f as ChosenEvent } from "./types-Cq1YlAQ6.mjs";
2
- import { B as AgentEventDescriptor, D as AgentDecisionExecutor, i as AgentRequestExecutor, k as AgentDecisionRequest, l as AgentTextRequest, s as AgentRequestExecutors } from "./text-logic-2EMJIS-n.mjs";
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 { E as AgentMachineConfig, T as AgentMachine, c as RunAgentResult, s as RunAgentOptions } from "./run-agent-XYjmBxHi.mjs";
4
+ import * as _$xstate from "xstate";
3
5
  import { FinishReason, LanguageModel, LanguageModelUsage, ModelMessage, Tool, ToolSet, TypedToolCall, TypedToolResult } from "ai";
4
6
 
5
7
  //#region src/ai-sdk/index.d.ts
@@ -54,7 +56,7 @@ type CreateAiSdkExecutorsOptions<TModels extends AiSdkModelMap = AiSdkModelMap>
54
56
  /**
55
57
  * AI SDK request-mapping settings shared by `generateText`/`streamText`.
56
58
  * `AgentTextRequest.messages` (`AgentMessage[]`) and AI SDK's `ModelMessage[]`
57
- * are structurally compatible by design (§1 of docs/p0-design.md) — the cast
59
+ * are structurally compatible by design (§1 of .scratch/p0-design.md) — the cast
58
60
  * below is a typed identity mapping, not a semantic conversion.
59
61
  */
60
62
  declare function toAiSdkCallSettings(request: AgentTextRequest & {
@@ -99,6 +101,15 @@ declare function toAiSdkToolChoice(toolChoice: AgentTextRequest["toolChoice"]):
99
101
  } | undefined;
100
102
  /** `true` when the request should use AI SDK structured `Output.object`. */
101
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;
102
113
  /**
103
114
  * Raw result shape from {@link AiSdkExecutors.generateText} — the `{ output }`
104
115
  * envelope (the validated structured object for structured-output requests,
@@ -153,8 +164,35 @@ interface AiSdkExecutors extends AgentRequestExecutors<AiSdkGenerateResult, AiSd
153
164
  * ```
154
165
  */
155
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>>;
156
194
  /** One AI SDK `tool()` per candidate event — the "tool-per-event +
157
- * toolChoice: 'required'" recipe from docs/p0-design.md §2.6. */
195
+ * toolChoice: 'required'" recipe from .scratch/p0-design.md §2.6. */
158
196
  declare function toAiSdkEventTools(events: AgentEventDescriptor[]): {
159
197
  [k: string]: Tool<unknown, never>;
160
198
  };
@@ -165,4 +203,4 @@ declare function toAiSdkEventTools(events: AgentEventDescriptor[]): {
165
203
  */
166
204
  declare function toDecisionMessages(request: Pick<AgentDecisionRequest, "messages" | "prompt" | "events" | "attempts">): ModelMessage[] | undefined;
167
205
  //#endregion
168
- export { AiSdkDecideResult, AiSdkExecutors, AiSdkGenerateResult, AiSdkModelMap, AiSdkStreamResult, CreateAiSdkExecutorsOptions, createAiSdkExecutors, defineModels, isStructuredOutputRequest, toAiSdkCallSettings, toAiSdkEventTools, toAiSdkToolChoice, toAiSdkTools, toDecisionMessages };
206
+ export { AiSdkDecideResult, AiSdkExecutors, AiSdkGenerateResult, AiSdkModelMap, AiSdkStreamResult, CreateAiSdkExecutorsOptions, CreatedAgent, createAgent, createAiSdkExecutors, defineModels, extractFirstJsonValue, isStructuredOutputRequest, runAgent, toAiSdkCallSettings, toAiSdkEventTools, toAiSdkToolChoice, toAiSdkTools, toDecisionMessages };
package/dist/ai-sdk.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { G as isStandardSchema, T as getAgentOutputMode, l as renderDecisionAttempts, x as buildEnvelopeSchema } from "./decision-D1654JdD.mjs";
2
- import { Output, generateText, stepCountIs, streamText, tool } from "ai";
1
+ import { a as runAgent$1, c as setupAgent } from "./run-agent-7OaHM7SB.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";
3
4
  //#region src/ai-sdk/index.ts
4
5
  /**
5
6
  * Maps an {@link AgentTools} map onto AI SDK `tool()` definitions. A tool that
@@ -84,7 +85,7 @@ function resolveAiSdkModel(options, modelRef) {
84
85
  /**
85
86
  * AI SDK request-mapping settings shared by `generateText`/`streamText`.
86
87
  * `AgentTextRequest.messages` (`AgentMessage[]`) and AI SDK's `ModelMessage[]`
87
- * are structurally compatible by design (§1 of docs/p0-design.md) — the cast
88
+ * are structurally compatible by design (§1 of .scratch/p0-design.md) — the cast
88
89
  * below is a typed identity mapping, not a semantic conversion.
89
90
  */
90
91
  function toAiSdkCallSettings(request) {
@@ -114,6 +115,56 @@ function isStructuredOutputRequest(request) {
114
115
  return getAgentOutputMode(request.outputSchema) === "structured";
115
116
  }
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
+ /**
117
168
  * The canonical Vercel AI SDK adapter: builds the `{ generateText, streamText,
118
169
  * decide }` executor set consumed by `runAgent`/`executeAgentRequest`. `ai`
119
170
  * must not become a dependency of core `src/` files — this subpath is the one
@@ -137,10 +188,21 @@ function createAiSdkExecutors(options) {
137
188
  };
138
189
  if (isStructuredOutputRequest(request)) {
139
190
  const envelope = buildEnvelopeSchema(request.outputSchema, { reasoning: request.reasoning });
140
- const result = await generateText({
141
- ...common,
142
- output: Output.object({ schema: envelope })
143
- });
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
+ }
144
206
  const { result: output, reasoning } = result.output;
145
207
  return {
146
208
  output,
@@ -212,8 +274,36 @@ function createAiSdkExecutors(options) {
212
274
  decide
213
275
  };
214
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
+ }
215
305
  /** One AI SDK `tool()` per candidate event — the "tool-per-event +
216
- * toolChoice: 'required'" recipe from docs/p0-design.md §2.6. */
306
+ * toolChoice: 'required'" recipe from .scratch/p0-design.md §2.6. */
217
307
  function toAiSdkEventTools(events) {
218
308
  return Object.fromEntries(events.map((event) => [event.toolName, tool({
219
309
  description: `Choose the '${event.type}' move.`,
@@ -238,4 +328,4 @@ function toDecisionMessages(request) {
238
328
  return messages;
239
329
  }
240
330
  //#endregion
241
- export { createAiSdkExecutors, defineModels, isStructuredOutputRequest, toAiSdkCallSettings, toAiSdkEventTools, toAiSdkToolChoice, toAiSdkTools, toDecisionMessages };
331
+ export { createAgent, createAiSdkExecutors, defineModels, extractFirstJsonValue, isStructuredOutputRequest, runAgent, toAiSdkCallSettings, toAiSdkEventTools, toAiSdkToolChoice, toAiSdkTools, toDecisionMessages };
package/dist/cli.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
- const require_src = require("./src-wBfi-kTA.cjs");
2
+ const require_run_agent = require("./run-agent-BQ3vV7UI.cjs");
3
+ const require_src = require("./src-CFtSqm-c.cjs");
3
4
  let node_fs = require("node:fs");
4
5
  //#region src/cli.ts
5
6
  /**
@@ -44,7 +45,7 @@ function main(argv) {
44
45
  }
45
46
  let machine;
46
47
  try {
47
- machine = require_src.setupAgent.fromConfig(config, { compileSchema: stubCompileSchema });
48
+ machine = require_run_agent.setupAgent.fromConfig(config, { compileSchema: stubCompileSchema });
48
49
  } catch (error) {
49
50
  process.stderr.write(`statelyai-agent: '${file}' is not a valid agent-machine config: ${error instanceof Error ? error.message : String(error)}\n`);
50
51
  return 2;
package/dist/cli.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { r as lintAgentMachine, v as setupAgent } from "./src-CEa947Dm.mjs";
2
+ import { c as setupAgent } from "./run-agent-7OaHM7SB.mjs";
3
+ import { r as lintAgentMachine } from "./src-d-jhiOgP.mjs";
3
4
  import { readFileSync } from "node:fs";
4
5
  //#region src/cli.ts
5
6
  /**
@@ -221,6 +221,9 @@ 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
+ }
224
227
  /**
225
228
  * Machine-carried wait-state predicates, keyed on the machine's root `config`
226
229
  * object. `config` is shared by reference across `machine.provide(...)` (unlike
@@ -266,6 +269,27 @@ const DECIDE_ACTOR = "agent.decide";
266
269
  const PLAN_ACTOR = "agent.plan";
267
270
  /** Synthetic `src` stamped on trace requests produced by `getRequests` state interpretation — NOT a registered actor source (nothing is invoked; the pass makes the call directly). */
268
271
  const INTERPRET_SOURCE = "agent.interpret";
272
+ /**
273
+ * Splits a portable `"provider/model-id"` model ref (the convention JSON
274
+ * workflows and registry-less hosts use, e.g. `"openai/gpt-5.4-mini"`) into
275
+ * its parts. A ref with no `/` has no provider — `modelId` is the whole ref.
276
+ * The standard building block for a host's `resolveModel`:
277
+ *
278
+ * @example
279
+ * ```ts
280
+ * const resolveModel = (ref: string) => openai(parseModelRef(ref).modelId);
281
+ * ```
282
+ */
283
+ function parseModelRef(modelRef) {
284
+ const slash = modelRef.indexOf("/");
285
+ return slash === -1 ? {
286
+ provider: void 0,
287
+ modelId: modelRef
288
+ } : {
289
+ provider: modelRef.slice(0, slash),
290
+ modelId: modelRef.slice(slash + 1)
291
+ };
292
+ }
269
293
  const agentTextInputSchema = { "~standard": {
270
294
  version: 1,
271
295
  vendor: "statelyai-agent",
@@ -336,7 +360,7 @@ const builtinTextActors = {
336
360
  [GENERATE_TEXT_ACTOR]: createBuiltinTextActor(GENERATE_TEXT_ACTOR, "generate", unknownOutputSchema),
337
361
  [STREAM_TEXT_ACTOR]: createBuiltinTextActor(STREAM_TEXT_ACTOR, "stream", stringOutputSchema)
338
362
  };
339
- /** The unbound `agent.userInput` builtin registered by setupAgent (an unbound-placeholder logic — see internal/registry.ts). @internal */
363
+ /** The unbound `agent.userInput` builtin registered by setupAgent (an unbound-placeholder logic — see internal/registry.ts). Output is `string` — what the human typed. @internal */
340
364
  const userInputActor = createAsyncLogic({ run: async () => {
341
365
  throw new Error(`'${USER_INPUT_ACTOR}' has no host execution. Provide an implementation with machine.provide({ actorSources: { '${USER_INPUT_ACTOR}': ... } }).`);
342
366
  } });
@@ -444,12 +468,15 @@ function createTextLogic(config, execute) {
444
468
  * });
445
469
  * ```
446
470
  */
447
- function bindRequestExecutor(logic, executor) {
471
+ function bindRequestExecutor(logic, executor, info) {
448
472
  return logic.withExecutor(async ({ request, signal }) => {
449
473
  const { output } = await executor({
450
474
  ...request,
451
475
  tools: request.tools ?? {}
452
- }, { signal });
476
+ }, {
477
+ signal,
478
+ onChunk: info?.onChunk
479
+ });
453
480
  return { output };
454
481
  });
455
482
  }
@@ -524,6 +551,17 @@ function buildEnvelopeSchema(inner, options = {}) {
524
551
  } }
525
552
  } };
526
553
  }
554
+ /**
555
+ * Validates a raw provider value against the structured-output envelope for
556
+ * `request` and returns the unwrapped `{ result, reasoning? }` — the checked
557
+ * replacement for `raw as StructuredOutputEnvelope` in hand-written hosts.
558
+ * Pair with {@link buildEnvelopeSchema} (which produced the schema the
559
+ * provider was asked to satisfy).
560
+ */
561
+ function parseStructuredEnvelope(request, value) {
562
+ if (!request.outputSchema) throw new Error("parseStructuredEnvelope: the request declares no outputSchema.");
563
+ return validateSchemaSync(buildEnvelopeSchema(request.outputSchema, { reasoning: request.reasoning }), value);
564
+ }
527
565
  function getStandardSchemaJson(schema) {
528
566
  const jsonSchema = (schema?.["~standard"])?.jsonSchema?.input?.();
529
567
  return jsonSchema && !(jsonSchema instanceof Promise) ? jsonSchema : void 0;
@@ -937,4 +975,4 @@ async function resolveDecision(request, executor, options = {}) {
937
975
  throw new DecisionExhaustedError(attempts);
938
976
  }
939
977
  //#endregion
940
- export { userInputActor as A, getAgentMessages as B, createTextLogic as C, isTextLogic as D, isStructuredOutputSchema as E, isUnboundPlaceholder as F, isStandardSchema as G, getJsonSchemaSync as H, machineSuspensionPredicates as I, toolMessage as J, persistSnapshot as K, missingActor as L, executorBoundLogics as M, getMachineSuspensionPredicate as N, normalizeGeneratorResult as O, getRegisteredAgentExecutionOptions as P, assistantMessage as R, builtinTextActors as S, getAgentOutputMode as T, getMachineStructuralHash as U, getJsonSchema as V, getStateMeta as W, validateSchemaSync as X, userMessage as Y, 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, agentExecutionOptions as j, parseOutput as k, renderDecisionAttempts as l, parseAgentEvent as m, PLAN_DONE_EVENT_TYPE as n, initialPlanLedger as o, matchesEventPattern as p, systemMessage 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, findNonSerializableContextPaths as z };
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 };