@ai-sdk/google 3.0.46 → 3.0.48

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/google",
3
- "version": "3.0.46",
3
+ "version": "3.0.48",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -44,8 +44,8 @@
44
44
  "tsup": "^8",
45
45
  "typescript": "5.8.3",
46
46
  "zod": "3.25.76",
47
- "@ai-sdk/test-server": "1.0.3",
48
- "@vercel/ai-tsconfig": "0.0.0"
47
+ "@vercel/ai-tsconfig": "0.0.0",
48
+ "@ai-sdk/test-server": "1.0.3"
49
49
  },
50
50
  "peerDependencies": {
51
51
  "zod": "^3.25.76 || ^4.1.8"
@@ -125,6 +125,9 @@ export function convertToGoogleGenerativeAIMessages(
125
125
  mimeType: part.mediaType,
126
126
  data: convertToBase64(part.data),
127
127
  },
128
+ ...(providerOpts?.thought === true
129
+ ? { thought: true }
130
+ : {}),
128
131
  thoughtSignature,
129
132
  };
130
133
  }
@@ -74,8 +74,16 @@ 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
+ // For single embeddings, use the single endpoint
78
80
  if (values.length === 1) {
81
+ const textPart = values[0] ? [{ text: values[0] }] : [];
82
+ const parts =
83
+ multimodalContent.length > 0
84
+ ? [...textPart, ...multimodalContent]
85
+ : [{ text: values[0] }];
86
+
79
87
  const {
80
88
  responseHeaders,
81
89
  value: response,
@@ -86,7 +94,7 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
86
94
  body: {
87
95
  model: `models/${this.modelId}`,
88
96
  content: {
89
- parts: [{ text: values[0] }],
97
+ parts,
90
98
  },
91
99
  outputDimensionality: googleOptions?.outputDimensionality,
92
100
  taskType: googleOptions?.taskType,
@@ -107,6 +115,8 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
107
115
  };
108
116
  }
109
117
 
118
+ // For multiple values, use the batch endpoint
119
+ // If multimodal content is provided, merge it into each request's parts
110
120
  const {
111
121
  responseHeaders,
112
122
  value: response,
@@ -115,12 +125,21 @@ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
115
125
  url: `${this.config.baseURL}/models/${this.modelId}:batchEmbedContents`,
116
126
  headers: mergedHeaders,
117
127
  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
- })),
128
+ requests: values.map(value => {
129
+ const textPart = value ? [{ text: value }] : [];
130
+ return {
131
+ model: `models/${this.modelId}`,
132
+ content: {
133
+ role: 'user',
134
+ parts:
135
+ multimodalContent.length > 0
136
+ ? [...textPart, ...multimodalContent]
137
+ : [{ text: value }],
138
+ },
139
+ outputDimensionality: googleOptions?.outputDimensionality,
140
+ taskType: googleOptions?.taskType,
141
+ };
142
+ }),
124
143
  },
125
144
  failedResponseHandler: googleFailedResponseHandler,
126
145
  successfulResponseHandler: createJsonResponseHandler(
@@ -9,6 +9,16 @@ export type GoogleGenerativeAIEmbeddingModelId =
9
9
  | 'gemini-embedding-001'
10
10
  | (string & {});
11
11
 
12
+ const googleEmbeddingContentPartSchema = z.union([
13
+ z.object({ text: z.string() }),
14
+ z.object({
15
+ inlineData: z.object({
16
+ mimeType: z.string(),
17
+ data: z.string(),
18
+ }),
19
+ }),
20
+ ]);
21
+
12
22
  export const googleEmbeddingModelOptions = lazySchema(() =>
13
23
  zodSchema(
14
24
  z.object({
@@ -42,6 +52,13 @@ export const googleEmbeddingModelOptions = lazySchema(() =>
42
52
  'CODE_RETRIEVAL_QUERY',
43
53
  ])
44
54
  .optional(),
55
+
56
+ /**
57
+ * Optional. Multimodal content parts for embedding non-text content
58
+ * (images, video, PDF, audio). When provided, these parts are used
59
+ * instead of the text values in the embedding request.
60
+ */
61
+ content: z.array(googleEmbeddingContentPartSchema).min(1).optional(),
45
62
  }),
46
63
  ),
47
64
  );
@@ -304,17 +304,23 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
304
304
  : undefined,
305
305
  });
306
306
  } else if ('inlineData' in part) {
307
+ const hasThought = part.thought === true;
308
+ const hasThoughtSignature = !!part.thoughtSignature;
307
309
  content.push({
308
310
  type: 'file' as const,
309
311
  data: part.inlineData.data,
310
312
  mediaType: part.inlineData.mimeType,
311
- providerMetadata: part.thoughtSignature
312
- ? {
313
- [providerOptionsName]: {
314
- thoughtSignature: part.thoughtSignature,
315
- },
316
- }
317
- : undefined,
313
+ providerMetadata:
314
+ hasThought || hasThoughtSignature
315
+ ? {
316
+ [providerOptionsName]: {
317
+ ...(hasThought ? { thought: true } : {}),
318
+ ...(hasThoughtSignature
319
+ ? { thoughtSignature: part.thoughtSignature }
320
+ : {}),
321
+ },
322
+ }
323
+ : undefined,
318
324
  });
319
325
  }
320
326
  }
@@ -590,19 +596,24 @@ export class GoogleGenerativeAILanguageModel implements LanguageModelV3 {
590
596
  currentReasoningBlockId = null;
591
597
  }
592
598
 
593
- // Process file parts inline to preserve order with text
594
- const thoughtSignatureMetadata = part.thoughtSignature
595
- ? {
596
- [providerOptionsName]: {
597
- thoughtSignature: part.thoughtSignature,
598
- },
599
- }
600
- : undefined;
599
+ const hasThought = part.thought === true;
600
+ const hasThoughtSignature = !!part.thoughtSignature;
601
+ const fileMeta =
602
+ hasThought || hasThoughtSignature
603
+ ? {
604
+ [providerOptionsName]: {
605
+ ...(hasThought ? { thought: true } : {}),
606
+ ...(hasThoughtSignature
607
+ ? { thoughtSignature: part.thoughtSignature }
608
+ : {}),
609
+ },
610
+ }
611
+ : undefined;
601
612
  controller.enqueue({
602
613
  type: 'file',
603
614
  mediaType: part.inlineData.mimeType,
604
615
  data: part.inlineData.data,
605
- providerMetadata: thoughtSignatureMetadata,
616
+ providerMetadata: fileMeta,
606
617
  });
607
618
  }
608
619
  }
@@ -935,6 +946,7 @@ const getContentSchema = () =>
935
946
  mimeType: z.string(),
936
947
  data: z.string(),
937
948
  }),
949
+ thought: z.boolean().nullish(),
938
950
  thoughtSignature: z.string().nullish(),
939
951
  }),
940
952
  z.object({