@ai-sdk/workflow 1.0.0-beta.3 → 1.0.0-beta.31

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.3",
3
+ "version": "1.0.0-beta.31",
4
4
  "description": "WorkflowAgent for building AI agents with AI SDK",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.js",
@@ -27,9 +27,9 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "ajv": "^8.18.0",
30
- "@ai-sdk/provider": "4.0.0-beta.12",
31
- "@ai-sdk/provider-utils": "5.0.0-beta.20",
32
- "ai": "7.0.0-beta.91"
30
+ "@ai-sdk/provider": "4.0.0-beta.14",
31
+ "ai": "7.0.0-beta.116",
32
+ "@ai-sdk/provider-utils": "5.0.0-beta.30"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "20.17.24",
@@ -47,12 +47,14 @@
47
47
  "node": ">=18"
48
48
  },
49
49
  "publishConfig": {
50
- "access": "public"
50
+ "access": "public",
51
+ "provenance": true
51
52
  },
52
53
  "homepage": "https://ai-sdk.dev/docs",
53
54
  "repository": {
54
55
  "type": "git",
55
- "url": "git+https://github.com/vercel/ai.git"
56
+ "url": "https://github.com/vercel/ai",
57
+ "directory": "packages/workflow"
56
58
  },
57
59
  "bugs": {
58
60
  "url": "https://github.com/vercel/ai/issues"
@@ -3,8 +3,9 @@ import type {
3
3
  LanguageModelV4Prompt,
4
4
  } from '@ai-sdk/provider';
5
5
  import {
6
- type Experimental_LanguageModelStreamPart as ModelCallStreamPart,
7
6
  experimental_streamLanguageModelCall as streamModelCall,
7
+ gateway,
8
+ type Experimental_LanguageModelStreamPart as ModelCallStreamPart,
8
9
  type FinishReason,
9
10
  type LanguageModel,
10
11
  type LanguageModelUsage,
@@ -15,13 +16,11 @@ import {
15
16
  type ToolChoice,
16
17
  type ToolSet,
17
18
  } from 'ai';
18
- import { gateway } from 'ai';
19
- import type { ProviderOptions, TelemetrySettings } from './workflow-agent.js';
19
+ import type { ProviderOptions, TelemetryOptions } from './workflow-agent.js';
20
20
  import {
21
21
  resolveSerializableTools,
22
22
  type SerializableToolDef,
23
23
  } from './serializable-schema.js';
24
-
25
24
  export type { Experimental_LanguageModelStreamPart as ModelCallStreamPart } from 'ai';
26
25
 
27
26
  export type ModelStopCondition = StopCondition<NoInfer<ToolSet>, any>;
@@ -54,7 +53,7 @@ export interface DoStreamStepOptions {
54
53
  providerOptions?: ProviderOptions;
55
54
  toolChoice?: ToolChoice<ToolSet>;
56
55
  includeRawChunks?: boolean;
57
- experimental_telemetry?: TelemetrySettings;
56
+ telemetry?: TelemetryOptions;
58
57
  repairToolCall?: ToolCallRepairFunction<ToolSet>;
59
58
  responseFormat?: LanguageModelV4CallOptions['responseFormat'];
60
59
  }
@@ -115,6 +114,7 @@ export async function doStreamStep(
115
114
  // pre-converted LanguageModelV4Prompt. standardizePrompt inside
116
115
  // streamModelCall handles both formats.
117
116
  messages: conversationPrompt as unknown as ModelMessage[],
117
+ allowSystemInMessages: true,
118
118
  tools,
119
119
  toolChoice: options?.toolChoice,
120
120
  includeRawChunks: options?.includeRawChunks,
@@ -241,7 +241,8 @@ export async function doStreamStep(
241
241
  },
242
242
  functionId: undefined,
243
243
  metadata: undefined,
244
- context: undefined,
244
+ runtimeContext: undefined,
245
+ toolsContext: {},
245
246
  content: [
246
247
  ...(text ? [{ type: 'text' as const, text }] : []),
247
248
  ...toolCalls
package/src/index.ts CHANGED
@@ -22,12 +22,12 @@ export {
22
22
  type WorkflowAgentOnFinishCallback,
23
23
  type WorkflowAgentOnStepFinishCallback,
24
24
  type StreamTextTransform,
25
- type TelemetrySettings,
25
+ type TelemetryOptions,
26
26
  type ToolCallRepairFunction,
27
27
  type WorkflowAgentOnStartCallback,
28
28
  type WorkflowAgentOnStepStartCallback,
29
- type WorkflowAgentOnToolCallStartCallback,
30
- type WorkflowAgentOnToolCallFinishCallback,
29
+ type WorkflowAgentOnToolExecutionStartCallback,
30
+ type WorkflowAgentOnToolExecutionEndCallback,
31
31
  } from './workflow-agent.js';
32
32
 
33
33
  export {
@@ -23,6 +23,8 @@ export type SerializableToolDef = {
23
23
  inputSchema: JSONSchema7;
24
24
  /** Present on provider tools (e.g. anthropic.tools.webSearch). */
25
25
  type?: 'provider';
26
+ /** Provider tool is executed by the provider. */
27
+ isProviderExecuted?: boolean;
26
28
  /** Provider tool ID, e.g. 'anthropic.web_search_20250305'. */
27
29
  id?: `${string}.${string}`;
28
30
  /** Provider tool configuration args (maxUses, allowedDomains, etc.). */
@@ -49,6 +51,7 @@ export function serializeToolSet(
49
51
  // them as provider-executed tools (e.g. anthropic webSearch).
50
52
  if ((t as any).type === 'provider') {
51
53
  def.type = 'provider';
54
+ def.isProviderExecuted = (t as any).isProviderExecuted ?? false;
52
55
  def.id = (t as any).id;
53
56
  def.args = (t as any).args;
54
57
  }
@@ -81,6 +84,7 @@ export function resolveSerializableTools(
81
84
  type: 'provider' as const,
82
85
  id: t.id!,
83
86
  args: t.args ?? {},
87
+ isProviderExecuted: t.isProviderExecuted ?? false,
84
88
  inputSchema: jsonSchema(t.inputSchema),
85
89
  }),
86
90
  ];
@@ -3,14 +3,15 @@ import type {
3
3
  LanguageModelV4Prompt,
4
4
  LanguageModelV4ToolResultPart,
5
5
  } from '@ai-sdk/provider';
6
- import type {
7
- Experimental_LanguageModelStreamPart as ModelCallStreamPart,
8
- LanguageModel,
9
- ModelMessage,
10
- StepResult,
11
- ToolCallRepairFunction,
12
- ToolChoice,
13
- ToolSet,
6
+ import {
7
+ experimental_filterActiveTools as filterActiveTools,
8
+ type Experimental_LanguageModelStreamPart as ModelCallStreamPart,
9
+ type LanguageModel,
10
+ type ModelMessage,
11
+ type StepResult,
12
+ type ToolCallRepairFunction,
13
+ type ToolChoice,
14
+ type ToolSet,
14
15
  } from 'ai';
15
16
  import {
16
17
  doStreamStep,
@@ -24,7 +25,7 @@ import type {
24
25
  PrepareStepCallback,
25
26
  WorkflowAgentOnErrorCallback,
26
27
  WorkflowAgentOnStepFinishCallback,
27
- TelemetrySettings,
28
+ TelemetryOptions,
28
29
  WorkflowAgentOnStepStartCallback,
29
30
  } from './workflow-agent.js';
30
31
 
@@ -55,7 +56,6 @@ export async function* streamTextIterator({
55
56
  writable,
56
57
  model,
57
58
  stopConditions,
58
- maxSteps,
59
59
  onStepFinish,
60
60
  onStepStart,
61
61
  onError,
@@ -63,7 +63,7 @@ export async function* streamTextIterator({
63
63
  generationSettings,
64
64
  toolChoice,
65
65
  experimental_context,
66
- experimental_telemetry,
66
+ telemetry,
67
67
  includeRawChunks = false,
68
68
  repairToolCall,
69
69
  responseFormat,
@@ -73,7 +73,6 @@ export async function* streamTextIterator({
73
73
  writable?: WritableStream<ModelCallStreamPart<ToolSet>>;
74
74
  model: LanguageModel;
75
75
  stopConditions?: ModelStopCondition[] | ModelStopCondition;
76
- maxSteps?: number;
77
76
  onStepFinish?: WorkflowAgentOnStepFinishCallback<any>;
78
77
  onStepStart?: WorkflowAgentOnStepStartCallback;
79
78
  onError?: WorkflowAgentOnErrorCallback;
@@ -81,7 +80,7 @@ export async function* streamTextIterator({
81
80
  generationSettings?: GenerationSettings;
82
81
  toolChoice?: ToolChoice<ToolSet>;
83
82
  experimental_context?: unknown;
84
- experimental_telemetry?: TelemetrySettings;
83
+ telemetry?: TelemetryOptions;
85
84
  includeRawChunks?: boolean;
86
85
  repairToolCall?: ToolCallRepairFunction<ToolSet>;
87
86
  responseFormat?: LanguageModelV4CallOptions['responseFormat'];
@@ -104,16 +103,7 @@ export async function* streamTextIterator({
104
103
  let lastStep: StepResult<any, any> | undefined;
105
104
  let lastStepWasToolCalls = false;
106
105
 
107
- // Default maxSteps to Infinity to preserve backwards compatibility
108
- // (agent loops until completion unless explicitly limited)
109
- const effectiveMaxSteps = maxSteps ?? Infinity;
110
-
111
106
  while (!done) {
112
- // Check if we've exceeded the maximum number of steps
113
- if (stepNumber >= effectiveMaxSteps) {
114
- break;
115
- }
116
-
117
107
  // Check for abort signal
118
108
  if (currentGenerationSettings.abortSignal?.aborted) {
119
109
  break;
@@ -242,6 +232,7 @@ export async function* streamTextIterator({
242
232
  stepNumber,
243
233
  model: currentModel,
244
234
  messages: conversationPrompt as unknown as ModelMessage[],
235
+ steps: [...steps],
245
236
  });
246
237
  }
247
238
 
@@ -249,7 +240,10 @@ export async function* streamTextIterator({
249
240
  // Filter tools if activeTools is specified
250
241
  const effectiveTools =
251
242
  currentActiveTools && currentActiveTools.length > 0
252
- ? filterToolSet(tools, currentActiveTools)
243
+ ? (filterActiveTools({
244
+ tools,
245
+ activeTools: currentActiveTools,
246
+ }) ?? tools)
253
247
  : tools;
254
248
 
255
249
  // Serialize tools before crossing the step boundary — zod schemas
@@ -267,7 +261,7 @@ export async function* streamTextIterator({
267
261
  ...currentGenerationSettings,
268
262
  toolChoice: currentToolChoice,
269
263
  includeRawChunks,
270
- experimental_telemetry,
264
+ telemetry,
271
265
  repairToolCall,
272
266
  responseFormat,
273
267
  },
@@ -393,19 +387,6 @@ export async function* streamTextIterator({
393
387
  return conversationPrompt;
394
388
  }
395
389
 
396
- /**
397
- * Filter a tool set to only include the specified active tools.
398
- */
399
- function filterToolSet(tools: ToolSet, activeTools: string[]): ToolSet {
400
- const filtered: ToolSet = {};
401
- for (const toolName of activeTools) {
402
- if (toolName in tools) {
403
- filtered[toolName] = tools[toolName];
404
- }
405
- }
406
- return filtered;
407
- }
408
-
409
390
  /**
410
391
  * Strip OpenAI's itemId from providerMetadata (requires reasoning items we don't preserve).
411
392
  * Preserves all other provider metadata (e.g., Gemini's thoughtSignature).
package/src/telemetry.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { TelemetrySettings } from './workflow-agent.js';
1
+ import type { TelemetryOptions } from './workflow-agent.js';
2
2
 
3
3
  // Minimal OTel type shims so we don't depend on @opentelemetry/api at compile time.
4
4
  type Attributes = Record<string, unknown>;
@@ -62,7 +62,7 @@ async function ensureOtelApi(): Promise<OtelApi | null> {
62
62
  * Returns a no-op–equivalent `null` when telemetry is disabled, so callers
63
63
  * don't need a separate init step.
64
64
  */
65
- function getTracer(telemetry?: TelemetrySettings): Tracer | null {
65
+ function getTracer(telemetry?: TelemetryOptions): Tracer | null {
66
66
  if (!telemetry?.isEnabled || !otelApi) return null;
67
67
  if (telemetry.tracer) return telemetry.tracer as Tracer;
68
68
  return otelApi.trace.getTracer('ai');
@@ -76,7 +76,7 @@ function getTracer(telemetry?: TelemetrySettings): Tracer | null {
76
76
  */
77
77
  function assembleOperationName(
78
78
  operationId: string,
79
- telemetry?: TelemetrySettings,
79
+ telemetry?: TelemetryOptions,
80
80
  ): Attributes {
81
81
  return {
82
82
  'operation.name': `${operationId}${
@@ -94,7 +94,7 @@ function assembleOperationName(
94
94
  */
95
95
  function buildAttributes(
96
96
  operationId: string,
97
- telemetry: TelemetrySettings | undefined,
97
+ telemetry: TelemetryOptions | undefined,
98
98
  extra?: Attributes,
99
99
  ): Attributes {
100
100
  if (!telemetry?.isEnabled) return {};
@@ -154,7 +154,7 @@ function recordErrorOnSpan(span: Span, error: unknown): void {
154
154
  */
155
155
  export async function recordSpan<T>(options: {
156
156
  name: string;
157
- telemetry?: TelemetrySettings;
157
+ telemetry?: TelemetryOptions;
158
158
  attributes?: Attributes;
159
159
  fn: (span?: Span) => PromiseLike<T> | T;
160
160
  }): Promise<T> {
@@ -5,7 +5,7 @@ import { tool } from 'ai';
5
5
  import { WorkflowAgent } from '../workflow-agent.js';
6
6
  import { mockTextModel, mockSequenceModel } from '../providers/mock.js';
7
7
  import { FatalError, getWritable } from 'workflow';
8
- import z from 'zod';
8
+ import { z } from 'zod';
9
9
 
10
10
  // ============================================================================
11
11
  // Tool step functions
@@ -334,10 +334,10 @@ export async function agentOnStepStartE2e() {
334
334
  }
335
335
 
336
336
  // ============================================================================
337
- // GAP tests — experimental_onToolCallStart
337
+ // GAP tests — experimental_onToolExecutionStart
338
338
  // ============================================================================
339
339
 
340
- export async function agentOnToolCallStartE2e() {
340
+ export async function agentonToolExecutionStartE2e() {
341
341
  'use workflow';
342
342
  const calls: string[] = [];
343
343
  const agent = new WorkflowAgent({
@@ -356,14 +356,14 @@ export async function agentOnToolCallStartE2e() {
356
356
  execute: echoStep,
357
357
  },
358
358
  },
359
- experimental_onToolCallStart: async () => {
359
+ experimental_onToolExecutionStart: async () => {
360
360
  calls.push('constructor');
361
361
  },
362
362
  } as any);
363
363
  await agent.stream({
364
364
  messages: [{ role: 'user', content: 'test' }],
365
365
  writable: getWritable(),
366
- experimental_onToolCallStart: async () => {
366
+ experimental_onToolExecutionStart: async () => {
367
367
  calls.push('method');
368
368
  },
369
369
  } as any);
@@ -371,10 +371,10 @@ export async function agentOnToolCallStartE2e() {
371
371
  }
372
372
 
373
373
  // ============================================================================
374
- // GAP tests — experimental_onToolCallFinish
374
+ // GAP tests — experimental_onToolExecutionEnd
375
375
  // ============================================================================
376
376
 
377
- export async function agentOnToolCallFinishE2e() {
377
+ export async function agentonToolExecutionEndE2e() {
378
378
  'use workflow';
379
379
  const calls: string[] = [];
380
380
  let capturedEvent: any = null;
@@ -394,14 +394,14 @@ export async function agentOnToolCallFinishE2e() {
394
394
  execute: addNumbers,
395
395
  },
396
396
  },
397
- experimental_onToolCallFinish: async () => {
397
+ experimental_onToolExecutionEnd: async () => {
398
398
  calls.push('constructor');
399
399
  },
400
400
  } as any);
401
401
  await agent.stream({
402
402
  messages: [{ role: 'user', content: 'test' }],
403
403
  writable: getWritable(),
404
- experimental_onToolCallFinish: async (event: any) => {
404
+ experimental_onToolExecutionEnd: async (event: any) => {
405
405
  calls.push('method');
406
406
  capturedEvent = {
407
407
  toolName: event?.toolCall?.toolName,
@@ -1,5 +1,8 @@
1
- import { type ToolSet, type UIMessageChunk } from 'ai';
2
- import type { Experimental_LanguageModelStreamPart as ModelCallStreamPart } from 'ai';
1
+ import type {
2
+ Experimental_LanguageModelStreamPart as ModelCallStreamPart,
3
+ ToolSet,
4
+ UIMessageChunk,
5
+ } from 'ai';
3
6
 
4
7
  /**
5
8
  * Convert a single ModelCallStreamPart to a UIMessageChunk.