@zhivex-ai/gemini 0.6.0 → 0.7.0-next.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.
- package/README.md +88 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1185 -118
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -8,10 +8,17 @@ const capabilities = {
|
|
|
8
8
|
toolChoice: true,
|
|
9
9
|
parallelToolCalls: false,
|
|
10
10
|
vision: true,
|
|
11
|
-
files:
|
|
11
|
+
files: true,
|
|
12
12
|
audioInput: false,
|
|
13
13
|
audioOutput: false,
|
|
14
14
|
embeddings: true,
|
|
15
|
+
fileSearch: true,
|
|
16
|
+
urlContext: true,
|
|
17
|
+
contextCaching: true,
|
|
18
|
+
batch: true,
|
|
19
|
+
interactions: true,
|
|
20
|
+
rawPrediction: true,
|
|
21
|
+
computerUse: true,
|
|
15
22
|
reasoning: true,
|
|
16
23
|
webSearch: true,
|
|
17
24
|
agentCapabilities: {
|
|
@@ -19,9 +26,9 @@ const capabilities = {
|
|
|
19
26
|
toolChoiceNone: true,
|
|
20
27
|
approvalRequests: false,
|
|
21
28
|
hostedWebSearch: true,
|
|
22
|
-
hostedFileSearch:
|
|
29
|
+
hostedFileSearch: true,
|
|
23
30
|
remoteMcp: false,
|
|
24
|
-
computerUse:
|
|
31
|
+
computerUse: true,
|
|
25
32
|
codeExecution: true,
|
|
26
33
|
toolsets: false
|
|
27
34
|
}
|
|
@@ -60,6 +67,85 @@ const groundedCapabilities = {
|
|
|
60
67
|
...capabilities,
|
|
61
68
|
webSearch: true
|
|
62
69
|
};
|
|
70
|
+
const imageGenerationCapabilities = {
|
|
71
|
+
...capabilities,
|
|
72
|
+
streaming: false,
|
|
73
|
+
tools: false,
|
|
74
|
+
structuredOutput: false,
|
|
75
|
+
jsonMode: false,
|
|
76
|
+
toolChoice: false,
|
|
77
|
+
parallelToolCalls: false,
|
|
78
|
+
embeddings: false,
|
|
79
|
+
imageGeneration: true,
|
|
80
|
+
videoGeneration: false,
|
|
81
|
+
musicGeneration: false,
|
|
82
|
+
reasoning: false,
|
|
83
|
+
webSearch: false,
|
|
84
|
+
agentCapabilities: {
|
|
85
|
+
supportTier: "tier-c",
|
|
86
|
+
toolChoiceNone: false,
|
|
87
|
+
approvalRequests: false,
|
|
88
|
+
hostedWebSearch: false,
|
|
89
|
+
hostedFileSearch: false,
|
|
90
|
+
remoteMcp: false,
|
|
91
|
+
computerUse: false,
|
|
92
|
+
codeExecution: false,
|
|
93
|
+
toolsets: false
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const videoGenerationCapabilities = {
|
|
97
|
+
...capabilities,
|
|
98
|
+
streaming: false,
|
|
99
|
+
tools: false,
|
|
100
|
+
structuredOutput: false,
|
|
101
|
+
jsonMode: false,
|
|
102
|
+
toolChoice: false,
|
|
103
|
+
parallelToolCalls: false,
|
|
104
|
+
vision: false,
|
|
105
|
+
embeddings: false,
|
|
106
|
+
imageGeneration: false,
|
|
107
|
+
videoGeneration: true,
|
|
108
|
+
musicGeneration: false,
|
|
109
|
+
reasoning: false,
|
|
110
|
+
webSearch: false,
|
|
111
|
+
agentCapabilities: {
|
|
112
|
+
supportTier: "tier-c",
|
|
113
|
+
toolChoiceNone: false,
|
|
114
|
+
approvalRequests: false,
|
|
115
|
+
hostedWebSearch: false,
|
|
116
|
+
hostedFileSearch: false,
|
|
117
|
+
remoteMcp: false,
|
|
118
|
+
computerUse: false,
|
|
119
|
+
codeExecution: false,
|
|
120
|
+
toolsets: false
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const musicGenerationCapabilities = {
|
|
124
|
+
...capabilities,
|
|
125
|
+
streaming: false,
|
|
126
|
+
tools: false,
|
|
127
|
+
structuredOutput: false,
|
|
128
|
+
jsonMode: false,
|
|
129
|
+
toolChoice: false,
|
|
130
|
+
parallelToolCalls: false,
|
|
131
|
+
embeddings: false,
|
|
132
|
+
imageGeneration: false,
|
|
133
|
+
videoGeneration: false,
|
|
134
|
+
musicGeneration: true,
|
|
135
|
+
reasoning: false,
|
|
136
|
+
webSearch: false,
|
|
137
|
+
agentCapabilities: {
|
|
138
|
+
supportTier: "tier-c",
|
|
139
|
+
toolChoiceNone: false,
|
|
140
|
+
approvalRequests: false,
|
|
141
|
+
hostedWebSearch: false,
|
|
142
|
+
hostedFileSearch: false,
|
|
143
|
+
remoteMcp: false,
|
|
144
|
+
computerUse: false,
|
|
145
|
+
codeExecution: false,
|
|
146
|
+
toolsets: false
|
|
147
|
+
}
|
|
148
|
+
};
|
|
63
149
|
const realtimeCapabilities = {
|
|
64
150
|
...capabilities,
|
|
65
151
|
streaming: false,
|
|
@@ -90,6 +176,207 @@ const toBase64 = (data) => {
|
|
|
90
176
|
const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
91
177
|
return Buffer.from(bytes).toString("base64");
|
|
92
178
|
};
|
|
179
|
+
const sleep = (ms, signal) => new Promise((resolve, reject) => {
|
|
180
|
+
if (ms <= 0) {
|
|
181
|
+
resolve();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (signal?.aborted) {
|
|
185
|
+
reject(new Error("Operation aborted."));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const timeout = setTimeout(() => {
|
|
189
|
+
signal?.removeEventListener("abort", onAbort);
|
|
190
|
+
resolve();
|
|
191
|
+
}, ms);
|
|
192
|
+
const onAbort = () => {
|
|
193
|
+
clearTimeout(timeout);
|
|
194
|
+
reject(new Error("Operation aborted."));
|
|
195
|
+
};
|
|
196
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
197
|
+
});
|
|
198
|
+
const splitGenerationConfig = (providerOptions) => {
|
|
199
|
+
const { generationConfig, ...rest } = providerOptions ?? {};
|
|
200
|
+
return {
|
|
201
|
+
generationConfig: generationConfig && typeof generationConfig === "object" ? generationConfig : {},
|
|
202
|
+
providerOptions: rest
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
const mediaInputToPart = (media) => media.uri
|
|
206
|
+
? {
|
|
207
|
+
fileData: {
|
|
208
|
+
mimeType: media.mediaType,
|
|
209
|
+
fileUri: media.uri
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
: {
|
|
213
|
+
inlineData: {
|
|
214
|
+
mimeType: media.mediaType,
|
|
215
|
+
data: media.data ? toBase64(media.data) : ""
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
const collectInlineMedia = (json, fallbackMediaType) => {
|
|
219
|
+
const text = [];
|
|
220
|
+
const media = [];
|
|
221
|
+
const candidates = Array.isArray(json.candidates) ? json.candidates : [];
|
|
222
|
+
for (const candidate of candidates) {
|
|
223
|
+
const parts = Array.isArray(candidate?.content?.parts) ? candidate.content.parts : [];
|
|
224
|
+
for (const part of parts) {
|
|
225
|
+
if (typeof part.text === "string" && part.text) {
|
|
226
|
+
text.push(part.text);
|
|
227
|
+
}
|
|
228
|
+
const inlineData = part.inlineData ?? part.inline_data;
|
|
229
|
+
if (inlineData?.data) {
|
|
230
|
+
media.push({
|
|
231
|
+
data: Uint8Array.from(Buffer.from(inlineData.data, "base64")),
|
|
232
|
+
mediaType: inlineData.mimeType ?? inlineData.mime_type ?? fallbackMediaType,
|
|
233
|
+
text: typeof part.text === "string" ? part.text : undefined
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
media,
|
|
240
|
+
text: text.length ? text.join("\n") : undefined
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
const mediaInputToVeoImage = (media) => media.uri
|
|
244
|
+
? {
|
|
245
|
+
gcsUri: media.uri,
|
|
246
|
+
mimeType: media.mediaType
|
|
247
|
+
}
|
|
248
|
+
: {
|
|
249
|
+
bytesBase64Encoded: media.data ? toBase64(media.data) : "",
|
|
250
|
+
mimeType: media.mediaType
|
|
251
|
+
};
|
|
252
|
+
const collectVideos = (json) => {
|
|
253
|
+
const samples = json.response?.generateVideoResponse?.generatedSamples ??
|
|
254
|
+
json.response?.generatedVideos ??
|
|
255
|
+
json.response?.generated_videos ??
|
|
256
|
+
[];
|
|
257
|
+
return (Array.isArray(samples) ? samples : [])
|
|
258
|
+
.map((sample) => sample.video ?? sample)
|
|
259
|
+
.map((video) => ({
|
|
260
|
+
data: video.videoBytes
|
|
261
|
+
? Uint8Array.from(Buffer.from(video.videoBytes, "base64"))
|
|
262
|
+
: video.bytesBase64Encoded
|
|
263
|
+
? Uint8Array.from(Buffer.from(video.bytesBase64Encoded, "base64"))
|
|
264
|
+
: undefined,
|
|
265
|
+
uri: video.uri ?? video.gcsUri,
|
|
266
|
+
mediaType: video.mimeType ?? "video/mp4",
|
|
267
|
+
providerMetadata: video
|
|
268
|
+
}))
|
|
269
|
+
.filter((video) => video.data || video.uri);
|
|
270
|
+
};
|
|
271
|
+
const dataToBytes = async (data) => {
|
|
272
|
+
if (typeof data === "string") {
|
|
273
|
+
return new TextEncoder().encode(data);
|
|
274
|
+
}
|
|
275
|
+
if (data instanceof Uint8Array) {
|
|
276
|
+
return data;
|
|
277
|
+
}
|
|
278
|
+
if (data instanceof ArrayBuffer) {
|
|
279
|
+
return new Uint8Array(data);
|
|
280
|
+
}
|
|
281
|
+
return new Uint8Array(await data.arrayBuffer());
|
|
282
|
+
};
|
|
283
|
+
const bytesToArrayBuffer = (bytes) => bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
284
|
+
const normalizeUploadedFile = (json) => {
|
|
285
|
+
const file = json.file ?? json;
|
|
286
|
+
return {
|
|
287
|
+
name: file.name ?? "",
|
|
288
|
+
uri: file.uri ?? file.fileUri ?? file.file_uri,
|
|
289
|
+
mimeType: file.mimeType ?? file.mime_type,
|
|
290
|
+
sizeBytes: file.sizeBytes ?? file.size_bytes,
|
|
291
|
+
state: file.state,
|
|
292
|
+
displayName: file.displayName ?? file.display_name,
|
|
293
|
+
rawResponse: json,
|
|
294
|
+
providerMetadata: file
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
const normalizeFileSearchStore = (json) => ({
|
|
298
|
+
name: json.name ?? "",
|
|
299
|
+
displayName: json.displayName ?? json.display_name,
|
|
300
|
+
createTime: json.createTime ?? json.create_time,
|
|
301
|
+
updateTime: json.updateTime ?? json.update_time,
|
|
302
|
+
rawResponse: json,
|
|
303
|
+
providerMetadata: json
|
|
304
|
+
});
|
|
305
|
+
const normalizeCachedContent = (json) => ({
|
|
306
|
+
name: json.name ?? "",
|
|
307
|
+
model: json.model,
|
|
308
|
+
displayName: json.displayName ?? json.display_name,
|
|
309
|
+
createTime: json.createTime ?? json.create_time,
|
|
310
|
+
updateTime: json.updateTime ?? json.update_time,
|
|
311
|
+
expireTime: json.expireTime ?? json.expire_time,
|
|
312
|
+
usageMetadata: json.usageMetadata ?? json.usage_metadata,
|
|
313
|
+
rawResponse: json,
|
|
314
|
+
providerMetadata: json
|
|
315
|
+
});
|
|
316
|
+
const normalizeBatchJob = (json) => ({
|
|
317
|
+
name: json.name ?? "",
|
|
318
|
+
model: json.model,
|
|
319
|
+
state: json.state ?? json.metadata?.state,
|
|
320
|
+
done: json.done,
|
|
321
|
+
createTime: json.createTime ?? json.create_time ?? json.metadata?.createTime,
|
|
322
|
+
updateTime: json.updateTime ?? json.update_time ?? json.metadata?.updateTime,
|
|
323
|
+
rawResponse: json,
|
|
324
|
+
providerMetadata: json
|
|
325
|
+
});
|
|
326
|
+
const normalizeInteraction = (json) => ({
|
|
327
|
+
id: json.id ?? json.name ?? "",
|
|
328
|
+
name: json.name,
|
|
329
|
+
model: json.model,
|
|
330
|
+
status: json.status,
|
|
331
|
+
outputs: json.outputs,
|
|
332
|
+
rawResponse: json,
|
|
333
|
+
providerMetadata: json
|
|
334
|
+
});
|
|
335
|
+
const normalizeOperation = (json) => ({
|
|
336
|
+
name: json.name ?? "",
|
|
337
|
+
done: json.done,
|
|
338
|
+
response: json.response,
|
|
339
|
+
error: json.error,
|
|
340
|
+
metadata: json.metadata,
|
|
341
|
+
rawResponse: json
|
|
342
|
+
});
|
|
343
|
+
const normalizePredictionResult = (json) => ({
|
|
344
|
+
predictions: json.predictions,
|
|
345
|
+
operationName: json.name,
|
|
346
|
+
operation: json.name || json.done !== undefined ? normalizeOperation(json) : undefined,
|
|
347
|
+
rawResponse: json,
|
|
348
|
+
providerMetadata: json
|
|
349
|
+
});
|
|
350
|
+
const appendQuery = (url, query) => {
|
|
351
|
+
const parsed = new URL(url);
|
|
352
|
+
for (const [key, value] of Object.entries(query)) {
|
|
353
|
+
if (value !== undefined) {
|
|
354
|
+
parsed.searchParams.set(key, String(value));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return parsed.toString();
|
|
358
|
+
};
|
|
359
|
+
const geminiUploadBaseURL = (baseURL) => baseURL.replace(/\/v1beta\/?$/, "/upload/v1beta");
|
|
360
|
+
const pollGeminiOperation = async (operation, baseURL, apiKey, fetcher, options) => {
|
|
361
|
+
if (options.pollIntervalMs === undefined && options.timeoutMs === undefined) {
|
|
362
|
+
return operation;
|
|
363
|
+
}
|
|
364
|
+
const startedAt = Date.now();
|
|
365
|
+
const timeoutMs = options.timeoutMs ?? 600_000;
|
|
366
|
+
let current = operation;
|
|
367
|
+
while (!current.done) {
|
|
368
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
369
|
+
throw new Error(`Gemini operation "${operation.name}" timed out after ${timeoutMs}ms.`);
|
|
370
|
+
}
|
|
371
|
+
await sleep(options.pollIntervalMs ?? 5_000, options.abortSignal);
|
|
372
|
+
const response = await withRetry(() => fetcher(`${baseURL}/${current.name}?key=${apiKey}`, {
|
|
373
|
+
method: "GET",
|
|
374
|
+
signal: options.abortSignal
|
|
375
|
+
}), options);
|
|
376
|
+
current = normalizeOperation(await parseJson(response));
|
|
377
|
+
}
|
|
378
|
+
return current;
|
|
379
|
+
};
|
|
93
380
|
const systemInstruction = (messages) => {
|
|
94
381
|
const text = messages
|
|
95
382
|
.filter((message) => message.role === "system")
|
|
@@ -110,6 +397,13 @@ const mapPart = (part) => {
|
|
|
110
397
|
data: part.image
|
|
111
398
|
}
|
|
112
399
|
};
|
|
400
|
+
case "file":
|
|
401
|
+
return {
|
|
402
|
+
fileData: {
|
|
403
|
+
mimeType: part.mediaType,
|
|
404
|
+
fileUri: part.data
|
|
405
|
+
}
|
|
406
|
+
};
|
|
113
407
|
case "tool-call":
|
|
114
408
|
return {
|
|
115
409
|
functionCall: {
|
|
@@ -484,6 +778,9 @@ const parseAssistantMessage = (candidate) => ({
|
|
|
484
778
|
}
|
|
485
779
|
};
|
|
486
780
|
}
|
|
781
|
+
if (part.inlineData?.data && String(part.inlineData.mimeType ?? "").startsWith("image/")) {
|
|
782
|
+
return { type: "image", image: part.inlineData.data, mediaType: part.inlineData.mimeType };
|
|
783
|
+
}
|
|
487
784
|
return { type: "text", text: JSON.stringify(part) };
|
|
488
785
|
}) ?? []
|
|
489
786
|
});
|
|
@@ -495,162 +792,746 @@ const extractGroundingSources = (candidate) => (candidate?.groundingMetadata?.gr
|
|
|
495
792
|
providerMetadata: chunk
|
|
496
793
|
}))
|
|
497
794
|
.filter((source) => typeof source.url === "string");
|
|
498
|
-
class
|
|
499
|
-
modelId;
|
|
795
|
+
class GeminiFilesClient {
|
|
500
796
|
apiKey;
|
|
501
797
|
baseURL;
|
|
502
798
|
fetcher;
|
|
503
|
-
|
|
504
|
-
capabilities = capabilities;
|
|
505
|
-
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
506
|
-
this.modelId = modelId;
|
|
799
|
+
constructor(apiKey, baseURL, fetcher) {
|
|
507
800
|
this.apiKey = apiKey;
|
|
508
801
|
this.baseURL = baseURL;
|
|
509
802
|
this.fetcher = fetcher;
|
|
510
803
|
}
|
|
511
|
-
url(
|
|
512
|
-
|
|
513
|
-
return `${this.baseURL}/models/${this.modelId}:${action}${separator}key=${this.apiKey}`;
|
|
804
|
+
url(path, query = {}) {
|
|
805
|
+
return appendQuery(`${this.baseURL}/${path}`, { key: this.apiKey, ...query });
|
|
514
806
|
}
|
|
515
|
-
|
|
807
|
+
uploadUrl(path) {
|
|
808
|
+
return appendQuery(`${geminiUploadBaseURL(this.baseURL)}/${path}`, { key: this.apiKey });
|
|
809
|
+
}
|
|
810
|
+
async upload(input) {
|
|
811
|
+
const bytes = await dataToBytes(input.data);
|
|
516
812
|
const { signal, cleanup } = withTimeoutSignal(input);
|
|
517
813
|
try {
|
|
518
|
-
const
|
|
814
|
+
const startResponse = await withRetry(() => this.fetcher(this.uploadUrl("files"), {
|
|
519
815
|
method: "POST",
|
|
520
|
-
headers: {
|
|
816
|
+
headers: {
|
|
817
|
+
"content-type": "application/json",
|
|
818
|
+
"x-goog-upload-protocol": "resumable",
|
|
819
|
+
"x-goog-upload-command": "start",
|
|
820
|
+
"x-goog-upload-header-content-length": String(bytes.byteLength),
|
|
821
|
+
"x-goog-upload-header-content-type": input.mediaType
|
|
822
|
+
},
|
|
521
823
|
signal,
|
|
522
824
|
body: JSON.stringify({
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
generationConfig: generationConfig(this.modelId, input)
|
|
825
|
+
file: {
|
|
826
|
+
...(input.displayName ? { displayName: input.displayName } : {}),
|
|
827
|
+
...(input.name ? { name: input.name } : {}),
|
|
828
|
+
...(input.providerOptions ?? {})
|
|
829
|
+
}
|
|
529
830
|
})
|
|
530
831
|
}), input);
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
832
|
+
if (!startResponse.ok) {
|
|
833
|
+
await parseJson(startResponse);
|
|
834
|
+
}
|
|
835
|
+
const resumableUrl = startResponse.headers.get("x-goog-upload-url");
|
|
836
|
+
if (!resumableUrl) {
|
|
837
|
+
throw new ProviderHTTPError('Gemini file upload did not return "x-goog-upload-url".', 500);
|
|
838
|
+
}
|
|
839
|
+
const uploadResponse = await withRetry(() => this.fetcher(resumableUrl, {
|
|
840
|
+
method: "POST",
|
|
841
|
+
headers: {
|
|
842
|
+
"content-type": input.mediaType,
|
|
843
|
+
"x-goog-upload-command": "upload, finalize",
|
|
844
|
+
"x-goog-upload-offset": "0"
|
|
845
|
+
},
|
|
846
|
+
signal,
|
|
847
|
+
body: new Blob([bytesToArrayBuffer(bytes)], { type: input.mediaType })
|
|
848
|
+
}), input);
|
|
849
|
+
return normalizeUploadedFile(await parseJson(uploadResponse));
|
|
544
850
|
}
|
|
545
851
|
finally {
|
|
546
852
|
cleanup();
|
|
547
853
|
}
|
|
548
854
|
}
|
|
549
|
-
async
|
|
855
|
+
async get(input) {
|
|
550
856
|
const { signal, cleanup } = withTimeoutSignal(input);
|
|
551
|
-
|
|
552
|
-
method: "
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
tools: mapTools(input.tools),
|
|
559
|
-
...input.providerOptions,
|
|
560
|
-
toolConfig: mapToolConfig(input.toolChoice, input.tools),
|
|
561
|
-
generationConfig: generationConfig(this.modelId, input)
|
|
562
|
-
})
|
|
563
|
-
}), input);
|
|
564
|
-
return (async function* () {
|
|
565
|
-
try {
|
|
566
|
-
for await (const event of streamSSE(response)) {
|
|
567
|
-
const json = JSON.parse(event.data);
|
|
568
|
-
const candidate = json.candidates?.[0];
|
|
569
|
-
const parts = candidate?.content?.parts ?? [];
|
|
570
|
-
for (const [index, part] of parts.entries()) {
|
|
571
|
-
if (part.text) {
|
|
572
|
-
yield { type: "text-delta", textDelta: part.text };
|
|
573
|
-
}
|
|
574
|
-
if (part.functionCall) {
|
|
575
|
-
yield {
|
|
576
|
-
type: "tool-call",
|
|
577
|
-
toolCall: {
|
|
578
|
-
id: part.functionCall.id ?? `${part.functionCall.name}-${index}`,
|
|
579
|
-
name: part.functionCall.name,
|
|
580
|
-
input: part.functionCall.args ?? {}
|
|
581
|
-
}
|
|
582
|
-
};
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
if (candidate?.finishReason) {
|
|
586
|
-
yield {
|
|
587
|
-
type: "finish",
|
|
588
|
-
finishReason: normalizeFinishReason(candidate.finishReason),
|
|
589
|
-
providerFinishReason: candidate.finishReason
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
finally {
|
|
595
|
-
cleanup();
|
|
596
|
-
}
|
|
597
|
-
})();
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
class GeminiEmbeddingModel {
|
|
601
|
-
modelId;
|
|
602
|
-
apiKey;
|
|
603
|
-
baseURL;
|
|
604
|
-
fetcher;
|
|
605
|
-
provider = "gemini";
|
|
606
|
-
capabilities = capabilities;
|
|
607
|
-
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
608
|
-
this.modelId = modelId;
|
|
609
|
-
this.apiKey = apiKey;
|
|
610
|
-
this.baseURL = baseURL;
|
|
611
|
-
this.fetcher = fetcher;
|
|
857
|
+
try {
|
|
858
|
+
const response = await withRetry(() => this.fetcher(this.url(input.name), { method: "GET", signal }), input);
|
|
859
|
+
return normalizeUploadedFile(await parseJson(response));
|
|
860
|
+
}
|
|
861
|
+
finally {
|
|
862
|
+
cleanup();
|
|
863
|
+
}
|
|
612
864
|
}
|
|
613
|
-
async
|
|
865
|
+
async list(input = {}) {
|
|
614
866
|
const { signal, cleanup } = withTimeoutSignal(input);
|
|
615
867
|
try {
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
method: "POST",
|
|
619
|
-
headers: { "content-type": "application/json" },
|
|
620
|
-
signal,
|
|
621
|
-
body: JSON.stringify({
|
|
622
|
-
content: { parts: [{ text: value }] }
|
|
623
|
-
})
|
|
624
|
-
}), input);
|
|
625
|
-
const json = await parseJson(response);
|
|
626
|
-
return json.embedding.values;
|
|
627
|
-
}));
|
|
868
|
+
const response = await withRetry(() => this.fetcher(this.url("files", { pageSize: input.pageSize, pageToken: input.pageToken }), { method: "GET", signal }), input);
|
|
869
|
+
const json = await parseJson(response);
|
|
628
870
|
return {
|
|
629
|
-
|
|
871
|
+
files: (json.files ?? []).map(normalizeUploadedFile),
|
|
872
|
+
nextPageToken: json.nextPageToken,
|
|
873
|
+
rawResponse: json
|
|
630
874
|
};
|
|
631
875
|
}
|
|
632
876
|
finally {
|
|
633
877
|
cleanup();
|
|
634
878
|
}
|
|
635
879
|
}
|
|
880
|
+
async delete(input) {
|
|
881
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
882
|
+
try {
|
|
883
|
+
const response = await withRetry(() => this.fetcher(this.url(input.name), { method: "DELETE", signal }), input);
|
|
884
|
+
const json = await parseJson(response);
|
|
885
|
+
return { name: input.name, rawResponse: json };
|
|
886
|
+
}
|
|
887
|
+
finally {
|
|
888
|
+
cleanup();
|
|
889
|
+
}
|
|
890
|
+
}
|
|
636
891
|
}
|
|
637
|
-
class
|
|
638
|
-
modelId;
|
|
892
|
+
class GeminiFileSearchStoresClient {
|
|
639
893
|
apiKey;
|
|
640
894
|
baseURL;
|
|
641
895
|
fetcher;
|
|
642
|
-
|
|
643
|
-
capabilities = transcriptionCapabilities;
|
|
644
|
-
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
645
|
-
this.modelId = modelId;
|
|
896
|
+
constructor(apiKey, baseURL, fetcher) {
|
|
646
897
|
this.apiKey = apiKey;
|
|
647
898
|
this.baseURL = baseURL;
|
|
648
899
|
this.fetcher = fetcher;
|
|
649
900
|
}
|
|
650
|
-
|
|
901
|
+
url(path, query = {}) {
|
|
902
|
+
return appendQuery(`${this.baseURL}/${path}`, { key: this.apiKey, ...query });
|
|
903
|
+
}
|
|
904
|
+
uploadUrl(path) {
|
|
905
|
+
return appendQuery(`${geminiUploadBaseURL(this.baseURL)}/${path}`, { key: this.apiKey });
|
|
906
|
+
}
|
|
907
|
+
async create(input = {}) {
|
|
651
908
|
const { signal, cleanup } = withTimeoutSignal(input);
|
|
652
909
|
try {
|
|
653
|
-
const response = await withRetry(() => this.fetcher(
|
|
910
|
+
const response = await withRetry(() => this.fetcher(this.url("fileSearchStores"), {
|
|
911
|
+
method: "POST",
|
|
912
|
+
headers: { "content-type": "application/json" },
|
|
913
|
+
signal,
|
|
914
|
+
body: JSON.stringify({
|
|
915
|
+
...(input.displayName ? { displayName: input.displayName } : {}),
|
|
916
|
+
...(input.providerOptions ?? {})
|
|
917
|
+
})
|
|
918
|
+
}), input);
|
|
919
|
+
return normalizeFileSearchStore(await parseJson(response));
|
|
920
|
+
}
|
|
921
|
+
finally {
|
|
922
|
+
cleanup();
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
async upload(input) {
|
|
926
|
+
const bytes = await dataToBytes(input.data);
|
|
927
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
928
|
+
try {
|
|
929
|
+
const startResponse = await withRetry(() => this.fetcher(this.uploadUrl(`${input.storeName}:uploadToFileSearchStore`), {
|
|
930
|
+
method: "POST",
|
|
931
|
+
headers: {
|
|
932
|
+
"content-type": "application/json",
|
|
933
|
+
"x-goog-upload-protocol": "resumable",
|
|
934
|
+
"x-goog-upload-command": "start",
|
|
935
|
+
"x-goog-upload-header-content-length": String(bytes.byteLength),
|
|
936
|
+
"x-goog-upload-header-content-type": input.mediaType
|
|
937
|
+
},
|
|
938
|
+
signal,
|
|
939
|
+
body: JSON.stringify({
|
|
940
|
+
file: {
|
|
941
|
+
...(input.displayName ? { displayName: input.displayName } : {}),
|
|
942
|
+
...(input.filename ? { name: input.filename } : {})
|
|
943
|
+
},
|
|
944
|
+
...(input.providerOptions ?? {})
|
|
945
|
+
})
|
|
946
|
+
}), input);
|
|
947
|
+
if (!startResponse.ok) {
|
|
948
|
+
await parseJson(startResponse);
|
|
949
|
+
}
|
|
950
|
+
const resumableUrl = startResponse.headers.get("x-goog-upload-url");
|
|
951
|
+
if (!resumableUrl) {
|
|
952
|
+
throw new ProviderHTTPError('Gemini file search upload did not return "x-goog-upload-url".', 500);
|
|
953
|
+
}
|
|
954
|
+
const uploadResponse = await withRetry(() => this.fetcher(resumableUrl, {
|
|
955
|
+
method: "POST",
|
|
956
|
+
headers: {
|
|
957
|
+
"content-type": input.mediaType,
|
|
958
|
+
"x-goog-upload-command": "upload, finalize",
|
|
959
|
+
"x-goog-upload-offset": "0"
|
|
960
|
+
},
|
|
961
|
+
signal,
|
|
962
|
+
body: new Blob([bytesToArrayBuffer(bytes)], { type: input.mediaType })
|
|
963
|
+
}), input);
|
|
964
|
+
return pollGeminiOperation(normalizeOperation(await parseJson(uploadResponse)), this.baseURL, this.apiKey, this.fetcher, {
|
|
965
|
+
...input,
|
|
966
|
+
abortSignal: signal
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
finally {
|
|
970
|
+
cleanup();
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
async importFile(input) {
|
|
974
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
975
|
+
try {
|
|
976
|
+
const response = await withRetry(() => this.fetcher(this.url(`${input.storeName}:importFile`), {
|
|
977
|
+
method: "POST",
|
|
978
|
+
headers: { "content-type": "application/json" },
|
|
979
|
+
signal,
|
|
980
|
+
body: JSON.stringify({
|
|
981
|
+
fileName: input.fileName,
|
|
982
|
+
...(input.providerOptions ?? {})
|
|
983
|
+
})
|
|
984
|
+
}), input);
|
|
985
|
+
return pollGeminiOperation(normalizeOperation(await parseJson(response)), this.baseURL, this.apiKey, this.fetcher, {
|
|
986
|
+
...input,
|
|
987
|
+
abortSignal: signal
|
|
988
|
+
});
|
|
989
|
+
}
|
|
990
|
+
finally {
|
|
991
|
+
cleanup();
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
async get(input) {
|
|
995
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
996
|
+
try {
|
|
997
|
+
const response = await withRetry(() => this.fetcher(this.url(input.name), { method: "GET", signal }), input);
|
|
998
|
+
return normalizeFileSearchStore(await parseJson(response));
|
|
999
|
+
}
|
|
1000
|
+
finally {
|
|
1001
|
+
cleanup();
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
async list(input = {}) {
|
|
1005
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1006
|
+
try {
|
|
1007
|
+
const response = await withRetry(() => this.fetcher(this.url("fileSearchStores", { pageSize: input.pageSize, pageToken: input.pageToken }), { method: "GET", signal }), input);
|
|
1008
|
+
const json = await parseJson(response);
|
|
1009
|
+
return {
|
|
1010
|
+
stores: (json.fileSearchStores ?? json.file_search_stores ?? []).map(normalizeFileSearchStore),
|
|
1011
|
+
nextPageToken: json.nextPageToken,
|
|
1012
|
+
rawResponse: json
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
finally {
|
|
1016
|
+
cleanup();
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
async delete(input) {
|
|
1020
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1021
|
+
try {
|
|
1022
|
+
const response = await withRetry(() => this.fetcher(this.url(input.name), { method: "DELETE", signal }), input);
|
|
1023
|
+
const json = await parseJson(response);
|
|
1024
|
+
return { name: input.name, rawResponse: json };
|
|
1025
|
+
}
|
|
1026
|
+
finally {
|
|
1027
|
+
cleanup();
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
class GeminiContextCachesClient {
|
|
1032
|
+
apiKey;
|
|
1033
|
+
baseURL;
|
|
1034
|
+
fetcher;
|
|
1035
|
+
constructor(apiKey, baseURL, fetcher) {
|
|
1036
|
+
this.apiKey = apiKey;
|
|
1037
|
+
this.baseURL = baseURL;
|
|
1038
|
+
this.fetcher = fetcher;
|
|
1039
|
+
}
|
|
1040
|
+
url(path, query = {}) {
|
|
1041
|
+
return appendQuery(`${this.baseURL}/${path}`, { key: this.apiKey, ...query });
|
|
1042
|
+
}
|
|
1043
|
+
async create(input) {
|
|
1044
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1045
|
+
try {
|
|
1046
|
+
const response = await withRetry(() => this.fetcher(this.url("cachedContents"), {
|
|
1047
|
+
method: "POST",
|
|
1048
|
+
headers: { "content-type": "application/json" },
|
|
1049
|
+
signal,
|
|
1050
|
+
body: JSON.stringify({
|
|
1051
|
+
model: input.modelId.startsWith("models/") ? input.modelId : `models/${input.modelId}`,
|
|
1052
|
+
contents: mapMessages(input.contents),
|
|
1053
|
+
...(input.system ? { systemInstruction: { parts: [{ text: input.system }] } } : { systemInstruction: systemInstruction(input.contents) }),
|
|
1054
|
+
...(input.tools ? { tools: mapTools(toToolSet(input.tools)) } : {}),
|
|
1055
|
+
...(input.displayName ? { displayName: input.displayName } : {}),
|
|
1056
|
+
...(input.ttl ? { ttl: input.ttl } : {}),
|
|
1057
|
+
...(input.expireTime ? { expireTime: input.expireTime } : {}),
|
|
1058
|
+
...(input.providerOptions ?? {})
|
|
1059
|
+
})
|
|
1060
|
+
}), input);
|
|
1061
|
+
return normalizeCachedContent(await parseJson(response));
|
|
1062
|
+
}
|
|
1063
|
+
finally {
|
|
1064
|
+
cleanup();
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
async get(input) {
|
|
1068
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1069
|
+
try {
|
|
1070
|
+
const response = await withRetry(() => this.fetcher(this.url(input.name), { method: "GET", signal }), input);
|
|
1071
|
+
return normalizeCachedContent(await parseJson(response));
|
|
1072
|
+
}
|
|
1073
|
+
finally {
|
|
1074
|
+
cleanup();
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
async list(input = {}) {
|
|
1078
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1079
|
+
try {
|
|
1080
|
+
const response = await withRetry(() => this.fetcher(this.url("cachedContents", { pageSize: input.pageSize, pageToken: input.pageToken }), { method: "GET", signal }), input);
|
|
1081
|
+
const json = await parseJson(response);
|
|
1082
|
+
return {
|
|
1083
|
+
caches: (json.cachedContents ?? json.cached_contents ?? []).map(normalizeCachedContent),
|
|
1084
|
+
nextPageToken: json.nextPageToken,
|
|
1085
|
+
rawResponse: json
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
finally {
|
|
1089
|
+
cleanup();
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
async delete(input) {
|
|
1093
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1094
|
+
try {
|
|
1095
|
+
const response = await withRetry(() => this.fetcher(this.url(input.name), { method: "DELETE", signal }), input);
|
|
1096
|
+
const json = await parseJson(response);
|
|
1097
|
+
return { name: input.name, rawResponse: json };
|
|
1098
|
+
}
|
|
1099
|
+
finally {
|
|
1100
|
+
cleanup();
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
class GeminiBatchesClient {
|
|
1105
|
+
apiKey;
|
|
1106
|
+
baseURL;
|
|
1107
|
+
fetcher;
|
|
1108
|
+
constructor(apiKey, baseURL, fetcher) {
|
|
1109
|
+
this.apiKey = apiKey;
|
|
1110
|
+
this.baseURL = baseURL;
|
|
1111
|
+
this.fetcher = fetcher;
|
|
1112
|
+
}
|
|
1113
|
+
url(path, query = {}) {
|
|
1114
|
+
return appendQuery(`${this.baseURL}/${path}`, { key: this.apiKey, ...query });
|
|
1115
|
+
}
|
|
1116
|
+
async create(input) {
|
|
1117
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1118
|
+
try {
|
|
1119
|
+
const response = await withRetry(() => this.fetcher(this.url(`models/${input.modelId}:batchGenerateContent`), {
|
|
1120
|
+
method: "POST",
|
|
1121
|
+
headers: { "content-type": "application/json" },
|
|
1122
|
+
signal,
|
|
1123
|
+
body: JSON.stringify({
|
|
1124
|
+
batch: {
|
|
1125
|
+
...(input.displayName ? { displayName: input.displayName } : {}),
|
|
1126
|
+
inputConfig: input.fileName
|
|
1127
|
+
? { fileName: input.fileName }
|
|
1128
|
+
: {
|
|
1129
|
+
requests: {
|
|
1130
|
+
requests: input.requests ?? []
|
|
1131
|
+
}
|
|
1132
|
+
},
|
|
1133
|
+
...(input.providerOptions ?? {})
|
|
1134
|
+
}
|
|
1135
|
+
})
|
|
1136
|
+
}), input);
|
|
1137
|
+
return normalizeBatchJob(await parseJson(response));
|
|
1138
|
+
}
|
|
1139
|
+
finally {
|
|
1140
|
+
cleanup();
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
async get(input) {
|
|
1144
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1145
|
+
try {
|
|
1146
|
+
const response = await withRetry(() => this.fetcher(this.url(input.name), { method: "GET", signal }), input);
|
|
1147
|
+
return normalizeBatchJob(await parseJson(response));
|
|
1148
|
+
}
|
|
1149
|
+
finally {
|
|
1150
|
+
cleanup();
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
async list(input = {}) {
|
|
1154
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1155
|
+
try {
|
|
1156
|
+
const response = await withRetry(() => this.fetcher(this.url("batches", { pageSize: input.pageSize, pageToken: input.pageToken }), { method: "GET", signal }), input);
|
|
1157
|
+
const json = await parseJson(response);
|
|
1158
|
+
return {
|
|
1159
|
+
batches: (json.batches ?? []).map(normalizeBatchJob),
|
|
1160
|
+
nextPageToken: json.nextPageToken,
|
|
1161
|
+
rawResponse: json
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
finally {
|
|
1165
|
+
cleanup();
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
async cancel(input) {
|
|
1169
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1170
|
+
try {
|
|
1171
|
+
const response = await withRetry(() => this.fetcher(this.url(`${input.name}:cancel`), {
|
|
1172
|
+
method: "POST",
|
|
1173
|
+
headers: { "content-type": "application/json" },
|
|
1174
|
+
signal,
|
|
1175
|
+
body: JSON.stringify(input.providerOptions ?? {})
|
|
1176
|
+
}), input);
|
|
1177
|
+
return normalizeBatchJob(await parseJson(response));
|
|
1178
|
+
}
|
|
1179
|
+
finally {
|
|
1180
|
+
cleanup();
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
async delete(input) {
|
|
1184
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1185
|
+
try {
|
|
1186
|
+
const response = await withRetry(() => this.fetcher(this.url(`${input.name}:delete`), { method: "POST", signal }), input);
|
|
1187
|
+
const json = await parseJson(response);
|
|
1188
|
+
return { name: input.name, rawResponse: json };
|
|
1189
|
+
}
|
|
1190
|
+
finally {
|
|
1191
|
+
cleanup();
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
class GeminiInteractionsClient {
|
|
1196
|
+
apiKey;
|
|
1197
|
+
baseURL;
|
|
1198
|
+
fetcher;
|
|
1199
|
+
constructor(apiKey, baseURL, fetcher) {
|
|
1200
|
+
this.apiKey = apiKey;
|
|
1201
|
+
this.baseURL = baseURL;
|
|
1202
|
+
this.fetcher = fetcher;
|
|
1203
|
+
}
|
|
1204
|
+
url(path, query = {}) {
|
|
1205
|
+
return appendQuery(`${this.baseURL}/${path}`, { key: this.apiKey, ...query });
|
|
1206
|
+
}
|
|
1207
|
+
body(input, stream = false) {
|
|
1208
|
+
return {
|
|
1209
|
+
...(input.modelId ? { model: input.modelId } : {}),
|
|
1210
|
+
...(input.agent ? { agent: input.agent } : {}),
|
|
1211
|
+
input: input.input,
|
|
1212
|
+
...(input.previousInteractionId ? { previous_interaction_id: input.previousInteractionId } : {}),
|
|
1213
|
+
...(input.tools ? { tools: mapTools(toToolSet(input.tools)) } : {}),
|
|
1214
|
+
...(input.background !== undefined ? { background: input.background } : {}),
|
|
1215
|
+
...(input.store !== undefined ? { store: input.store } : {}),
|
|
1216
|
+
...(stream ? { stream: true } : {}),
|
|
1217
|
+
...(input.providerOptions ?? {})
|
|
1218
|
+
};
|
|
1219
|
+
}
|
|
1220
|
+
async create(input) {
|
|
1221
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1222
|
+
try {
|
|
1223
|
+
const response = await withRetry(() => this.fetcher(this.url("interactions"), {
|
|
1224
|
+
method: "POST",
|
|
1225
|
+
headers: { "content-type": "application/json" },
|
|
1226
|
+
signal,
|
|
1227
|
+
body: JSON.stringify(this.body(input))
|
|
1228
|
+
}), input);
|
|
1229
|
+
return normalizeInteraction(await parseJson(response));
|
|
1230
|
+
}
|
|
1231
|
+
finally {
|
|
1232
|
+
cleanup();
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
async get(input) {
|
|
1236
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1237
|
+
try {
|
|
1238
|
+
const response = await withRetry(() => this.fetcher(this.url(`interactions/${input.id}`), { method: "GET", signal }), input);
|
|
1239
|
+
return normalizeInteraction(await parseJson(response));
|
|
1240
|
+
}
|
|
1241
|
+
finally {
|
|
1242
|
+
cleanup();
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
async stream(input) {
|
|
1246
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1247
|
+
const response = await withRetry(() => this.fetcher(this.url("interactions", { alt: "sse" }), {
|
|
1248
|
+
method: "POST",
|
|
1249
|
+
headers: { "content-type": "application/json" },
|
|
1250
|
+
signal,
|
|
1251
|
+
body: JSON.stringify(this.body(input, true))
|
|
1252
|
+
}), input);
|
|
1253
|
+
return (async function* () {
|
|
1254
|
+
try {
|
|
1255
|
+
for await (const event of streamSSE(response)) {
|
|
1256
|
+
const json = JSON.parse(event.data);
|
|
1257
|
+
const text = json.text ??
|
|
1258
|
+
json.delta?.text ??
|
|
1259
|
+
json.output?.text ??
|
|
1260
|
+
(Array.isArray(json.outputs) ? json.outputs.find((output) => typeof output.text === "string")?.text : undefined);
|
|
1261
|
+
if (typeof text === "string" && text) {
|
|
1262
|
+
yield { type: "text-delta", textDelta: text };
|
|
1263
|
+
}
|
|
1264
|
+
else {
|
|
1265
|
+
yield { type: "provider-data", provider: "gemini", data: json };
|
|
1266
|
+
}
|
|
1267
|
+
if (json.status === "completed" || json.done) {
|
|
1268
|
+
yield { type: "finish", finishReason: "stop" };
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
finally {
|
|
1273
|
+
cleanup();
|
|
1274
|
+
}
|
|
1275
|
+
})();
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
class GeminiPredictionModel {
|
|
1279
|
+
modelId;
|
|
1280
|
+
apiKey;
|
|
1281
|
+
baseURL;
|
|
1282
|
+
fetcher;
|
|
1283
|
+
provider = "gemini";
|
|
1284
|
+
capabilities = {
|
|
1285
|
+
...capabilities,
|
|
1286
|
+
rawPrediction: true
|
|
1287
|
+
};
|
|
1288
|
+
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
1289
|
+
this.modelId = modelId;
|
|
1290
|
+
this.apiKey = apiKey;
|
|
1291
|
+
this.baseURL = baseURL;
|
|
1292
|
+
this.fetcher = fetcher;
|
|
1293
|
+
}
|
|
1294
|
+
url(action) {
|
|
1295
|
+
return `${this.baseURL}/models/${this.modelId}:${action}?key=${this.apiKey}`;
|
|
1296
|
+
}
|
|
1297
|
+
body(input) {
|
|
1298
|
+
return input.body ?? {
|
|
1299
|
+
...(input.instances ? { instances: input.instances } : {}),
|
|
1300
|
+
...(input.parameters ? { parameters: input.parameters } : {}),
|
|
1301
|
+
...(input.providerOptions ?? {})
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
async predictRaw(input) {
|
|
1305
|
+
const action = typeof input.providerOptions?.action === "string" ? input.providerOptions.action : "predict";
|
|
1306
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1307
|
+
try {
|
|
1308
|
+
const response = await withRetry(() => this.fetcher(this.url(action), {
|
|
1309
|
+
method: "POST",
|
|
1310
|
+
headers: { "content-type": "application/json" },
|
|
1311
|
+
signal,
|
|
1312
|
+
body: JSON.stringify(this.body(input))
|
|
1313
|
+
}), input);
|
|
1314
|
+
return normalizePredictionResult(await parseJson(response));
|
|
1315
|
+
}
|
|
1316
|
+
finally {
|
|
1317
|
+
cleanup();
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
async rawPredict(input) {
|
|
1321
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1322
|
+
try {
|
|
1323
|
+
const response = await withRetry(() => this.fetcher(this.url("rawPredict"), {
|
|
1324
|
+
method: "POST",
|
|
1325
|
+
headers: { "content-type": "application/json" },
|
|
1326
|
+
signal,
|
|
1327
|
+
body: JSON.stringify(this.body(input))
|
|
1328
|
+
}), input);
|
|
1329
|
+
return normalizePredictionResult(await parseJson(response));
|
|
1330
|
+
}
|
|
1331
|
+
finally {
|
|
1332
|
+
cleanup();
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
async invoke(input) {
|
|
1336
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1337
|
+
try {
|
|
1338
|
+
const response = await withRetry(() => this.fetcher(this.url("invoke"), {
|
|
1339
|
+
method: "POST",
|
|
1340
|
+
headers: { "content-type": "application/json" },
|
|
1341
|
+
signal,
|
|
1342
|
+
body: JSON.stringify(this.body(input))
|
|
1343
|
+
}), input);
|
|
1344
|
+
return normalizePredictionResult(await parseJson(response));
|
|
1345
|
+
}
|
|
1346
|
+
finally {
|
|
1347
|
+
cleanup();
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
async predictLongRunning(input) {
|
|
1351
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1352
|
+
try {
|
|
1353
|
+
const response = await withRetry(() => this.fetcher(this.url("predictLongRunning"), {
|
|
1354
|
+
method: "POST",
|
|
1355
|
+
headers: { "content-type": "application/json" },
|
|
1356
|
+
signal,
|
|
1357
|
+
body: JSON.stringify(this.body(input))
|
|
1358
|
+
}), input);
|
|
1359
|
+
return normalizeOperation(await parseJson(response));
|
|
1360
|
+
}
|
|
1361
|
+
finally {
|
|
1362
|
+
cleanup();
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
async fetchPredictionOperation(input) {
|
|
1366
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1367
|
+
try {
|
|
1368
|
+
const response = await withRetry(() => this.fetcher(`${this.baseURL}/${input.name}?key=${this.apiKey}`, {
|
|
1369
|
+
method: "GET",
|
|
1370
|
+
signal
|
|
1371
|
+
}), input);
|
|
1372
|
+
return normalizeOperation(await parseJson(response));
|
|
1373
|
+
}
|
|
1374
|
+
finally {
|
|
1375
|
+
cleanup();
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
class GeminiLanguageModel {
|
|
1380
|
+
modelId;
|
|
1381
|
+
apiKey;
|
|
1382
|
+
baseURL;
|
|
1383
|
+
fetcher;
|
|
1384
|
+
provider = "gemini";
|
|
1385
|
+
capabilities = capabilities;
|
|
1386
|
+
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
1387
|
+
this.modelId = modelId;
|
|
1388
|
+
this.apiKey = apiKey;
|
|
1389
|
+
this.baseURL = baseURL;
|
|
1390
|
+
this.fetcher = fetcher;
|
|
1391
|
+
}
|
|
1392
|
+
url(action) {
|
|
1393
|
+
const separator = action.includes("?") ? "&" : "?";
|
|
1394
|
+
return `${this.baseURL}/models/${this.modelId}:${action}${separator}key=${this.apiKey}`;
|
|
1395
|
+
}
|
|
1396
|
+
async generate(input) {
|
|
1397
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1398
|
+
try {
|
|
1399
|
+
const response = await withRetry(() => this.fetcher(this.url("generateContent"), {
|
|
1400
|
+
method: "POST",
|
|
1401
|
+
headers: { "content-type": "application/json" },
|
|
1402
|
+
signal,
|
|
1403
|
+
body: JSON.stringify({
|
|
1404
|
+
contents: mapMessages(input.messages),
|
|
1405
|
+
systemInstruction: systemInstruction(input.messages),
|
|
1406
|
+
tools: mapTools(input.tools),
|
|
1407
|
+
...input.providerOptions,
|
|
1408
|
+
toolConfig: mapToolConfig(input.toolChoice, input.tools),
|
|
1409
|
+
generationConfig: generationConfig(this.modelId, input)
|
|
1410
|
+
})
|
|
1411
|
+
}), input);
|
|
1412
|
+
const json = await parseJson(response);
|
|
1413
|
+
const candidate = json.candidates?.[0];
|
|
1414
|
+
const assistantMessage = parseAssistantMessage(candidate);
|
|
1415
|
+
return {
|
|
1416
|
+
messages: [assistantMessage],
|
|
1417
|
+
text: assistantMessage.parts
|
|
1418
|
+
.filter((part) => part.type === "text")
|
|
1419
|
+
.map((part) => part.text)
|
|
1420
|
+
.join(""),
|
|
1421
|
+
finishReason: normalizeFinishReason(candidate?.finishReason),
|
|
1422
|
+
providerFinishReason: candidate?.finishReason,
|
|
1423
|
+
rawResponse: json
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
finally {
|
|
1427
|
+
cleanup();
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
async stream(input) {
|
|
1431
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1432
|
+
const response = await withRetry(() => this.fetcher(this.url("streamGenerateContent?alt=sse"), {
|
|
1433
|
+
method: "POST",
|
|
1434
|
+
headers: { "content-type": "application/json" },
|
|
1435
|
+
signal,
|
|
1436
|
+
body: JSON.stringify({
|
|
1437
|
+
contents: mapMessages(input.messages),
|
|
1438
|
+
systemInstruction: systemInstruction(input.messages),
|
|
1439
|
+
tools: mapTools(input.tools),
|
|
1440
|
+
...input.providerOptions,
|
|
1441
|
+
toolConfig: mapToolConfig(input.toolChoice, input.tools),
|
|
1442
|
+
generationConfig: generationConfig(this.modelId, input)
|
|
1443
|
+
})
|
|
1444
|
+
}), input);
|
|
1445
|
+
return (async function* () {
|
|
1446
|
+
try {
|
|
1447
|
+
for await (const event of streamSSE(response)) {
|
|
1448
|
+
const json = JSON.parse(event.data);
|
|
1449
|
+
const candidate = json.candidates?.[0];
|
|
1450
|
+
const parts = candidate?.content?.parts ?? [];
|
|
1451
|
+
for (const [index, part] of parts.entries()) {
|
|
1452
|
+
if (part.text) {
|
|
1453
|
+
yield { type: "text-delta", textDelta: part.text };
|
|
1454
|
+
}
|
|
1455
|
+
if (part.functionCall) {
|
|
1456
|
+
yield {
|
|
1457
|
+
type: "tool-call",
|
|
1458
|
+
toolCall: {
|
|
1459
|
+
id: part.functionCall.id ?? `${part.functionCall.name}-${index}`,
|
|
1460
|
+
name: part.functionCall.name,
|
|
1461
|
+
input: part.functionCall.args ?? {}
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
if (candidate?.finishReason) {
|
|
1467
|
+
yield {
|
|
1468
|
+
type: "finish",
|
|
1469
|
+
finishReason: normalizeFinishReason(candidate.finishReason),
|
|
1470
|
+
providerFinishReason: candidate.finishReason
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
finally {
|
|
1476
|
+
cleanup();
|
|
1477
|
+
}
|
|
1478
|
+
})();
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
class GeminiEmbeddingModel {
|
|
1482
|
+
modelId;
|
|
1483
|
+
apiKey;
|
|
1484
|
+
baseURL;
|
|
1485
|
+
fetcher;
|
|
1486
|
+
provider = "gemini";
|
|
1487
|
+
capabilities = capabilities;
|
|
1488
|
+
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
1489
|
+
this.modelId = modelId;
|
|
1490
|
+
this.apiKey = apiKey;
|
|
1491
|
+
this.baseURL = baseURL;
|
|
1492
|
+
this.fetcher = fetcher;
|
|
1493
|
+
}
|
|
1494
|
+
async embed(input) {
|
|
1495
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1496
|
+
try {
|
|
1497
|
+
const embeddings = await Promise.all(input.values.map(async (value) => {
|
|
1498
|
+
const response = await withRetry(() => this.fetcher(`${this.baseURL}/models/${this.modelId}:embedContent?key=${this.apiKey}`, {
|
|
1499
|
+
method: "POST",
|
|
1500
|
+
headers: { "content-type": "application/json" },
|
|
1501
|
+
signal,
|
|
1502
|
+
body: JSON.stringify({
|
|
1503
|
+
content: { parts: [{ text: value }] }
|
|
1504
|
+
})
|
|
1505
|
+
}), input);
|
|
1506
|
+
const json = await parseJson(response);
|
|
1507
|
+
return json.embedding.values;
|
|
1508
|
+
}));
|
|
1509
|
+
return {
|
|
1510
|
+
embeddings
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
finally {
|
|
1514
|
+
cleanup();
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
class GeminiTranscriptionModel {
|
|
1519
|
+
modelId;
|
|
1520
|
+
apiKey;
|
|
1521
|
+
baseURL;
|
|
1522
|
+
fetcher;
|
|
1523
|
+
provider = "gemini";
|
|
1524
|
+
capabilities = transcriptionCapabilities;
|
|
1525
|
+
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
1526
|
+
this.modelId = modelId;
|
|
1527
|
+
this.apiKey = apiKey;
|
|
1528
|
+
this.baseURL = baseURL;
|
|
1529
|
+
this.fetcher = fetcher;
|
|
1530
|
+
}
|
|
1531
|
+
async transcribe(input) {
|
|
1532
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1533
|
+
try {
|
|
1534
|
+
const response = await withRetry(() => this.fetcher(`${this.baseURL}/models/${this.modelId}:generateContent?key=${this.apiKey}`, {
|
|
654
1535
|
method: "POST",
|
|
655
1536
|
headers: { "content-type": "application/json" },
|
|
656
1537
|
signal,
|
|
@@ -736,6 +1617,183 @@ class GeminiSpeechModel {
|
|
|
736
1617
|
}
|
|
737
1618
|
}
|
|
738
1619
|
}
|
|
1620
|
+
class GeminiImageGenerationModel {
|
|
1621
|
+
modelId;
|
|
1622
|
+
apiKey;
|
|
1623
|
+
baseURL;
|
|
1624
|
+
fetcher;
|
|
1625
|
+
provider = "gemini";
|
|
1626
|
+
capabilities = imageGenerationCapabilities;
|
|
1627
|
+
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
1628
|
+
this.modelId = modelId;
|
|
1629
|
+
this.apiKey = apiKey;
|
|
1630
|
+
this.baseURL = baseURL;
|
|
1631
|
+
this.fetcher = fetcher;
|
|
1632
|
+
}
|
|
1633
|
+
async generateImage(input) {
|
|
1634
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1635
|
+
const { generationConfig, providerOptions } = splitGenerationConfig(input.providerOptions);
|
|
1636
|
+
try {
|
|
1637
|
+
const response = await withRetry(() => this.fetcher(`${this.baseURL}/models/${this.modelId}:generateContent?key=${this.apiKey}`, {
|
|
1638
|
+
method: "POST",
|
|
1639
|
+
headers: { "content-type": "application/json" },
|
|
1640
|
+
signal,
|
|
1641
|
+
body: JSON.stringify({
|
|
1642
|
+
contents: [
|
|
1643
|
+
{
|
|
1644
|
+
role: "user",
|
|
1645
|
+
parts: [
|
|
1646
|
+
{ text: input.negativePrompt ? `${input.prompt}\n\nNegative prompt: ${input.negativePrompt}` : input.prompt },
|
|
1647
|
+
...(input.images ?? []).map(mediaInputToPart)
|
|
1648
|
+
]
|
|
1649
|
+
}
|
|
1650
|
+
],
|
|
1651
|
+
...providerOptions,
|
|
1652
|
+
generationConfig: {
|
|
1653
|
+
responseModalities: ["TEXT", "IMAGE"],
|
|
1654
|
+
...(input.count ? { candidateCount: input.count } : {}),
|
|
1655
|
+
...(input.outputMimeType ? { responseMimeType: input.outputMimeType } : {}),
|
|
1656
|
+
...(input.aspectRatio || input.size
|
|
1657
|
+
? {
|
|
1658
|
+
imageConfig: {
|
|
1659
|
+
...(input.aspectRatio ? { aspectRatio: input.aspectRatio } : {}),
|
|
1660
|
+
...(input.size ? { imageSize: input.size } : {})
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
: {}),
|
|
1664
|
+
...generationConfig
|
|
1665
|
+
}
|
|
1666
|
+
})
|
|
1667
|
+
}), input);
|
|
1668
|
+
const json = await parseJson(response);
|
|
1669
|
+
const { media, text } = collectInlineMedia(json, input.outputMimeType ?? "image/png");
|
|
1670
|
+
return {
|
|
1671
|
+
images: media,
|
|
1672
|
+
text,
|
|
1673
|
+
rawResponse: json
|
|
1674
|
+
};
|
|
1675
|
+
}
|
|
1676
|
+
finally {
|
|
1677
|
+
cleanup();
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
class GeminiMusicGenerationModel {
|
|
1682
|
+
modelId;
|
|
1683
|
+
apiKey;
|
|
1684
|
+
baseURL;
|
|
1685
|
+
fetcher;
|
|
1686
|
+
provider = "gemini";
|
|
1687
|
+
capabilities = musicGenerationCapabilities;
|
|
1688
|
+
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
1689
|
+
this.modelId = modelId;
|
|
1690
|
+
this.apiKey = apiKey;
|
|
1691
|
+
this.baseURL = baseURL;
|
|
1692
|
+
this.fetcher = fetcher;
|
|
1693
|
+
}
|
|
1694
|
+
async generateMusic(input) {
|
|
1695
|
+
const { signal, cleanup } = withTimeoutSignal(input);
|
|
1696
|
+
const { generationConfig, providerOptions } = splitGenerationConfig(input.providerOptions);
|
|
1697
|
+
try {
|
|
1698
|
+
const response = await withRetry(() => this.fetcher(`${this.baseURL}/models/${this.modelId}:generateContent?key=${this.apiKey}`, {
|
|
1699
|
+
method: "POST",
|
|
1700
|
+
headers: { "content-type": "application/json" },
|
|
1701
|
+
signal,
|
|
1702
|
+
body: JSON.stringify({
|
|
1703
|
+
contents: [
|
|
1704
|
+
{
|
|
1705
|
+
role: "user",
|
|
1706
|
+
parts: [
|
|
1707
|
+
{ text: input.negativePrompt ? `${input.prompt}\n\nNegative prompt: ${input.negativePrompt}` : input.prompt },
|
|
1708
|
+
...(input.images ?? []).map(mediaInputToPart)
|
|
1709
|
+
]
|
|
1710
|
+
}
|
|
1711
|
+
],
|
|
1712
|
+
...providerOptions,
|
|
1713
|
+
generationConfig: {
|
|
1714
|
+
responseModalities: ["AUDIO", "TEXT"],
|
|
1715
|
+
...(input.outputMimeType ? { responseMimeType: input.outputMimeType } : {}),
|
|
1716
|
+
...generationConfig
|
|
1717
|
+
}
|
|
1718
|
+
})
|
|
1719
|
+
}), input);
|
|
1720
|
+
const json = await parseJson(response);
|
|
1721
|
+
const { media, text } = collectInlineMedia(json, input.outputMimeType ?? "audio/mpeg");
|
|
1722
|
+
return {
|
|
1723
|
+
audio: media,
|
|
1724
|
+
text,
|
|
1725
|
+
rawResponse: json
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1728
|
+
finally {
|
|
1729
|
+
cleanup();
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
class GeminiVideoGenerationModel {
|
|
1734
|
+
modelId;
|
|
1735
|
+
apiKey;
|
|
1736
|
+
baseURL;
|
|
1737
|
+
fetcher;
|
|
1738
|
+
provider = "gemini";
|
|
1739
|
+
capabilities = videoGenerationCapabilities;
|
|
1740
|
+
constructor(modelId, apiKey, baseURL, fetcher) {
|
|
1741
|
+
this.modelId = modelId;
|
|
1742
|
+
this.apiKey = apiKey;
|
|
1743
|
+
this.baseURL = baseURL;
|
|
1744
|
+
this.fetcher = fetcher;
|
|
1745
|
+
}
|
|
1746
|
+
async generateVideo(input) {
|
|
1747
|
+
const timeoutMs = input.timeoutMs ?? 600_000;
|
|
1748
|
+
const { signal, cleanup } = withTimeoutSignal({ ...input, timeoutMs });
|
|
1749
|
+
const startedAt = Date.now();
|
|
1750
|
+
try {
|
|
1751
|
+
const response = await withRetry(() => this.fetcher(`${this.baseURL}/models/${this.modelId}:predictLongRunning?key=${this.apiKey}`, {
|
|
1752
|
+
method: "POST",
|
|
1753
|
+
headers: { "content-type": "application/json" },
|
|
1754
|
+
signal,
|
|
1755
|
+
body: JSON.stringify({
|
|
1756
|
+
instances: [
|
|
1757
|
+
{
|
|
1758
|
+
prompt: input.prompt,
|
|
1759
|
+
...(input.image ? { image: mediaInputToVeoImage(input.image) } : {})
|
|
1760
|
+
}
|
|
1761
|
+
],
|
|
1762
|
+
parameters: {
|
|
1763
|
+
...(input.count ? { sampleCount: input.count } : {}),
|
|
1764
|
+
...(input.aspectRatio ? { aspectRatio: input.aspectRatio } : {}),
|
|
1765
|
+
...(input.negativePrompt ? { negativePrompt: input.negativePrompt } : {}),
|
|
1766
|
+
...(input.durationSeconds ? { durationSeconds: input.durationSeconds } : {}),
|
|
1767
|
+
...(input.outputStorageUri ? { storageUri: input.outputStorageUri } : {}),
|
|
1768
|
+
...input.providerOptions
|
|
1769
|
+
}
|
|
1770
|
+
})
|
|
1771
|
+
}), input);
|
|
1772
|
+
let operation = await parseJson(response);
|
|
1773
|
+
const operationName = operation.name;
|
|
1774
|
+
const pollIntervalMs = input.pollIntervalMs ?? 10_000;
|
|
1775
|
+
while (!operation.done) {
|
|
1776
|
+
if (Date.now() - startedAt >= timeoutMs) {
|
|
1777
|
+
throw new Error(`Gemini video generation timed out after ${timeoutMs}ms.`);
|
|
1778
|
+
}
|
|
1779
|
+
await sleep(pollIntervalMs, signal);
|
|
1780
|
+
const pollResponse = await withRetry(() => this.fetcher(`${this.baseURL}/${operationName}?key=${this.apiKey}`, {
|
|
1781
|
+
method: "GET",
|
|
1782
|
+
signal
|
|
1783
|
+
}), input);
|
|
1784
|
+
operation = await parseJson(pollResponse);
|
|
1785
|
+
}
|
|
1786
|
+
return {
|
|
1787
|
+
videos: collectVideos(operation),
|
|
1788
|
+
operationName,
|
|
1789
|
+
rawResponse: operation
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
finally {
|
|
1793
|
+
cleanup();
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
739
1797
|
class GeminiGroundedLanguageModel {
|
|
740
1798
|
modelId;
|
|
741
1799
|
apiKey;
|
|
@@ -925,8 +1983,17 @@ export const createGemini = (options = {}) => {
|
|
|
925
1983
|
embeddingModel: (modelId) => new GeminiEmbeddingModel(modelId, apiKey, baseURL, fetcher),
|
|
926
1984
|
transcriptionModel: (modelId) => new GeminiTranscriptionModel(modelId, apiKey, baseURL, fetcher),
|
|
927
1985
|
speechModel: (modelId) => new GeminiSpeechModel(modelId, apiKey, baseURL, fetcher),
|
|
1986
|
+
imageGenerationModel: (modelId) => new GeminiImageGenerationModel(modelId, apiKey, baseURL, fetcher),
|
|
1987
|
+
videoGenerationModel: (modelId) => new GeminiVideoGenerationModel(modelId, apiKey, baseURL, fetcher),
|
|
1988
|
+
musicGenerationModel: (modelId) => new GeminiMusicGenerationModel(modelId, apiKey, baseURL, fetcher),
|
|
928
1989
|
realtimeModel: (modelId) => new GeminiRealtimeModel(modelId, apiKey, baseURL, fetcher, options.realtimeConnectionFactory, options.realtimeURL, options.browserTokenURL),
|
|
929
1990
|
groundedLanguageModel: (modelId) => new GeminiGroundedLanguageModel(modelId, apiKey, baseURL, fetcher),
|
|
1991
|
+
files: new GeminiFilesClient(apiKey, baseURL, fetcher),
|
|
1992
|
+
fileSearchStores: new GeminiFileSearchStoresClient(apiKey, baseURL, fetcher),
|
|
1993
|
+
caches: new GeminiContextCachesClient(apiKey, baseURL, fetcher),
|
|
1994
|
+
batches: new GeminiBatchesClient(apiKey, baseURL, fetcher),
|
|
1995
|
+
interactions: new GeminiInteractionsClient(apiKey, baseURL, fetcher),
|
|
1996
|
+
predictionModel: (modelId) => new GeminiPredictionModel(modelId, apiKey, baseURL, fetcher),
|
|
930
1997
|
rawFetch: fetcher
|
|
931
1998
|
});
|
|
932
1999
|
};
|