@statelyai/agent 2.0.0-alpha.28 → 2.0.0-alpha.29

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 (75) hide show
  1. package/dist/ai-sdk.cjs +149 -26
  2. package/dist/ai-sdk.d.cts +57 -34
  3. package/dist/ai-sdk.d.mts +57 -34
  4. package/dist/ai-sdk.mjs +147 -23
  5. package/dist/{decision-RQ0iv0oZ.mjs → decision-Bl_rKQnU.mjs} +73 -7
  6. package/dist/{decision-CmM8-HHz.cjs → decision-oevZnkBe.cjs} +112 -29
  7. package/dist/{text-logic-f5F5sCdc.cjs → event-log-Dtb16p1p.cjs} +813 -6
  8. package/dist/{text-logic-CIqHAmBi.mjs → event-log-GPZO9p7_.mjs} +679 -3
  9. package/dist/{event-log-store-BIPOz-di.d.mts → event-log-store-CN9ygggF.d.cts} +90 -5
  10. package/dist/{event-log-store-2xzFmgr2.d.cts → event-log-store-DS836wch.d.mts} +90 -5
  11. package/dist/event-log-store-bCdskPNS.cjs +95 -0
  12. package/dist/event-log-store-yalq8C77.mjs +84 -0
  13. package/dist/index.cjs +571 -58
  14. package/dist/index.d.cts +104 -510
  15. package/dist/index.d.mts +104 -510
  16. package/dist/index.mjs +542 -32
  17. package/dist/log.cjs +77 -20
  18. package/dist/log.d.cts +5 -5
  19. package/dist/log.d.mts +5 -5
  20. package/dist/log.mjs +58 -3
  21. package/dist/machines.cjs +1 -1
  22. package/dist/machines.d.cts +15 -15
  23. package/dist/machines.d.mts +15 -15
  24. package/dist/machines.mjs +1 -1
  25. package/dist/model-source-C7FFP2Sj.mjs +39 -0
  26. package/dist/model-source-DjJPjGSP.cjs +44 -0
  27. package/dist/openai.cjs +10 -10
  28. package/dist/openai.d.cts +27 -25
  29. package/dist/openai.d.mts +27 -25
  30. package/dist/openai.mjs +2 -2
  31. package/dist/otel.cjs +5 -4
  32. package/dist/otel.d.cts +5 -7
  33. package/dist/otel.d.mts +5 -7
  34. package/dist/otel.mjs +5 -3
  35. package/dist/{run-agent-COXXc0RW.d.mts → run-agent-C9ubX8Tx.d.cts} +87 -30
  36. package/dist/{run-agent-xNTxpt82.mjs → run-agent-CuQT1xSS.mjs} +170 -42
  37. package/dist/{run-agent-ByO-Bxyd.d.cts → run-agent-CxSyZmIE.d.mts} +87 -30
  38. package/dist/{run-agent-Dmf8GV2d.cjs → run-agent-cToZ3K42.cjs} +219 -86
  39. package/dist/{setup-agent-DV4cTou-.cjs → setup-agent-DTF3NQg3.cjs} +31 -20
  40. package/dist/setup-agent-DlbgwsIJ.d.cts +577 -0
  41. package/dist/{setup-agent-BuanDXeh.mjs → setup-agent-DniLvDu7.mjs} +15 -9
  42. package/dist/setup-agent-tsc3vm5I.d.mts +577 -0
  43. package/dist/tanstack-ai.cjs +627 -0
  44. package/dist/tanstack-ai.d.cts +204 -0
  45. package/dist/tanstack-ai.d.mts +204 -0
  46. package/dist/tanstack-ai.mjs +618 -0
  47. package/dist/testing.cjs +98 -985
  48. package/dist/testing.d.cts +51 -347
  49. package/dist/testing.d.mts +51 -347
  50. package/dist/testing.mjs +86 -973
  51. package/dist/{text-logic-IjfYy9DP.d.cts → text-logic-9fv1i9aK.d.cts} +50 -10
  52. package/dist/{text-logic-D-czVPYp.d.mts → text-logic-BDbGjYMh.d.mts} +50 -10
  53. package/dist/{types-BgNbNKnJ.d.mts → types-Dp5_Ru4R.d.cts} +2 -2
  54. package/dist/{types-hR5f5YXa.d.cts → types-Dp5_Ru4R.d.mts} +2 -2
  55. package/dist/usage-D8UphgEA.d.mts +17 -0
  56. package/dist/usage-R1NTmLxY.d.cts +17 -0
  57. package/dist/{utils-_q7F-AZu.d.mts → utils-BnXdWih3.d.mts} +1 -2
  58. package/dist/{utils-o4YRdHJX.d.cts → utils-ebVpCYoF.d.cts} +1 -2
  59. package/dist/validate.cjs +239 -8
  60. package/dist/validate.d.cts +110 -3
  61. package/dist/validate.d.mts +110 -3
  62. package/dist/validate.mjs +238 -7
  63. package/dist/verify-B5qGC5WN.mjs +1181 -0
  64. package/dist/verify-CBuYIpsa.d.mts +414 -0
  65. package/dist/verify-Cqghu4gz.cjs +1222 -0
  66. package/dist/verify-DYH_2VzU.d.cts +414 -0
  67. package/package.json +44 -31
  68. package/readme.md +38 -26
  69. package/skills/generate-machine/SKILL.md +140 -66
  70. package/skills/improve-machine/SKILL.md +190 -0
  71. package/skills/improve-machine/reference.md +96 -0
  72. package/dist/event-log-store-2pAFiWuc.mjs +0 -576
  73. package/dist/event-log-store-C-COhIXP.cjs +0 -702
  74. package/dist/usage-BdEjFuIi.mjs +0 -5
  75. package/dist/usage-efOQPdf_.cjs +0 -10
