@anvia/gemini 1.0.0-rc.6 → 1.0.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 +7 -5
- package/dist/index.d.ts +11 -5
- package/dist/index.js +577 -107
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -8,6 +8,9 @@ var __export = (target, all) => {
|
|
|
8
8
|
var gemini_exports = {};
|
|
9
9
|
__export(gemini_exports, {
|
|
10
10
|
GEMINI_2_5_FLASH_IMAGE: () => GEMINI_2_5_FLASH_IMAGE,
|
|
11
|
+
GEMINI_3_1_FLASH_IMAGE: () => GEMINI_3_1_FLASH_IMAGE,
|
|
12
|
+
GEMINI_3_1_FLASH_LITE_IMAGE: () => GEMINI_3_1_FLASH_LITE_IMAGE,
|
|
13
|
+
GEMINI_3_PRO_IMAGE: () => GEMINI_3_PRO_IMAGE,
|
|
11
14
|
GEMINI_3_PRO_IMAGE_PREVIEW: () => GEMINI_3_PRO_IMAGE_PREVIEW,
|
|
12
15
|
GeminiClient: () => GeminiClient,
|
|
13
16
|
IMAGEN_4_GENERATE: () => IMAGEN_4_GENERATE
|
|
@@ -25,6 +28,8 @@ import { GoogleGenAI } from "@google/genai";
|
|
|
25
28
|
// src/gemini/completion.ts
|
|
26
29
|
import {
|
|
27
30
|
assertCompletionRequestSupported,
|
|
31
|
+
CompletionProviderOutputError,
|
|
32
|
+
isJsonValue,
|
|
28
33
|
Usage,
|
|
29
34
|
withContextUsage
|
|
30
35
|
} from "@anvia/core/completion";
|
|
@@ -102,21 +107,37 @@ var GeminiCompletionModel = class {
|
|
|
102
107
|
const params = toGeminiGenerateContentParams(this.modelId, request);
|
|
103
108
|
applyAbortSignal(params, options);
|
|
104
109
|
const stream = await this.client.models.generateContentStream(params);
|
|
110
|
+
const streamState = new GeminiCompletionStreamState();
|
|
105
111
|
for await (const chunk of stream) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
const mapping = mapGeminiGenerateContentStreamChunk(chunk);
|
|
113
|
+
streamState.accept(chunk, mapping);
|
|
114
|
+
for (const event of mapping.events) {
|
|
115
|
+
if (event.type !== "final") {
|
|
116
|
+
yield event;
|
|
117
|
+
}
|
|
111
118
|
}
|
|
112
119
|
}
|
|
120
|
+
streamState.assertComplete();
|
|
121
|
+
const finalEvent = streamState.finalEvent();
|
|
122
|
+
if (finalEvent !== void 0) {
|
|
123
|
+
yield {
|
|
124
|
+
...finalEvent,
|
|
125
|
+
response: withContextUsage(finalEvent.response, this.modelInfo())
|
|
126
|
+
};
|
|
127
|
+
}
|
|
113
128
|
}
|
|
114
129
|
};
|
|
115
130
|
function toGeminiGenerateContentParams(modelId, request) {
|
|
116
131
|
const messages = requestMessages(request);
|
|
117
|
-
|
|
132
|
+
if (request.providerOptions !== void 0 && (!isPlainObject2(request.providerOptions) || !isJsonValue(request.providerOptions))) {
|
|
133
|
+
throw new TypeError("Gemini providerOptions must be a JSON object.");
|
|
134
|
+
}
|
|
135
|
+
const providerOptions = request.providerOptions ?? {};
|
|
118
136
|
const { config: providerConfigValue, ...providerTopLevel } = providerOptions;
|
|
119
|
-
|
|
137
|
+
if (providerConfigValue !== void 0 && !isPlainObject2(providerConfigValue)) {
|
|
138
|
+
throw new TypeError("Gemini providerOptions.config must be a JSON object.");
|
|
139
|
+
}
|
|
140
|
+
const providerConfig = providerConfigValue === void 0 ? {} : { ...providerConfigValue };
|
|
120
141
|
delete providerConfig.tools;
|
|
121
142
|
const config = disableGeminiNativeRetries({
|
|
122
143
|
...providerConfig,
|
|
@@ -164,10 +185,10 @@ function toolChoiceSummary(toolChoice) {
|
|
|
164
185
|
function compactJsonObject(values) {
|
|
165
186
|
return Object.fromEntries(
|
|
166
187
|
Object.entries(values).flatMap(([key, value]) => {
|
|
167
|
-
if (value
|
|
188
|
+
if (!isJsonValue(value)) {
|
|
168
189
|
return [];
|
|
169
190
|
}
|
|
170
|
-
return [[key,
|
|
191
|
+
return [[key, value]];
|
|
171
192
|
})
|
|
172
193
|
);
|
|
173
194
|
}
|
|
@@ -416,11 +437,20 @@ function toolChoiceToGemini(toolChoice) {
|
|
|
416
437
|
};
|
|
417
438
|
}
|
|
418
439
|
function fromGeminiGenerateContentResponse(response) {
|
|
419
|
-
const raw = response;
|
|
420
|
-
const
|
|
440
|
+
const raw = isPlainObject2(response) ? response : {};
|
|
441
|
+
const usage = usageFromGemini(raw.usageMetadata);
|
|
442
|
+
const parts = candidateParts(raw, usage);
|
|
443
|
+
const providerFinishReason = providerFinishReasonFromGeminiResponse(raw);
|
|
444
|
+
const finishError = geminiToolFinishError(
|
|
445
|
+
providerFinishReason,
|
|
446
|
+
hasGeminiFunctionCallMarker(raw, parts),
|
|
447
|
+
usage
|
|
448
|
+
);
|
|
449
|
+
if (finishError !== void 0) throw finishError;
|
|
450
|
+
const choice = assistantContentFromGeminiResponse(raw, usage);
|
|
421
451
|
const result = {
|
|
422
452
|
choice,
|
|
423
|
-
usage
|
|
453
|
+
usage,
|
|
424
454
|
rawResponse: response
|
|
425
455
|
};
|
|
426
456
|
applyGeminiFinishReason(result, raw);
|
|
@@ -428,34 +458,52 @@ function fromGeminiGenerateContentResponse(response) {
|
|
|
428
458
|
if (id !== void 0) {
|
|
429
459
|
result.messageId = id;
|
|
430
460
|
}
|
|
461
|
+
assertSafeGeminiCompletionResponse(result);
|
|
431
462
|
return result;
|
|
432
463
|
}
|
|
433
|
-
function applyGeminiFinishReason(response, raw) {
|
|
434
|
-
const value =
|
|
464
|
+
function applyGeminiFinishReason(response, raw, hasStreamedToolCalls = false) {
|
|
465
|
+
const value = providerFinishReasonFromGeminiResponse(raw);
|
|
435
466
|
if (value === void 0) return;
|
|
436
|
-
response
|
|
467
|
+
applyGeminiFinishReasonValue(response, value, hasStreamedToolCalls);
|
|
468
|
+
}
|
|
469
|
+
function applyGeminiFinishReasonValue(response, value, hasStreamedToolCalls) {
|
|
470
|
+
response.finishReason = geminiFinishReason(
|
|
471
|
+
value,
|
|
472
|
+
hasStreamedToolCalls || response.choice.some((part) => part.type === "tool-call")
|
|
473
|
+
);
|
|
437
474
|
response.providerFinishReason = value;
|
|
438
475
|
}
|
|
439
|
-
function geminiFinishReason(value,
|
|
476
|
+
function geminiFinishReason(value, hasToolCalls) {
|
|
440
477
|
if (value === "MAX_TOKENS") return "length";
|
|
441
478
|
if (value === "SAFETY" || value === "RECITATION" || value === "BLOCKLIST" || value === "PROHIBITED_CONTENT" || value === "SPII" || value === "IMAGE_SAFETY" || value === "IMAGE_PROHIBITED_CONTENT") {
|
|
442
479
|
return "content-filter";
|
|
443
480
|
}
|
|
444
481
|
if (value === "STOP") {
|
|
445
|
-
return
|
|
482
|
+
return hasToolCalls ? "tool-calls" : "stop";
|
|
446
483
|
}
|
|
447
484
|
return "other";
|
|
448
485
|
}
|
|
449
|
-
function
|
|
486
|
+
function mapGeminiGenerateContentStreamChunk(chunk) {
|
|
450
487
|
if (!isPlainObject2(chunk)) {
|
|
451
|
-
return
|
|
488
|
+
return {
|
|
489
|
+
events: [],
|
|
490
|
+
toolCalls: [],
|
|
491
|
+
hasToolCallMarker: false,
|
|
492
|
+
hasSyntheticToolCalls: false
|
|
493
|
+
};
|
|
452
494
|
}
|
|
453
495
|
const events = [];
|
|
454
|
-
const
|
|
455
|
-
|
|
496
|
+
const usage = usageFromGemini(chunk.usageMetadata);
|
|
497
|
+
const parts = candidateParts(chunk, usage);
|
|
498
|
+
const providerFinishReason = providerFinishReasonFromGeminiResponse(chunk);
|
|
499
|
+
const hasToolCallMarker = hasGeminiFunctionCallMarker(chunk, parts);
|
|
500
|
+
const terminalError = providerFinishReason === void 0 ? void 0 : geminiToolFinishError(providerFinishReason, hasToolCallMarker, usage);
|
|
501
|
+
const calls = terminalError === void 0 ? functionCallsFromGeminiResponse(chunk, parts, usage) : [];
|
|
502
|
+
const directText = textFromGeminiResponse(chunk, parts);
|
|
503
|
+
if (terminalError === void 0 && directText.length > 0 && parts.length === 0) {
|
|
456
504
|
events.push({ type: "text_delta", delta: directText });
|
|
457
505
|
}
|
|
458
|
-
for (const part of
|
|
506
|
+
for (const { part } of terminalError === void 0 ? parts : []) {
|
|
459
507
|
if (typeof part.text === "string" && part.text.length > 0) {
|
|
460
508
|
if (part.thought === true) {
|
|
461
509
|
events.push({ type: "reasoning_delta", delta: part.text, contentType: "summary" });
|
|
@@ -464,18 +512,22 @@ function fromGeminiGenerateContentStreamChunk(chunk) {
|
|
|
464
512
|
}
|
|
465
513
|
}
|
|
466
514
|
}
|
|
467
|
-
for (const call of
|
|
515
|
+
for (const call of calls) {
|
|
468
516
|
events.push(
|
|
469
|
-
toolCallDelta(call.
|
|
470
|
-
callId: call.
|
|
517
|
+
toolCallDelta(call.toolCallId, {
|
|
518
|
+
callId: call.callId,
|
|
471
519
|
name: call.name,
|
|
472
520
|
signature: call.signature
|
|
473
521
|
})
|
|
474
522
|
);
|
|
523
|
+
const argumentsDelta = JSON.stringify(call.args);
|
|
524
|
+
if (argumentsDelta === void 0) {
|
|
525
|
+
throw invalidGeminiToolCallArguments(call.toolCallId, usage);
|
|
526
|
+
}
|
|
475
527
|
events.push(
|
|
476
|
-
toolCallDelta(call.
|
|
477
|
-
callId: call.
|
|
478
|
-
argumentsDelta
|
|
528
|
+
toolCallDelta(call.toolCallId, {
|
|
529
|
+
callId: call.callId,
|
|
530
|
+
argumentsDelta,
|
|
479
531
|
argumentsMode: "replace"
|
|
480
532
|
})
|
|
481
533
|
);
|
|
@@ -485,18 +537,171 @@ function fromGeminiGenerateContentStreamChunk(chunk) {
|
|
|
485
537
|
events.push({ type: "message_id", id });
|
|
486
538
|
}
|
|
487
539
|
if (isPlainObject2(chunk.usageMetadata)) {
|
|
488
|
-
|
|
540
|
+
if (terminalError === void 0) {
|
|
541
|
+
events.push({ type: "final", response: fromGeminiGenerateContentResponse(chunk) });
|
|
542
|
+
} else {
|
|
543
|
+
const response = { choice: [], usage, rawResponse: chunk };
|
|
544
|
+
if (providerFinishReason !== void 0) {
|
|
545
|
+
applyGeminiFinishReasonValue(response, providerFinishReason, true);
|
|
546
|
+
}
|
|
547
|
+
events.push({ type: "final", response });
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
return providerFinishReason === void 0 ? {
|
|
551
|
+
events,
|
|
552
|
+
toolCalls: calls.map(toolCallFromGeminiFunctionCall),
|
|
553
|
+
hasToolCallMarker,
|
|
554
|
+
hasSyntheticToolCalls: calls.some((call) => call.callId === void 0),
|
|
555
|
+
terminalError
|
|
556
|
+
} : {
|
|
557
|
+
events,
|
|
558
|
+
toolCalls: calls.map(toolCallFromGeminiFunctionCall),
|
|
559
|
+
hasToolCallMarker,
|
|
560
|
+
hasSyntheticToolCalls: calls.some((call) => call.callId === void 0),
|
|
561
|
+
providerFinishReason,
|
|
562
|
+
terminalError
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
var GeminiCompletionStreamState = class {
|
|
566
|
+
toolCalls = /* @__PURE__ */ new Map();
|
|
567
|
+
providerFinishReason;
|
|
568
|
+
terminalChunk;
|
|
569
|
+
finalResponse;
|
|
570
|
+
sawToolCallMarker = false;
|
|
571
|
+
sawSyntheticToolCallChunk = false;
|
|
572
|
+
terminalError;
|
|
573
|
+
accept(chunk, mapping) {
|
|
574
|
+
if (mapping.hasSyntheticToolCalls && this.sawSyntheticToolCallChunk) {
|
|
575
|
+
const toolCallId = mapping.toolCalls.find(
|
|
576
|
+
(toolCall) => toolCall.callId === void 0
|
|
577
|
+
)?.toolCallId;
|
|
578
|
+
throw toolCallId === void 0 ? new CompletionProviderOutputError({
|
|
579
|
+
kind: "invalid-tool-call",
|
|
580
|
+
usage: this.currentUsage()
|
|
581
|
+
}) : invalidGeminiToolCall(toolCallId, this.currentUsage());
|
|
582
|
+
}
|
|
583
|
+
if (this.providerFinishReason !== void 0 && (mapping.hasToolCallMarker || hasGeminiSemanticProgress(mapping.events))) {
|
|
584
|
+
throw new CompletionProviderOutputError({
|
|
585
|
+
kind: "invalid-tool-call",
|
|
586
|
+
finishReason: "other",
|
|
587
|
+
usage: this.currentUsage()
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
for (const toolCall of mapping.toolCalls) {
|
|
591
|
+
const existing = this.toolCalls.get(toolCall.toolCallId);
|
|
592
|
+
if (existing !== void 0) {
|
|
593
|
+
if (existing.callId === void 0 || toolCall.callId === void 0 || !sameGeminiToolCall(existing, toolCall)) {
|
|
594
|
+
throw invalidGeminiToolCall(toolCall.toolCallId, this.currentUsage());
|
|
595
|
+
}
|
|
596
|
+
continue;
|
|
597
|
+
}
|
|
598
|
+
this.toolCalls.set(toolCall.toolCallId, toolCall);
|
|
599
|
+
}
|
|
600
|
+
this.sawToolCallMarker ||= mapping.hasToolCallMarker;
|
|
601
|
+
this.sawSyntheticToolCallChunk ||= mapping.hasSyntheticToolCalls;
|
|
602
|
+
for (const event of mapping.events) {
|
|
603
|
+
if (event.type === "final") {
|
|
604
|
+
this.finalResponse = event.response;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
this.terminalError ??= mapping.terminalError;
|
|
608
|
+
if (mapping.providerFinishReason !== void 0) {
|
|
609
|
+
if (this.providerFinishReason !== void 0 && this.providerFinishReason !== mapping.providerFinishReason) {
|
|
610
|
+
throw new CompletionProviderOutputError({
|
|
611
|
+
kind: "invalid-tool-call",
|
|
612
|
+
finishReason: "other",
|
|
613
|
+
usage: this.currentUsage()
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
this.providerFinishReason = mapping.providerFinishReason;
|
|
617
|
+
this.terminalChunk = chunk;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
assertComplete() {
|
|
621
|
+
if (this.terminalError !== void 0) {
|
|
622
|
+
throw geminiProviderOutputErrorWithUsage(this.terminalError, this.currentUsage());
|
|
623
|
+
}
|
|
624
|
+
if (!this.sawToolCallMarker && this.toolCalls.size === 0) return;
|
|
625
|
+
if (this.providerFinishReason !== void 0) {
|
|
626
|
+
assertSafeGeminiToolFinishReason(this.providerFinishReason, this.currentUsage());
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
const toolCallId = this.toolCalls.keys().next().value;
|
|
630
|
+
throw new CompletionProviderOutputError(
|
|
631
|
+
toolCallId === void 0 ? { kind: "incomplete-tool-call", usage: this.currentUsage() } : { kind: "incomplete-tool-call", toolCallId, usage: this.currentUsage() }
|
|
632
|
+
);
|
|
489
633
|
}
|
|
490
|
-
|
|
634
|
+
finalEvent() {
|
|
635
|
+
let response = this.finalResponse;
|
|
636
|
+
if (response === void 0) {
|
|
637
|
+
if (this.terminalChunk === void 0) {
|
|
638
|
+
return void 0;
|
|
639
|
+
}
|
|
640
|
+
const raw = isPlainObject2(this.terminalChunk) ? this.terminalChunk : {};
|
|
641
|
+
response = {
|
|
642
|
+
choice: [],
|
|
643
|
+
usage: usageFromGemini(raw.usageMetadata),
|
|
644
|
+
rawResponse: this.terminalChunk
|
|
645
|
+
};
|
|
646
|
+
const messageId = stringFrom(raw.responseId) ?? stringFrom(raw.id);
|
|
647
|
+
if (messageId !== void 0) response.messageId = messageId;
|
|
648
|
+
}
|
|
649
|
+
response = mergeGeminiStreamToolCalls(response, [...this.toolCalls.values()]);
|
|
650
|
+
if (this.providerFinishReason !== void 0) {
|
|
651
|
+
applyGeminiFinishReasonValue(response, this.providerFinishReason, this.toolCalls.size > 0);
|
|
652
|
+
}
|
|
653
|
+
assertSafeGeminiCompletionResponse(response);
|
|
654
|
+
return { type: "final", response };
|
|
655
|
+
}
|
|
656
|
+
currentUsage() {
|
|
657
|
+
if (this.finalResponse !== void 0) {
|
|
658
|
+
return this.finalResponse.usage;
|
|
659
|
+
}
|
|
660
|
+
const raw = isPlainObject2(this.terminalChunk) ? this.terminalChunk : {};
|
|
661
|
+
return usageFromGemini(raw.usageMetadata);
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
function hasGeminiSemanticProgress(events) {
|
|
665
|
+
return events.some(
|
|
666
|
+
(event) => event.type === "text_delta" || event.type === "reasoning_delta" || event.type === "tool_call_delta" || event.type === "tool_call" || event.type === "provider_tool_call"
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
function sameGeminiToolCall(left, right) {
|
|
670
|
+
return left.toolName === right.toolName && left.callId === right.callId && left.signature === right.signature && sameJsonValue(left.input, right.input);
|
|
491
671
|
}
|
|
492
|
-
function
|
|
493
|
-
|
|
672
|
+
function sameJsonValue(left, right) {
|
|
673
|
+
if (Object.is(left, right)) return true;
|
|
674
|
+
if (isJsonArray(left) || isJsonArray(right)) {
|
|
675
|
+
return isJsonArray(left) && isJsonArray(right) && left.length === right.length && left.every((value, index) => {
|
|
676
|
+
const rightValue = right[index];
|
|
677
|
+
return rightValue !== void 0 && sameJsonValue(value, rightValue);
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
if (left === null || right === null || typeof left !== "object" || typeof right !== "object") {
|
|
681
|
+
return false;
|
|
682
|
+
}
|
|
683
|
+
const leftKeys = Object.keys(left);
|
|
684
|
+
const rightKeys = Object.keys(right);
|
|
685
|
+
return leftKeys.length === rightKeys.length && leftKeys.every(
|
|
686
|
+
(key) => Object.hasOwn(right, key) && sameJsonValue(left[key], right[key])
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
function isJsonArray(value) {
|
|
690
|
+
return Array.isArray(value);
|
|
691
|
+
}
|
|
692
|
+
function assistantContentFromGeminiResponse(response, usage) {
|
|
693
|
+
const parts = candidateParts(response, usage);
|
|
694
|
+
const calls = functionCallsFromGeminiResponse(response, parts, usage);
|
|
494
695
|
if (parts.length === 0) {
|
|
495
|
-
const
|
|
496
|
-
|
|
696
|
+
const choice2 = [];
|
|
697
|
+
const text = textFromGeminiResponse(response, parts);
|
|
698
|
+
if (text.length > 0) choice2.push({ type: "text", text });
|
|
699
|
+
choice2.push(...calls.map(toolCallFromGeminiFunctionCall));
|
|
700
|
+
return choice2;
|
|
497
701
|
}
|
|
702
|
+
const callsByPartIndex = new Map(calls.map((call) => [call.partIndex, call]));
|
|
498
703
|
const choice = [];
|
|
499
|
-
for (const part of parts) {
|
|
704
|
+
for (const { index, part } of parts) {
|
|
500
705
|
if (typeof part.text === "string" && part.text.length > 0) {
|
|
501
706
|
if (part.thought === true) {
|
|
502
707
|
choice.push({
|
|
@@ -514,89 +719,336 @@ function assistantContentFromGeminiResponse(response) {
|
|
|
514
719
|
choice.push(text);
|
|
515
720
|
}
|
|
516
721
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
const toolCallId = call.id ?? crypto.randomUUID();
|
|
521
|
-
let toolCall = {
|
|
522
|
-
type: "tool-call",
|
|
523
|
-
toolCallId,
|
|
524
|
-
toolName: call.name,
|
|
525
|
-
input: call.args
|
|
526
|
-
};
|
|
527
|
-
if (call.id !== void 0) toolCall = { ...toolCall, callId: call.id };
|
|
528
|
-
if (call.signature !== void 0) toolCall = { ...toolCall, signature: call.signature };
|
|
529
|
-
choice.push(toolCall);
|
|
530
|
-
}
|
|
722
|
+
const call = callsByPartIndex.get(index);
|
|
723
|
+
if (call !== void 0) {
|
|
724
|
+
choice.push(toolCallFromGeminiFunctionCall(call));
|
|
531
725
|
}
|
|
532
726
|
}
|
|
533
727
|
return choice;
|
|
534
728
|
}
|
|
535
|
-
function textFromGeminiResponse(response) {
|
|
536
|
-
if (
|
|
537
|
-
return
|
|
729
|
+
function textFromGeminiResponse(response, parts = candidateParts(response)) {
|
|
730
|
+
if (parts.length > 0) {
|
|
731
|
+
return parts.flatMap(
|
|
732
|
+
({ part }) => part.thought !== true && typeof part.text === "string" ? [part.text] : []
|
|
733
|
+
).join("");
|
|
538
734
|
}
|
|
539
|
-
|
|
735
|
+
if (hasGeminiCandidatePayload(response)) {
|
|
736
|
+
return "";
|
|
737
|
+
}
|
|
738
|
+
const directText = ownDataProperty(response, "text");
|
|
739
|
+
return typeof directText === "string" ? directText : "";
|
|
540
740
|
}
|
|
541
|
-
function functionCallsFromGeminiResponse(response) {
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
normalized.signature = signature;
|
|
741
|
+
function functionCallsFromGeminiResponse(response, parts, usage) {
|
|
742
|
+
if (parts.length > 0) {
|
|
743
|
+
const calls2 = parts.flatMap(({ index, part }) => {
|
|
744
|
+
if (part.functionCall === void 0) {
|
|
745
|
+
return [];
|
|
746
|
+
}
|
|
747
|
+
if (!isPlainObject2(part.functionCall)) {
|
|
748
|
+
throw invalidGeminiToolCall(deterministicGeminiToolCallId(index), usage);
|
|
749
|
+
}
|
|
750
|
+
return [functionCallFromGeminiPart(part.functionCall, part, index, usage)];
|
|
751
|
+
});
|
|
752
|
+
assertDistinctGeminiFunctionCalls(calls2, usage);
|
|
753
|
+
return calls2;
|
|
754
|
+
}
|
|
755
|
+
if (hasGeminiCandidatePayload(response)) {
|
|
756
|
+
return [];
|
|
757
|
+
}
|
|
758
|
+
const camelCaseCalls = ownDataProperty(response, "functionCalls");
|
|
759
|
+
const snakeCaseCalls = ownDataProperty(response, "function_calls");
|
|
760
|
+
const directCalls = Array.isArray(camelCaseCalls) ? camelCaseCalls : Array.isArray(snakeCaseCalls) ? snakeCaseCalls : [];
|
|
761
|
+
const calls = directCalls.map((call, index) => {
|
|
762
|
+
if (!isPlainObject2(call)) {
|
|
763
|
+
throw invalidGeminiToolCall(deterministicGeminiToolCallId(index), usage);
|
|
565
764
|
}
|
|
566
|
-
return
|
|
765
|
+
return functionCallFromGeminiPart(call, call, index, usage);
|
|
567
766
|
});
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
767
|
+
assertDistinctGeminiFunctionCalls(calls, usage);
|
|
768
|
+
return calls;
|
|
769
|
+
}
|
|
770
|
+
function functionCallFromGeminiPart(call, part, partIndex, usage) {
|
|
771
|
+
const fallbackId = deterministicGeminiToolCallId(partIndex);
|
|
772
|
+
const rawCallId = call.id;
|
|
773
|
+
const callId = isNonblankString(rawCallId) ? rawCallId : void 0;
|
|
774
|
+
const toolCallId = callId ?? fallbackId;
|
|
775
|
+
if (rawCallId !== void 0 && callId === void 0) {
|
|
776
|
+
throw invalidGeminiToolCall(toolCallId, usage);
|
|
777
|
+
}
|
|
778
|
+
if (call.partialArgs !== void 0 || call.partial_args !== void 0 || call.willContinue !== void 0 || call.will_continue !== void 0) {
|
|
779
|
+
throw new CompletionProviderOutputError({
|
|
780
|
+
kind: "incomplete-tool-call",
|
|
781
|
+
toolCallId,
|
|
782
|
+
usage
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
const name = call.name;
|
|
786
|
+
if (!isNonblankString(name)) {
|
|
787
|
+
throw invalidGeminiToolCall(toolCallId, usage);
|
|
788
|
+
}
|
|
789
|
+
const args = call.args;
|
|
790
|
+
if (!isPlainObject2(args) || !isJsonValue(args)) {
|
|
791
|
+
throw invalidGeminiToolCallArguments(toolCallId, usage);
|
|
573
792
|
}
|
|
574
793
|
const normalized = {
|
|
575
|
-
|
|
576
|
-
|
|
794
|
+
toolCallId,
|
|
795
|
+
name,
|
|
796
|
+
args,
|
|
797
|
+
partIndex
|
|
577
798
|
};
|
|
578
|
-
const id = stringFrom(call.id);
|
|
579
799
|
const signature = thoughtSignatureFrom(part) ?? thoughtSignatureFrom(call);
|
|
580
|
-
if (
|
|
581
|
-
normalized
|
|
800
|
+
if (callId !== void 0) {
|
|
801
|
+
return signature === void 0 ? { ...normalized, callId } : { ...normalized, callId, signature };
|
|
802
|
+
}
|
|
803
|
+
return signature === void 0 ? normalized : { ...normalized, signature };
|
|
804
|
+
}
|
|
805
|
+
function candidateParts(response, usage) {
|
|
806
|
+
const candidate = primaryGeminiCandidate(response);
|
|
807
|
+
if (candidate === void 0 || candidate.content === void 0) {
|
|
808
|
+
return [];
|
|
809
|
+
}
|
|
810
|
+
if (!isPlainObject2(candidate.content)) {
|
|
811
|
+
throw new CompletionProviderOutputError({ kind: "invalid-tool-call", usage });
|
|
582
812
|
}
|
|
583
|
-
if (
|
|
584
|
-
|
|
813
|
+
if (candidate.content.parts === void 0) return [];
|
|
814
|
+
if (!Array.isArray(candidate.content.parts)) {
|
|
815
|
+
throw new CompletionProviderOutputError({ kind: "invalid-tool-call", usage });
|
|
585
816
|
}
|
|
586
|
-
|
|
817
|
+
if (candidate.content.parts.some((part) => !isPlainObject2(part))) {
|
|
818
|
+
throw new CompletionProviderOutputError({ kind: "invalid-tool-call", usage });
|
|
819
|
+
}
|
|
820
|
+
return candidate.content.parts.map((part, index) => ({
|
|
821
|
+
index,
|
|
822
|
+
part
|
|
823
|
+
}));
|
|
587
824
|
}
|
|
588
|
-
function
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
825
|
+
function primaryGeminiCandidate(response) {
|
|
826
|
+
if (response.candidates === void 0) return void 0;
|
|
827
|
+
if (!Array.isArray(response.candidates)) {
|
|
828
|
+
throw new CompletionProviderOutputError({ kind: "invalid-tool-call" });
|
|
829
|
+
}
|
|
830
|
+
const candidates = response.candidates;
|
|
831
|
+
if (candidates.some(
|
|
832
|
+
(candidate2) => !isPlainObject2(candidate2) || candidate2.index !== void 0 && (!Number.isSafeInteger(candidate2.index) || candidate2.index < 0)
|
|
833
|
+
)) {
|
|
834
|
+
throw new CompletionProviderOutputError({ kind: "invalid-tool-call" });
|
|
835
|
+
}
|
|
836
|
+
const primaryCandidates = candidates.filter(
|
|
837
|
+
(candidate2) => isPlainObject2(candidate2) && candidate2.index === 0
|
|
838
|
+
);
|
|
839
|
+
if (primaryCandidates.length === 1) {
|
|
840
|
+
return primaryCandidates[0];
|
|
841
|
+
}
|
|
842
|
+
if (primaryCandidates.length > 1) {
|
|
843
|
+
throw new CompletionProviderOutputError({ kind: "invalid-tool-call" });
|
|
844
|
+
}
|
|
845
|
+
if (candidates.length === 0) return void 0;
|
|
846
|
+
if (candidates.length !== 1) {
|
|
847
|
+
throw new CompletionProviderOutputError({ kind: "invalid-tool-call" });
|
|
848
|
+
}
|
|
849
|
+
const candidate = candidates[0];
|
|
850
|
+
if (candidate.index !== void 0 && candidate.index !== 0) {
|
|
851
|
+
throw new CompletionProviderOutputError({ kind: "invalid-tool-call" });
|
|
852
|
+
}
|
|
853
|
+
return candidate;
|
|
854
|
+
}
|
|
855
|
+
function providerFinishReasonFromGeminiResponse(response) {
|
|
856
|
+
const candidateFinishReason = stringFrom(primaryGeminiCandidate(response)?.finishReason);
|
|
857
|
+
if (candidateFinishReason !== void 0) return candidateFinishReason;
|
|
858
|
+
const promptFeedback = response.promptFeedback ?? response.prompt_feedback;
|
|
859
|
+
if (promptFeedback === void 0) return void 0;
|
|
860
|
+
if (!isPlainObject2(promptFeedback)) {
|
|
861
|
+
throw new CompletionProviderOutputError({ kind: "invalid-response" });
|
|
862
|
+
}
|
|
863
|
+
const blockReason = promptFeedback.blockReason ?? promptFeedback.block_reason;
|
|
864
|
+
if (blockReason === void 0) return void 0;
|
|
865
|
+
if (typeof blockReason !== "string" || blockReason.length === 0) {
|
|
866
|
+
throw new CompletionProviderOutputError({ kind: "invalid-response" });
|
|
867
|
+
}
|
|
868
|
+
return blockReason;
|
|
869
|
+
}
|
|
870
|
+
function hasGeminiCandidatePayload(response) {
|
|
871
|
+
return Array.isArray(response.candidates) && response.candidates.length > 0;
|
|
872
|
+
}
|
|
873
|
+
function hasGeminiFunctionCallMarker(response, parts) {
|
|
874
|
+
if (parts.some(({ part }) => ownDataProperty(part, "functionCall") !== void 0)) {
|
|
875
|
+
return true;
|
|
876
|
+
}
|
|
877
|
+
if (hasGeminiCandidatePayload(response)) return false;
|
|
878
|
+
const camelCaseCalls = ownDataProperty(response, "functionCalls");
|
|
879
|
+
const snakeCaseCalls = ownDataProperty(response, "function_calls");
|
|
880
|
+
return Array.isArray(camelCaseCalls) && camelCaseCalls.length > 0 || Array.isArray(snakeCaseCalls) && snakeCaseCalls.length > 0;
|
|
881
|
+
}
|
|
882
|
+
function deterministicGeminiToolCallId(partIndex) {
|
|
883
|
+
return `gemini-tool-${partIndex.toString()}`;
|
|
884
|
+
}
|
|
885
|
+
function toolCallFromGeminiFunctionCall(call) {
|
|
886
|
+
let toolCall = {
|
|
887
|
+
type: "tool-call",
|
|
888
|
+
toolCallId: call.toolCallId,
|
|
889
|
+
toolName: call.name,
|
|
890
|
+
input: call.args
|
|
891
|
+
};
|
|
892
|
+
if (call.callId !== void 0) toolCall = { ...toolCall, callId: call.callId };
|
|
893
|
+
if (call.signature !== void 0) toolCall = { ...toolCall, signature: call.signature };
|
|
894
|
+
return toolCall;
|
|
895
|
+
}
|
|
896
|
+
function mergeGeminiStreamToolCalls(response, toolCalls) {
|
|
897
|
+
if (toolCalls.length === 0) return response;
|
|
898
|
+
const finalIds = new Set(
|
|
899
|
+
response.choice.flatMap((part) => part.type === "tool-call" ? [part.toolCallId] : [])
|
|
900
|
+
);
|
|
901
|
+
const missing = toolCalls.filter((toolCall) => !finalIds.has(toolCall.toolCallId));
|
|
902
|
+
return missing.length === 0 ? response : { ...response, choice: [...response.choice, ...missing] };
|
|
903
|
+
}
|
|
904
|
+
function assertSafeGeminiToolFinishReason(value, usage) {
|
|
905
|
+
const error = geminiToolFinishError(value, true, usage);
|
|
906
|
+
if (error !== void 0) throw error;
|
|
907
|
+
}
|
|
908
|
+
function geminiToolFinishError(value, hasToolCalls, usage) {
|
|
909
|
+
if (value === "MALFORMED_FUNCTION_CALL") {
|
|
910
|
+
return new CompletionProviderOutputError({ kind: "malformed-tool-arguments", usage });
|
|
911
|
+
}
|
|
912
|
+
if (value === "UNEXPECTED_TOOL_CALL" || value === "TOO_MANY_TOOL_CALLS") {
|
|
913
|
+
return new CompletionProviderOutputError({ kind: "invalid-tool-call", usage });
|
|
914
|
+
}
|
|
915
|
+
if (!hasToolCalls) return void 0;
|
|
916
|
+
if (value === void 0) {
|
|
917
|
+
return new CompletionProviderOutputError({ kind: "incomplete-tool-call", usage });
|
|
918
|
+
}
|
|
919
|
+
const finishReason = geminiFinishReason(value, true);
|
|
920
|
+
if (finishReason === "tool-calls") return void 0;
|
|
921
|
+
if (finishReason === "length") {
|
|
922
|
+
return new CompletionProviderOutputError({
|
|
923
|
+
kind: "truncated-tool-call",
|
|
924
|
+
finishReason,
|
|
925
|
+
usage
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
if (finishReason === "content-filter") {
|
|
929
|
+
return new CompletionProviderOutputError({
|
|
930
|
+
kind: "filtered-tool-call",
|
|
931
|
+
finishReason,
|
|
932
|
+
usage
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
return new CompletionProviderOutputError({ kind: "invalid-tool-call", finishReason, usage });
|
|
936
|
+
}
|
|
937
|
+
function assertSafeGeminiCompletionResponse(response) {
|
|
938
|
+
const toolCalls = response.choice.filter(
|
|
939
|
+
(part) => part.type === "tool-call"
|
|
940
|
+
);
|
|
941
|
+
if (toolCalls.length > 0) {
|
|
942
|
+
if (response.finishReason === void 0) {
|
|
943
|
+
throw new CompletionProviderOutputError({
|
|
944
|
+
kind: "incomplete-tool-call",
|
|
945
|
+
usage: response.usage
|
|
946
|
+
});
|
|
947
|
+
}
|
|
948
|
+
assertNormalizedGeminiToolFinishReason(response.finishReason, response.usage);
|
|
949
|
+
} else if (toolCalls.length === 0 && response.finishReason === "tool-calls") {
|
|
950
|
+
throw new CompletionProviderOutputError({
|
|
951
|
+
kind: "invalid-tool-call",
|
|
952
|
+
finishReason: response.finishReason,
|
|
953
|
+
usage: response.usage
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
const toolCallIds = /* @__PURE__ */ new Set();
|
|
957
|
+
const callIds = /* @__PURE__ */ new Set();
|
|
958
|
+
for (const toolCall of toolCalls) {
|
|
959
|
+
if (toolCallIds.has(toolCall.toolCallId)) {
|
|
960
|
+
throw invalidGeminiToolCall(toolCall.toolCallId, response.usage);
|
|
593
961
|
}
|
|
594
|
-
|
|
962
|
+
toolCallIds.add(toolCall.toolCallId);
|
|
963
|
+
if (toolCall.callId !== void 0) {
|
|
964
|
+
if (callIds.has(toolCall.callId)) {
|
|
965
|
+
throw invalidGeminiToolCall(toolCall.toolCallId, response.usage);
|
|
966
|
+
}
|
|
967
|
+
callIds.add(toolCall.callId);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
function assertDistinctGeminiFunctionCalls(calls, usage) {
|
|
972
|
+
const toolCallIds = /* @__PURE__ */ new Set();
|
|
973
|
+
const callIds = /* @__PURE__ */ new Set();
|
|
974
|
+
for (const call of calls) {
|
|
975
|
+
if (toolCallIds.has(call.toolCallId)) {
|
|
976
|
+
throw invalidGeminiToolCall(call.toolCallId, usage);
|
|
977
|
+
}
|
|
978
|
+
toolCallIds.add(call.toolCallId);
|
|
979
|
+
if (call.callId !== void 0) {
|
|
980
|
+
if (callIds.has(call.callId)) {
|
|
981
|
+
throw invalidGeminiToolCall(call.toolCallId, usage);
|
|
982
|
+
}
|
|
983
|
+
callIds.add(call.callId);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
function assertNormalizedGeminiToolFinishReason(finishReason, usage) {
|
|
988
|
+
if (finishReason === "stop" || finishReason === "tool-calls") return;
|
|
989
|
+
if (finishReason === "length") {
|
|
990
|
+
throw new CompletionProviderOutputError({
|
|
991
|
+
kind: "truncated-tool-call",
|
|
992
|
+
finishReason,
|
|
993
|
+
usage
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
if (finishReason === "content-filter") {
|
|
997
|
+
throw new CompletionProviderOutputError({
|
|
998
|
+
kind: "filtered-tool-call",
|
|
999
|
+
finishReason,
|
|
1000
|
+
usage
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
throw new CompletionProviderOutputError({ kind: "invalid-tool-call", finishReason, usage });
|
|
1004
|
+
}
|
|
1005
|
+
function geminiProviderOutputErrorWithUsage(error, usage) {
|
|
1006
|
+
if (error.kind === "truncated-tool-call") {
|
|
1007
|
+
return new CompletionProviderOutputError({
|
|
1008
|
+
kind: error.kind,
|
|
1009
|
+
finishReason: "length",
|
|
1010
|
+
toolCallId: error.toolCallId,
|
|
1011
|
+
usage
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
if (error.kind === "filtered-tool-call") {
|
|
1015
|
+
return new CompletionProviderOutputError({
|
|
1016
|
+
kind: error.kind,
|
|
1017
|
+
finishReason: "content-filter",
|
|
1018
|
+
toolCallId: error.toolCallId,
|
|
1019
|
+
usage
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
1022
|
+
if (error.finishReason === "length" || error.finishReason === "content-filter") {
|
|
1023
|
+
throw error;
|
|
1024
|
+
}
|
|
1025
|
+
return new CompletionProviderOutputError({
|
|
1026
|
+
kind: error.kind,
|
|
1027
|
+
finishReason: error.finishReason,
|
|
1028
|
+
toolCallId: error.toolCallId,
|
|
1029
|
+
usage
|
|
595
1030
|
});
|
|
596
1031
|
}
|
|
597
|
-
function
|
|
598
|
-
|
|
599
|
-
|
|
1032
|
+
function invalidGeminiToolCall(toolCallId, usage) {
|
|
1033
|
+
return new CompletionProviderOutputError({ kind: "invalid-tool-call", toolCallId, usage });
|
|
1034
|
+
}
|
|
1035
|
+
function invalidGeminiToolCallArguments(toolCallId, usage) {
|
|
1036
|
+
return new CompletionProviderOutputError({
|
|
1037
|
+
kind: "invalid-tool-arguments",
|
|
1038
|
+
toolCallId,
|
|
1039
|
+
usage
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1042
|
+
function ownDataProperty(value, key) {
|
|
1043
|
+
try {
|
|
1044
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
1045
|
+
return descriptor !== void 0 && "value" in descriptor ? descriptor.value : void 0;
|
|
1046
|
+
} catch {
|
|
1047
|
+
return void 0;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
function isNonblankString(value) {
|
|
1051
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
600
1052
|
}
|
|
601
1053
|
function usageFromGemini(usage) {
|
|
602
1054
|
const raw = isPlainObject2(usage) ? usage : {};
|
|
@@ -624,17 +1076,11 @@ function usageFromGemini(usage) {
|
|
|
624
1076
|
}
|
|
625
1077
|
};
|
|
626
1078
|
}
|
|
627
|
-
function toJsonValue(value) {
|
|
628
|
-
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value) || isPlainObject2(value)) {
|
|
629
|
-
return value;
|
|
630
|
-
}
|
|
631
|
-
return String(value);
|
|
632
|
-
}
|
|
633
1079
|
function isPlainObject2(value) {
|
|
634
1080
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
635
1081
|
}
|
|
636
1082
|
function numberFrom(value) {
|
|
637
|
-
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
1083
|
+
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
638
1084
|
}
|
|
639
1085
|
function stringFrom(value) {
|
|
640
1086
|
return typeof value === "string" ? value : void 0;
|
|
@@ -735,6 +1181,9 @@ function isNumberArray(value) {
|
|
|
735
1181
|
// src/gemini/image-generation.ts
|
|
736
1182
|
import { Buffer as Buffer2 } from "buffer";
|
|
737
1183
|
var GEMINI_2_5_FLASH_IMAGE = "gemini-2.5-flash-image";
|
|
1184
|
+
var GEMINI_3_1_FLASH_IMAGE = "gemini-3.1-flash-image";
|
|
1185
|
+
var GEMINI_3_1_FLASH_LITE_IMAGE = "gemini-3.1-flash-lite-image";
|
|
1186
|
+
var GEMINI_3_PRO_IMAGE = "gemini-3-pro-image";
|
|
738
1187
|
var GEMINI_3_PRO_IMAGE_PREVIEW = "gemini-3-pro-image-preview";
|
|
739
1188
|
var IMAGEN_4_GENERATE = "imagen-4.0-generate-001";
|
|
740
1189
|
var GeminiImageGenerationModel = class {
|
|
@@ -931,11 +1380,29 @@ var GEMINI_COMPLETION_MODEL_CONTEXT_LIMITS = {
|
|
|
931
1380
|
maxInputTokens: 65536,
|
|
932
1381
|
maxOutputTokens: 65536
|
|
933
1382
|
},
|
|
1383
|
+
"gemini-3.1-flash-image": {
|
|
1384
|
+
contextWindow: 131072,
|
|
1385
|
+
maxInputTokens: 131072,
|
|
1386
|
+
maxOutputTokens: 32768
|
|
1387
|
+
},
|
|
1388
|
+
"gemini-3.1-flash-lite-image": {
|
|
1389
|
+
contextWindow: 65536,
|
|
1390
|
+
maxInputTokens: 65536,
|
|
1391
|
+
maxOutputTokens: 4096
|
|
1392
|
+
},
|
|
934
1393
|
"gemini-3.1-flash-lite": CONTEXT_1M_64K,
|
|
935
1394
|
"gemini-3.1-flash-lite-preview": CONTEXT_1M_64K,
|
|
936
1395
|
"gemini-3.1-pro-preview": CONTEXT_1M_64K,
|
|
937
1396
|
"gemini-3.1-pro-preview-customtools": CONTEXT_1M_64K,
|
|
938
1397
|
"gemini-3.5-flash": CONTEXT_1M_64K,
|
|
1398
|
+
"gemini-3.5-flash-lite": CONTEXT_1M_64K,
|
|
1399
|
+
"gemini-3.6-flash": CONTEXT_1M_64K,
|
|
1400
|
+
"gemini-3.7-flash": CONTEXT_1M_64K,
|
|
1401
|
+
"gemini-3-pro-image": {
|
|
1402
|
+
contextWindow: 65536,
|
|
1403
|
+
maxInputTokens: 65536,
|
|
1404
|
+
maxOutputTokens: 32768
|
|
1405
|
+
},
|
|
939
1406
|
"gemini-flash-latest": CONTEXT_1M_64K,
|
|
940
1407
|
"gemini-flash-lite-latest": CONTEXT_1M_64K,
|
|
941
1408
|
"gemma-4-26b-a4b-it": {
|
|
@@ -1220,6 +1687,9 @@ function isAsyncIterable(value) {
|
|
|
1220
1687
|
}
|
|
1221
1688
|
export {
|
|
1222
1689
|
GEMINI_2_5_FLASH_IMAGE,
|
|
1690
|
+
GEMINI_3_1_FLASH_IMAGE,
|
|
1691
|
+
GEMINI_3_1_FLASH_LITE_IMAGE,
|
|
1692
|
+
GEMINI_3_PRO_IMAGE,
|
|
1223
1693
|
GEMINI_3_PRO_IMAGE_PREVIEW,
|
|
1224
1694
|
GeminiClient,
|
|
1225
1695
|
IMAGEN_4_GENERATE,
|