@depup/ai-sdk__google 3.0.43-depup.0

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 (48) hide show
  1. package/CHANGELOG.md +2531 -0
  2. package/LICENSE +13 -0
  3. package/README.md +25 -0
  4. package/changes.json +5 -0
  5. package/dist/index.d.mts +367 -0
  6. package/dist/index.d.ts +367 -0
  7. package/dist/index.js +2404 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/index.mjs +2454 -0
  10. package/dist/index.mjs.map +1 -0
  11. package/dist/internal/index.d.mts +283 -0
  12. package/dist/internal/index.d.ts +283 -0
  13. package/dist/internal/index.js +1670 -0
  14. package/dist/internal/index.js.map +1 -0
  15. package/dist/internal/index.mjs +1678 -0
  16. package/dist/internal/index.mjs.map +1 -0
  17. package/docs/15-google-generative-ai.mdx +1298 -0
  18. package/internal.d.ts +1 -0
  19. package/package.json +96 -0
  20. package/src/convert-google-generative-ai-usage.ts +51 -0
  21. package/src/convert-json-schema-to-openapi-schema.ts +158 -0
  22. package/src/convert-to-google-generative-ai-messages.ts +236 -0
  23. package/src/get-model-path.ts +3 -0
  24. package/src/google-error.ts +26 -0
  25. package/src/google-generative-ai-embedding-model.ts +159 -0
  26. package/src/google-generative-ai-embedding-options.ts +51 -0
  27. package/src/google-generative-ai-image-model.ts +359 -0
  28. package/src/google-generative-ai-image-settings.ts +17 -0
  29. package/src/google-generative-ai-language-model.ts +1056 -0
  30. package/src/google-generative-ai-options.ts +198 -0
  31. package/src/google-generative-ai-prompt.ts +38 -0
  32. package/src/google-generative-ai-video-model.ts +374 -0
  33. package/src/google-generative-ai-video-settings.ts +8 -0
  34. package/src/google-prepare-tools.ts +254 -0
  35. package/src/google-provider.ts +227 -0
  36. package/src/google-supported-file-url.ts +20 -0
  37. package/src/google-tools.ts +71 -0
  38. package/src/index.ts +29 -0
  39. package/src/internal/index.ts +3 -0
  40. package/src/map-google-generative-ai-finish-reason.ts +29 -0
  41. package/src/tool/code-execution.ts +35 -0
  42. package/src/tool/enterprise-web-search.ts +18 -0
  43. package/src/tool/file-search.ts +51 -0
  44. package/src/tool/google-maps.ts +14 -0
  45. package/src/tool/google-search.ts +43 -0
  46. package/src/tool/url-context.ts +16 -0
  47. package/src/tool/vertex-rag-store.ts +31 -0
  48. package/src/version.ts +6 -0
