@ai-sdk/workflow 1.0.38 → 1.0.40
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/CHANGELOG.md +21 -0
- package/dist/index.d.ts +19 -2
- package/dist/index.js +117 -120
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/serializable-schema.ts +43 -4
- package/src/stream-text-iterator.ts +45 -74
- package/src/workflow-agent.ts +44 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/workflow",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.40",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "WorkflowAgent for building AI agents with AI SDK",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"ajv": "^8.20.0",
|
|
30
30
|
"@ai-sdk/provider": "4.0.4",
|
|
31
|
-
"
|
|
32
|
-
"ai": "
|
|
31
|
+
"ai": "7.0.40",
|
|
32
|
+
"@ai-sdk/provider-utils": "5.0.14"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "22.19.19",
|
|
@@ -11,7 +11,13 @@
|
|
|
11
11
|
* to use that interface directly.
|
|
12
12
|
*/
|
|
13
13
|
import type { JSONSchema7 } from '@ai-sdk/provider';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
asSchema,
|
|
16
|
+
type Experimental_SandboxSession as SandboxSession,
|
|
17
|
+
type InferToolSetContext,
|
|
18
|
+
jsonSchema,
|
|
19
|
+
type Tool,
|
|
20
|
+
} from '@ai-sdk/provider-utils';
|
|
15
21
|
import { tool, type ToolSet } from 'ai';
|
|
16
22
|
import Ajv from 'ajv';
|
|
17
23
|
|
|
@@ -37,13 +43,25 @@ export type SerializableToolDef = {
|
|
|
37
43
|
* (as JSON Schema) are preserved — execute functions are stripped since they
|
|
38
44
|
* run outside the step.
|
|
39
45
|
*/
|
|
40
|
-
export function serializeToolSet(
|
|
41
|
-
tools:
|
|
46
|
+
export function serializeToolSet<TOOLS extends ToolSet>(
|
|
47
|
+
tools: TOOLS,
|
|
48
|
+
{
|
|
49
|
+
toolsContext = {} as InferToolSetContext<TOOLS>,
|
|
50
|
+
experimental_sandbox: sandbox,
|
|
51
|
+
}: {
|
|
52
|
+
toolsContext?: InferToolSetContext<TOOLS>;
|
|
53
|
+
experimental_sandbox?: SandboxSession;
|
|
54
|
+
} = {},
|
|
42
55
|
): Record<string, SerializableToolDef> {
|
|
43
56
|
return Object.fromEntries(
|
|
44
57
|
Object.entries(tools).map(([name, t]) => {
|
|
45
58
|
const def: SerializableToolDef = {
|
|
46
|
-
description:
|
|
59
|
+
description: resolveToolDescription({
|
|
60
|
+
tool: t,
|
|
61
|
+
toolName: name,
|
|
62
|
+
toolsContext,
|
|
63
|
+
experimental_sandbox: sandbox,
|
|
64
|
+
}),
|
|
47
65
|
inputSchema: asSchema(t.inputSchema).jsonSchema as JSONSchema7,
|
|
48
66
|
};
|
|
49
67
|
|
|
@@ -61,6 +79,27 @@ export function serializeToolSet(
|
|
|
61
79
|
);
|
|
62
80
|
}
|
|
63
81
|
|
|
82
|
+
function resolveToolDescription<TOOLS extends ToolSet>({
|
|
83
|
+
tool,
|
|
84
|
+
toolName,
|
|
85
|
+
toolsContext,
|
|
86
|
+
experimental_sandbox: sandbox,
|
|
87
|
+
}: {
|
|
88
|
+
tool: Tool;
|
|
89
|
+
toolName: string;
|
|
90
|
+
toolsContext: InferToolSetContext<TOOLS>;
|
|
91
|
+
experimental_sandbox?: SandboxSession;
|
|
92
|
+
}): string | undefined {
|
|
93
|
+
return tool.description === undefined
|
|
94
|
+
? undefined
|
|
95
|
+
: typeof tool.description === 'string'
|
|
96
|
+
? tool.description
|
|
97
|
+
: tool.description({
|
|
98
|
+
context: toolsContext[toolName as keyof InferToolSetContext<TOOLS>],
|
|
99
|
+
experimental_sandbox: sandbox,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
64
103
|
/**
|
|
65
104
|
* Reconstructs tool objects from serializable tool definitions inside a step.
|
|
66
105
|
*
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
experimental_filterActiveTools as filterActiveTools,
|
|
10
10
|
type Experimental_LanguageModelStreamPart as ModelCallStreamPart,
|
|
11
11
|
type Experimental_SandboxSession as SandboxSession,
|
|
12
|
+
type Instructions,
|
|
12
13
|
type LanguageModel,
|
|
13
14
|
type LanguageModelUsage,
|
|
14
15
|
type ModelMessage,
|
|
@@ -40,6 +41,36 @@ import type {
|
|
|
40
41
|
// Re-export for consumers
|
|
41
42
|
export type { ProviderExecutedToolResult } from './do-stream-step.js';
|
|
42
43
|
|
|
44
|
+
const prepareStepGenerationSettingKeys = [
|
|
45
|
+
'maxOutputTokens',
|
|
46
|
+
'temperature',
|
|
47
|
+
'topP',
|
|
48
|
+
'topK',
|
|
49
|
+
'presencePenalty',
|
|
50
|
+
'frequencyPenalty',
|
|
51
|
+
'stopSequences',
|
|
52
|
+
'seed',
|
|
53
|
+
'maxRetries',
|
|
54
|
+
'headers',
|
|
55
|
+
'reasoning',
|
|
56
|
+
'providerOptions',
|
|
57
|
+
] as const satisfies readonly (keyof GenerationSettings)[];
|
|
58
|
+
|
|
59
|
+
function mergePrepareStepGenerationSettings(
|
|
60
|
+
current: GenerationSettings,
|
|
61
|
+
overrides: Partial<GenerationSettings>,
|
|
62
|
+
): GenerationSettings {
|
|
63
|
+
const definedOverrides: Partial<GenerationSettings> = {};
|
|
64
|
+
|
|
65
|
+
for (const key of prepareStepGenerationSettingKeys) {
|
|
66
|
+
if (overrides[key] !== undefined) {
|
|
67
|
+
Object.assign(definedOverrides, { [key]: overrides[key] });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return { ...current, ...definedOverrides };
|
|
72
|
+
}
|
|
73
|
+
|
|
43
74
|
/**
|
|
44
75
|
* The value yielded by the stream text iterator when tool calls are requested.
|
|
45
76
|
* Contains both the tool calls and the current conversation messages.
|
|
@@ -64,6 +95,8 @@ export interface StreamTextIteratorYieldValue {
|
|
|
64
95
|
// This runs in the workflow context
|
|
65
96
|
export async function* streamTextIterator({
|
|
66
97
|
prompt,
|
|
98
|
+
initialInstructions,
|
|
99
|
+
initialMessages = prompt as unknown as ModelMessage[],
|
|
67
100
|
tools = {},
|
|
68
101
|
writable,
|
|
69
102
|
model,
|
|
@@ -84,6 +117,8 @@ export async function* streamTextIterator({
|
|
|
84
117
|
experimental_sandbox: sandbox,
|
|
85
118
|
}: {
|
|
86
119
|
prompt: LanguageModelV4Prompt;
|
|
120
|
+
initialInstructions?: Instructions;
|
|
121
|
+
initialMessages?: Array<ModelMessage>;
|
|
87
122
|
tools: ToolSet;
|
|
88
123
|
writable?: WritableStream<ModelCallStreamPart<ToolSet>>;
|
|
89
124
|
model: LanguageModel;
|
|
@@ -150,6 +185,8 @@ export async function* streamTextIterator({
|
|
|
150
185
|
if (prepareStep) {
|
|
151
186
|
const prepareResult = await prepareStep({
|
|
152
187
|
model: currentModel,
|
|
188
|
+
initialInstructions,
|
|
189
|
+
initialMessages,
|
|
153
190
|
stepNumber,
|
|
154
191
|
steps,
|
|
155
192
|
messages: conversationPrompt,
|
|
@@ -202,79 +239,10 @@ export async function* streamTextIterator({
|
|
|
202
239
|
if (prepareResult?.activeTools !== undefined) {
|
|
203
240
|
currentActiveTools = prepareResult.activeTools;
|
|
204
241
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
maxOutputTokens: prepareResult.maxOutputTokens,
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
if (prepareResult?.temperature !== undefined) {
|
|
213
|
-
currentGenerationSettings = {
|
|
214
|
-
...currentGenerationSettings,
|
|
215
|
-
temperature: prepareResult.temperature,
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
if (prepareResult?.topP !== undefined) {
|
|
219
|
-
currentGenerationSettings = {
|
|
220
|
-
...currentGenerationSettings,
|
|
221
|
-
topP: prepareResult.topP,
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
if (prepareResult?.topK !== undefined) {
|
|
225
|
-
currentGenerationSettings = {
|
|
226
|
-
...currentGenerationSettings,
|
|
227
|
-
topK: prepareResult.topK,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
if (prepareResult?.presencePenalty !== undefined) {
|
|
231
|
-
currentGenerationSettings = {
|
|
232
|
-
...currentGenerationSettings,
|
|
233
|
-
presencePenalty: prepareResult.presencePenalty,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
if (prepareResult?.frequencyPenalty !== undefined) {
|
|
237
|
-
currentGenerationSettings = {
|
|
238
|
-
...currentGenerationSettings,
|
|
239
|
-
frequencyPenalty: prepareResult.frequencyPenalty,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
if (prepareResult?.stopSequences !== undefined) {
|
|
243
|
-
currentGenerationSettings = {
|
|
244
|
-
...currentGenerationSettings,
|
|
245
|
-
stopSequences: prepareResult.stopSequences,
|
|
246
|
-
};
|
|
247
|
-
}
|
|
248
|
-
if (prepareResult?.seed !== undefined) {
|
|
249
|
-
currentGenerationSettings = {
|
|
250
|
-
...currentGenerationSettings,
|
|
251
|
-
seed: prepareResult.seed,
|
|
252
|
-
};
|
|
253
|
-
}
|
|
254
|
-
if (prepareResult?.maxRetries !== undefined) {
|
|
255
|
-
currentGenerationSettings = {
|
|
256
|
-
...currentGenerationSettings,
|
|
257
|
-
maxRetries: prepareResult.maxRetries,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
if (prepareResult?.headers !== undefined) {
|
|
261
|
-
currentGenerationSettings = {
|
|
262
|
-
...currentGenerationSettings,
|
|
263
|
-
headers: prepareResult.headers,
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
if (prepareResult?.reasoning !== undefined) {
|
|
267
|
-
currentGenerationSettings = {
|
|
268
|
-
...currentGenerationSettings,
|
|
269
|
-
reasoning: prepareResult.reasoning,
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
if (prepareResult?.providerOptions !== undefined) {
|
|
273
|
-
currentGenerationSettings = {
|
|
274
|
-
...currentGenerationSettings,
|
|
275
|
-
providerOptions: prepareResult.providerOptions,
|
|
276
|
-
};
|
|
277
|
-
}
|
|
242
|
+
currentGenerationSettings = mergePrepareStepGenerationSettings(
|
|
243
|
+
currentGenerationSettings,
|
|
244
|
+
prepareResult ?? {},
|
|
245
|
+
);
|
|
278
246
|
if (prepareResult?.toolChoice !== undefined) {
|
|
279
247
|
currentToolChoice = prepareResult.toolChoice;
|
|
280
248
|
}
|
|
@@ -322,7 +290,10 @@ export async function* streamTextIterator({
|
|
|
322
290
|
// Serialize tools before crossing the step boundary — zod schemas
|
|
323
291
|
// contain functions that can't be serialized by the workflow runtime.
|
|
324
292
|
// Tools are reconstructed with Ajv validation inside doStreamStep.
|
|
325
|
-
const serializedTools = serializeToolSet(effectiveTools
|
|
293
|
+
const serializedTools = serializeToolSet(effectiveTools, {
|
|
294
|
+
toolsContext: currentToolsContext as never,
|
|
295
|
+
experimental_sandbox: stepSandbox,
|
|
296
|
+
});
|
|
326
297
|
const modelCallInfo = getModelInfo(currentModel);
|
|
327
298
|
|
|
328
299
|
await telemetryDispatcher.onLanguageModelCallStart?.({
|
package/src/workflow-agent.ts
CHANGED
|
@@ -256,6 +256,16 @@ export interface PrepareStepInfo<
|
|
|
256
256
|
*/
|
|
257
257
|
model: LanguageModel;
|
|
258
258
|
|
|
259
|
+
/**
|
|
260
|
+
* The initial instructions passed to the stream.
|
|
261
|
+
*/
|
|
262
|
+
initialInstructions: Instructions | undefined;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* The initial messages passed to the stream.
|
|
266
|
+
*/
|
|
267
|
+
initialMessages: Array<ModelMessage>;
|
|
268
|
+
|
|
259
269
|
/**
|
|
260
270
|
* The current step number (0-indexed).
|
|
261
271
|
*/
|
|
@@ -371,6 +381,11 @@ export interface PrepareCallOptions<
|
|
|
371
381
|
tools: TTools;
|
|
372
382
|
instructions?: Instructions;
|
|
373
383
|
toolChoice?: ToolChoice<TTools>;
|
|
384
|
+
stopWhen?:
|
|
385
|
+
| StopCondition<NoInfer<ToolSet>, any>
|
|
386
|
+
| Array<StopCondition<NoInfer<ToolSet>, any>>;
|
|
387
|
+
activeTools?: ActiveTools<NoInfer<TTools>>;
|
|
388
|
+
experimental_download?: DownloadFunction;
|
|
374
389
|
telemetry?: TelemetryOptions<TRuntimeContext, TTools>;
|
|
375
390
|
/**
|
|
376
391
|
* Runtime context that flows through the agent loop.
|
|
@@ -837,7 +852,14 @@ export type WorkflowAgentStreamOptions<
|
|
|
837
852
|
}
|
|
838
853
|
) & {
|
|
839
854
|
/**
|
|
840
|
-
*
|
|
855
|
+
* Instructions override for this stream call.
|
|
856
|
+
*/
|
|
857
|
+
instructions?: Instructions;
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Optional system prompt override.
|
|
861
|
+
*
|
|
862
|
+
* @deprecated Use `instructions` instead.
|
|
841
863
|
*/
|
|
842
864
|
system?: string;
|
|
843
865
|
|
|
@@ -1324,7 +1346,8 @@ export class WorkflowAgent<
|
|
|
1324
1346
|
|
|
1325
1347
|
// Call prepareCall to transform parameters before the agent loop
|
|
1326
1348
|
let effectiveModel: LanguageModel = this.model;
|
|
1327
|
-
let effectiveInstructions =
|
|
1349
|
+
let effectiveInstructions =
|
|
1350
|
+
options.instructions ?? options.system ?? this.instructions;
|
|
1328
1351
|
let effectivePrompt: string | Array<ModelMessage> | undefined =
|
|
1329
1352
|
options.prompt;
|
|
1330
1353
|
let effectiveMessages: Array<ModelMessage> | undefined = options.messages;
|
|
@@ -1338,6 +1361,11 @@ export class WorkflowAgent<
|
|
|
1338
1361
|
Context | undefined
|
|
1339
1362
|
>;
|
|
1340
1363
|
let effectiveToolChoiceFromPrepare = options.toolChoice ?? this.toolChoice;
|
|
1364
|
+
let effectiveStopWhenFromPrepare = options.stopWhen ?? this.stopWhen;
|
|
1365
|
+
let effectiveActiveToolsFromPrepare =
|
|
1366
|
+
options.activeTools ?? this.activeTools;
|
|
1367
|
+
let effectiveDownloadFromPrepare =
|
|
1368
|
+
options.experimental_download ?? this.experimentalDownload;
|
|
1341
1369
|
let effectiveTelemetryFromPrepare = options.telemetry ?? this.telemetry;
|
|
1342
1370
|
|
|
1343
1371
|
// Resolve messages for prepareCall: use messages directly, or convert prompt
|
|
@@ -1354,6 +1382,9 @@ export class WorkflowAgent<
|
|
|
1354
1382
|
tools: this.tools,
|
|
1355
1383
|
instructions: effectiveInstructions,
|
|
1356
1384
|
toolChoice: effectiveToolChoiceFromPrepare as ToolChoice<TBaseTools>,
|
|
1385
|
+
stopWhen: effectiveStopWhenFromPrepare,
|
|
1386
|
+
activeTools: effectiveActiveToolsFromPrepare,
|
|
1387
|
+
experimental_download: effectiveDownloadFromPrepare,
|
|
1357
1388
|
telemetry: effectiveTelemetryFromPrepare,
|
|
1358
1389
|
runtimeContext: effectiveRuntimeContext,
|
|
1359
1390
|
toolsContext: effectiveToolsContext as InferToolSetContext<TBaseTools>,
|
|
@@ -1378,6 +1409,12 @@ export class WorkflowAgent<
|
|
|
1378
1409
|
if (prepared.toolChoice !== undefined)
|
|
1379
1410
|
effectiveToolChoiceFromPrepare =
|
|
1380
1411
|
prepared.toolChoice as ToolChoice<TBaseTools>;
|
|
1412
|
+
if (prepared.stopWhen !== undefined)
|
|
1413
|
+
effectiveStopWhenFromPrepare = prepared.stopWhen;
|
|
1414
|
+
if (prepared.activeTools !== undefined)
|
|
1415
|
+
effectiveActiveToolsFromPrepare = prepared.activeTools;
|
|
1416
|
+
if (prepared.experimental_download !== undefined)
|
|
1417
|
+
effectiveDownloadFromPrepare = prepared.experimental_download;
|
|
1381
1418
|
if (prepared.telemetry !== undefined)
|
|
1382
1419
|
effectiveTelemetryFromPrepare = prepared.telemetry;
|
|
1383
1420
|
if (prepared.maxOutputTokens !== undefined)
|
|
@@ -1423,7 +1460,7 @@ export class WorkflowAgent<
|
|
|
1423
1460
|
? { prompt: effectivePrompt }
|
|
1424
1461
|
: { messages: effectiveMessages! }),
|
|
1425
1462
|
} as Prompt);
|
|
1426
|
-
const download =
|
|
1463
|
+
const download = effectiveDownloadFromPrepare;
|
|
1427
1464
|
const sandbox = options.experimental_sandbox ?? this.experimentalSandbox;
|
|
1428
1465
|
|
|
1429
1466
|
// Process tool approval responses before starting the agent loop.
|
|
@@ -1832,7 +1869,7 @@ export class WorkflowAgent<
|
|
|
1832
1869
|
const effectiveToolChoice = effectiveToolChoiceFromPrepare;
|
|
1833
1870
|
|
|
1834
1871
|
// Filter tools if activeTools is specified (stream-level overrides constructor default)
|
|
1835
|
-
const effectiveActiveTools =
|
|
1872
|
+
const effectiveActiveTools = effectiveActiveToolsFromPrepare;
|
|
1836
1873
|
const effectiveTools =
|
|
1837
1874
|
effectiveActiveTools && effectiveActiveTools.length > 0
|
|
1838
1875
|
? (filterActiveTools({
|
|
@@ -2100,8 +2137,9 @@ export class WorkflowAgent<
|
|
|
2100
2137
|
tools: effectiveTools as ToolSet,
|
|
2101
2138
|
writable: options.writable,
|
|
2102
2139
|
prompt: modelPrompt,
|
|
2103
|
-
|
|
2104
|
-
|
|
2140
|
+
initialInstructions: effectiveInstructions,
|
|
2141
|
+
initialMessages: prompt.messages,
|
|
2142
|
+
stopConditions: effectiveStopWhenFromPrepare,
|
|
2105
2143
|
onStepEnd: mergedOnStepEnd as any,
|
|
2106
2144
|
onStepStart: mergedOnStepStart as any,
|
|
2107
2145
|
onError: options.onError,
|