@ai-sdk/google 4.0.0-beta.8 → 4.0.0-canary.50
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/CHANGELOG.md +351 -4
- package/README.md +6 -4
- package/dist/index.d.ts +97 -54
- package/dist/index.js +1644 -580
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +66 -26
- package/dist/internal/index.js +1258 -450
- package/dist/internal/index.js.map +1 -1
- package/docs/{15-google-generative-ai.mdx → 15-google.mdx} +46 -40
- package/package.json +13 -14
- package/src/{convert-google-generative-ai-usage.ts → convert-google-usage.ts} +12 -5
- package/src/convert-json-schema-to-openapi-schema.ts +1 -1
- package/src/convert-to-google-messages.ts +577 -0
- package/src/{google-generative-ai-embedding-options.ts → google-embedding-model-options.ts} +2 -2
- package/src/{google-generative-ai-embedding-model.ts → google-embedding-model.ts} +31 -18
- package/src/google-error.ts +1 -1
- package/src/google-files.ts +225 -0
- package/src/google-image-model-options.ts +23 -0
- package/src/{google-generative-ai-image-model.ts → google-image-model.ts} +74 -62
- package/src/{google-generative-ai-image-settings.ts → google-image-settings.ts} +2 -2
- package/src/google-json-accumulator.ts +336 -0
- package/src/{google-generative-ai-options.ts → google-language-model-options.ts} +32 -5
- package/src/{google-generative-ai-language-model.ts → google-language-model.ts} +609 -214
- package/src/google-prepare-tools.ts +72 -12
- package/src/google-prompt.ts +82 -0
- package/src/google-provider.ts +63 -54
- package/src/google-video-model-options.ts +43 -0
- package/src/{google-generative-ai-video-model.ts → google-video-model.ts} +17 -56
- package/src/{google-generative-ai-video-settings.ts → google-video-settings.ts} +2 -1
- package/src/index.ts +28 -9
- package/src/internal/index.ts +2 -2
- package/src/{map-google-generative-ai-finish-reason.ts → map-google-finish-reason.ts} +3 -3
- package/src/tool/code-execution.ts +2 -2
- package/src/tool/enterprise-web-search.ts +9 -3
- package/src/tool/file-search.ts +5 -7
- package/src/tool/google-maps.ts +3 -2
- package/src/tool/google-search.ts +10 -11
- package/src/tool/url-context.ts +4 -2
- package/src/tool/vertex-rag-store.ts +9 -6
- package/dist/index.d.mts +0 -384
- package/dist/index.mjs +0 -2519
- package/dist/index.mjs.map +0 -1
- package/dist/internal/index.d.mts +0 -287
- package/dist/internal/index.mjs +0 -1708
- package/dist/internal/index.mjs.map +0 -1
- package/src/convert-to-google-generative-ai-messages.ts +0 -239
- package/src/google-generative-ai-prompt.ts +0 -47
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AISDKError,
|
|
3
|
+
type FilesV4,
|
|
4
|
+
type FilesV4UploadFileCallOptions,
|
|
5
|
+
type FilesV4UploadFileResult,
|
|
6
|
+
type SharedV4Warning,
|
|
7
|
+
} from '@ai-sdk/provider';
|
|
8
|
+
import {
|
|
9
|
+
combineHeaders,
|
|
10
|
+
convertInlineFileDataToUint8Array,
|
|
11
|
+
createJsonResponseHandler,
|
|
12
|
+
delay,
|
|
13
|
+
lazySchema,
|
|
14
|
+
parseProviderOptions,
|
|
15
|
+
zodSchema,
|
|
16
|
+
getFromApi,
|
|
17
|
+
type FetchFunction,
|
|
18
|
+
} from '@ai-sdk/provider-utils';
|
|
19
|
+
import { z } from 'zod/v4';
|
|
20
|
+
import { googleFailedResponseHandler } from './google-error';
|
|
21
|
+
|
|
22
|
+
export type GoogleFilesUploadOptions = {
|
|
23
|
+
displayName?: string | null;
|
|
24
|
+
pollIntervalMs?: number | null;
|
|
25
|
+
pollTimeoutMs?: number | null;
|
|
26
|
+
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
interface GoogleFilesConfig {
|
|
31
|
+
provider: string;
|
|
32
|
+
baseURL: string;
|
|
33
|
+
headers: () => Record<string, string | undefined>;
|
|
34
|
+
fetch?: FetchFunction;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class GoogleFiles implements FilesV4 {
|
|
38
|
+
readonly specificationVersion = 'v4';
|
|
39
|
+
|
|
40
|
+
get provider(): string {
|
|
41
|
+
return this.config.provider;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
constructor(private readonly config: GoogleFilesConfig) {}
|
|
45
|
+
|
|
46
|
+
async uploadFile(
|
|
47
|
+
options: FilesV4UploadFileCallOptions,
|
|
48
|
+
): Promise<FilesV4UploadFileResult> {
|
|
49
|
+
const googleOptions = (await parseProviderOptions({
|
|
50
|
+
provider: 'google',
|
|
51
|
+
providerOptions: options.providerOptions,
|
|
52
|
+
schema: googleFilesUploadOptionsSchema,
|
|
53
|
+
})) as GoogleFilesUploadOptions | undefined;
|
|
54
|
+
|
|
55
|
+
const resolvedHeaders = this.config.headers();
|
|
56
|
+
const fetchFn = this.config.fetch ?? globalThis.fetch;
|
|
57
|
+
|
|
58
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
59
|
+
if (options.filename != null) {
|
|
60
|
+
warnings.push({ type: 'unsupported', feature: 'filename' });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const fileBytes = convertInlineFileDataToUint8Array(options.data);
|
|
64
|
+
|
|
65
|
+
const mediaType = options.mediaType;
|
|
66
|
+
const displayName = googleOptions?.displayName;
|
|
67
|
+
|
|
68
|
+
const baseOrigin = this.config.baseURL.replace(/\/v1beta$/, '');
|
|
69
|
+
|
|
70
|
+
const initResponse = await fetchFn(`${baseOrigin}/upload/v1beta/files`, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: {
|
|
73
|
+
...resolvedHeaders,
|
|
74
|
+
'X-Goog-Upload-Protocol': 'resumable',
|
|
75
|
+
'X-Goog-Upload-Command': 'start',
|
|
76
|
+
'X-Goog-Upload-Header-Content-Length': String(fileBytes.length),
|
|
77
|
+
'X-Goog-Upload-Header-Content-Type': mediaType,
|
|
78
|
+
'Content-Type': 'application/json',
|
|
79
|
+
},
|
|
80
|
+
body: JSON.stringify({
|
|
81
|
+
file: {
|
|
82
|
+
...(displayName != null ? { display_name: displayName } : {}),
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (!initResponse.ok) {
|
|
88
|
+
const errorBody = await initResponse.text();
|
|
89
|
+
throw new AISDKError({
|
|
90
|
+
name: 'GOOGLE_FILES_UPLOAD_ERROR',
|
|
91
|
+
message: `Failed to initiate resumable upload: ${initResponse.status} ${errorBody}`,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const uploadUrl = initResponse.headers.get('x-goog-upload-url');
|
|
96
|
+
if (!uploadUrl) {
|
|
97
|
+
throw new AISDKError({
|
|
98
|
+
name: 'GOOGLE_FILES_UPLOAD_ERROR',
|
|
99
|
+
message: 'No upload URL returned from initiation request',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const uploadResponse = await fetchFn(uploadUrl, {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
headers: {
|
|
106
|
+
'Content-Length': String(fileBytes.length),
|
|
107
|
+
'X-Goog-Upload-Offset': '0',
|
|
108
|
+
'X-Goog-Upload-Command': 'upload, finalize',
|
|
109
|
+
},
|
|
110
|
+
body: fileBytes,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
if (!uploadResponse.ok) {
|
|
114
|
+
const errorBody = await uploadResponse.text();
|
|
115
|
+
throw new AISDKError({
|
|
116
|
+
name: 'GOOGLE_FILES_UPLOAD_ERROR',
|
|
117
|
+
message: `Failed to upload file data: ${uploadResponse.status} ${errorBody}`,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const uploadResult = (await uploadResponse.json()) as {
|
|
122
|
+
file: GoogleFileResource;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
let file = uploadResult.file;
|
|
126
|
+
|
|
127
|
+
const pollIntervalMs = googleOptions?.pollIntervalMs ?? 2000;
|
|
128
|
+
const pollTimeoutMs = googleOptions?.pollTimeoutMs ?? 300000;
|
|
129
|
+
const startTime = Date.now();
|
|
130
|
+
|
|
131
|
+
while (file.state === 'PROCESSING') {
|
|
132
|
+
if (Date.now() - startTime > pollTimeoutMs) {
|
|
133
|
+
throw new AISDKError({
|
|
134
|
+
name: 'GOOGLE_FILES_UPLOAD_TIMEOUT',
|
|
135
|
+
message: `File processing timed out after ${pollTimeoutMs}ms`,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
await delay(pollIntervalMs);
|
|
140
|
+
|
|
141
|
+
const { value: fileStatus } = await getFromApi({
|
|
142
|
+
url: `${this.config.baseURL}/${file.name}`,
|
|
143
|
+
headers: combineHeaders(resolvedHeaders),
|
|
144
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
145
|
+
googleFileResponseSchema,
|
|
146
|
+
),
|
|
147
|
+
failedResponseHandler: googleFailedResponseHandler,
|
|
148
|
+
fetch: this.config.fetch,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
file = fileStatus;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (file.state === 'FAILED') {
|
|
155
|
+
throw new AISDKError({
|
|
156
|
+
name: 'GOOGLE_FILES_UPLOAD_FAILED',
|
|
157
|
+
message: `File processing failed for ${file.name}`,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
warnings,
|
|
163
|
+
providerReference: { google: file.uri },
|
|
164
|
+
mediaType: file.mimeType ?? options.mediaType,
|
|
165
|
+
providerMetadata: {
|
|
166
|
+
google: {
|
|
167
|
+
name: file.name,
|
|
168
|
+
displayName: file.displayName,
|
|
169
|
+
mimeType: file.mimeType,
|
|
170
|
+
sizeBytes: file.sizeBytes,
|
|
171
|
+
state: file.state,
|
|
172
|
+
uri: file.uri,
|
|
173
|
+
...(file.createTime != null ? { createTime: file.createTime } : {}),
|
|
174
|
+
...(file.updateTime != null ? { updateTime: file.updateTime } : {}),
|
|
175
|
+
...(file.expirationTime != null
|
|
176
|
+
? { expirationTime: file.expirationTime }
|
|
177
|
+
: {}),
|
|
178
|
+
...(file.sha256Hash != null ? { sha256Hash: file.sha256Hash } : {}),
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
type GoogleFileResource = {
|
|
186
|
+
name: string;
|
|
187
|
+
displayName?: string | null;
|
|
188
|
+
mimeType: string;
|
|
189
|
+
sizeBytes?: string | null;
|
|
190
|
+
createTime?: string | null;
|
|
191
|
+
updateTime?: string | null;
|
|
192
|
+
expirationTime?: string | null;
|
|
193
|
+
sha256Hash?: string | null;
|
|
194
|
+
uri: string;
|
|
195
|
+
state: string;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const googleFileResponseSchema = lazySchema(() =>
|
|
199
|
+
zodSchema(
|
|
200
|
+
z.object({
|
|
201
|
+
name: z.string(),
|
|
202
|
+
displayName: z.string().nullish(),
|
|
203
|
+
mimeType: z.string(),
|
|
204
|
+
sizeBytes: z.string().nullish(),
|
|
205
|
+
createTime: z.string().nullish(),
|
|
206
|
+
updateTime: z.string().nullish(),
|
|
207
|
+
expirationTime: z.string().nullish(),
|
|
208
|
+
sha256Hash: z.string().nullish(),
|
|
209
|
+
uri: z.string(),
|
|
210
|
+
state: z.string(),
|
|
211
|
+
}),
|
|
212
|
+
),
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
const googleFilesUploadOptionsSchema = lazySchema(() =>
|
|
216
|
+
zodSchema(
|
|
217
|
+
z
|
|
218
|
+
.object({
|
|
219
|
+
displayName: z.string().nullish(),
|
|
220
|
+
pollIntervalMs: z.number().positive().nullish(),
|
|
221
|
+
pollTimeoutMs: z.number().positive().nullish(),
|
|
222
|
+
})
|
|
223
|
+
.passthrough(),
|
|
224
|
+
),
|
|
225
|
+
);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {
|
|
2
|
+
lazySchema,
|
|
3
|
+
zodSchema,
|
|
4
|
+
type InferSchema,
|
|
5
|
+
} from '@ai-sdk/provider-utils';
|
|
6
|
+
import { z } from 'zod/v4';
|
|
7
|
+
|
|
8
|
+
// Note: For the initial GA launch of Imagen 3, safety filters are not configurable.
|
|
9
|
+
// https://ai.google.dev/gemini-api/docs/imagen#imagen-model
|
|
10
|
+
export const googleImageModelOptionsSchema = lazySchema(() =>
|
|
11
|
+
zodSchema(
|
|
12
|
+
z.object({
|
|
13
|
+
personGeneration: z
|
|
14
|
+
.enum(['dont_allow', 'allow_adult', 'allow_all'])
|
|
15
|
+
.nullish(),
|
|
16
|
+
aspectRatio: z.enum(['1:1', '3:4', '4:3', '9:16', '16:9']).nullish(),
|
|
17
|
+
}),
|
|
18
|
+
),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export type GoogleImageModelOptions = InferSchema<
|
|
22
|
+
typeof googleImageModelOptionsSchema
|
|
23
|
+
>;
|
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import type {
|
|
2
|
+
ImageModelV4,
|
|
3
|
+
LanguageModelV4Prompt,
|
|
4
|
+
SharedV4Warning,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import {
|
|
7
7
|
combineHeaders,
|
|
8
8
|
convertToBase64,
|
|
9
9
|
createJsonResponseHandler,
|
|
10
|
-
FetchFunction,
|
|
11
10
|
generateId as defaultGenerateId,
|
|
12
|
-
type InferSchema,
|
|
13
11
|
lazySchema,
|
|
14
12
|
parseProviderOptions,
|
|
15
13
|
postJsonToApi,
|
|
16
|
-
Resolvable,
|
|
17
14
|
resolve,
|
|
15
|
+
serializeModelOptions,
|
|
16
|
+
WORKFLOW_SERIALIZE,
|
|
17
|
+
WORKFLOW_DESERIALIZE,
|
|
18
18
|
zodSchema,
|
|
19
|
+
type FetchFunction,
|
|
20
|
+
type Resolvable,
|
|
19
21
|
} from '@ai-sdk/provider-utils';
|
|
20
22
|
import { z } from 'zod/v4';
|
|
21
23
|
import { googleFailedResponseHandler } from './google-error';
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
import
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
import { googleImageModelOptionsSchema } from './google-image-model-options';
|
|
25
|
+
import type {
|
|
26
|
+
GoogleImageModelId,
|
|
27
|
+
GoogleImageSettings,
|
|
28
|
+
} from './google-image-settings';
|
|
29
|
+
import { GoogleLanguageModel } from './google-language-model';
|
|
30
|
+
import type { GoogleLanguageModelOptions } from './google-language-model-options';
|
|
31
|
+
|
|
32
|
+
interface GoogleImageModelConfig {
|
|
30
33
|
provider: string;
|
|
31
34
|
baseURL: string;
|
|
32
35
|
headers?: Resolvable<Record<string, string | undefined>>;
|
|
@@ -37,8 +40,22 @@ interface GoogleGenerativeAIImageModelConfig {
|
|
|
37
40
|
};
|
|
38
41
|
}
|
|
39
42
|
|
|
40
|
-
export class
|
|
41
|
-
readonly specificationVersion = '
|
|
43
|
+
export class GoogleImageModel implements ImageModelV4 {
|
|
44
|
+
readonly specificationVersion = 'v4';
|
|
45
|
+
|
|
46
|
+
static [WORKFLOW_SERIALIZE](model: GoogleImageModel) {
|
|
47
|
+
return serializeModelOptions({
|
|
48
|
+
modelId: model.modelId,
|
|
49
|
+
config: model.config,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
54
|
+
modelId: string;
|
|
55
|
+
config: GoogleImageModelConfig;
|
|
56
|
+
}) {
|
|
57
|
+
return new GoogleImageModel(options.modelId, {}, options.config);
|
|
58
|
+
}
|
|
42
59
|
|
|
43
60
|
get maxImagesPerCall(): number {
|
|
44
61
|
if (this.settings.maxImagesPerCall != null) {
|
|
@@ -57,14 +74,14 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
|
|
|
57
74
|
}
|
|
58
75
|
|
|
59
76
|
constructor(
|
|
60
|
-
readonly modelId:
|
|
61
|
-
private readonly settings:
|
|
62
|
-
private readonly config:
|
|
77
|
+
readonly modelId: GoogleImageModelId,
|
|
78
|
+
private readonly settings: GoogleImageSettings,
|
|
79
|
+
private readonly config: GoogleImageModelConfig,
|
|
63
80
|
) {}
|
|
64
81
|
|
|
65
82
|
async doGenerate(
|
|
66
|
-
options: Parameters<
|
|
67
|
-
): Promise<Awaited<ReturnType<
|
|
83
|
+
options: Parameters<ImageModelV4['doGenerate']>[0],
|
|
84
|
+
): Promise<Awaited<ReturnType<ImageModelV4['doGenerate']>>> {
|
|
68
85
|
// Gemini image models use the language model API internally
|
|
69
86
|
if (isGeminiModel(this.modelId)) {
|
|
70
87
|
return this.doGenerateGemini(options);
|
|
@@ -73,8 +90,8 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
|
|
|
73
90
|
}
|
|
74
91
|
|
|
75
92
|
private async doGenerateImagen(
|
|
76
|
-
options: Parameters<
|
|
77
|
-
): Promise<Awaited<ReturnType<
|
|
93
|
+
options: Parameters<ImageModelV4['doGenerate']>[0],
|
|
94
|
+
): Promise<Awaited<ReturnType<ImageModelV4['doGenerate']>>> {
|
|
78
95
|
const {
|
|
79
96
|
prompt,
|
|
80
97
|
n = 1,
|
|
@@ -87,19 +104,19 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
|
|
|
87
104
|
files,
|
|
88
105
|
mask,
|
|
89
106
|
} = options;
|
|
90
|
-
const warnings: Array<
|
|
107
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
91
108
|
|
|
92
109
|
// Imagen API endpoints do not support image editing
|
|
93
110
|
if (files != null && files.length > 0) {
|
|
94
111
|
throw new Error(
|
|
95
|
-
'Google
|
|
112
|
+
'Google Gemini API does not support image editing with Imagen models. ' +
|
|
96
113
|
'Use Google Vertex AI (@ai-sdk/google-vertex) for image editing capabilities.',
|
|
97
114
|
);
|
|
98
115
|
}
|
|
99
116
|
|
|
100
117
|
if (mask != null) {
|
|
101
118
|
throw new Error(
|
|
102
|
-
'Google
|
|
119
|
+
'Google Gemini API does not support image editing with masks. ' +
|
|
103
120
|
'Use Google Vertex AI (@ai-sdk/google-vertex) for image editing capabilities.',
|
|
104
121
|
);
|
|
105
122
|
}
|
|
@@ -151,7 +168,10 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
|
|
|
151
168
|
predictions: Array<{ bytesBase64Encoded: string }>;
|
|
152
169
|
}>({
|
|
153
170
|
url: `${this.config.baseURL}/models/${this.modelId}:predict`,
|
|
154
|
-
headers: combineHeaders(
|
|
171
|
+
headers: combineHeaders(
|
|
172
|
+
this.config.headers ? await resolve(this.config.headers) : undefined,
|
|
173
|
+
headers,
|
|
174
|
+
),
|
|
155
175
|
body,
|
|
156
176
|
failedResponseHandler: googleFailedResponseHandler,
|
|
157
177
|
successfulResponseHandler: createJsonResponseHandler(
|
|
@@ -181,8 +201,8 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
|
|
|
181
201
|
}
|
|
182
202
|
|
|
183
203
|
private async doGenerateGemini(
|
|
184
|
-
options: Parameters<
|
|
185
|
-
): Promise<Awaited<ReturnType<
|
|
204
|
+
options: Parameters<ImageModelV4['doGenerate']>[0],
|
|
205
|
+
): Promise<Awaited<ReturnType<ImageModelV4['doGenerate']>>> {
|
|
186
206
|
const {
|
|
187
207
|
prompt,
|
|
188
208
|
n,
|
|
@@ -195,7 +215,7 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
|
|
|
195
215
|
files,
|
|
196
216
|
mask,
|
|
197
217
|
} = options;
|
|
198
|
-
const warnings: Array<
|
|
218
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
199
219
|
|
|
200
220
|
// Gemini does not support mask-based inpainting
|
|
201
221
|
if (mask != null) {
|
|
@@ -220,45 +240,51 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
|
|
|
220
240
|
});
|
|
221
241
|
}
|
|
222
242
|
|
|
223
|
-
// Build user message content for language model
|
|
224
243
|
const userContent: Array<
|
|
225
244
|
| { type: 'text'; text: string }
|
|
226
|
-
| {
|
|
245
|
+
| {
|
|
246
|
+
type: 'file';
|
|
247
|
+
data:
|
|
248
|
+
| { type: 'data'; data: string | Uint8Array }
|
|
249
|
+
| { type: 'url'; url: URL };
|
|
250
|
+
mediaType: string;
|
|
251
|
+
}
|
|
227
252
|
> = [];
|
|
228
253
|
|
|
229
|
-
// Add text prompt
|
|
230
254
|
if (prompt != null) {
|
|
231
255
|
userContent.push({ type: 'text', text: prompt });
|
|
232
256
|
}
|
|
233
257
|
|
|
234
|
-
// Add input images for editing
|
|
235
258
|
if (files != null && files.length > 0) {
|
|
236
259
|
for (const file of files) {
|
|
237
260
|
if (file.type === 'url') {
|
|
238
261
|
userContent.push({
|
|
239
262
|
type: 'file',
|
|
240
|
-
data: new URL(file.url),
|
|
263
|
+
data: { type: 'url', url: new URL(file.url) },
|
|
241
264
|
mediaType: 'image/*',
|
|
242
265
|
});
|
|
243
266
|
} else {
|
|
244
267
|
userContent.push({
|
|
245
268
|
type: 'file',
|
|
246
|
-
data:
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
269
|
+
data: {
|
|
270
|
+
type: 'data',
|
|
271
|
+
data:
|
|
272
|
+
typeof file.data === 'string'
|
|
273
|
+
? file.data
|
|
274
|
+
: new Uint8Array(file.data),
|
|
275
|
+
},
|
|
250
276
|
mediaType: file.mediaType,
|
|
251
277
|
});
|
|
252
278
|
}
|
|
253
279
|
}
|
|
254
280
|
}
|
|
255
281
|
|
|
256
|
-
const languageModelPrompt:
|
|
282
|
+
const languageModelPrompt: LanguageModelV4Prompt = [
|
|
257
283
|
{ role: 'user', content: userContent },
|
|
258
284
|
];
|
|
259
285
|
|
|
260
286
|
// Instantiate language model
|
|
261
|
-
const languageModel = new
|
|
287
|
+
const languageModel = new GoogleLanguageModel(this.modelId, {
|
|
262
288
|
provider: this.config.provider,
|
|
263
289
|
baseURL: this.config.baseURL,
|
|
264
290
|
headers: this.config.headers ?? {},
|
|
@@ -292,11 +318,14 @@ export class GoogleGenerativeAIImageModel implements ImageModelV3 {
|
|
|
292
318
|
|
|
293
319
|
const currentDate = this.config._internal?.currentDate?.() ?? new Date();
|
|
294
320
|
|
|
295
|
-
// Extract images from language model response
|
|
296
321
|
const images: string[] = [];
|
|
297
322
|
for (const part of result.content) {
|
|
298
|
-
if (
|
|
299
|
-
|
|
323
|
+
if (
|
|
324
|
+
part.type === 'file' &&
|
|
325
|
+
part.mediaType.startsWith('image/') &&
|
|
326
|
+
part.data.type === 'data'
|
|
327
|
+
) {
|
|
328
|
+
images.push(convertToBase64(part.data.data));
|
|
300
329
|
}
|
|
301
330
|
}
|
|
302
331
|
|
|
@@ -340,20 +369,3 @@ const googleImageResponseSchema = lazySchema(() =>
|
|
|
340
369
|
}),
|
|
341
370
|
),
|
|
342
371
|
);
|
|
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
|
-
>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type GoogleImageModelId =
|
|
2
2
|
// Imagen models (use :predict API)
|
|
3
3
|
| 'imagen-4.0-generate-001'
|
|
4
4
|
| 'imagen-4.0-ultra-generate-001'
|
|
@@ -9,7 +9,7 @@ export type GoogleGenerativeAIImageModelId =
|
|
|
9
9
|
| 'gemini-3.1-flash-image-preview'
|
|
10
10
|
| (string & {});
|
|
11
11
|
|
|
12
|
-
export interface
|
|
12
|
+
export interface GoogleImageSettings {
|
|
13
13
|
/**
|
|
14
14
|
* Override the maximum number of images per call (default 4)
|
|
15
15
|
*/
|