vargai 0.4.0-alpha28 → 0.4.0-alpha29
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
|
@@ -41,7 +41,9 @@
|
|
|
41
41
|
"@ai-sdk/fal": "^1.0.23",
|
|
42
42
|
"@ai-sdk/fireworks": "^2.0.16",
|
|
43
43
|
"@ai-sdk/groq": "^3.0.12",
|
|
44
|
+
"@ai-sdk/google": "^3.0.13",
|
|
44
45
|
"@ai-sdk/openai": "^3.0.9",
|
|
46
|
+
"@google/genai": "^1.0.0",
|
|
45
47
|
"@ai-sdk/provider": "^3.0.2",
|
|
46
48
|
"@ai-sdk/provider-utils": "^4.0.4",
|
|
47
49
|
"@ai-sdk/replicate": "^2.0.5",
|
|
@@ -66,7 +68,7 @@
|
|
|
66
68
|
"vargai": "^0.4.0-alpha11",
|
|
67
69
|
"zod": "^4.2.1"
|
|
68
70
|
},
|
|
69
|
-
"version": "0.4.0-
|
|
71
|
+
"version": "0.4.0-alpha29",
|
|
70
72
|
"exports": {
|
|
71
73
|
".": "./src/index.ts",
|
|
72
74
|
"./ai": "./src/ai-sdk/index.ts",
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { generateImage } from "ai";
|
|
2
|
+
import { File, google } from "../index";
|
|
3
|
+
|
|
4
|
+
async function main() {
|
|
5
|
+
console.log("testing google image generation via varg provider...\n");
|
|
6
|
+
|
|
7
|
+
console.log("1. text-to-image with nano-banana-pro...");
|
|
8
|
+
try {
|
|
9
|
+
const { images, warnings } = await generateImage({
|
|
10
|
+
model: google.imageModel("nano-banana-pro"),
|
|
11
|
+
prompt: "a beautiful mountain landscape with snow peaks and a calm lake",
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
console.log(` generated ${images.length} image(s)`);
|
|
15
|
+
if (warnings.length > 0) {
|
|
16
|
+
console.log(
|
|
17
|
+
` warnings: ${warnings.map((w) => ("details" in w ? w.details : w.type)).join(", ")}`,
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
if (images[0]) {
|
|
21
|
+
console.log(` size: ${images[0].uint8Array.byteLength} bytes`);
|
|
22
|
+
await Bun.write("output/google-mountain.png", images[0].uint8Array);
|
|
23
|
+
console.log(" saved to output/google-mountain.png");
|
|
24
|
+
}
|
|
25
|
+
} catch (error: any) {
|
|
26
|
+
console.error(" error:", error.message || error);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
console.log("\n2. image-to-image with nano-banana-pro/edit...");
|
|
30
|
+
try {
|
|
31
|
+
const sourceFile = File.fromPath("output/google-mountain.png");
|
|
32
|
+
|
|
33
|
+
const { images, warnings } = await generateImage({
|
|
34
|
+
model: google.imageModel("nano-banana-pro/edit"),
|
|
35
|
+
prompt: {
|
|
36
|
+
text: "transform into a sunset scene with warm orange and pink sky",
|
|
37
|
+
images: [await sourceFile.data()],
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
console.log(` generated ${images.length} image(s)`);
|
|
42
|
+
if (warnings.length > 0) {
|
|
43
|
+
console.log(
|
|
44
|
+
` warnings: ${warnings.map((w) => ("details" in w ? w.details : w.type)).join(", ")}`,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
if (images[0]) {
|
|
48
|
+
console.log(` size: ${images[0].uint8Array.byteLength} bytes`);
|
|
49
|
+
await Bun.write(
|
|
50
|
+
"output/google-mountain-sunset.png",
|
|
51
|
+
images[0].uint8Array,
|
|
52
|
+
);
|
|
53
|
+
console.log(" saved to output/google-mountain-sunset.png");
|
|
54
|
+
}
|
|
55
|
+
} catch (error: any) {
|
|
56
|
+
console.error(" error:", error.message || error);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
console.log("\ndone!");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
main();
|
package/src/ai-sdk/index.ts
CHANGED
|
@@ -63,6 +63,12 @@ export {
|
|
|
63
63
|
VOICES,
|
|
64
64
|
} from "./providers/elevenlabs";
|
|
65
65
|
export { createFal, type FalProvider, fal } from "./providers/fal";
|
|
66
|
+
export {
|
|
67
|
+
createGoogle,
|
|
68
|
+
type GoogleProvider,
|
|
69
|
+
type GoogleProviderSettings,
|
|
70
|
+
google,
|
|
71
|
+
} from "./providers/google";
|
|
66
72
|
export {
|
|
67
73
|
createHiggsfield,
|
|
68
74
|
type HiggsfieldImageModelSettings,
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createGoogleGenerativeAI,
|
|
3
|
+
type GoogleGenerativeAIProviderSettings,
|
|
4
|
+
} from "@ai-sdk/google";
|
|
5
|
+
import {
|
|
6
|
+
type EmbeddingModelV3,
|
|
7
|
+
type ImageModelV3,
|
|
8
|
+
type ImageModelV3CallOptions,
|
|
9
|
+
type LanguageModelV3,
|
|
10
|
+
NoSuchModelError,
|
|
11
|
+
type ProviderV3,
|
|
12
|
+
type SharedV3Warning,
|
|
13
|
+
} from "@ai-sdk/provider";
|
|
14
|
+
import { GoogleGenAI } from "@google/genai";
|
|
15
|
+
import { generateText } from "ai";
|
|
16
|
+
import type { VideoModelV3, VideoModelV3CallOptions } from "../video-model";
|
|
17
|
+
|
|
18
|
+
// re-export base types
|
|
19
|
+
export type { GoogleGenerativeAIProviderSettings };
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Image Models
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
const IMAGE_MODELS: Record<string, string> = {
|
|
26
|
+
// gemini 3 models (use imageConfig for aspectRatio)
|
|
27
|
+
"gemini-3-pro-image": "gemini-3-pro-image-preview",
|
|
28
|
+
"nano-banana-pro": "gemini-3-pro-image-preview",
|
|
29
|
+
"nano-banana-pro/edit": "gemini-3-pro-image-preview",
|
|
30
|
+
// gemini 2 models (use responseModalities)
|
|
31
|
+
"gemini-2.0-flash-exp-image-generation":
|
|
32
|
+
"gemini-2.0-flash-exp-image-generation",
|
|
33
|
+
"gemini-2-flash-image": "gemini-2.0-flash-exp-image-generation",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const GEMINI_3_MODELS = new Set(["gemini-3-pro-image-preview"]);
|
|
37
|
+
|
|
38
|
+
const GEMINI_2_MODELS = new Set(["gemini-2.0-flash-exp-image-generation"]);
|
|
39
|
+
|
|
40
|
+
class GoogleImageModel implements ImageModelV3 {
|
|
41
|
+
readonly specificationVersion = "v3" as const;
|
|
42
|
+
readonly provider = "google";
|
|
43
|
+
readonly modelId: string;
|
|
44
|
+
readonly maxImagesPerCall = 1;
|
|
45
|
+
|
|
46
|
+
private apiKey: string;
|
|
47
|
+
|
|
48
|
+
constructor(modelId: string, options: { apiKey?: string } = {}) {
|
|
49
|
+
this.modelId = modelId;
|
|
50
|
+
this.apiKey =
|
|
51
|
+
options.apiKey ?? process.env.GOOGLE_GENERATIVE_AI_API_KEY ?? "";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async doGenerate(options: ImageModelV3CallOptions) {
|
|
55
|
+
const { prompt, aspectRatio, files, providerOptions } = options;
|
|
56
|
+
const warnings: SharedV3Warning[] = [];
|
|
57
|
+
|
|
58
|
+
const model = IMAGE_MODELS[this.modelId] ?? this.modelId;
|
|
59
|
+
|
|
60
|
+
const content: Array<
|
|
61
|
+
{ type: "text"; text: string } | { type: "image"; image: Buffer | URL }
|
|
62
|
+
> = [{ type: "text", text: prompt ?? "" }];
|
|
63
|
+
|
|
64
|
+
if (files && files.length > 0) {
|
|
65
|
+
for (const file of files) {
|
|
66
|
+
if (file.type === "file") {
|
|
67
|
+
const data =
|
|
68
|
+
typeof file.data === "string"
|
|
69
|
+
? Buffer.from(file.data, "base64")
|
|
70
|
+
: Buffer.from(file.data);
|
|
71
|
+
content.push({ type: "image", image: data });
|
|
72
|
+
} else {
|
|
73
|
+
content.push({ type: "image", image: new URL(file.url) });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// create google provider with api key
|
|
79
|
+
const googleProvider = createGoogleGenerativeAI({
|
|
80
|
+
apiKey: this.apiKey,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// google returns generated images in result.files[] via generateText
|
|
84
|
+
const googleOptions = (providerOptions?.google ?? {}) as Record<
|
|
85
|
+
string,
|
|
86
|
+
unknown
|
|
87
|
+
>;
|
|
88
|
+
|
|
89
|
+
// gemini 3 uses imageConfig for aspectRatio, gemini 2 uses responseModalities
|
|
90
|
+
const isGemini3 = GEMINI_3_MODELS.has(model);
|
|
91
|
+
const providerOpts: Record<string, unknown> = { ...googleOptions };
|
|
92
|
+
|
|
93
|
+
if (isGemini3) {
|
|
94
|
+
providerOpts.imageConfig = {
|
|
95
|
+
...(aspectRatio ? { aspectRatio } : {}),
|
|
96
|
+
...((googleOptions.imageConfig as Record<string, unknown>) ?? {}),
|
|
97
|
+
};
|
|
98
|
+
} else {
|
|
99
|
+
providerOpts.responseModalities = ["TEXT", "IMAGE"];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const result = await generateText({
|
|
103
|
+
model: googleProvider(model) as unknown as Parameters<
|
|
104
|
+
typeof generateText
|
|
105
|
+
>[0]["model"],
|
|
106
|
+
messages: [
|
|
107
|
+
{
|
|
108
|
+
role: "user",
|
|
109
|
+
content,
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
providerOptions: {
|
|
113
|
+
google: providerOpts as Record<
|
|
114
|
+
string,
|
|
115
|
+
string | string[] | Record<string, string>
|
|
116
|
+
>,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const imageFiles = result.files?.filter((file) =>
|
|
121
|
+
file.mediaType?.startsWith("image/"),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
if (!imageFiles || imageFiles.length === 0) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
`No images generated. Model response: ${result.text?.slice(0, 200) || "(no text)"}`,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const images = imageFiles.map((file) => {
|
|
131
|
+
const bytes =
|
|
132
|
+
typeof file.base64 === "string"
|
|
133
|
+
? Uint8Array.from(atob(file.base64), (c) => c.charCodeAt(0))
|
|
134
|
+
: new Uint8Array(0);
|
|
135
|
+
return bytes;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (options.seed !== undefined) {
|
|
139
|
+
warnings.push({
|
|
140
|
+
type: "unsupported",
|
|
141
|
+
feature: "seed",
|
|
142
|
+
details: "Seed is not supported by Google image generation",
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (options.size !== undefined) {
|
|
147
|
+
warnings.push({
|
|
148
|
+
type: "unsupported",
|
|
149
|
+
feature: "size",
|
|
150
|
+
details: "Use aspectRatio instead for Google image generation",
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (aspectRatio && GEMINI_2_MODELS.has(model)) {
|
|
155
|
+
warnings.push({
|
|
156
|
+
type: "unsupported",
|
|
157
|
+
feature: "aspectRatio",
|
|
158
|
+
details: `aspectRatio not supported by ${model}, use gemini-3-pro-image instead`,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
images,
|
|
164
|
+
warnings,
|
|
165
|
+
response: {
|
|
166
|
+
timestamp: new Date(),
|
|
167
|
+
modelId: this.modelId,
|
|
168
|
+
headers: undefined,
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ============================================================================
|
|
175
|
+
// Video Models
|
|
176
|
+
// ============================================================================
|
|
177
|
+
|
|
178
|
+
const VIDEO_MODELS: Record<string, string> = {
|
|
179
|
+
"veo-3.1": "veo-3.1-generate-preview",
|
|
180
|
+
"veo-3": "veo-3.0-generate-preview",
|
|
181
|
+
"veo-3-fast": "veo-3.0-fast-generate-001",
|
|
182
|
+
"veo-2": "veo-2.0-generate-001",
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const DEFAULT_POLL_INTERVAL_MS = 10000;
|
|
186
|
+
const DEFAULT_MAX_POLL_DURATION_MS = 300000; // 5 minutes
|
|
187
|
+
|
|
188
|
+
class GoogleVideoModel implements VideoModelV3 {
|
|
189
|
+
readonly specificationVersion = "v3" as const;
|
|
190
|
+
readonly provider = "google";
|
|
191
|
+
readonly modelId: string;
|
|
192
|
+
readonly maxVideosPerCall = 1;
|
|
193
|
+
|
|
194
|
+
private client: GoogleGenAI;
|
|
195
|
+
private apiKey: string;
|
|
196
|
+
private pollIntervalMs: number;
|
|
197
|
+
private maxPollDurationMs: number;
|
|
198
|
+
private onProgress?: (progress: number, operationName: string) => void;
|
|
199
|
+
|
|
200
|
+
constructor(
|
|
201
|
+
modelId: string,
|
|
202
|
+
options: { apiKey?: string; polling?: GooglePollingConfig } = {},
|
|
203
|
+
) {
|
|
204
|
+
this.modelId = modelId;
|
|
205
|
+
this.apiKey =
|
|
206
|
+
options.apiKey ?? process.env.GOOGLE_GENERATIVE_AI_API_KEY ?? "";
|
|
207
|
+
this.client = new GoogleGenAI({ apiKey: this.apiKey });
|
|
208
|
+
this.pollIntervalMs =
|
|
209
|
+
options.polling?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
210
|
+
this.maxPollDurationMs =
|
|
211
|
+
options.polling?.maxPollDurationMs ?? DEFAULT_MAX_POLL_DURATION_MS;
|
|
212
|
+
this.onProgress = options.polling?.onProgress;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async doGenerate(options: VideoModelV3CallOptions) {
|
|
216
|
+
const {
|
|
217
|
+
prompt,
|
|
218
|
+
duration,
|
|
219
|
+
aspectRatio,
|
|
220
|
+
fps,
|
|
221
|
+
seed,
|
|
222
|
+
files,
|
|
223
|
+
providerOptions,
|
|
224
|
+
abortSignal,
|
|
225
|
+
} = options;
|
|
226
|
+
const warnings: SharedV3Warning[] = [];
|
|
227
|
+
|
|
228
|
+
// resolve model endpoint
|
|
229
|
+
const model = VIDEO_MODELS[this.modelId] ?? this.modelId;
|
|
230
|
+
|
|
231
|
+
// build config
|
|
232
|
+
const config: Record<string, unknown> = {
|
|
233
|
+
numberOfVideos: 1,
|
|
234
|
+
...(providerOptions?.google as Record<string, unknown>),
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
if (aspectRatio) {
|
|
238
|
+
config.aspectRatio = aspectRatio;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (duration) {
|
|
242
|
+
config.durationSeconds = duration;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (fps) {
|
|
246
|
+
config.fps = fps;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (seed !== undefined) {
|
|
250
|
+
config.seed = seed;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// handle image input for image-to-video
|
|
254
|
+
let image: { data: string; mimeType: string } | undefined;
|
|
255
|
+
if (files && files.length > 0) {
|
|
256
|
+
const imageFile = files.find((f) => {
|
|
257
|
+
if (f.type === "file") return f.mediaType?.startsWith("image/");
|
|
258
|
+
return /\.(jpg|jpeg|png|webp)$/i.test(f.url);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
if (imageFile) {
|
|
262
|
+
if (imageFile.type === "file") {
|
|
263
|
+
const base64 =
|
|
264
|
+
typeof imageFile.data === "string"
|
|
265
|
+
? imageFile.data
|
|
266
|
+
: Buffer.from(imageFile.data).toString("base64");
|
|
267
|
+
image = {
|
|
268
|
+
data: base64,
|
|
269
|
+
mimeType: imageFile.mediaType ?? "image/png",
|
|
270
|
+
};
|
|
271
|
+
} else {
|
|
272
|
+
const response = await fetch(imageFile.url, { signal: abortSignal });
|
|
273
|
+
if (!response.ok) {
|
|
274
|
+
throw new Error(
|
|
275
|
+
`Failed to fetch image from ${imageFile.url}: ${response.status} ${response.statusText}`,
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
const buffer = await response.arrayBuffer();
|
|
279
|
+
const base64 = Buffer.from(buffer).toString("base64");
|
|
280
|
+
const mimeType = response.headers.get("content-type") ?? "image/png";
|
|
281
|
+
image = { data: base64, mimeType };
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
let operation = await this.client.models.generateVideos({
|
|
287
|
+
model,
|
|
288
|
+
prompt,
|
|
289
|
+
image,
|
|
290
|
+
config,
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
const operationName = operation.name ?? "unknown";
|
|
294
|
+
this.onProgress?.(0, operationName);
|
|
295
|
+
|
|
296
|
+
const startTime = Date.now();
|
|
297
|
+
|
|
298
|
+
while (!operation.done) {
|
|
299
|
+
if (abortSignal?.aborted) {
|
|
300
|
+
throw new Error("Video generation aborted");
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const elapsed = Date.now() - startTime;
|
|
304
|
+
if (elapsed > this.maxPollDurationMs) {
|
|
305
|
+
throw new Error(
|
|
306
|
+
`Video generation timed out after ${Math.round(elapsed / 1000)}s (max: ${Math.round(this.maxPollDurationMs / 1000)}s)`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));
|
|
311
|
+
operation = await this.client.operations.getVideosOperation({
|
|
312
|
+
operation,
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
if (operation.metadata?.progress) {
|
|
316
|
+
this.onProgress?.(operation.metadata.progress as number, operationName);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (operation.error) {
|
|
321
|
+
throw new Error(
|
|
322
|
+
`Google video generation failed: ${operation.error.message}`,
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// download generated videos
|
|
327
|
+
const generatedVideos = operation.response?.generatedVideos;
|
|
328
|
+
if (!generatedVideos || generatedVideos.length === 0) {
|
|
329
|
+
throw new Error("No videos generated by Google model");
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const videos: Uint8Array[] = [];
|
|
333
|
+
for (const video of generatedVideos) {
|
|
334
|
+
const videoUri = video.video?.uri;
|
|
335
|
+
if (!videoUri) continue;
|
|
336
|
+
|
|
337
|
+
const videoUrl = `${videoUri}&key=${this.apiKey}`;
|
|
338
|
+
|
|
339
|
+
const response = await fetch(videoUrl, { signal: abortSignal });
|
|
340
|
+
if (!response.ok) {
|
|
341
|
+
throw new Error(`Failed to download video: ${response.statusText}`);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const buffer = await response.arrayBuffer();
|
|
345
|
+
videos.push(new Uint8Array(buffer));
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (videos.length === 0) {
|
|
349
|
+
throw new Error("Failed to download any videos from Google");
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// warn about unsupported options
|
|
353
|
+
if (options.resolution !== undefined) {
|
|
354
|
+
warnings.push({
|
|
355
|
+
type: "unsupported",
|
|
356
|
+
feature: "resolution",
|
|
357
|
+
details:
|
|
358
|
+
"Use aspectRatio instead. Google Veo determines resolution automatically.",
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return {
|
|
363
|
+
videos,
|
|
364
|
+
warnings,
|
|
365
|
+
response: {
|
|
366
|
+
timestamp: new Date(),
|
|
367
|
+
modelId: this.modelId,
|
|
368
|
+
headers: undefined,
|
|
369
|
+
},
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// ============================================================================
|
|
375
|
+
// Provider
|
|
376
|
+
// ============================================================================
|
|
377
|
+
|
|
378
|
+
export interface GooglePollingConfig {
|
|
379
|
+
pollIntervalMs?: number;
|
|
380
|
+
maxPollDurationMs?: number;
|
|
381
|
+
onProgress?: (progress: number, operationName: string) => void;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export interface GoogleProviderSettings {
|
|
385
|
+
apiKey?: string;
|
|
386
|
+
polling?: GooglePollingConfig;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export interface GoogleProvider extends ProviderV3 {
|
|
390
|
+
imageModel(modelId: string): ImageModelV3;
|
|
391
|
+
videoModel(modelId: string): VideoModelV3;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function createGoogle(
|
|
395
|
+
settings: GoogleProviderSettings = {},
|
|
396
|
+
): GoogleProvider {
|
|
397
|
+
const apiKey = settings.apiKey ?? process.env.GOOGLE_GENERATIVE_AI_API_KEY;
|
|
398
|
+
const polling = settings.polling;
|
|
399
|
+
|
|
400
|
+
return {
|
|
401
|
+
specificationVersion: "v3",
|
|
402
|
+
imageModel(modelId: string): GoogleImageModel {
|
|
403
|
+
return new GoogleImageModel(modelId, { apiKey });
|
|
404
|
+
},
|
|
405
|
+
videoModel(modelId: string): GoogleVideoModel {
|
|
406
|
+
return new GoogleVideoModel(modelId, { apiKey, polling });
|
|
407
|
+
},
|
|
408
|
+
languageModel(modelId: string): LanguageModelV3 {
|
|
409
|
+
throw new NoSuchModelError({
|
|
410
|
+
modelId,
|
|
411
|
+
modelType: "languageModel",
|
|
412
|
+
});
|
|
413
|
+
},
|
|
414
|
+
embeddingModel(modelId: string): EmbeddingModelV3 {
|
|
415
|
+
throw new NoSuchModelError({
|
|
416
|
+
modelId,
|
|
417
|
+
modelType: "embeddingModel",
|
|
418
|
+
});
|
|
419
|
+
},
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export const google = createGoogle();
|