package/dist/ai-sdk.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_text_logic = require("./text-logic-f5F5sCdc.cjs");
3
- const require_decision = require("./decision-CmM8-HHz.cjs");
4
- require("./validate.cjs");
2
+ const require_event_log = require("./event-log-Dtb16p1p.cjs");
3
+ const require_decision = require("./decision-oevZnkBe.cjs");
4
+ const require_model_source = require("./model-source-DjJPjGSP.cjs");
5
5
  let ai = require("ai");
6
6
  //#region src/ai-sdk/mappers.ts
7
7
  /**
@@ -25,7 +25,7 @@ function toAiSdkTools(tools) {
25
25
  })]);
26
26
  continue;
27
27
  }
28
- if (require_text_logic.isStandardSchema(descriptor.inputSchema)) {
28
+ if (require_event_log.isStandardSchema(descriptor.inputSchema) || descriptor.type === "provider") {
29
29
  entries.push([name, descriptor]);
30
30
  continue;
31
31
  }
@@ -132,7 +132,7 @@ function toAiSdkToolChoice(toolChoice) {
132
132
  }
133
133
  /** `true` when the request should use AI SDK structured `Output.object`. */
134
134
  function isStructuredOutputRequest(request) {
135
- return require_text_logic.getAgentOutputMode(request.outputSchema) === "structured";
135
+ return require_event_log.getAgentOutputMode(request.outputSchema) === "structured";
136
136
  }
137
137
  /**
138
138
  * Extracts the first complete top-level JSON value from `text`, or returns
@@ -175,6 +175,53 @@ function toAiSdkEventTools(events) {
175
175
  inputSchema: event.inputSchema ? event.inputSchema : unknownSchema
176
176
  })]));
177
177
  }
178
+ /** Tool name of the single closed-choice tool {@link toAiSdkOptionTool} builds. */
179
+ const OPTION_TOOL_NAME = "choose_option";
180
+ /**
181
+ * A closed choice as ONE AI SDK tool: its input is `{ option }`, an enum of
182
+ * option ids (see core's `decisionOptionIds`), with each id's description in
183
+ * the tool description. Map the answer back with `ids.indexOf(input.option)`.
184
+ */
185
+ function toAiSdkOptionTool(options) {
186
+ const ids = require_decision.decisionOptionIds(options);
187
+ const lines = options.map((option, index) => option.description ? `- ${ids[index]}: ${option.description}` : `- ${ids[index]}`);
188
+ return {
189
+ ids,
190
+ tools: { [OPTION_TOOL_NAME]: (0, ai.tool)({
191
+ description: `Choose exactly one option:\n${lines.join("\n")}`,
192
+ inputSchema: (0, ai.jsonSchema)({
193
+ type: "object",
194
+ properties: { option: {
195
+ type: "string",
196
+ enum: ids,
197
+ description: "The id of the chosen option."
198
+ } },
199
+ required: ["option"],
200
+ additionalProperties: false
201
+ })
202
+ }) }
203
+ };
204
+ }
205
+ /**
206
+ * The event a closed-choice tool call names: the offered option whose id is
207
+ * `input.option`. A call to another tool, or an id that is not offered, maps
208
+ * to {@link unofferedOption}, so the choice is retried instead of thrown.
209
+ */
210
+ function fromAiSdkOptionCall(toolCall, options, ids) {
211
+ if (toolCall.toolName !== OPTION_TOOL_NAME) return unofferedOption(`tool '${toolCall.toolName}'`, ids);
212
+ const id = require_decision.isRecord(toolCall.input) ? toolCall.input.option : void 0;
213
+ const option = typeof id === "string" ? options[ids.indexOf(id)] : void 0;
214
+ return option ? option.event : unofferedOption(`option ${JSON.stringify(id)}`, ids);
215
+ }
216
+ /**
217
+ * A stand-in event for a closed-choice answer that names no offered option.
218
+ * Its `type` is no candidate event, so `resolveDecision` records it as a
219
+ * failed `'unknown-event'` attempt (the type, which names the answer and the
220
+ * valid ids, is the attempt's reason) and asks again.
221
+ */
222
+ function unofferedOption(answer, ids) {
223
+ return { type: `${answer} was not offered (valid ids: ${ids.join(", ") || "none"})` };
224
+ }
178
225
  /**
179
226
  * Messages for a decision request, with prior failed `attempts` (§2.6)
180
227
  * rendered as appended user messages (via core's {@link renderDecisionAttempts})
@@ -198,6 +245,9 @@ function maxStepsSetting(request) {
198
245
  const maxSteps = request.maxSteps;
199
246
  return typeof maxSteps === "number" ? { stopWhen: (0, ai.stepCountIs)(maxSteps) } : {};
200
247
  }
248
+ function isDecisionModel(model) {
249
+ return require_decision.isRecord(model) && (typeof model.doDecide === "function" || typeof model.doEvaluate === "function");
250
+ }
201
251
  /**
202
252
  * Splits a portable `"provider/model-id"` model ref (the convention JSON
203
253
  * workflows and registry-less hosts use, e.g. `"openai/gpt-5.4-mini"`) into
@@ -232,12 +282,22 @@ function resolveAiSdkModel(options, modelRef) {
232
282
  if (!entry) throw new Error(`createAiSdkExecutors: unknown model '${modelRef}'.`);
233
283
  return isModelWithSettings(entry) ? entry : { model: entry };
234
284
  }
285
+ function resolveLanguageModel(options, request) {
286
+ const { model, settings } = resolveAiSdkModel(options, request.model);
287
+ if (isDecisionModel(model)) throw new Error(`createAiSdkExecutors: model '${request.model}' is a decision model, which only answers decide requests with options; text request '${request.name ?? "(unnamed)"}' needs a language model.`);
288
+ return {
289
+ model,
290
+ ...settings ? { settings } : {}
291
+ };
292
+ }
235
293
  /**
236
294
  * The `LanguageModel` inside a map entry, whichever form it takes. `AiSdkModelMap`
237
295
  * widens its return to {@link AiSdkModelMap}, so reading an entry out of the map
238
- * to hand to a raw AI SDK call needs this to get past the union.
296
+ * to hand to a raw AI SDK call needs this to get past the union. Throws for a
297
+ * decision model.
239
298
  */
