@ai-sdk/google 3.0.49 → 3.0.51

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.
@@ -74,14 +74,24 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
74
74
  headers,
75
75
  );
76
76
 
77
- const multimodalContent = googleOptions?.content ?? [];
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
+ }
78
87
 
79
88
  // For single embeddings, use the single endpoint
80
89
  if (values.length === 1) {
90
+ const valueParts = multimodalContent?.[0];
81
91
  const textPart = values[0] ? [{ text: values[0] }] : [];
82
92
  const parts =
83
- multimodalContent.length > 0
84
- ? [...textPart, ...multimodalContent]
93
+ valueParts != null
94
+ ? [...textPart, ...valueParts]
85
95
  : [{ text: values[0] }];
86
96
 
87
97
  const {
@@ -116,7 +126,6 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
116
126
  }
117
127
 
118
128
  // For multiple values, use the batch endpoint
119
- // If multimodal content is provided, merge it into each request's parts
120
129
  const {
121
130
  responseHeaders,
122
131
  value: response,
@@ -125,15 +134,16 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
125
134
  url: `${this.config.baseURL}/models/${this.modelId}:batchEmbedContents`,
126
135
  headers: mergedHeaders,
127
136
  body: {
128
- requests: values.map(value => {
137
+ requests: values.map((value, index) => {
138
+ const valueParts = multimodalContent?.[index];
129
139
  const textPart = value ? [{ text: value }] : [];
130
140
  return {
131
141
  model: `models/${this.modelId}`,
132
142
  content: {
133
143
  role: 'user',
134
144
  parts:
135
- multimodalContent.length > 0
136
- ? [...textPart, ...multimodalContent]
145
+ valueParts != null
146
+ ? [...textPart, ...valueParts]
137
147
  : [{ text: value }],
138
148
  },
139
149
  outputDimensionality: googleOptions?.outputDimensionality,
@@ -7,6 +7,7 @@ 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
 
12
13
  const googleEmbeddingContentPartSchema = z.union([
@@ -54,11 +55,17 @@ export const googleEmbeddingModelOptions = lazySchema(() =>
54
55
  .optional(),
55
56
 
56
57
  /**
57
- * Optional. Multimodal content parts for embedding non-text content
58
- * (images, video, PDF, audio). When provided, these parts are merged
59
- * with the text values in the embedding request.
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.
60
65
  */
61
- content: z.array(googleEmbeddingContentPartSchema).min(1).optional(),
66
+ content: z
67
+ .array(z.array(googleEmbeddingContentPartSchema).min(1).nullable())
68
+ .optional(),
62
69
  }),
63
70
  ),
64
71
  );
@@ -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
 
@@ -355,7 +358,8 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
355
358
  urlContextMetadata: candidate.urlContextMetadata ?? null,
356
359
  safetyRatings: candidate.safetyRatings ?? null,
357
360
  usageMetadata: usageMetadata ?? null,
358
- },
361
+ finishMessage: candidate.finishMessage ?? null,
362
+ } satisfies GoogleGenerativeAIProviderMetadata,
359
363
  },
360
364
  request: { body: args },
361
365
  response: {
@@ -674,16 +678,10 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
674
678
  groundingMetadata: lastGroundingMetadata,
675
679
  urlContextMetadata: lastUrlContextMetadata,
676
680
  safetyRatings: candidate.safetyRatings ?? null,
677
- },
681
+ usageMetadata: usageMetadata ?? null,
682
+ finishMessage: candidate.finishMessage ?? null,
683
+ } satisfies GoogleGenerativeAIProviderMetadata,
678
684
  };
679
- if (usageMetadata != null) {
680
- (
681
- providerMetadata[providerOptionsName] as Record<
682
- string,
683
- unknown
684
- >
685
- ).usageMetadata = usageMetadata;
686
- }
687
685
  }
688
686
  },
689
687
 
@@ -1012,6 +1010,7 @@ const responseSchema = lazySchema(() =>
1012
1010
  z.object({
1013
1011
  content: getContentSchema().nullish().or(z.object({}).strict()),
1014
1012
  finishReason: z.string().nullish(),
1013
+ finishMessage: z.string().nullish(),
1015
1014
  safetyRatings: z.array(getSafetyRatingSchema()).nullish(),
1016
1015
  groundingMetadata: getGroundingMetadataSchema().nullish(),
1017
1016
  urlContextMetadata: getUrlContextMetadataSchema().nullish(),
@@ -1047,6 +1046,14 @@ export type SafetyRatingSchema = NonNullable<
1047
1046
  InferSchema<typeof responseSchema>['candidates'][number]['safetyRatings']
1048
1047
  >[number];
1049
1048
 
1049
+ export type PromptFeedbackSchema = NonNullable<
1050
+ InferSchema<typeof responseSchema>['promptFeedback']
1051
+ >;
1052
+
1053
+ export type UsageMetadataSchema = NonNullable<
1054
+ InferSchema<typeof responseSchema>['usageMetadata']
1055
+ >;
1056
+
1050
1057
  // limited version of the schema, focussed on what is needed for the implementation
1051
1058
  // this approach limits breakages when the API changes and increases efficiency
1052
1059
  const chunkSchema = lazySchema(() =>
@@ -1057,6 +1064,7 @@ const chunkSchema = lazySchema(() =>
1057
1064
  z.object({
1058
1065
  content: getContentSchema().nullish(),
1059
1066
  finishReason: z.string().nullish(),
1067
+ finishMessage: z.string().nullish(),
1060
1068
  safetyRatings: z.array(getSafetyRatingSchema()).nullish(),
1061
1069
  groundingMetadata: getGroundingMetadataSchema().nullish(),
1062
1070
  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
  }