ai 7.0.0-beta.21 → 7.0.0-beta.23

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 (33) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/index.js +44 -41
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +44 -41
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/internal/index.js +1 -1
  7. package/dist/internal/index.mjs +1 -1
  8. package/docs/03-ai-sdk-core/16-mcp-tools.mdx +6 -0
  9. package/docs/03-ai-sdk-core/35-image-generation.mdx +1 -1
  10. package/docs/03-ai-sdk-core/40-middleware.mdx +13 -13
  11. package/docs/03-ai-sdk-core/55-testing.mdx +10 -10
  12. package/docs/03-ai-sdk-core/65-event-listeners.mdx +1 -1
  13. package/docs/06-advanced/04-caching.mdx +10 -10
  14. package/docs/07-reference/01-ai-sdk-core/01-generate-text.mdx +3 -3
  15. package/docs/07-reference/01-ai-sdk-core/02-stream-text.mdx +3 -3
  16. package/docs/07-reference/01-ai-sdk-core/10-generate-image.mdx +1 -1
  17. package/docs/07-reference/01-ai-sdk-core/11-transcribe.mdx +1 -1
  18. package/docs/07-reference/01-ai-sdk-core/12-generate-speech.mdx +1 -1
  19. package/docs/07-reference/01-ai-sdk-core/13-generate-video.mdx +1 -1
  20. package/docs/07-reference/01-ai-sdk-core/16-tool-loop-agent.mdx +1 -1
  21. package/docs/07-reference/01-ai-sdk-core/23-create-mcp-client.mdx +7 -0
  22. package/docs/07-reference/01-ai-sdk-core/30-model-message.mdx +2 -2
  23. package/docs/07-reference/01-ai-sdk-core/60-wrap-language-model.mdx +4 -4
  24. package/docs/07-reference/01-ai-sdk-core/61-wrap-image-model.mdx +4 -4
  25. package/docs/07-reference/01-ai-sdk-core/65-language-model-v2-middleware.mdx +9 -9
  26. package/docs/07-reference/01-ai-sdk-core/66-extract-reasoning-middleware.mdx +1 -1
  27. package/docs/07-reference/01-ai-sdk-core/68-default-settings-middleware.mdx +1 -1
  28. package/docs/08-migration-guides/23-migration-guide-7-0.mdx +29 -0
  29. package/docs/09-troubleshooting/30-model-is-not-assignable-to-type.mdx +1 -1
  30. package/package.json +3 -3
  31. package/src/generate-text/create-stream-text-part-transform.ts +64 -12
  32. package/src/generate-text/run-tools-transformation.ts +35 -58
  33. package/src/telemetry/open-telemetry-integration.ts +2 -2
@@ -1,18 +1,44 @@
1
1
  import { LanguageModelV4StreamPart } from '@ai-sdk/provider';
2
2
  import { ProviderMetadata } from '../types/provider-metadata';
3
+ import { DefaultGeneratedFileWithType, GeneratedFile } from './generated-file';
3
4
 
4
5
  export type UglyTransformedStreamTextPart =
5
6
  | Exclude<
6
7
  LanguageModelV4StreamPart,
7
- {
8
- type: 'text-delta';
9
- }
8
+ | {
9
+ type: 'text-delta';
10
+ }
11
+ | {
12
+ type: 'reasoning-delta';
13
+ }
14
+ | {
15
+ type: 'file';
16
+ }
17
+ | {
18
+ type: 'reasoning-file';
19
+ }
10
20
  >
11
21
  | {
12
22
  type: 'text-delta';
13
23
  id: string;
14
24
  providerMetadata?: ProviderMetadata;
15
25
  text: string;
26
+ }
27
+ | {
28
+ type: 'reasoning-delta';
29
+ id: string;
30
+ providerMetadata?: ProviderMetadata;
31
+ text: string;
32
+ }
33
+ | {
34
+ type: 'file';
35
+ file: GeneratedFile;
36
+ providerMetadata?: ProviderMetadata;
37
+ }
38
+ | {
39
+ type: 'reasoning-file';
40
+ file: GeneratedFile;
41
+ providerMetadata?: ProviderMetadata;
16
42
  };
17
43
 