240
299
  function toLanguageModel(entry) {
300
+ if (isDecisionModel(entry)) throw new TypeError("toLanguageModel: the entry is a decision model, not a language model.");
241
301
  return isModelWithSettings(entry) ? entry.model : entry;
242
302
  }
243
303
  function isModelWithSettings(entry) {
@@ -261,30 +321,17 @@ function withJsonRepair(output) {
261
321
  };
262
322
  }
263
323
  function truncated(request, info, partialOutput, cause) {
264
- return new require_text_logic.AgentTruncatedError(`createAiSdkExecutors: request '${request.name ?? "(unnamed)"}' hit the output token limit — its structured output never completed. Raise \`maxOutputTokens\`, shorten the input, or ask for a smaller output schema.`, {
324
+ return new require_event_log.AgentTruncatedError(`createAiSdkExecutors: request '${request.name ?? "(unnamed)"}' hit the output token limit — its structured output never completed. Raise \`maxOutputTokens\`, shorten the input, or ask for a smaller output schema.`, {
265
325
  requestName: request.name ?? "(unnamed)",
266
326
  ...info?.requestId !== void 0 ? { requestId: info.requestId } : {},
267
327
  ...partialOutput !== void 0 ? { partialOutput } : {},
268
328
  ...cause !== void 0 ? { cause } : {}
269
329
  });
270
330
  }
271
- /**
272
- * The canonical Vercel AI SDK adapter: builds the `{ generateText, streamText,
273
- * decide }` executor set consumed by `createAgentRuntime`/`executeAgentRequest`. `ai`
274
- * must not become a dependency of core `src/` files — this subpath is the one
275
- * place it's imported, and callers must supply their own model resolver so no
276
- * concrete provider package (e.g. `@ai-sdk/openai`) becomes a dependency here
277
- * either.
278
- *
279
- * @example
280
- * ```ts
281
- * const executors = createAiSdkExecutors({ models: { quick: openai('gpt-5.4-mini') } });
282
- * const result = await runToQuiescence(createAgentRuntime(machine, { executors }), { input });
283
- * ```
284
- */
285
- function createAiSdkExecutors(options) {
331
+ function createAiSdkExecutors(source) {
332
+ const options = require_model_source.resolveModelSource("createAiSdkExecutors", source);
286
333
  const generateText = async (request, info) => {
287
- const { model, settings: modelSettings } = resolveAiSdkModel(options, request.model);
334
+ const { model, settings: modelSettings } = resolveLanguageModel(options, request);
288
335
  const common = {
289
336
  model,
290
337
  abortSignal: info?.signal,
@@ -294,7 +341,7 @@ function createAiSdkExecutors(options) {
294
341
  ...maxStepsSetting(request)
295
342
  };
296
343
  if (isStructuredOutputRequest(request)) {
297
- const outputSchema = require_text_logic.providerOutputSchema(request.outputSchema, { reasoning: request.includeReasoning });
344
+ const outputSchema = require_event_log.providerOutputSchema(request.outputSchema, { reasoning: request.includeReasoning });
298
345
  const structuredOutput = withJsonRepair(ai.Output.object({ schema: outputSchema }));
299
346
  const result = await (0, ai.generateText)({
300
347
  ...common,
@@ -333,7 +380,7 @@ function createAiSdkExecutors(options) {
333
380
  };
334
381
  };
335
382
  const streamText = async (request, info) => {
336
- const { model, settings: modelSettings } = resolveAiSdkModel(options, request.model);
383
+ const { model, settings: modelSettings } = resolveLanguageModel(options, request);
337
384
  const result = (0, ai.streamText)({
338
385
  model,
339
386
  abortSignal: info?.signal,
@@ -353,7 +400,9 @@ function createAiSdkExecutors(options) {
353
400
  };
354
401
  const decide = async (request, info) => {
355
402
  const { model, settings: modelSettings } = resolveAiSdkModel(options, request.model);
356
- const tools = toAiSdkEventTools(request.events);
403
+ if (isDecisionModel(model)) return decideWithDecisionModel(model, request, info);
404
+ const choice = request.options ? toAiSdkOptionTool(request.options) : void 0;
405
+ const tools = choice ? choice.tools : toAiSdkEventTools(request.events);
357
406
  const messages = toDecisionMessages(request);
358
407
  const result = await (0, ai.generateText)({
359
408
  model,
@@ -372,6 +421,11 @@ function createAiSdkExecutors(options) {
372
421
  });
373
422
  const toolCall = result.toolCalls[0];
374
423
  if (!toolCall) throw new Error("createAiSdkExecutors: decide — model did not call an event tool.");
424
+ if (choice) return {
425
+ event: fromAiSdkOptionCall(toolCall, request.options, choice.ids),
426
+ usage: toAgentCallUsage(result.usage),
427
+ finishReason: result.finishReason
428
+ };
375
429
  const chosenEvent = request.events.find((event) => event.toolName === toolCall.toolName);
376
430
  if (!chosenEvent) throw new Error(`createAiSdkExecutors: decide — model called unknown tool '${toolCall.toolName}'.`);
377
431
  return {
@@ -389,6 +443,75 @@ function createAiSdkExecutors(options) {
389
443
  decide
390
444
  };
391
445
  }
446
+ /** The question id a decision model's closed choice is asked under. */
447
+ const DECISION_QUESTION_ID = "next";
448
+ async function decideWithDecisionModel(model, request, info) {
449
+ const offered = request.options;
450
+ if (!offered?.length) throw new Error(`createAiSdkExecutors: decision '${request.name ?? "(unnamed)"}' uses decision model '${request.model}', which needs a closed choice: pass \`payloads\` on agent.decide, or use decideNext.`);
451
+ const ids = require_decision.decisionOptionIds(offered);
452
+ const criteria = Object.fromEntries(offered.map((option, index) => [ids[index], option.description ?? JSON.stringify(option.event)]));
453
+ const instructions = [[request.system, request.prompt].filter(Boolean).join("\n\n") || "Which option should happen next?", ...require_decision.renderDecisionAttempts(request).map((message) => message.content)].join("\n\n");
454
+ const ask = () => (0, ai.experimental_decide)({
455
+ model,
456
+ state: toDecisionState(request.input),
457
+ questions: { [DECISION_QUESTION_ID]: {
458
+ type: "choice",
459
+ instructions,
460
+ criteria
461
+ } },
462
+ ...info?.signal ? { abortSignal: info.signal } : {}
463
+ });
464
+ let result;
465
+ try {
466
+ result = await ask();
467
+ } catch (error) {
468
+ const chosen = unofferedChoice(error, ids);
469
+ if (chosen === void 0) throw error;
470
+ return decisionResult(unofferedOption(`option ${JSON.stringify(chosen)}`, ids));
471
+ }
472
+ const answer = result.answers[DECISION_QUESTION_ID];
473
+ const option = offered[ids.indexOf(answer.choice)];
474
+ if (!option) return decisionResult(unofferedOption(`option ${JSON.stringify(answer.choice)}`, ids));
475
+ const reported = (result.providerMetadata?.typesafe?.confidence)?.[DECISION_QUESTION_ID];
476
+ const confidence = typeof reported === "number" ? reported : answer.probabilities?.[answer.choice];
477
+ return decisionResult(option.event, result.usage, confidence);
478
+ }
479
+ function decisionResult(event, usage = {}, confidence) {
480
+ return {
481
+ event,
482
+ usage: toAgentCallUsage({
483
+ inputTokens: usage.inputTokens,
484
+ outputTokens: usage.outputTokens,
485
+ totalTokens: usage.totalTokens,
486
+ inputTokenDetails: {
487
+ noCacheTokens: void 0,
488
+ cacheReadTokens: void 0,
489
+ cacheWriteTokens: void 0
490
+ },
491
+ outputTokenDetails: {
492
+ textTokens: void 0,
493
+ reasoningTokens: void 0
494
+ }
495
+ }),
496
+ finishReason: "stop",
497
+ ...confidence !== void 0 ? { confidence } : {}
498
+ };
499
+ }
500
+ function unofferedChoice(error, ids) {
501
+ if (!ai.InvalidResponseDataError.isInstance(error) || !require_decision.isRecord(error.data)) return void 0;
502
+ const answer = error.data[DECISION_QUESTION_ID];
503
+ const choice = require_decision.isRecord(answer) ? answer.choice : void 0;
504
+ return typeof choice === "string" && !ids.includes(choice) ? choice : void 0;
505
+ }
506
+ function toDecisionState(value) {
507
+ if (typeof value === "string") return value;
508
+ try {
509
+ const json = JSON.parse(JSON.stringify(value ?? {}));
510
+ return require_decision.isRecord(json) ? json : { value: json };
511
+ } catch {
512
+ return String(value);
513
+ }
514
+ }
392
515
  //#endregion
393
516
  exports.createAiSdkExecutors = createAiSdkExecutors;
394
517
  exports.parseModelRef = parseModelRef;
package/dist/ai-sdk.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { s as AgentTools, u as ChosenEvent } from "./types-hR5f5YXa.cjs";
2
- import { M as AgentDecisionRequest, c as AgentRequestExecutorInfo, f as AgentTextRequest, r as AgentFinishReason, t as AgentCallUsage } from "./text-logic-IjfYy9DP.cjs";
3
- import { FinishReason, LanguageModel, LanguageModelUsage, ModelMessage, ToolSet, TypedToolCall, TypedToolResult, generateText } from "ai";
4
-
1
+ import { s as AgentTools, u as ChosenEvent } from "./types-Dp5_Ru4R.cjs";
2
+ import { N as AgentDecisionRequest, c as AgentRequestExecutorInfo, f as AgentTextRequest, r as AgentFinishReason, t as AgentCallUsage } from "./text-logic-9fv1i9aK.cjs";
3
+ import { Experimental_DecisionModel, FinishReason, LanguageModel, LanguageModelUsage, ModelMessage, ToolSet, TypedToolCall, TypedToolResult, generateText } from "ai";
4
+ import { AnyStateMachine } from "xstate";
5
5
  //#region src/ai-sdk/mappers.d.ts
6
6
  /**
7
7
  * One call's usage as the adapter reports it: the AI SDK's `LanguageModelUsage`
@@ -12,15 +12,20 @@ type AiSdkCallUsage = LanguageModelUsage & Pick<AgentCallUsage, "reasoningTokens
12
12
  //#endregion
13
13
  //#region src/ai-sdk/index.d.ts
14
14
  /**
15
- * One entry in an {@link AiSdkModelMap}: a bare `LanguageModel`, or a model
16
- * paired with the {@link AiSdkCallSettings} that ref always runs with. The
17
- * paired form is how a host gives a ref a persona — `deep` thinks harder than
18
- * `quick` — without the machine naming a provider knob.
15
+ * One entry in an {@link AiSdkModelMap}: a bare `LanguageModel`, a model
16
+ * paired with the {@link AiSdkCallSettings} that ref always runs with, or an
17
+ * AI SDK decision model. The paired form is how a host gives a ref a persona —
18
+ * `deep` thinks harder than `quick` — without the machine naming a provider knob.
19
+ *
20
+ * A decision model (such as `typeSafeAi.decisionModel('jev-latest')`) answers
21
+ * `decide` requests that carry a closed choice (`options`) through
22
+ * `experimental_decide`. Text requests need a language model.
19
23
  */
20
- type AiSdkModelEntry = LanguageModel | {
24
+ export type AiSdkModelEntry = LanguageModel | AiSdkDecisionModel | {
21
25
  model: LanguageModel;
22
26
  settings?: AiSdkCallSettings;
23
27
  };
28
+ type AiSdkDecisionModel = Exclude<Experimental_DecisionModel, string>;
24
29
  /**
25
30
  * Splits a portable `"provider/model-id"` model ref (the convention JSON
26
31
  * workflows and registry-less hosts use, e.g. `"openai/gpt-5.4-mini"`) into
@@ -32,12 +37,12 @@ type AiSdkModelEntry = LanguageModel | {
32
37
  * const resolveModel = (ref: string) => openai(parseModelRef(ref).modelId);
33
38
  * ```
34
39
  */
35
- declare function parseModelRef(modelRef: string): {
40
+ export declare function parseModelRef(modelRef: string): {
36
41
  provider: string | undefined;
37
42
  modelId: string;
38
43
  };
39
44
  /** AI SDK model registry: maps model refs (as used in `setupAgent({ models })`/`AgentTextRequest.model`) to AI SDK `LanguageModel` values, or to `{ model, settings }` pairs. The optional `TKey` parameter pins the ref keys; it defaults to `string`, so bare `AiSdkModelMap` stays `Record<string, AiSdkModelEntry>`. */
40
- type AiSdkModelMap<TKey extends string = string> = Record<TKey, AiSdkModelEntry>;
45
+ export type AiSdkModelMap<TKey extends string = string> = Record<TKey, AiSdkModelEntry>;
41
46
  /**
42
47
  * Per-call AI SDK settings a host can apply on top of what the machine asked
43
48
  * for — reasoning effort, `providerOptions`, and anything else the SDK's call
@@ -48,7 +53,7 @@ type AiSdkModelMap<TKey extends string = string> = Record<TKey, AiSdkModelEntry>
48
53
  * generation settings every provider shares) are excluded: those belong to the
49
54
  * machine, and a host override would silently contradict it.
50
55
  */
51
- type AiSdkCallSettings = Omit<Parameters<typeof generateText>[0], "model" | "prompt" | "messages" | "system" | "instructions" | "tools" | "toolChoice" | "output" | "abortSignal" | "stopWhen">;
56
+ export type AiSdkCallSettings = Omit<Parameters<typeof generateText>[0], "model" | "prompt" | "messages" | "system" | "instructions" | "tools" | "toolChoice" | "output" | "abortSignal" | "stopWhen">;
52
57
  /**
53
58
  * Options for {@link createAiSdkExecutors}: either a static `models` map
54
59
  * (model refs resolved by lookup), a `resolveModel` function (refs resolved
@@ -61,21 +66,22 @@ type AiSdkCallSettings = Omit<Parameters<typeof generateText>[0], "model" | "pro
61
66
  * registered key). Core neither declares nor reads these: a machine stays
62
67
  * portable, and a host that cannot honor a knob simply does not set it.
63
68
  */
64
- type CreateAiSdkExecutorsOptions<TModels extends AiSdkModelMap = AiSdkModelMap> = {
69
+ export type CreateAiSdkExecutorsOptions<TModels extends AiSdkModelMap = AiSdkModelMap> = {
65
70
  settings?: AiSdkCallSettings | ((request: AgentTextRequest | AgentDecisionRequest) => AiSdkCallSettings | undefined);
66
71
  } & ({
67
72
  models: TModels;
68
- resolveModel?: (modelRef: keyof TModels & string) => LanguageModel;
73
+ resolveModel?: (modelRef: keyof TModels & string) => LanguageModel | AiSdkDecisionModel;
69
74
  } | {
70
75
  models?: TModels;
71
- resolveModel: (modelRef: string) => LanguageModel;
76
+ resolveModel: (modelRef: string) => LanguageModel | AiSdkDecisionModel;
72
77
  });
73
78
  /**
74
79
  * The `LanguageModel` inside a map entry, whichever form it takes. `AiSdkModelMap`
75
80
  * widens its return to {@link AiSdkModelMap}, so reading an entry out of the map
76
- * to hand to a raw AI SDK call needs this to get past the union.
81
+ * to hand to a raw AI SDK call needs this to get past the union. Throws for a
82
+ * decision model.
77
83
  */
78
- declare function toLanguageModel(entry: AiSdkModelEntry): LanguageModel;
84
+ export declare function toLanguageModel(entry: AiSdkModelEntry): LanguageModel;
79
85
  /**
80
86
  * Raw result shape from {@link AiSdkExecutors.generateText} — `result` (the
81
87
  * validated structured object for structured-output requests, or the
@@ -85,7 +91,7 @@ declare function toLanguageModel(entry: AiSdkModelEntry): LanguageModel;
85
91
  * `raw as AiSdkGenerateResult` is the supported cast for token accounting and
86
92
  * tracing.
87
93
  */
88
- type AiSdkGenerateResult = {
94
+ export type AiSdkGenerateResult = {
89
95
  result: unknown;
90
96
  /** The model's reasoning, present only when the request opted in via
91
97
  * `reasoning: true` and the model produced it (see
@@ -95,31 +101,42 @@ type AiSdkGenerateResult = {
95
101
  * `reasoningTokens`/`cachedInputTokens` fields are what the runtime folds into
96
102
  * the run result's aggregated `AgentUsage`; the AI SDK's own nested
97
103
  * `inputTokenDetails`/`outputTokenDetails` and `raw` ride along untouched. */
98
- usage: AiSdkCallUsage; /** Why the call stopped, normalized to the portable {@link AgentFinishReason}. The SDK's own value stays on `raw`. */
104
+ usage: AiSdkCallUsage;
105
+ /** Why the call stopped, normalized to the portable {@link AgentFinishReason}. The SDK's own value stays on `raw`. */
99
106
  finishReason: AgentFinishReason;
100
107
  toolCalls: TypedToolCall<ToolSet>[];
101
- toolResults: TypedToolResult<ToolSet>[]; /** AI SDK response messages, including tool calls/results from every step. */
102
- messages: ModelMessage[]; /** The untouched AI SDK result. */
108
+ toolResults: TypedToolResult<ToolSet>[];
109
+ /** AI SDK response messages, including tool calls/results from every step. */
110
+ messages: ModelMessage[];
111
+ /** The untouched AI SDK result. */
103
112
  raw: unknown;
104
113
  };
105
114
  /** Raw result shape from {@link AiSdkExecutors.streamText} — `result` is the fully-accumulated text once the stream finishes (chunks are delivered separately via `onChunk`), plus the response messages and the stream's final usage/finish metadata for `onResult`. */
106
- type AiSdkStreamResult = {
107
- result: string; /** The stream's final (awaited) usage; aggregated into the run result's `AgentUsage`. */
108
- usage: AiSdkCallUsage; /** Why the stream stopped, normalized to the portable {@link AgentFinishReason}. The SDK's own value stays on `raw`. */
109
- finishReason: AgentFinishReason; /** AI SDK response messages, including tool calls/results from every step. */
110
- messages: ModelMessage[]; /** The untouched AI SDK result. */
115
+ export type AiSdkStreamResult = {
116
+ result: string;
117
+ /** The stream's final (awaited) usage; aggregated into the run result's `AgentUsage`. */
118
+ usage: AiSdkCallUsage;
119
+ /** Why the stream stopped, normalized to the portable {@link AgentFinishReason}. The SDK's own value stays on `raw`. */
120
+ finishReason: AgentFinishReason;
121
+ /** AI SDK response messages, including tool calls/results from every step. */
122
+ messages: ModelMessage[];
123
+ /** The untouched AI SDK result. */
111
124
  raw: unknown;
112
125
  };
113
126
  /** Raw result shape from {@link AiSdkExecutors.decide} — the chosen event plus the AI SDK call metadata, delivered per decision attempt to `onResult`. */
114
- type AiSdkDecideResult = {
115
- event: ChosenEvent; /** This attempt's usage; aggregated into the run result's `AgentUsage`. */
127
+ export type AiSdkDecideResult = {
128
+ event: ChosenEvent;
129
+ /** This attempt's usage; aggregated into the run result's `AgentUsage`. */
116
130
  usage: AiSdkCallUsage;
131
+ /** `'stop'` for a decision model, which reports no finish reason. */
117
132
  finishReason: FinishReason;
133
+ /** A decision model's confidence in the chosen option, when it reports one. */
134
+ confidence?: number;
118
135
  };
119
136
  /** `createAiSdkExecutors` always populates all three slots (unlike the
120
137
  * general `AgentRequestExecutors`, where `streamText`/`decide` are optional),
121
138
  * and its `generateText`/`streamText` results are concretely typed. */
122
- interface AiSdkExecutors {
139
+ export interface AiSdkExecutors {
123
140
  generateText: (request: AgentTextRequest & {
124
141
  tools: AgentTools;
125
142
  }, info?: AgentRequestExecutorInfo) => Promise<AiSdkGenerateResult>;
@@ -136,12 +153,18 @@ interface AiSdkExecutors {
136
153
  * concrete provider package (e.g. `@ai-sdk/openai`) becomes a dependency here
137
154
  * either.
138
155
  *
156
+ * Pass the options object, or pass the machine (or its `setupAgent(...)`
157
+ * result) to reuse the `models` declared in `setupAgent({ models })`. Anything
158
+ * else throws here, at construction.
159
+ *
139
160
  * @example
140
161
  * ```ts
141
- * const executors = createAiSdkExecutors({ models: { quick: openai('gpt-5.4-mini') } });
142
- * const result = await runToQuiescence(createAgentRuntime(machine, { executors }), { input });
162
+ * const agentSetup = setupAgent({ models: { quick: openai('gpt-5.4-mini') }, ... });
163
+ * const machine = agentSetup.createMachine({ ... });
164
+ * const result = await runAgent(machine, { input, executors: createAiSdkExecutors(machine) });
165
+ * // Or explicitly: createAiSdkExecutors({ models: { quick: openai('gpt-5.4-mini') } })
143
166
  * ```
144
167
  */
145
- declare function createAiSdkExecutors<TModels extends AiSdkModelMap>(options: CreateAiSdkExecutorsOptions<TModels>): AiSdkExecutors;
146
- //#endregion
147
- export { AiSdkCallSettings, AiSdkDecideResult, AiSdkExecutors, AiSdkGenerateResult, AiSdkModelEntry, AiSdkModelMap, AiSdkStreamResult, CreateAiSdkExecutorsOptions, createAiSdkExecutors, parseModelRef, toLanguageModel };
168
+ export declare function createAiSdkExecutors<TModels extends AiSdkModelMap>(options: CreateAiSdkExecutorsOptions<TModels>): AiSdkExecutors;
169
+ export declare function createAiSdkExecutors(machine: AnyStateMachine): AiSdkExecutors;
170
+ //#endregion
package/dist/ai-sdk.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { s as AgentTools, u as ChosenEvent } from "./types-BgNbNKnJ.mjs";
2
- import { M as AgentDecisionRequest, c as AgentRequestExecutorInfo, f as AgentTextRequest, r as AgentFinishReason, t as AgentCallUsage } from "./text-logic-D-czVPYp.mjs";
3
- import { FinishReason, LanguageModel, LanguageModelUsage, ModelMessage, ToolSet, TypedToolCall, TypedToolResult, generateText } from "ai";
4
-
1
+ import { s as AgentTools, u as ChosenEvent } from "./types-Dp5_Ru4R.mjs";
2
+ import { N as AgentDecisionRequest, c as AgentRequestExecutorInfo, f as AgentTextRequest, r as AgentFinishReason, t as AgentCallUsage } from "./text-logic-BDbGjYMh.mjs";
3
+ import { AnyStateMachine } from "xstate";
4
+ import { Experimental_DecisionModel, FinishReason, LanguageModel, LanguageModelUsage, ModelMessage, ToolSet, TypedToolCall, TypedToolResult, generateText } from "ai";
5
5
  //#region src/ai-sdk/mappers.d.ts
6
6
  /**
7
7
  * One call's usage as the adapter reports it: the AI SDK's `LanguageModelUsage`
@@ -12,15 +12,20 @@ type AiSdkCallUsage = LanguageModelUsage & Pick<AgentCallUsage, "reasoningTokens
12
12
  //#endregion
13
13
  //#region src/ai-sdk/index.d.ts
14
14
  /**
15
- * One entry in an {@link AiSdkModelMap}: a bare `LanguageModel`, or a model
16
- * paired with the {@link AiSdkCallSettings} that ref always runs with. The
17
- * paired form is how a host gives a ref a persona — `deep` thinks harder than
18
- * `quick` — without the machine naming a provider knob.
15
+ * One entry in an {@link AiSdkModelMap}: a bare `LanguageModel`, a model
16
+ * paired with the {@link AiSdkCallSettings} that ref always runs with, or an
17
+ * AI SDK decision model. The paired form is how a host gives a ref a persona —
18
+ * `deep` thinks harder than `quick` — without the machine naming a provider knob.
19
+ *
20
+ * A decision model (such as `typeSafeAi.decisionModel('jev-latest')`) answers
21
+ * `decide` requests that carry a closed choice (`options`) through
22
+ * `experimental_decide`. Text requests need a language model.
19
23
  */
20
- type AiSdkModelEntry = LanguageModel | {
24
+ export type AiSdkModelEntry = LanguageModel | AiSdkDecisionModel | {
21
25
  model: LanguageModel;
22
26
  settings?: AiSdkCallSettings;
23
27
  };
28
+ type AiSdkDecisionModel = Exclude<Experimental_DecisionModel, string>;
24
29
  /**
25
30
  * Splits a portable `"provider/model-id"` model ref (the convention JSON
26
31
  * workflows and registry-less hosts use, e.g. `"openai/gpt-5.4-mini"`) into
@@ -32,12 +37,12 @@ type AiSdkModelEntry = LanguageModel | {
32
37
  * const resolveModel = (ref: string) => openai(parseModelRef(ref).modelId);
33
38
  * ```
34
39
  */
35
- declare function parseModelRef(modelRef: string): {
40
+ export declare function parseModelRef(modelRef: string): {
36
41
  provider: string | undefined;
37
42
  modelId: string;
38
43
  };
39
44
  /** AI SDK model registry: maps model refs (as used in `setupAgent({ models })`/`AgentTextRequest.model`) to AI SDK `LanguageModel` values, or to `{ model, settings }` pairs. The optional `TKey` parameter pins the ref keys; it defaults to `string`, so bare `AiSdkModelMap` stays `Record<string, AiSdkModelEntry>`. */
40
- type AiSdkModelMap<TKey extends string = string> = Record<TKey, AiSdkModelEntry>;
45
+ export type AiSdkModelMap<TKey extends string = string> = Record<TKey, AiSdkModelEntry>;
41
46
  /**
42
47
  * Per-call AI SDK settings a host can apply on top of what the machine asked
43
48
  * for — reasoning effort, `providerOptions`, and anything else the SDK's call
@@ -48,7 +53,7 @@ type AiSdkModelMap<TKey extends string = string> = Record<TKey, AiSdkModelEntry>
48
53
  * generation settings every provider shares) are excluded: those belong to the
49
54
  * machine, and a host override would silently contradict it.
50
55
  */
51
- type AiSdkCallSettings = Omit<Parameters<typeof generateText>[0], "model" | "prompt" | "messages" | "system" | "instructions" | "tools" | "toolChoice" | "output" | "abortSignal" | "stopWhen">;
56
+ export type AiSdkCallSettings = Omit<Parameters<typeof generateText>[0], "model" | "prompt" | "messages" | "system" | "instructions" | "tools" | "toolChoice" | "output" | "abortSignal" | "stopWhen">;
52
57
  /**
53
58
  * Options for {@link createAiSdkExecutors}: either a static `models` map
54
59
  * (model refs resolved by lookup), a `resolveModel` function (refs resolved
@@ -61,21 +66,22 @@ type AiSdkCallSettings = Omit<Parameters<typeof generateText>[0], "model" | "pro
61
66
  * registered key). Core neither declares nor reads these: a machine stays
62
67
  * portable, and a host that cannot honor a knob simply does not set it.
63
68
  */
64
- type CreateAiSdkExecutorsOptions<TModels extends AiSdkModelMap = AiSdkModelMap> = {
69
+ export type CreateAiSdkExecutorsOptions<TModels extends AiSdkModelMap = AiSdkModelMap> = {
65
70
  settings?: AiSdkCallSettings | ((request: AgentTextRequest | AgentDecisionRequest) => AiSdkCallSettings | undefined);
66
71
  } & ({
67
72
  models: TModels;
68
- resolveModel?: (modelRef: keyof TModels & string) => LanguageModel;
73
+ resolveModel?: (modelRef: keyof TModels & string) => LanguageModel | AiSdkDecisionModel;
69
74
  } | {
70
75
  models?: TModels;
71
- resolveModel: (modelRef: string) => LanguageModel;
76
+ resolveModel: (modelRef: string) => LanguageModel | AiSdkDecisionModel;
72
77
  });
73
78
  /**
74
79
  * The `LanguageModel` inside a map entry, whichever form it takes. `AiSdkModelMap`
75
80
  * widens its return to {@link AiSdkModelMap}, so reading an entry out of the map
76
- * to hand to a raw AI SDK call needs this to get past the union.
81
+ * to hand to a raw AI SDK call needs this to get past the union. Throws for a
82
+ * decision model.
77
83
  */
78
- declare function toLanguageModel(entry: AiSdkModelEntry): LanguageModel;
84
+ export declare function toLanguageModel(entry: AiSdkModelEntry): LanguageModel;
79
85
  /**
80
86
  * Raw result shape from {@link AiSdkExecutors.generateText} — `result` (the
81
87
  * validated structured object for structured-output requests, or the
@@ -85,7 +91,7 @@ declare function toLanguageModel(entry: AiSdkModelEntry): LanguageModel;
85
91
  * `raw as AiSdkGenerateResult` is the supported cast for token accounting and
86
92
  * tracing.
87
93
  */
88
- type AiSdkGenerateResult = {
94
+ export type AiSdkGenerateResult = {
89
95
  result: unknown;
90
96
  /** The model's reasoning, present only when the request opted in via
91
97
  * `reasoning: true` and the model produced it (see
@@ -95,31 +101,42 @@ type AiSdkGenerateResult = {
95
101
  * `reasoningTokens`/`cachedInputTokens` fields are what the runtime folds into
96
102
  * the run result's aggregated `AgentUsage`; the AI SDK's own nested
97
103
  * `inputTokenDetails`/`outputTokenDetails` and `raw` ride along untouched. */
98
- usage: AiSdkCallUsage; /** Why the call stopped, normalized to the portable {@link AgentFinishReason}. The SDK's own value stays on `raw`. */
104
+ usage: AiSdkCallUsage;
105
+ /** Why the call stopped, normalized to the portable {@link AgentFinishReason}. The SDK's own value stays on `raw`. */
99
106
  finishReason: AgentFinishReason;
100
107
  toolCalls: TypedToolCall<ToolSet>[];
101
- toolResults: TypedToolResult<ToolSet>[]; /** AI SDK response messages, including tool calls/results from every step. */
102
- messages: ModelMessage[]; /** The untouched AI SDK result. */
108
+ toolResults: TypedToolResult<ToolSet>[];
109
+ /** AI SDK response messages, including tool calls/results from every step. */
110
+ messages: ModelMessage[];
111
+ /** The untouched AI SDK result. */
103
112
  raw: unknown;
104
113
  };
105
114
  /** Raw result shape from {@link AiSdkExecutors.streamText} — `result` is the fully-accumulated text once the stream finishes (chunks are delivered separately via `onChunk`), plus the response messages and the stream's final usage/finish metadata for `onResult`. */
106
- type AiSdkStreamResult = {
107
- result: string; /** The stream's final (awaited) usage; aggregated into the run result's `AgentUsage`. */
108
- usage: AiSdkCallUsage; /** Why the stream stopped, normalized to the portable {@link AgentFinishReason}. The SDK's own value stays on `raw`. */
109
- finishReason: AgentFinishReason; /** AI SDK response messages, including tool calls/results from every step. */
110
- messages: ModelMessage[]; /** The untouched AI SDK result. */
115
+ export type AiSdkStreamResult = {
116
+ result: string;
117
+ /** The stream's final (awaited) usage; aggregated into the run result's `AgentUsage`. */
118
+ usage: AiSdkCallUsage;
119
+ /** Why the stream stopped, normalized to the portable {@link AgentFinishReason}. The SDK's own value stays on `raw`. */
120
+ finishReason: AgentFinishReason;
121
+ /** AI SDK response messages, including tool calls/results from every step. */
122
+ messages: ModelMessage[];
123
+ /** The untouched AI SDK result. */
111
124
  raw: unknown;
112
125
  };
113
126
  /** Raw result shape from {@link AiSdkExecutors.decide} — the chosen event plus the AI SDK call metadata, delivered per decision attempt to `onResult`. */
114
- type AiSdkDecideResult = {
115
- event: ChosenEvent; /** This attempt's usage; aggregated into the run result's `AgentUsage`. */
127
+ export type AiSdkDecideResult = {
128
+ event: ChosenEvent;
129
+ /** This attempt's usage; aggregated into the run result's `AgentUsage`. */
116
130
  usage: AiSdkCallUsage;
131
+ /** `'stop'` for a decision model, which reports no finish reason. */
117
132
  finishReason: FinishReason;
133
+ /** A decision model's confidence in the chosen option, when it reports one. */
134
+ confidence?: number;
118
135
  };
119
136
  /** `createAiSdkExecutors` always populates all three slots (unlike the
120
137
  * general `AgentRequestExecutors`, where `streamText`/`decide` are optional),
121
138
  * and its `generateText`/`streamText` results are concretely typed. */
122
- interface AiSdkExecutors {
139
+ export interface AiSdkExecutors {
123
140
  generateText: (request: AgentTextRequest & {
124
141
  tools: AgentTools;
125
142
  }, info?: AgentRequestExecutorInfo) => Promise<AiSdkGenerateResult>;
@@ -136,12 +153,18 @@ interface AiSdkExecutors {
136
153
  * concrete provider package (e.g. `@ai-sdk/openai`) becomes a dependency here
137
154
  * either.
138
155
  *
156
+ * Pass the options object, or pass the machine (or its `setupAgent(...)`
157
+ * result) to reuse the `models` declared in `setupAgent({ models })`. Anything
158
+ * else throws here, at construction.
159
+ *
139
160
  * @example
140
161
  * ```ts
141
- * const executors = createAiSdkExecutors({ models: { quick: openai('gpt-5.4-mini') } });
142
- * const result = await runToQuiescence(createAgentRuntime(machine, { executors }), { input });
162
+ * const agentSetup = setupAgent({ models: { quick: openai('gpt-5.4-mini') }, ... });
163
+ * const machine = agentSetup.createMachine({ ... });
164
+ * const result = await runAgent(machine, { input, executors: createAiSdkExecutors(machine) });
165
+ * // Or explicitly: createAiSdkExecutors({ models: { quick: openai('gpt-5.4-mini') } })
143
166
  * ```
144
167
  */
145
- declare function createAiSdkExecutors<TModels extends AiSdkModelMap>(options: CreateAiSdkExecutorsOptions<TModels>): AiSdkExecutors;
146
- //#endregion
147
- export { AiSdkCallSettings, AiSdkDecideResult, AiSdkExecutors, AiSdkGenerateResult, AiSdkModelEntry, AiSdkModelMap, AiSdkStreamResult, CreateAiSdkExecutorsOptions, createAiSdkExecutors, parseModelRef, toLanguageModel };
168
+ export declare function createAiSdkExecutors<TModels extends AiSdkModelMap>(options: CreateAiSdkExecutorsOptions<TModels>): AiSdkExecutors;
169
+ export declare function createAiSdkExecutors(machine: AnyStateMachine): AiSdkExecutors;
170
+ //#endregion