@ai-sdk/workflow 1.0.0-beta.2 → 1.0.0-beta.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/workflow",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.4",
4
4
  "description": "WorkflowAgent for building AI agents with AI SDK",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.js",
@@ -29,7 +29,7 @@
29
29
  "ajv": "^8.18.0",
30
30
  "@ai-sdk/provider": "4.0.0-beta.12",
31
31
  "@ai-sdk/provider-utils": "5.0.0-beta.20",
32
- "ai": "7.0.0-beta.91"
32
+ "ai": "7.0.0-beta.92"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "20.17.24",
@@ -21,7 +21,6 @@ import {
21
21
  resolveSerializableTools,
22
22
  type SerializableToolDef,
23
23
  } from './serializable-schema.js';
24
- import type { CompatibleLanguageModel } from './types.js';
25
24
 
26
25
  export type { Experimental_LanguageModelStreamPart as ModelCallStreamPart } from 'ai';
27
26
 
@@ -87,10 +86,7 @@ export interface StreamFinish {
87
86
 
88
87
  export async function doStreamStep(
89
88
  conversationPrompt: LanguageModelV4Prompt,
90
- modelInit:
91
- | string
92
- | CompatibleLanguageModel
93
- | (() => Promise<CompatibleLanguageModel>),
89
+ modelInit: LanguageModel,
94
90
  writable?: WritableStream<ModelCallStreamPart<ToolSet>>,
95
91
  serializedTools?: Record<string, SerializableToolDef>,
96
92
  options?: DoStreamStepOptions,
@@ -98,22 +94,10 @@ export async function doStreamStep(
98
94
  'use step';
99
95
 
100
96
  // Resolve model inside step (must happen here for serialization boundary)
101
- let model: CompatibleLanguageModel;
102
- if (typeof modelInit === 'string') {
103
- model = gateway.languageModel(modelInit) as CompatibleLanguageModel;
104
- } else if (typeof modelInit === 'function') {
105
- model = await modelInit();
106
- } else if (
107
- typeof modelInit === 'object' &&
108
- modelInit !== null &&
109
- 'modelId' in modelInit
110
- ) {
111
- model = modelInit;
112
- } else {
113
- throw new Error(
114
- 'Invalid "model initialization" argument. Must be a string, a LanguageModel instance, or a function that returns a LanguageModel instance.',
115
- );
116
- }
97
+ const model: LanguageModel =
98
+ typeof modelInit === 'string'
99
+ ? gateway.languageModel(modelInit)
100
+ : modelInit;
117
101
 
118
102
  // Reconstruct tools from serializable definitions with Ajv validation.
119
103
  // Tools are serialized before crossing the step boundary because zod schemas
@@ -126,7 +110,7 @@ export async function doStreamStep(
126
110
  // model.doStream(), retry logic, and stream part transformation
127
111
  // (tool call parsing, finish reason mapping, file wrapping).
128
112
  const { stream: modelStream } = await streamModelCall({
129
- model: model as LanguageModel,
113
+ model,
130
114
  // streamModelCall expects Prompt (ModelMessage[]) but we pass the
131
115
  // pre-converted LanguageModelV4Prompt. standardizePrompt inside
132
116
  // streamModelCall handles both formats.
package/src/index.ts CHANGED
@@ -17,9 +17,10 @@ export {
17
17
  type PrepareStepInfo,
18
18
  type PrepareStepResult,
19
19
  type ProviderOptions,
20
- type StreamTextOnAbortCallback,
21
- type StreamTextOnErrorCallback,
22
- type StreamTextOnFinishCallback,
20
+ type WorkflowAgentOnAbortCallback,
21
+ type WorkflowAgentOnErrorCallback,
22
+ type WorkflowAgentOnFinishCallback,
23
+ type WorkflowAgentOnStepFinishCallback,
23
24
  type StreamTextTransform,
24
25
  type TelemetrySettings,
25
26
  type ToolCallRepairFunction,
@@ -6,19 +6,55 @@ export type MockResponseDescriptor =
6
6
 
7
7
  /**
8
8
  * Mock model that returns a fixed text response.
9
- * Same 'use step' pattern as real providers (anthropic, openai, etc.).
10
- * Only captures `text` (string) — fully serializable across step boundary.
11
9
  */
12
10
  export function mockTextModel(text: string) {
13
- return async () => {
14
- 'use step';
15
- // Bind closure var at step body level so SWC plugin detects it
16
- const _text = text;
17
- return mockProvider({
18
- doStream: async () => ({
19
- stream: new ReadableStream({
20
- start(c) {
21
- for (const v of [
11
+ return mockProvider({
12
+ doStream: async () => ({
13
+ stream: new ReadableStream({
14
+ start(c) {
15
+ for (const v of [
16
+ { type: 'stream-start', warnings: [] },
17
+ {
18
+ type: 'response-metadata',
19
+ id: 'r',
20
+ modelId: 'mock',
21
+ timestamp: new Date(),
22
+ },
23
+ { type: 'text-start', id: '1' },
24
+ { type: 'text-delta', id: '1', delta: text },
25
+ { type: 'text-end', id: '1' },
26
+ {
27
+ type: 'finish',
28
+ finishReason: { unified: 'stop', raw: 'stop' },
29
+ usage: {
30
+ inputTokens: { total: 5, noCache: 5 },
31
+ outputTokens: { total: 10, text: 10 },
32
+ },
33
+ },
34
+ ] as any[])
35
+ c.enqueue(v);
36
+ c.close();
37
+ },
38
+ }),
39
+ }),
40
+ });
41
+ }
42
+
43
+ /**
44
+ * Mock model that plays through a sequence of responses.
45
+ * Determines which response to return by counting assistant messages in the prompt.
46
+ */
47
+ export function mockSequenceModel(responses: MockResponseDescriptor[]) {
48
+ return mockProvider({
49
+ doStream: async (options: any) => {
50
+ const idx = Math.min(
51
+ options.prompt.filter((m: any) => m.role === 'assistant').length,
52
+ responses.length - 1,
53
+ );
54
+ const r = responses[idx];
55
+ const parts =
56
+ r.type === 'text'
57
+ ? [
22
58
  { type: 'stream-start', warnings: [] },
23
59
  {
24
60
  type: 'response-metadata',
@@ -27,7 +63,7 @@ export function mockTextModel(text: string) {
27
63
  timestamp: new Date(),
28
64
  },
29
65
  { type: 'text-start', id: '1' },
30
- { type: 'text-delta', id: '1', delta: _text },
66
+ { type: 'text-delta', id: '1', delta: r.text },
31
67
  { type: 'text-end', id: '1' },
32
68
  {
33
69
  type: 'finish',
@@ -37,87 +73,38 @@ export function mockTextModel(text: string) {
37
73
  outputTokens: { total: 10, text: 10 },
38
74
  },
39
75
  },
40
- ] as any[])
41
- c.enqueue(v);
76
+ ]
77
+ : [
78
+ { type: 'stream-start', warnings: [] },
79
+ {
80
+ type: 'response-metadata',
81
+ id: 'r',
82
+ modelId: 'mock',
83
+ timestamp: new Date(),
84
+ },
85
+ {
86
+ type: 'tool-call',
87
+ toolCallId: `call-${idx + 1}`,
88
+ toolName: r.toolName,
89
+ input: r.input,
90
+ },
91
+ {
92
+ type: 'finish',
93
+ finishReason: { unified: 'tool-calls', raw: undefined },
94
+ usage: {
95
+ inputTokens: { total: 5, noCache: 5 },
96
+ outputTokens: { total: 10, text: 10 },
97
+ },
98
+ },
99
+ ];
100
+ return {
101
+ stream: new ReadableStream({
102
+ start(c) {
103
+ for (const p of parts as any[]) c.enqueue(p);
42
104
  c.close();
43
105
  },
44
106
  }),
45
- }),
46
- });
47
- };
48
- }
49
-
50
- /**
51
- * Mock model that plays through a sequence of responses.
52
- * Determines which response to return by counting assistant messages in the prompt.
53
- * Only captures `responses` (array of plain objects) — fully serializable.
54
- */
55
- export function mockSequenceModel(responses: MockResponseDescriptor[]) {
56
- return async () => {
57
- 'use step';
58
- // Bind closure var at step body level so SWC plugin detects it
59
- const _responses = responses;
60
- return mockProvider({
61
- doStream: async (options: any) => {
62
- const idx = Math.min(
63
- options.prompt.filter((m: any) => m.role === 'assistant').length,
64
- _responses.length - 1,
65
- );
66
- const r = _responses[idx];
67
- const parts =
68
- r.type === 'text'
69
- ? [
70
- { type: 'stream-start', warnings: [] },
71
- {
72
- type: 'response-metadata',
73
- id: 'r',
74
- modelId: 'mock',
75
- timestamp: new Date(),
76
- },
77
- { type: 'text-start', id: '1' },
78
- { type: 'text-delta', id: '1', delta: r.text },
79
- { type: 'text-end', id: '1' },
80
- {
81
- type: 'finish',
82
- finishReason: { unified: 'stop', raw: 'stop' },
83
- usage: {
84
- inputTokens: { total: 5, noCache: 5 },
85
- outputTokens: { total: 10, text: 10 },
86
- },
87
- },
88
- ]
89
- : [
90
- { type: 'stream-start', warnings: [] },
91
- {
92
- type: 'response-metadata',
93
- id: 'r',
94
- modelId: 'mock',
95
- timestamp: new Date(),
96
- },
97
- {
98
- type: 'tool-call',
99
- toolCallId: `call-${idx + 1}`,
100
- toolName: r.toolName,
101
- input: r.input,
102
- },
103
- {
104
- type: 'finish',
105
- finishReason: { unified: 'tool-calls', raw: undefined },
106
- usage: {
107
- inputTokens: { total: 5, noCache: 5 },
108
- outputTokens: { total: 10, text: 10 },
109
- },
110
- },
111
- ];
112
- return {
113
- stream: new ReadableStream({
114
- start(c) {
115
- for (const p of parts as any[]) c.enqueue(p);
116
- c.close();
117
- },
118
- }),
119
- };
120
- },
121
- });
122
- };
107
+ };
108
+ },
109
+ });
123
110
  }
@@ -5,9 +5,9 @@ import type {
5
5
  } from '@ai-sdk/provider';
6
6
  import type {
7
7
  Experimental_LanguageModelStreamPart as ModelCallStreamPart,
8
+ LanguageModel,
8
9
  ModelMessage,
9
10
  StepResult,
10
- StreamTextOnStepFinishCallback,
11
11
  ToolCallRepairFunction,
12
12
  ToolChoice,
13
13
  ToolSet,
@@ -22,11 +22,11 @@ import { serializeToolSet } from './serializable-schema.js';
22
22
  import type {
23
23
  GenerationSettings,
24
24
  PrepareStepCallback,
25
- StreamTextOnErrorCallback,
25
+ WorkflowAgentOnErrorCallback,
26
+ WorkflowAgentOnStepFinishCallback,
26
27
  TelemetrySettings,
27
28
  WorkflowAgentOnStepStartCallback,
28
29
  } from './workflow-agent.js';
29
- import type { CompatibleLanguageModel } from './types.js';
30
30
 
31
31
  // Re-export for consumers
32
32
  export type { ProviderExecutedToolResult } from './do-stream-step.js';
@@ -71,15 +71,12 @@ export async function* streamTextIterator({
71
71
  prompt: LanguageModelV4Prompt;
72
72
  tools: ToolSet;
73
73
  writable?: WritableStream<ModelCallStreamPart<ToolSet>>;
74
- model:
75
- | string
76
- | CompatibleLanguageModel
77
- | (() => Promise<CompatibleLanguageModel>);
74
+ model: LanguageModel;
78
75
  stopConditions?: ModelStopCondition[] | ModelStopCondition;
79
76
  maxSteps?: number;
80
- onStepFinish?: StreamTextOnStepFinishCallback<any, any>;
77
+ onStepFinish?: WorkflowAgentOnStepFinishCallback<any>;
81
78
  onStepStart?: WorkflowAgentOnStepStartCallback;
82
- onError?: StreamTextOnErrorCallback;
79
+ onError?: WorkflowAgentOnErrorCallback;
83
80
  prepareStep?: PrepareStepCallback<any>;
84
81
  generationSettings?: GenerationSettings;
85
82
  toolChoice?: ToolChoice<ToolSet>;
@@ -94,10 +91,7 @@ export async function* streamTextIterator({
94
91
  LanguageModelV4ToolResultPart[]
95
92
  > {
96
93
  let conversationPrompt = [...prompt]; // Create a mutable copy
97
- let currentModel:
98
- | string
99
- | CompatibleLanguageModel
100
- | (() => Promise<CompatibleLanguageModel>) = model;
94
+ let currentModel: LanguageModel = model;
101
95
  let currentGenerationSettings = generationSettings ?? {};
102
96
  let currentToolChoice = toolChoice;
103
97
  let currentContext = experimental_context;
@@ -21,6 +21,7 @@ import {
21
21
  type ToolChoice,
22
22
  type ToolSet,
23
23
  type UIMessage,
24
+ LanguageModel,
24
25
  } from 'ai';
25
26
  import {
26
27
  convertToLanguageModelPrompt,
@@ -34,6 +35,15 @@ import type { CompatibleLanguageModel } from './types.js';
34
35
  // Re-export for consumers
35
36
  export type { CompatibleLanguageModel } from './types.js';
36
37
 
38
+ /**
39
+ * Callback function to be called after each step completes.
40
+ * Alias for the AI SDK's StreamTextOnStepFinishCallback, using
41
+ * WorkflowAgent-consistent naming.
42
+ */
43
+ export type WorkflowAgentOnStepFinishCallback<
44
+ TTools extends ToolSet = ToolSet,
45
+ > = StreamTextOnStepFinishCallback<TTools, any>;
46
+
37
47
  /**
38
48
  * Infer the type of the tools of a workflow agent.
39
49
  */
@@ -248,10 +258,7 @@ export interface PrepareStepInfo<TTools extends ToolSet = ToolSet> {
248
258
  * The current model configuration (string or function).
249
259
  * The function should return a LanguageModelV4 instance.
250
260
  */
251
- model:
252
- | string
253
- | CompatibleLanguageModel
254
- | (() => Promise<CompatibleLanguageModel>);
261
+ model: LanguageModel;
255
262
 
256
263
  /**
257
264
  * The current step number (0-indexed).
@@ -282,12 +289,8 @@ export interface PrepareStepInfo<TTools extends ToolSet = ToolSet> {
282
289
  export interface PrepareStepResult extends Partial<GenerationSettings> {
283
290
  /**
284
291
  * Override the model for this step.
285
- * The function should return a LanguageModelV4 instance.
286
292
  */
287
- model?:
288
- | string
289
- | CompatibleLanguageModel
290
- | (() => Promise<CompatibleLanguageModel>);
293
+ model?: LanguageModel;
291
294
 
292
295
  /**
293
296
  * Override the system message for this step.
@@ -332,10 +335,7 @@ export type PrepareStepCallback<TTools extends ToolSet = ToolSet> = (
332
335
  export interface PrepareCallOptions<
333
336
  TTools extends ToolSet = ToolSet,
334
337
  > extends Partial<GenerationSettings> {
335
- model:
336
- | string
337
- | CompatibleLanguageModel
338
- | (() => Promise<CompatibleLanguageModel>);
338
+ model: LanguageModel;
339
339
  tools: TTools;
340
340
  instructions?: string | SystemModelMessage | Array<SystemModelMessage>;
341
341
  toolChoice?: ToolChoice<TTools>;
@@ -371,12 +371,9 @@ export interface WorkflowAgentOptions<
371
371
  * The model provider to use for the agent.
372
372
  *
373
373
  * This should be a string compatible with the Vercel AI Gateway (e.g., 'anthropic/claude-opus'),
374
- * or a step function that returns a LanguageModelV4 instance.
374
+ * or a LanguageModelV4 instance from a provider.
375
375
  */
376
- model:
377
- | string
378
- | CompatibleLanguageModel
379
- | (() => Promise<CompatibleLanguageModel>);
376
+ model: LanguageModel;
380
377
 
381
378
  /**
382
379
  * A set of tools available to the agent.
@@ -428,12 +425,12 @@ export interface WorkflowAgentOptions<
428
425
  /**
429
426
  * Callback function to be called after each step completes.
430
427
  */
431
- onStepFinish?: StreamTextOnStepFinishCallback<ToolSet, any>;
428
+ onStepFinish?: WorkflowAgentOnStepFinishCallback<ToolSet>;
432
429
 
433
430
  /**
434
431
  * Callback that is called when the LLM response and all request tool executions are finished.
435
432
  */
436
- onFinish?: StreamTextOnFinishCallback<ToolSet>;
433
+ onFinish?: WorkflowAgentOnFinishCallback<ToolSet>;
437
434
 
438
435
  /**
439
436
  * Callback called when the agent starts streaming, before any LLM calls.
@@ -466,7 +463,7 @@ export interface WorkflowAgentOptions<
466
463
  /**
467
464
  * Callback that is called when the LLM response and all request tool executions are finished.
468
465
  */
469
- export type StreamTextOnFinishCallback<
466
+ export type WorkflowAgentOnFinishCallback<
470
467
  TTools extends ToolSet = ToolSet,
471
468
  OUTPUT = never,
472
469
  > = (event: {
@@ -510,14 +507,14 @@ export type StreamTextOnFinishCallback<
510
507
  /**
511
508
  * Callback that is invoked when an error occurs during streaming.
512
509
  */
513
- export type StreamTextOnErrorCallback = (event: {
510
+ export type WorkflowAgentOnErrorCallback = (event: {
514
511
  error: unknown;
515
512
  }) => PromiseLike<void> | void;
516
513
 
517
514
  /**
518
515
  * Callback that is set using the `onAbort` option.
519
516
  */
520
- export type StreamTextOnAbortCallback<TTools extends ToolSet = ToolSet> =
517
+ export type WorkflowAgentOnAbortCallback<TTools extends ToolSet = ToolSet> =
521
518
  (event: {
522
519
  /**
523
520
  * Details for all previously finished steps.
@@ -530,10 +527,7 @@ export type StreamTextOnAbortCallback<TTools extends ToolSet = ToolSet> =
530
527
  */
531
528
  export type WorkflowAgentOnStartCallback = (event: {
532
529
  /** The model being used */
533
- readonly model:
534
- | string
535
- | CompatibleLanguageModel
536
- | (() => Promise<CompatibleLanguageModel>);
530
+ readonly model: LanguageModel;
537
531
  /** The messages being sent */
538
532
  readonly messages: ModelMessage[];
539
533
  }) => PromiseLike<void> | void;
@@ -545,10 +539,7 @@ export type WorkflowAgentOnStepStartCallback = (event: {
545
539
  /** The current step number (0-based) */
546
540
  readonly stepNumber: number;
547
541
  /** The model being used for this step */
548
- readonly model:
549
- | string
550
- | CompatibleLanguageModel
551
- | (() => Promise<CompatibleLanguageModel>);
542
+ readonly model: LanguageModel;
552
543
  /** The messages being sent for this step */
553
544
  readonly messages: ModelMessage[];
554
545
  }) => PromiseLike<void> | void;
@@ -710,24 +701,24 @@ export interface WorkflowAgentStreamOptions<
710
701
  /**
711
702
  * Callback function to be called after each step completes.
712
703
  */
713
- onStepFinish?: StreamTextOnStepFinishCallback<TTools, any>;
704
+ onStepFinish?: WorkflowAgentOnStepFinishCallback<TTools>;
714
705
 
715
706
  /**
716
707
  * Callback that is invoked when an error occurs during streaming.
717
708
  * You can use it to log errors.
718
709
  */
719
- onError?: StreamTextOnErrorCallback;
710
+ onError?: WorkflowAgentOnErrorCallback;
720
711
 
721
712
  /**
722
713
  * Callback that is called when the LLM response and all request tool executions
723
714
  * (for tools that have an `execute` function) are finished.
724
715
  */
725
- onFinish?: StreamTextOnFinishCallback<TTools, OUTPUT>;
716
+ onFinish?: WorkflowAgentOnFinishCallback<TTools, OUTPUT>;
726
717
 
727
718
  /**
728
719
  * Callback that is called when the operation is aborted.
729
720
  */
730
- onAbort?: StreamTextOnAbortCallback<TTools>;
721
+ onAbort?: WorkflowAgentOnAbortCallback<TTools>;
731
722
 
732
723
  /**
733
724
  * Callback called when the agent starts streaming, before any LLM calls.
@@ -898,10 +889,7 @@ export interface WorkflowAgentStreamResult<
898
889
  * ```
899
890
  */
900
891
  export class WorkflowAgent<TBaseTools extends ToolSet = ToolSet> {
901
- private model:
902
- | string
903
- | CompatibleLanguageModel
904
- | (() => Promise<CompatibleLanguageModel>);
892
+ private model: LanguageModel;
905
893
  /**
906
894
  * The tool set configured for this agent.
907
895
  */
@@ -915,11 +903,8 @@ export class WorkflowAgent<TBaseTools extends ToolSet = ToolSet> {
915
903
  private telemetry?: TelemetrySettings;
916
904
  private experimentalContext: unknown;
917
905
  private prepareStep?: PrepareStepCallback<TBaseTools>;
918
- private constructorOnStepFinish?: StreamTextOnStepFinishCallback<
919
- ToolSet,
920
- any
921
- >;
922
- private constructorOnFinish?: StreamTextOnFinishCallback<ToolSet>;
906
+ private constructorOnStepFinish?: WorkflowAgentOnStepFinishCallback<ToolSet>;
907
+ private constructorOnFinish?: WorkflowAgentOnFinishCallback<ToolSet>;
923
908
  private constructorOnStart?: WorkflowAgentOnStartCallback;
924
909
  private constructorOnStepStart?: WorkflowAgentOnStepStartCallback;
925
910
  private constructorOnToolCallStart?: WorkflowAgentOnToolCallStartCallback;
@@ -972,10 +957,7 @@ export class WorkflowAgent<TBaseTools extends ToolSet = ToolSet> {
972
957
  options: WorkflowAgentStreamOptions<TTools, OUTPUT, PARTIAL_OUTPUT>,
973
958
  ): Promise<WorkflowAgentStreamResult<TTools, OUTPUT>> {
974
959
  // Call prepareCall to transform parameters before the agent loop
975
- let effectiveModel:
976
- | string
977
- | CompatibleLanguageModel
978
- | (() => Promise<CompatibleLanguageModel>) = this.model;
960
+ let effectiveModel: LanguageModel = this.model;
979
961
  let effectiveInstructions = options.system ?? this.instructions;
980
962
  let effectiveMessages = options.messages;
981
963
  let effectiveGenerationSettings = { ...this.generationSettings };
@@ -1210,13 +1192,13 @@ export class WorkflowAgent<TBaseTools extends ToolSet = ToolSet> {
1210
1192
  // Merge constructor + stream callbacks (constructor first, then stream)
1211
1193
  const mergedOnStepFinish = mergeCallbacks(
1212
1194
  this.constructorOnStepFinish as
1213
- | StreamTextOnStepFinishCallback<TTools, any>
1195
+ | WorkflowAgentOnStepFinishCallback<TTools>
1214
1196
  | undefined,
1215
1197
  options.onStepFinish,
1216
1198
  );
1217
1199
  const mergedOnFinish = mergeCallbacks(
1218
1200
  this.constructorOnFinish as
1219
- | StreamTextOnFinishCallback<TTools, OUTPUT>
1201
+ | WorkflowAgentOnFinishCallback<TTools, OUTPUT>
1220
1202
  | undefined,
1221
1203
  options.onFinish,
1222
1204
  );