@@ -0,0 +1,159 @@
1
+ import {
2
+ EmbeddingModelV3,
3
+ TooManyEmbeddingValuesForCallError,
4
+ } from '@ai-sdk/provider';
5
+ import {
6
+ combineHeaders,
7
+ createJsonResponseHandler,
8
+ FetchFunction,
9
+ lazySchema,
10
+ parseProviderOptions,
11
+ postJsonToApi,
12
+ resolve,
13
+ zodSchema,
14
+ } from '@ai-sdk/provider-utils';
15
+ import { z } from 'zod/v4';
16
+ import { googleFailedResponseHandler } from './google-error';
17
+ import {
18
+ GoogleGenerativeAIEmbeddingModelId,
19
+ googleEmbeddingModelOptions,
20
+ } from './google-generative-ai-embedding-options';
21
+
22
+ type GoogleGenerativeAIEmbeddingConfig = {
23
+ provider: string;
24
+ baseURL: string;
25
+ headers: () => Record<string, string | undefined>;
26
+ fetch?: FetchFunction;
27
+ };
28
+
29
+ export class GoogleGenerativeAIEmbeddingModel implements EmbeddingModelV3 {
30
+ readonly specificationVersion = 'v3';
31
+ readonly modelId: GoogleGenerativeAIEmbeddingModelId;
32
+ readonly maxEmbeddingsPerCall = 2048;
33
+ readonly supportsParallelCalls = true;
34
+
35
+ private readonly config: GoogleGenerativeAIEmbeddingConfig;
36
+
37
+ get provider(): string {
38
+ return this.config.provider;
39
+ }
40
+ constructor(
41
+ modelId: GoogleGenerativeAIEmbeddingModelId,
42
+ config: GoogleGenerativeAIEmbeddingConfig,
43
+ ) {
44
+ this.modelId = modelId;
45
+ this.config = config;
46
+ }
47
+
48
+ async doEmbed({
49
+ values,
50
+ headers,
51
+ abortSignal,
52
+ providerOptions,
53
+ }: Parameters<EmbeddingModelV3['doEmbed']>[0]): Promise<
54
+ Awaited<ReturnType<EmbeddingModelV3['doEmbed']>>
55
+ > {
56
+ // Parse provider options
57
+ const googleOptions = await parseProviderOptions({
58
+ provider: 'google',
59
+ providerOptions,
60
+ schema: googleEmbeddingModelOptions,
61
+ });
62
+
63
+ if (values.length > this.maxEmbeddingsPerCall) {
64
+ throw new TooManyEmbeddingValuesForCallError({
65
+ provider: this.provider,
66
+ modelId: this.modelId,
67
+ maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
68
+ values,
69
+ });
70
+ }
71
+
72
+ const mergedHeaders = combineHeaders(
73
+ await resolve(this.config.headers),
74
+ headers,
75
+ );
76
+
77
+ // For single embeddings, use the single endpoint (ratelimits, etc.)
78
+ if (values.length === 1) {
79
+ const {
80
+ responseHeaders,
81
+ value: response,
82
+ rawValue,
83
+ } = await postJsonToApi({
84
+ url: `${this.config.baseURL}/models/${this.modelId}:embedContent`,
85
+ headers: mergedHeaders,
86
+ body: {
87
+ model: `models/${this.modelId}`,
88
+ content: {
89
+ parts: [{ text: values[0] }],
90
+ },
91
+ outputDimensionality: googleOptions?.outputDimensionality,
92
+ taskType: googleOptions?.taskType,
93
+ },
94
+ failedResponseHandler: googleFailedResponseHandler,
95
+ successfulResponseHandler: createJsonResponseHandler(
96
+ googleGenerativeAISingleEmbeddingResponseSchema,
97
+ ),
98
+ abortSignal,
99
+ fetch: this.config.fetch,
100
+ });
101
+
102
+ return {
103
+ warnings: [],
104
+ embeddings: [response.embedding.values],
105
+ usage: undefined,
106
+ response: { headers: responseHeaders, body: rawValue },
107
+ };
108
+ }
109
+
110
+ const {
111
+ responseHeaders,
112
+ value: response,
113
+ rawValue,
114
+ } = await postJsonToApi({
115
+ url: `${this.config.baseURL}/models/${this.modelId}:batchEmbedContents`,
116
+ headers: mergedHeaders,
117
+ 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
+ })),
124
+ },
125
+ failedResponseHandler: googleFailedResponseHandler,
126
+ successfulResponseHandler: createJsonResponseHandler(
127
+ googleGenerativeAITextEmbeddingResponseSchema,
128
+ ),
129
+ abortSignal,
130
+ fetch: this.config.fetch,
131
+ });
132
+
133
+ return {
134
+ warnings: [],
135
+ embeddings: response.embeddings.map(item => item.values),
136
+ usage: undefined,
137
+ response: { headers: responseHeaders, body: rawValue },
138
+ };
139
+ }
140
+ }
141
+
142
+ // minimal version of the schema, focussed on what is needed for the implementation
143
+ // this approach limits breakages when the API changes and increases efficiency
144
+ const googleGenerativeAITextEmbeddingResponseSchema = lazySchema(() =>
145
+ zodSchema(
146
+ z.object({
147
+ embeddings: z.array(z.object({ values: z.array(z.number()) })),
148
+ }),
149
+ ),
150
+ );
151
+
152
+ // Schema for single embedding response
153
+ const googleGenerativeAISingleEmbeddingResponseSchema = lazySchema(() =>
154
+ zodSchema(
155
+ z.object({
156
+ embedding: z.object({ values: z.array(z.number()) }),
157
+ }),
158
+ ),
159
+ );
@@ -0,0 +1,51 @@
1
+ import {
2
+ type InferSchema,
3
+ lazySchema,
4
+ zodSchema,
5
+ } from '@ai-sdk/provider-utils';
6
+ import { z } from 'zod/v4';
7
+
8
+ export type GoogleGenerativeAIEmbeddingModelId =
9
+ | 'gemini-embedding-001'
10
+ | (string & {});
11
+
12
+ export const googleEmbeddingModelOptions = lazySchema(() =>
13
+ zodSchema(
14
+ z.object({
15
+ /**
16
+ * Optional. Optional reduced dimension for the output embedding.
17
+ * If set, excessive values in the output embedding are truncated from the end.
18
+ */
19
+ outputDimensionality: z.number().optional(),
20
+
21
+ /**
22
+ * Optional. Specifies the task type for generating embeddings.
23
+ * Supported task types:
24
+ * - SEMANTIC_SIMILARITY: Optimized for text similarity.
25
+ * - CLASSIFICATION: Optimized for text classification.
26
+ * - CLUSTERING: Optimized for clustering texts based on similarity.
27
+ * - RETRIEVAL_DOCUMENT: Optimized for document retrieval.
28
+ * - RETRIEVAL_QUERY: Optimized for query-based retrieval.
29
+ * - QUESTION_ANSWERING: Optimized for answering questions.
30
+ * - FACT_VERIFICATION: Optimized for verifying factual information.
31
+ * - CODE_RETRIEVAL_QUERY: Optimized for retrieving code blocks based on natural language queries.
32
+ */
33
+ taskType: z
34
+ .enum([
35
+ 'SEMANTIC_SIMILARITY',
36
+ 'CLASSIFICATION',
37
+ 'CLUSTERING',
38
+ 'RETRIEVAL_DOCUMENT',
39
+ 'RETRIEVAL_QUERY',
40
+ 'QUESTION_ANSWERING',
41
+ 'FACT_VERIFICATION',
42
+ 'CODE_RETRIEVAL_QUERY',
43
+ ])
44
+ .optional(),
45
+ }),
46
+ ),
47
+ );
48
+
49
+ export type GoogleEmbeddingModelOptions = InferSchema<
50
+ typeof googleEmbeddingModelOptions
51
+ >;
@@ -0,0 +1,359 @@
1
+ import {
2
+ ImageModelV3,
3
+ LanguageModelV3Prompt,
4
+ SharedV3Warning,
5
+ } from '@ai-sdk/provider';
6
+ import {
7
+ combineHeaders,
8
+ convertToBase64,
9
+ createJsonResponseHandler,
10
+ FetchFunction,
11
+ generateId as defaultGenerateId,
12
+ type InferSchema,
13
+ lazySchema,
14
+ parseProviderOptions,
15
+ postJsonToApi,
16
+ Resolvable,
17
+ resolve,
18
+ zodSchema,
19
+ } from '@ai-sdk/provider-utils';
20
+ import { z } from 'zod/v4';
21
+ import { googleFailedResponseHandler } from './google-error';
22
+ import {
23
+ GoogleGenerativeAIImageModelId,
24
+ GoogleGenerativeAIImageSettings,
25
+ } from './google-generative-ai-image-settings';
26
+ import { GoogleGenerativeAILanguageModel } from './google-generative-ai-language-model';
27
+ import type { GoogleLanguageModelOptions } from './google-generative-ai-options';
28
+
29
+ interface GoogleGenerativeAIImageModelConfig {
30
+ provider: string;
31
+ baseURL: string;
32
+ headers?: Resolvable<Record<string, string | undefined>>;
33
+ fetch?: FetchFunction;
34
+ generateId?: () => string;
35
+ _internal?: {
36
+ currentDate?: () => Date;
37
+ };
38
+ }
39
+
40
+ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
41
+ readonly specificationVersion = 'v3';
42
+
43
+ get maxImagesPerCall(): number {
44
+ if (this.settings.maxImagesPerCall != null) {
45
+ return this.settings.maxImagesPerCall;
46
+ }
47
+ // https://docs.cloud.google.com/vertex-ai/generative-ai/docs/models/gemini/2-5-flash-image
48
+ if (isGeminiModel(this.modelId)) {
49
+ return 10;
50
+ }
51
+ // https://ai.google.dev/gemini-api/docs/imagen#imagen-model
52
+ return 4;
53
+ }
54
+
55
+ get provider(): string {
56
+ return this.config.provider;
57
+ }
58
+
59
+ constructor(
60
+ readonly modelId: GoogleGenerativeAIImageModelId,
61
+ private readonly settings: GoogleGenerativeAIImageSettings,
62
+ private readonly config: GoogleGenerativeAIImageModelConfig,
63
+ ) {}
64
+
65
+ async doGenerate(
66
+ options: Parameters<ImageModelV3['doGenerate']>[0],
67
+ ): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>> {
68
+ // Gemini image models use the language model API internally
69
+ if (isGeminiModel(this.modelId)) {
70
+ return this.doGenerateGemini(options);
71
+ }
72
+ return this.doGenerateImagen(options);
73
+ }
74
+
75
+ private async doGenerateImagen(
76
+ options: Parameters<ImageModelV3['doGenerate']>[0],
77
+ ): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>> {
78
+ const {
79
+ prompt,
80
+ n = 1,
81
+ size,
82
+ aspectRatio = '1:1',
83
+ seed,
84
+ providerOptions,
85
+ headers,
86
+ abortSignal,
87
+ files,
88
+ mask,
89
+ } = options;
90
+ const warnings: Array<SharedV3Warning> = [];
91
+
92
+ // Imagen API endpoints do not support image editing
93
+ if (files != null && files.length > 0) {
94
+ throw new Error(
95
+ 'Google Generative AI does not support image editing with Imagen models. ' +
96
+ 'Use Google Vertex AI (@ai-sdk/google-vertex) for image editing capabilities.',
97
+ );
98
+ }
99
+
100
+ if (mask != null) {
101
+ throw new Error(
102
+ 'Google Generative AI does not support image editing with masks. ' +
103
+ 'Use Google Vertex AI (@ai-sdk/google-vertex) for image editing capabilities.',
104
+ );
105
+ }
106
+
107
+ if (size != null) {
108
+ warnings.push({
109
+ type: 'unsupported',
110
+ feature: 'size',
111
+ details:
112
+ 'This model does not support the `size` option. Use `aspectRatio` instead.',
113
+ });
114
+ }
115
+
116
+ if (seed != null) {
117
+ warnings.push({
118
+ type: 'unsupported',
119
+ feature: 'seed',
120
+ details:
121
+ 'This model does not support the `seed` option through this provider.',
122
+ });
123
+ }
124
+
125
+ const googleOptions = await parseProviderOptions({
126
+ provider: 'google',
127
+ providerOptions,
128
+ schema: googleImageModelOptionsSchema,
129
+ });
130
+
131
+ const currentDate = this.config._internal?.currentDate?.() ?? new Date();
132
+
133
+ const parameters: Record<string, unknown> = {
134
+ sampleCount: n,
135
+ };
136
+
137
+ if (aspectRatio != null) {
138
+ parameters.aspectRatio = aspectRatio;
139
+ }
140
+
141
+ if (googleOptions) {
142
+ Object.assign(parameters, googleOptions);
143
+ }
144
+
145
+ const body = {
146
+ instances: [{ prompt }],
147
+ parameters,
148
+ };
149
+
150
+ const { responseHeaders, value: response } = await postJsonToApi<{
151
+ predictions: Array<{ bytesBase64Encoded: string }>;
152
+ }>({
153
+ url: `${this.config.baseURL}/models/${this.modelId}:predict`,
154
+ headers: combineHeaders(await resolve(this.config.headers), headers),
155
+ body,
156
+ failedResponseHandler: googleFailedResponseHandler,
157
+ successfulResponseHandler: createJsonResponseHandler(
158
+ googleImageResponseSchema,
159
+ ),
160
+ abortSignal,
161
+ fetch: this.config.fetch,
162
+ });
163
+ return {
164
+ images: response.predictions.map(
165
+ (p: { bytesBase64Encoded: string }) => p.bytesBase64Encoded,
166
+ ),
167
+ warnings,
168
+ providerMetadata: {
169
+ google: {
170
+ images: response.predictions.map(() => ({
171
+ // Add any prediction-specific metadata here
172
+ })),
173
+ },
174
+ },
175
+ response: {
176
+ timestamp: currentDate,
177
+ modelId: this.modelId,
178
+ headers: responseHeaders,
179
+ },
180
+ };
181
+ }
182
+
183
+ private async doGenerateGemini(
184
+ options: Parameters<ImageModelV3['doGenerate']>[0],
185
+ ): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>> {
186
+ const {
187
+ prompt,
188
+ n,
189
+ size,
190
+ aspectRatio,
191
+ seed,
192
+ providerOptions,
193
+ headers,
194
+ abortSignal,
195
+ files,
196
+ mask,
197
+ } = options;
198
+ const warnings: Array<SharedV3Warning> = [];
199
+
200
+ // Gemini does not support mask-based inpainting
201
+ if (mask != null) {
202
+ throw new Error(
203
+ 'Gemini image models do not support mask-based image editing.',
204
+ );
205
+ }
206
+
207
+ // Gemini does not support generating multiple images per call via n parameter
208
+ if (n != null && n > 1) {
209
+ throw new Error(
210
+ 'Gemini image models do not support generating a set number of images per call. Use n=1 or omit the n parameter.',
211
+ );
212
+ }
213
+
214
+ if (size != null) {
215
+ warnings.push({
216
+ type: 'unsupported',
217
+ feature: 'size',
218
+ details:
219
+ 'This model does not support the `size` option. Use `aspectRatio` instead.',
220
+ });
221
+ }
222
+
223
+ // Build user message content for language model
224
+ const userContent: Array<
225
+ | { type: 'text'; text: string }
226
+ | { type: 'file'; data: string | Uint8Array | URL; mediaType: string }
227
+ > = [];
228
+
229
+ // Add text prompt
230
+ if (prompt != null) {
231
+ userContent.push({ type: 'text', text: prompt });
232
+ }
233
+
234
+ // Add input images for editing
235
+ if (files != null && files.length > 0) {
236
+ for (const file of files) {
237
+ if (file.type === 'url') {
238
+ userContent.push({
239
+ type: 'file',
240
+ data: new URL(file.url),
241
+ mediaType: 'image/*',
242
+ });
243
+ } else {
244
+ userContent.push({
245
+ type: 'file',
246
+ data:
247
+ typeof file.data === 'string'
248
+ ? file.data
249
+ : new Uint8Array(file.data),
250
+ mediaType: file.mediaType,
251
+ });
252
+ }
253
+ }
254
+ }
255
+
256
+ const languageModelPrompt: LanguageModelV3Prompt = [
257
+ { role: 'user', content: userContent },
258
+ ];
259
+
260
+ // Instantiate language model
261
+ const languageModel = new GoogleGenerativeAILanguageModel(this.modelId, {
262
+ provider: this.config.provider,
263
+ baseURL: this.config.baseURL,
264
+ headers: this.config.headers ?? {},
265
+ fetch: this.config.fetch,
266
+ generateId: this.config.generateId ?? defaultGenerateId,
267
+ });
268
+
269
+ // Call language model with image-only response modality
270
+ const result = await languageModel.doGenerate({
271
+ prompt: languageModelPrompt,
272
+ seed,
273
+ providerOptions: {
274
+ google: {
275
+ responseModalities: ['IMAGE'],
276
+ imageConfig: aspectRatio
277
+ ? {
278
+ aspectRatio: aspectRatio as NonNullable<
279
+ GoogleLanguageModelOptions['imageConfig']
280
+ >['aspectRatio'],
281
+ }
282
+ : undefined,
283
+ ...((providerOptions?.google as Omit<
284
+ GoogleLanguageModelOptions,
285
+ 'responseModalities' | 'imageConfig'
286
+ >) ?? {}),
287
+ } satisfies GoogleLanguageModelOptions,
288
+ },
289
+ headers,
290
+ abortSignal,
291
+ });
292
+
293
+ const currentDate = this.config._internal?.currentDate?.() ?? new Date();
294
+
295
+ // Extract images from language model response
296
+ const images: string[] = [];
297
+ for (const part of result.content) {
298
+ if (part.type === 'file' && part.mediaType.startsWith('image/')) {
299
+ images.push(convertToBase64(part.data));
300
+ }
301
+ }
302
+
303
+ return {
304
+ images,
305
+ warnings,
306
+ providerMetadata: {
307
+ google: {
308
+ images: images.map(() => ({})),
309
+ },
310
+ },
311
+ response: {
312
+ timestamp: currentDate,
313
+ modelId: this.modelId,
314
+ headers: result.response?.headers,
315
+ },
316
+ usage: result.usage
317
+ ? {
318
+ inputTokens: result.usage.inputTokens.total,
319
+ outputTokens: result.usage.outputTokens.total,
320
+ totalTokens:
321
+ (result.usage.inputTokens.total ?? 0) +
322
+ (result.usage.outputTokens.total ?? 0),
323
+ }
324
+ : undefined,
325
+ };
326
+ }
327
+ }
328
+
329
+ function isGeminiModel(modelId: string): boolean {
330
+ return modelId.startsWith('gemini-');
331
+ }
332
+
333
+ // minimal version of the schema
334
+ const googleImageResponseSchema = lazySchema(() =>
335
+ zodSchema(
336
+ z.object({
337
+ predictions: z
338
+ .array(z.object({ bytesBase64Encoded: z.string() }))
339
+ .default([]),
340
+ }),
341
+ ),
342
+ );
343
+
344
+ // Note: For the initial GA launch of Imagen 3, safety filters are not configurable.
345
+ // https://ai.google.dev/gemini-api/docs/imagen#imagen-model
346
+ const googleImageModelOptionsSchema = lazySchema(() =>
347
+ zodSchema(
348
+ z.object({
349
+ personGeneration: z
350
+ .enum(['dont_allow', 'allow_adult', 'allow_all'])
351
+ .nullish(),
352
+ aspectRatio: z.enum(['1:1', '3:4', '4:3', '9:16', '16:9']).nullish(),
353
+ }),
354
+ ),
355
+ );
356
+
357
+ export type GoogleImageModelOptions = InferSchema<
358
+ typeof googleImageModelOptionsSchema
359
+ >;
@@ -0,0 +1,17 @@
1
+ export type GoogleGenerativeAIImageModelId =
2
+ // Imagen models (use :predict API)
3
+ | 'imagen-4.0-generate-001'
4
+ | 'imagen-4.0-ultra-generate-001'
5
+ | 'imagen-4.0-fast-generate-001'
6
+ // Gemini image models (technically multimodal output language models, use :generateContent API)
7
+ | 'gemini-2.5-flash-image'
8
+ | 'gemini-3-pro-image-preview'
9
+ | 'gemini-3.1-flash-image-preview'
10
+ | (string & {});
11
+
12
+ export interface GoogleGenerativeAIImageSettings {
13
+ /**
14
+ * Override the maximum number of images per call (default 4)
15
+ */
16
+ maxImagesPerCall?: number;
17
+ }