@ai-sdk/google 4.0.0-beta.1 → 4.0.0-beta.11

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.
@@ -1,4 +1,4 @@
1
- import { LanguageModelV3Usage } from '@ai-sdk/provider';
1
+ import { LanguageModelV4Usage } from '@ai-sdk/provider';
2
2
 
3
3
  export type GoogleGenerativeAIUsageMetadata = {
4
4
  promptTokenCount?: number | null;
@@ -11,7 +11,7 @@ export type GoogleGenerativeAIUsageMetadata = {
11
11
 
12
12
  export function convertGoogleGenerativeAIUsage(
13
13
  usage: GoogleGenerativeAIUsageMetadata | undefined | null,
14
- ): LanguageModelV3Usage {
14
+ ): LanguageModelV4Usage {
15
15
  if (usage == null) {
16
16
  return {
17
17
  inputTokens: {
@@ -1,5 +1,5 @@
1
1
  import {
2
- LanguageModelV3Prompt,
2
+ LanguageModelV4Prompt,
3
3
  UnsupportedFunctionalityError,
4
4
  } from '@ai-sdk/provider';
5
5
  import {
@@ -10,7 +10,7 @@ import {
10
10
  import { convertToBase64 } from '@ai-sdk/provider-utils';
11
11
 
12
12
  export function convertToGoogleGenerativeAIMessages(
13
- prompt: LanguageModelV3Prompt,
13
+ prompt: LanguageModelV4Prompt,
14
14
  options?: { isGemmaModel?: boolean; providerOptionsName?: string },
15
15
  ): GoogleGenerativeAIPrompt {
16
16
  const systemInstructionParts: Array<{ text: string }> = [];
@@ -112,6 +112,24 @@ export function convertToGoogleGenerativeAIMessages(
112
112
  };
113
113
  }
114
114
 
115
+ case 'reasoning-file': {
116
+ if (part.data instanceof URL) {
117
+ throw new UnsupportedFunctionalityError({
118
+ functionality:
119
+ 'File data URLs in assistant messages are not supported',
120
+ });
121
+ }
122
+
123
+ return {
124
+ inlineData: {
125
+ mimeType: part.mediaType,
126
+ data: convertToBase64(part.data),
127
+ },
128
+ thought: true,
129
+ thoughtSignature,
130
+ };
131
+ }
132
+
115
133
  case 'file': {
116
134
  if (part.data instanceof URL) {
117
135
  throw new UnsupportedFunctionalityError({
@@ -125,6 +143,9 @@ export function convertToGoogleGenerativeAIMessages(
125
143
  mimeType: part.mediaType,
126
144
  data: convertToBase64(part.data),
127
145
  },
146
+ ...(providerOpts?.thought === true
147
+ ? { thought: true }
148
+ : {}),
128
149
  thoughtSignature,
129
150
  };
130
151
  }
@@ -1,5 +1,5 @@
1
1
  import {
2
- EmbeddingModelV3,
2
+ EmbeddingModelV4,
3
3
  TooManyEmbeddingValuesForCallError,
4
4
  } from '@ai-sdk/provider';
5
5
  import {
@@ -26,8 +26,8 @@ type GoogleGenerativeAIEmbeddingConfig = {
26
26
  fetch?: FetchFunction;
27
27
  };
28
28
 
29
- export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
30
- readonly specificationVersion = 'v3';
29
+ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV4 {
30
+ readonly specificationVersion = 'v4';
31
31
  readonly modelId: GoogleGenerativeAIEmbeddingModelId;
32
32
  readonly maxEmbeddingsPerCall = 2048;
33
33
  readonly supportsParallelCalls = true;
@@ -50,8 +50,8 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
50
50
  headers,
51
51
  abortSignal,
52
52
  providerOptions,
53
- }: Parameters<EmbeddingModelV3['doEmbed']>[0]): Promise<
54
- Awaited<ReturnType<EmbeddingModelV3['doEmbed']>>
53
+ }: Parameters<EmbeddingModelV4['doEmbed']>[0]): Promise<
54
+ Awaited<ReturnType<EmbeddingModelV4['doEmbed']>>
55
55
  > {
56
56
  // Parse provider options
57
57
  const googleOptions = await parseProviderOptions({
@@ -74,8 +74,26 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
74
74
  headers,
75
75
  );
76
76
 
77
- // For single embeddings, use the single endpoint (ratelimits, etc.)
77
+ const multimodalContent = googleOptions?.content;
78
+
79
+ if (
80
+ multimodalContent != null &&
81
+ multimodalContent.length !== values.length
82
+ ) {
83
+ throw new Error(
84
+ `The number of multimodal content entries (${multimodalContent.length}) must match the number of values (${values.length}).`,
85
+ );
86
+ }
87
+
88
+ // For single embeddings, use the single endpoint
78
89
  if (values.length === 1) {
90
+ const valueParts = multimodalContent?.[0];
91
+ const textPart = values[0] ? [{ text: values[0] }] : [];
92
+ const parts =
93
+ valueParts != null
94
+ ? [...textPart, ...valueParts]
95
+ : [{ text: values[0] }];
96
+
79
97
  const {
80
98
  responseHeaders,
81
99
  value: response,
@@ -86,7 +104,7 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
86
104
  body: {
87
105
  model: `models/${this.modelId}`,
88
106
  content: {
89
- parts: [{ text: values[0] }],
107
+ parts,
90
108
  },
91
109
  outputDimensionality: googleOptions?.outputDimensionality,
92
110
  taskType: googleOptions?.taskType,
@@ -107,6 +125,7 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
107
125
  };
108
126
  }
109
127
 
128
+ // For multiple values, use the batch endpoint
110
129
  const {
111
130
  responseHeaders,
112
131
  value: response,
@@ -115,12 +134,22 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
115
134
  url: `${this.config.baseURL}/models/${this.modelId}:batchEmbedContents`,
116
135
  headers: mergedHeaders,
117
136
  body: {
118
- requests: values.map(value => ({
119
- model: `models/${this.modelId}`,
120
- content: { role: 'user', parts: [{ text: value }] },
121
- outputDimensionality: googleOptions?.outputDimensionality,
122
- taskType: googleOptions?.taskType,
123
- })),
137
+ requests: values.map((value, index) => {
138
+ const valueParts = multimodalContent?.[index];
139
+ const textPart = value ? [{ text: value }] : [];
140
+ return {
141
+ model: `models/${this.modelId}`,
142
+ content: {
143
+ role: 'user',
144
+ parts:
145
+ valueParts != null
146
+ ? [...textPart, ...valueParts]
147
+ : [{ text: value }],
148
+ },
149
+ outputDimensionality: googleOptions?.outputDimensionality,
150
+ taskType: googleOptions?.taskType,
151
+ };
152
+ }),
124
153
  },
125
154
  failedResponseHandler: googleFailedResponseHandler,
126
155
  successfulResponseHandler: createJsonResponseHandler(
@@ -7,8 +7,19 @@ import { z } from 'zod/v4';
7
7
 
8
8
  export type GoogleGenerativeAIEmbeddingModelId =
9
9
  | 'gemini-embedding-001'
10
+ | 'gemini-embedding-2-preview'
10
11
  | (string & {});
11
12
 
13
+ const googleEmbeddingContentPartSchema = z.union([
14
+ z.object({ text: z.string() }),
15
+ z.object({
16
+ inlineData: z.object({
17
+ mimeType: z.string(),
18
+ data: z.string(),
19
+ }),
20
+ }),
21
+ ]);
22
+
12
23
  export const googleEmbeddingModelOptions = lazySchema(() =>
13
24
  zodSchema(
14
25
  z.object({
@@ -42,6 +53,19 @@ export const googleEmbeddingModelOptions = lazySchema(() =>
42
53
  'CODE_RETRIEVAL_QUERY',
43
54
  ])
44
55
  .optional(),
56
+
57
+ /**
58
+ * Optional. Per-value multimodal content parts for embedding non-text
59
+ * content (images, video, PDF, audio). Each entry corresponds to the
60
+ * embedding value at the same index and its parts are merged with the
61
+ * text value in the request. Use `null` for entries that are text-only.
62
+ *
63
+ * The array length must match the number of values being embedded. In
64
+ * the case of a single embedding, the array length must be 1.
65
+ */
66
+ content: z
67
+ .array(z.array(googleEmbeddingContentPartSchema).min(1).nullable())
68
+ .optional(),
45
69
  }),
46
70
  ),
47
71
  );
@@ -1,7 +1,7 @@
1
1
  import {
2
- ImageModelV3,
3
- LanguageModelV3Prompt,
4
- SharedV3Warning,
2
+ ImageModelV4,
3
+ LanguageModelV4Prompt,
4
+ SharedV4Warning,
5
5
  } from '@ai-sdk/provider';
6
6
  import {
7
7
  combineHeaders,
@@ -37,8 +37,8 @@ interface GoogleGenerativeAIImageModelConfig {
37
37
  };
38
38
  }
39
39
 
40
- export class GoogleGenerativeAIImageModel implements ImageModelV3 {
41
- readonly specificationVersion = 'v3';
40
+ export class GoogleGenerativeAIImageModel implements ImageModelV4 {
41
+ readonly specificationVersion = 'v4';
42
42
 
43
43
  get maxImagesPerCall(): number {
44
44
  if (this.settings.maxImagesPerCall != null) {
@@ -63,8 +63,8 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
63
63
  ) {}
64
64
 
65
65
  async doGenerate(
66
- options: Parameters<ImageModelV3['doGenerate']>[0],
67
- ): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>> {
66
+ options: Parameters<ImageModelV4['doGenerate']>[0],
67
+ ): Promise<Awaited<ReturnType<ImageModelV4['doGenerate']>>> {
68
68
  // Gemini image models use the language model API internally
69
69
  if (isGeminiModel(this.modelId)) {
70
70
  return this.doGenerateGemini(options);
@@ -73,8 +73,8 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
73
73
  }
74
74
 
75
75
  private async doGenerateImagen(
76
- options: Parameters<ImageModelV3['doGenerate']>[0],
77
- ): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>> {
76
+ options: Parameters<ImageModelV4['doGenerate']>[0],
77
+ ): Promise<Awaited<ReturnType<ImageModelV4['doGenerate']>>> {
78
78
  const {
79
79
  prompt,
80
80
  n = 1,
@@ -87,7 +87,7 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
87
87
  files,
88
88
  mask,
89
89
  } = options;
90
- const warnings: Array<SharedV3Warning> = [];
90
+ const warnings: Array<SharedV4Warning> = [];
91
91
 
92
92
  // Imagen API endpoints do not support image editing
93
93
  if (files != null && files.length > 0) {
@@ -181,8 +181,8 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
181
181
  }
182
182
 
183
183
  private async doGenerateGemini(
184
- options: Parameters<ImageModelV3['doGenerate']>[0],
185
- ): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>> {
184
+ options: Parameters<ImageModelV4['doGenerate']>[0],
185
+ ): Promise<Awaited<ReturnType<ImageModelV4['doGenerate']>>> {
186
186
  const {
187
187
  prompt,
188
188
  n,
@@ -195,7 +195,7 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
195
195
  files,
196
196
  mask,
197
197
  } = options;
198
- const warnings: Array<SharedV3Warning> = [];
198
+ const warnings: Array<SharedV4Warning> = [];
199
199
 
200
200
  // Gemini does not support mask-based inpainting
201
201
  if (mask != null) {
@@ -253,7 +253,7 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
253
253
  }
254
254
  }
255
255
 
256
- const languageModelPrompt: LanguageModelV3Prompt = [
256
+ const languageModelPrompt: LanguageModelV4Prompt = [
257
257
  { role: 'user', content: userContent },
258
258
  ];
259
259
 
@@ -1,14 +1,14 @@
1
1
  import {
2
- LanguageModelV3,
3
- LanguageModelV3CallOptions,
4
- LanguageModelV3Content,
5
- LanguageModelV3FinishReason,
6
- LanguageModelV3GenerateResult,
7
- LanguageModelV3Source,
8
- LanguageModelV3StreamPart,
9
- LanguageModelV3StreamResult,
10
- SharedV3ProviderMetadata,
11
- SharedV3Warning,
2
+ LanguageModelV4,
3
+ LanguageModelV4CallOptions,
4
+ LanguageModelV4Content,
5
+ LanguageModelV4FinishReason,
6
+ LanguageModelV4GenerateResult,
7
+ LanguageModelV4Source,
8
+ LanguageModelV4StreamPart,
9
+ LanguageModelV4StreamResult,
10
+ SharedV4ProviderMetadata,
11
+ SharedV4Warning,
12
12
  } from '@ai-sdk/provider';
13
13
  import {
14
14
  combineHeaders,
@@ -38,7 +38,10 @@ import {
38
38
  GoogleGenerativeAIModelId,
39
39
  googleLanguageModelOptions,
40
40
  } from './google-generative-ai-options';
41
- import { GoogleGenerativeAIContentPart } from './google-generative-ai-prompt';
41
+ import {
42
+ GoogleGenerativeAIContentPart,
43
+ GoogleGenerativeAIProviderMetadata,
44
+ } from './google-generative-ai-prompt';
42
45
  import { prepareTools } from './google-prepare-tools';
43
46
  import { mapGoogleGenerativeAIFinishReason } from './map-google-generative-ai-finish-reason';
44
47
 
@@ -52,11 +55,11 @@ type GoogleGenerativeAIConfig = {
52
55
  /**
53
56
  * The supported URLs for the model.
54
57
  */
55
- supportedUrls?: () => LanguageModelV3['supportedUrls'];
58
+ supportedUrls?: () => LanguageModelV4['supportedUrls'];
56
59
  };
57
60
 
58
- export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
59
- readonly specificationVersion = 'v3';
61
+ export class GoogleGenerativeAILanguageModel implements LanguageModelV4 {
62
+ readonly specificationVersion = 'v4';
60
63
 
61
64
  readonly modelId: GoogleGenerativeAIModelId;
62
65
 
@@ -94,8 +97,8 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
94
97
  tools,
95
98
  toolChoice,
96
99
  providerOptions,
97
- }: LanguageModelV3CallOptions) {
98
- const warnings: SharedV3Warning[] = [];
100
+ }: LanguageModelV4CallOptions) {
101
+ const warnings: SharedV4Warning[] = [];
99
102
 
100
103
  const providerOptionsName = this.config.provider.includes('vertex')
101
104
  ? 'vertex'
@@ -206,8 +209,8 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
206
209
  }
207
210
 
208
211
  async doGenerate(
209
- options: LanguageModelV3CallOptions,
210
- ): Promise<LanguageModelV3GenerateResult> {
212
+ options: LanguageModelV4CallOptions,
213
+ ): Promise<LanguageModelV4GenerateResult> {
211
214
  const { args, warnings, providerOptionsName } = await this.getArgs(options);
212
215
 
213
216
  const mergedHeaders = combineHeaders(
@@ -232,7 +235,7 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
232
235
  });
233
236
 
234
237
  const candidate = response.candidates[0];
235
- const content: Array<LanguageModelV3Content> = [];
238
+ const content: Array<LanguageModelV4Content> = [];
236
239
 
237
240
  // map ordered parts to content:
238
241
  const parts = candidate.content?.parts ?? [];
@@ -304,11 +307,13 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
304
307
  : undefined,
305
308
  });
306
309
  } else if ('inlineData' in part) {
310
+ const hasThought = part.thought === true;
311
+ const hasThoughtSignature = !!part.thoughtSignature;
307
312
  content.push({
308
- type: 'file' as const,
313
+ type: hasThought ? 'reasoning-file' : 'file',
309
314
  data: part.inlineData.data,
310
315
  mediaType: part.inlineData.mimeType,
311
- providerMetadata: part.thoughtSignature
316
+ providerMetadata: hasThoughtSignature
312
317
  ? {
313
318
  [providerOptionsName]: {
314
319
  thoughtSignature: part.thoughtSignature,
@@ -349,7 +354,8 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
349
354
  urlContextMetadata: candidate.urlContextMetadata ?? null,
350
355
  safetyRatings: candidate.safetyRatings ?? null,
351
356
  usageMetadata: usageMetadata ?? null,
352
- },
357
+ finishMessage: candidate.finishMessage ?? null,
358
+ } satisfies GoogleGenerativeAIProviderMetadata,
353
359
  },
354
360
  request: { body: args },
355
361
  response: {
@@ -361,8 +367,8 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
361
367
  }
362
368
 
363
369
  async doStream(
364
- options: LanguageModelV3CallOptions,
365
- ): Promise<LanguageModelV3StreamResult> {
370
+ options: LanguageModelV4CallOptions,
371
+ ): Promise<LanguageModelV4StreamResult> {
366
372
  const { args, warnings, providerOptionsName } = await this.getArgs(options);
367
373
 
368
374
  const headers = combineHeaders(
@@ -382,12 +388,14 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
382
388
  fetch: this.config.fetch,
383
389
  });
384
390
 
385
- let finishReason: LanguageModelV3FinishReason = {
391
+ let finishReason: LanguageModelV4FinishReason = {
386
392
  unified: 'other',
387
393
  raw: undefined,
388
394
  };
389
395
  let usage: GoogleGenerativeAIUsageMetadata | undefined = undefined;
390
- let providerMetadata: SharedV3ProviderMetadata | undefined = undefined;
396
+ let providerMetadata: SharedV4ProviderMetadata | undefined = undefined;
397
+ let lastGroundingMetadata: GroundingMetadataSchema | null = null;
398
+ let lastUrlContextMetadata: UrlContextMetadataSchema | null = null;
391
399
 
392
400
  const generateId = this.config.generateId;
393
401
  let hasToolCalls = false;
@@ -406,7 +414,7 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
406
414
  stream: response.pipeThrough(
407
415
  new TransformStream<
408
416
  ParseResult<ChunkSchema>,
409
- LanguageModelV3StreamPart
417
+ LanguageModelV4StreamPart
410
418
  >({
411
419
  start(controller) {
412
420
  controller.enqueue({ type: 'stream-start', warnings });
@@ -439,6 +447,13 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
439
447
 
440
448
  const content = candidate.content;
441
449
 
450
+ if (candidate.groundingMetadata != null) {
451
+ lastGroundingMetadata = candidate.groundingMetadata;
452
+ }
453
+ if (candidate.urlContextMetadata != null) {
454
+ lastUrlContextMetadata = candidate.urlContextMetadata;
455
+ }
456
+
442
457
  const sources = extractSources({
443
458
  groundingMetadata: candidate.groundingMetadata,
444
459
  generateId,
@@ -581,8 +596,9 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
581
596
  currentReasoningBlockId = null;
582
597
  }
583
598
 
584
- // Process file parts inline to preserve order with text
585
- const thoughtSignatureMetadata = part.thoughtSignature
599
+ const hasThought = part.thought === true;
600
+ const hasThoughtSignature = !!part.thoughtSignature;
601
+ const fileMeta = hasThoughtSignature
586
602
  ? {
587
603
  [providerOptionsName]: {
588
604
  thoughtSignature: part.thoughtSignature,
@@ -590,10 +606,10 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
590
606
  }
591
607
  : undefined;
592
608
  controller.enqueue({
593
- type: 'file',
609
+ type: hasThought ? 'reasoning-file' : 'file',
594
610
  mediaType: part.inlineData.mimeType,
595
611
  data: part.inlineData.data,
596
- providerMetadata: thoughtSignatureMetadata,
612
+ providerMetadata: fileMeta,
597
613
  });
598
614
  }
599
615
  }
@@ -651,19 +667,13 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
651
667
  providerMetadata = {
652
668
  [providerOptionsName]: {
653
669
  promptFeedback: value.promptFeedback ?? null,
654
- groundingMetadata: candidate.groundingMetadata ?? null,
655
- urlContextMetadata: candidate.urlContextMetadata ?? null,
670
+ groundingMetadata: lastGroundingMetadata,
671
+ urlContextMetadata: lastUrlContextMetadata,
656
672
  safetyRatings: candidate.safetyRatings ?? null,
657
- },
673
+ usageMetadata: usageMetadata ?? null,
674
+ finishMessage: candidate.finishMessage ?? null,
675
+ } satisfies GoogleGenerativeAIProviderMetadata,
658
676
  };
659
- if (usageMetadata != null) {
660
- (
661
- providerMetadata[providerOptionsName] as Record<
662
- string,
663
- unknown
664
- >
665
- ).usageMetadata = usageMetadata;
666
- }
667
677
  }
668
678
  },
669
679
 
@@ -737,12 +747,12 @@ function extractSources({
737
747
  }: {
738
748
  groundingMetadata: GroundingMetadataSchema | undefined | null;
739
749
  generateId: () => string;
740
- }): undefined | LanguageModelV3Source[] {
750
+ }): undefined | LanguageModelV4Source[] {
741
751
  if (!groundingMetadata?.groundingChunks) {
742
752
  return undefined;
743
753
  }
744
754
 
745
- const sources: LanguageModelV3Source[] = [];
755
+ const sources: LanguageModelV4Source[] = [];
746
756
 
747
757
  for (const chunk of groundingMetadata.groundingChunks) {
748
758
  if (chunk.web != null) {
@@ -926,6 +936,7 @@ const getContentSchema = () =>
926
936
  mimeType: z.string(),
927
937
  data: z.string(),
928
938
  }),
939
+ thought: z.boolean().nullish(),
929
940
  thoughtSignature: z.string().nullish(),
930
941
  }),
931
942
  z.object({
@@ -991,6 +1002,7 @@ const responseSchema = lazySchema(() =>
991
1002
  z.object({
992
1003
  content: getContentSchema().nullish().or(z.object({}).strict()),
993
1004
  finishReason: z.string().nullish(),
1005
+ finishMessage: z.string().nullish(),
994
1006
  safetyRatings: z.array(getSafetyRatingSchema()).nullish(),
995
1007
  groundingMetadata: getGroundingMetadataSchema().nullish(),
996
1008
  urlContextMetadata: getUrlContextMetadataSchema().nullish(),
@@ -1026,6 +1038,14 @@ export type SafetyRatingSchema = NonNullable<
1026
1038
  InferSchema<typeof responseSchema>['candidates'][number]['safetyRatings']
1027
1039
  >[number];
1028
1040
 
1041
+ export type PromptFeedbackSchema = NonNullable<
1042
+ InferSchema<typeof responseSchema>['promptFeedback']
1043
+ >;
1044
+
1045
+ export type UsageMetadataSchema = NonNullable<
1046
+ InferSchema<typeof responseSchema>['usageMetadata']
1047
+ >;
1048
+
1029
1049
  // limited version of the schema, focussed on what is needed for the implementation
1030
1050
  // this approach limits breakages when the API changes and increases efficiency
1031
1051
  const chunkSchema = lazySchema(() =>
@@ -1036,6 +1056,7 @@ const chunkSchema = lazySchema(() =>
1036
1056
  z.object({
1037
1057
  content: getContentSchema().nullish(),
1038
1058
  finishReason: z.string().nullish(),
1059
+ finishMessage: z.string().nullish(),
1039
1060
  safetyRatings: z.array(getSafetyRatingSchema()).nullish(),
1040
1061
  groundingMetadata: getGroundingMetadataSchema().nullish(),
1041
1062
  urlContextMetadata: getUrlContextMetadataSchema().nullish(),
@@ -1,6 +1,8 @@
1
1
  import {
2
2
  GroundingMetadataSchema,
3
+ PromptFeedbackSchema,
3
4
  UrlContextMetadataSchema,
5
+ UsageMetadataSchema,
4
6
  } from './google-generative-ai-language-model';
5
7
  import { type SafetyRatingSchema } from './google-generative-ai-language-model';
6
8
 
@@ -31,8 +33,15 @@ export type GoogleGenerativeAIUrlContextMetadata = UrlContextMetadataSchema;
31
33
 
32
34
  export type GoogleGenerativeAISafetyRating = SafetyRatingSchema;
33
35
 
36
+ export type GoogleGenerativeAIPromptFeedback = PromptFeedbackSchema;
37
+
38
+ export type GoogleGenerativeAIUsageMetadata = UsageMetadataSchema;
39
+
34
40
  export interface GoogleGenerativeAIProviderMetadata {
41
+ promptFeedback: GoogleGenerativeAIPromptFeedback | null;
35
42
  groundingMetadata: GoogleGenerativeAIGroundingMetadata | null;
36
43
  urlContextMetadata: GoogleGenerativeAIUrlContextMetadata | null;
37
44
  safetyRatings: GoogleGenerativeAISafetyRating[] | null;
45
+ usageMetadata: GoogleGenerativeAIUsageMetadata | null;
46
+ finishMessage: string | null;
38
47
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  AISDKError,
3
- type Experimental_VideoModelV3,
4
- type SharedV3Warning,
3
+ type Experimental_VideoModelV4,
4
+ type SharedV4Warning,
5
5
  } from '@ai-sdk/provider';
6
6
  import {
7
7
  combineHeaders,
@@ -50,8 +50,8 @@ interface GoogleGenerativeAIVideoModelConfig {
50
50
  };
51
51
  }
52
52
 
53
- export class GoogleGenerativeAIVideoModel implements Experimental_VideoModelV3 {
54
- readonly specificationVersion = 'v3';
53
+ export class GoogleGenerativeAIVideoModel implements Experimental_VideoModelV4 {
54
+ readonly specificationVersion = 'v4';
55
55
 
56
56
  get provider(): string {
57
57
  return this.config.provider;
@@ -68,10 +68,10 @@ export class GoogleGenerativeAIVideoModel implements Experimental_VideoModelV3 {
68
68
  ) {}
69
69
 
70
70
  async doGenerate(
71
- options: Parameters<Experimental_VideoModelV3['doGenerate']>[0],
72
- ): Promise<Awaited<ReturnType<Experimental_VideoModelV3['doGenerate']>>> {
71
+ options: Parameters<Experimental_VideoModelV4['doGenerate']>[0],
72
+ ): Promise<Awaited<ReturnType<Experimental_VideoModelV4['doGenerate']>>> {
73
73
  const currentDate = this.config._internal?.currentDate?.() ?? new Date();
74
- const warnings: SharedV3Warning[] = [];
74
+ const warnings: SharedV4Warning[] = [];
75
75
 
76
76
  const googleOptions = (await parseProviderOptions({
77
77
  provider: 'google',
@@ -1,6 +1,6 @@
1
1
  import {
2
- LanguageModelV3CallOptions,
3
- SharedV3Warning,
2
+ LanguageModelV4CallOptions,
3
+ SharedV4Warning,
4
4
  UnsupportedFunctionalityError,
5
5
  } from '@ai-sdk/provider';
6
6
  import { convertJSONSchemaToOpenAPISchema } from './convert-json-schema-to-openapi-schema';
@@ -11,8 +11,8 @@ export function prepareTools({
11
11
  toolChoice,
12
12
  modelId,
13
13
  }: {
14
- tools: LanguageModelV3CallOptions['tools'];
15
- toolChoice?: LanguageModelV3CallOptions['toolChoice'];
14
+ tools: LanguageModelV4CallOptions['tools'];
15
+ toolChoice?: LanguageModelV4CallOptions['toolChoice'];
16
16
  modelId: GoogleGenerativeAIModelId;
17
17
  }): {
18
18
  tools:
@@ -35,12 +35,12 @@ export function prepareTools({
35
35
  allowedFunctionNames?: string[];
36
36
  };
37
37
  };
38
- toolWarnings: SharedV3Warning[];
38
+ toolWarnings: SharedV4Warning[];
39
39
  } {
40
40
  // when the tools array is empty, change it to undefined to prevent errors:
41
41
  tools = tools?.length ? tools : undefined;
42
42
 
43
- const toolWarnings: SharedV3Warning[] = [];
43
+ const toolWarnings: SharedV4Warning[] = [];
44
44
 
45
45
  const isLatest = (
46
46
  [