18
44
  export function createStreamTextPartTransform() {
@@ -21,15 +47,41 @@ export function createStreamTextPartTransform() {
21
47
  UglyTransformedStreamTextPart
22
48
  >({
23
49
  async transform(chunk, controller) {
24
- if (chunk.type === 'text-delta') {
25
- controller.enqueue({
26
- type: 'text-delta',
27
- id: chunk.id,
28
- text: chunk.delta,
29
- providerMetadata: chunk.providerMetadata,
30
- });
31
- } else {
32
- controller.enqueue(chunk);
50
+ switch (chunk.type) {
51
+ case 'text-delta':
52
+ controller.enqueue({
53
+ type: 'text-delta',
54
+ id: chunk.id,
55
+ text: chunk.delta,
56
+ providerMetadata: chunk.providerMetadata,
57
+ });
58
+ break;
59
+
60
+ case 'reasoning-delta':
61
+ controller.enqueue({
62
+ type: 'reasoning-delta',
63
+ id: chunk.id,
64
+ text: chunk.delta,
65
+ providerMetadata: chunk.providerMetadata,
66
+ });
67
+ break;
68
+
69
+ case 'file':
70
+ case 'reasoning-file': {
71
+ controller.enqueue({
72
+ type: chunk.type,
73
+ file: new DefaultGeneratedFileWithType({
74
+ data: chunk.data,
75
+ mediaType: chunk.mediaType,
76
+ }),
77
+ providerMetadata: chunk.providerMetadata,
78
+ });
79
+ break;
80
+ }
81
+
82
+ default:
83
+ controller.enqueue(chunk);
84
+ break;
33
85
  }
34
86
  },
35
87
  });
@@ -13,7 +13,7 @@ import { Source } from '../types/language-model';
13
13
  import { asLanguageModelUsage } from '../types/usage';
14
14
  import { UglyTransformedStreamTextPart } from './create-stream-text-part-transform';
15
15
  import { executeToolCall } from './execute-tool-call';
16
- import { DefaultGeneratedFileWithType, GeneratedFile } from './generated-file';
16
+ import { GeneratedFile } from './generated-file';
17
17
  import { isApprovalNeeded } from './is-approval-needed';
18
18
  import { parseToolCall } from './parse-tool-call';
19
19
  import {
@@ -153,7 +153,8 @@ export function runToolsTransformation<TOOLS extends ToolSet>({
153
153
  | Array<StreamTextOnToolCallFinishCallback<TOOLS> | undefined | null>;
154
154
  executeToolInTelemetryContext?: TelemetryIntegration['executeTool'];
155
155
  }): ReadableStream<SingleRequestTextStreamPart<TOOLS>> {
156
- // tool results stream
156
+ // there is a separate stream for tool results, because
157
+ // tool results might be emitted after the generator stream has finished
157
158
  let toolResultsStreamController: ReadableStreamDefaultController<
158
159
  SingleRequestTextStreamPart<TOOLS>
159
160
  > | null = null;
@@ -168,10 +169,8 @@ export function runToolsTransformation<TOOLS extends ToolSet>({
168
169
  // keep track of outstanding tool results for stream closing:
169
170
  const outstandingToolResults = new Set<string>();
170
171
 
171
- // keep track of tool inputs for provider-side tool results
172
- const toolInputs = new Map<string, unknown>();
173
-
174
172
  // keep track of parsed tool calls so provider-emitted approval requests can reference them
173
+ // keep track of tool inputs for provider-side tool results
175
174
  const toolCallsByToolCallId = new Map<string, TypedToolCall<TOOLS>>();
176
175
 
177
176
  let canClose = false;
@@ -213,10 +212,13 @@ export function runToolsTransformation<TOOLS extends ToolSet>({
213
212
  case 'text-delta':
214
213
  case 'text-end':
215
214
  case 'reasoning-start':
215
+ case 'reasoning-delta':
216
216
  case 'reasoning-end':
217
217
  case 'tool-input-start':
218
218
  case 'tool-input-delta':
219
219
  case 'tool-input-end':
220
+ case 'file':
221
+ case 'reasoning-file':
220
222
  case 'source':
221
223
  case 'response-metadata':
222
224
  case 'error':
@@ -225,30 +227,6 @@ export function runToolsTransformation<TOOLS extends ToolSet>({
225
227
  break;
226
228
  }
227
229
 
228
- case 'reasoning-delta':
229
- controller.enqueue({
230
- type: 'reasoning-delta',
231
- id: chunk.id,
232
- text: chunk.delta,
233
- providerMetadata: chunk.providerMetadata,
234
- });
235
- break;
236
-
237
- case 'file':
238
- case 'reasoning-file': {
239
- controller.enqueue({
240
- type: chunk.type,
241
- file: new DefaultGeneratedFileWithType({
242
- data: chunk.data,
243
- mediaType: chunk.mediaType,
244
- }),
245
- ...(chunk.providerMetadata != null
246
- ? { providerMetadata: chunk.providerMetadata }
247
- : {}),
248
- });
249
- break;
250
- }
251
-
252
230
  case 'finish': {
253
231
  finishChunk = {
254
232
  type: 'finish',
@@ -342,8 +320,6 @@ export function runToolsTransformation<TOOLS extends ToolSet>({
342
320
  break;
343
321
  }
344
322
 
345
- toolInputs.set(toolCall.toolCallId, toolCall.input);
346
-
347
323
  // Only execute tools that are not provider-executed:
348
324
  if (tool.execute != null && toolCall.providerExecuted !== true) {
349
325
  const toolExecutionId = generateId(); // use our own id to guarantee uniqueness
@@ -394,33 +370,34 @@ export function runToolsTransformation<TOOLS extends ToolSet>({
394
370
  case 'tool-result': {
395
371
  const toolName = chunk.toolName as keyof TOOLS & string;
396
372
 
397
- if (chunk.isError) {
398
- toolResultsStreamController!.enqueue({
399
- type: 'tool-error',
400
- toolCallId: chunk.toolCallId,
401
- toolName,
402
- input: toolInputs.get(chunk.toolCallId),
403
- providerExecuted: true,
404
- error: chunk.result,
405
- dynamic: chunk.dynamic,
406
- ...(chunk.providerMetadata != null
407
- ? { providerMetadata: chunk.providerMetadata }
408
- : {}),
409
- } as TypedToolError<TOOLS>);
410
- } else {
411
- controller.enqueue({
412
- type: 'tool-result',
413
- toolCallId: chunk.toolCallId,
414
- toolName,
415
- input: toolInputs.get(chunk.toolCallId),
416
- output: chunk.result,
417
- providerExecuted: true,
418
- dynamic: chunk.dynamic,
419
- ...(chunk.providerMetadata != null
420
- ? { providerMetadata: chunk.providerMetadata }
421
- : {}),
422
- } as TypedToolResult<TOOLS>);
423
- }
373
+ controller.enqueue(
374
+ chunk.isError
375
+ ? ({
376
+ type: 'tool-error',
377
+ toolCallId: chunk.toolCallId,
378
+ toolName,
379
+ input: toolCallsByToolCallId.get(chunk.toolCallId)?.input,
380
+ providerExecuted: true,
381
+ error: chunk.result,
382
+ dynamic: chunk.dynamic,
383
+ ...(chunk.providerMetadata != null
384
+ ? { providerMetadata: chunk.providerMetadata }
385
+ : {}),
386
+ } as TypedToolError<TOOLS>)
387
+ : ({
388
+ type: 'tool-result',
389
+ toolCallId: chunk.toolCallId,
390
+ toolName,
391
+ input: toolCallsByToolCallId.get(chunk.toolCallId)?.input,
392
+ output: chunk.result,
393
+ providerExecuted: true,
394
+ dynamic: chunk.dynamic,
395
+ ...(chunk.providerMetadata != null
396
+ ? { providerMetadata: chunk.providerMetadata }
397
+ : {}),
398
+ } as TypedToolResult<TOOLS>),
399
+ );
400
+
424
401
  break;
425
402
  }
426
403
 
@@ -1,4 +1,4 @@
1
- import { LanguageModelV3Prompt } from '@ai-sdk/provider';
1
+ import { LanguageModelV4Prompt } from '@ai-sdk/provider';
2
2
  import {
3
3
  context,
4
4
  trace,
@@ -99,7 +99,7 @@ interface OtelStepStartEvent<
99
99
  TOOLS extends ToolSet = ToolSet,
100
100
  OUTPUT extends Output = Output,
101
101
  > extends OnStepStartEvent<TOOLS, OUTPUT> {
102
- readonly promptMessages?: LanguageModelV3Prompt;
102
+ readonly promptMessages?: LanguageModelV4Prompt;
103
103
  readonly stepTools?: ReadonlyArray<Record<string, unknown>>;
104
104
  readonly stepToolChoice?: unknown;
105
105
  }