@openclaw/ai 2026.9.2 → 2026.9.3
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 +3 -2
- package/dist/anthropic-CZy5U0NY.mjs +376 -0
- package/dist/{anthropic-payload-policy-d46X2pR0.d.mts → anthropic-payload-policy-wuRCb6MH.d.mts} +16 -6
- package/dist/{anthropic-compaction-replay-DB2FGLQc.mjs → anthropic-stream-reducer-B_yo_7pf.mjs} +923 -181
- package/dist/{api-registry-DWtPjzyn.d.mts → api-registry-CB1-1oQ2.d.mts} +2 -2
- package/dist/assistant-output-iqnlJCV2.mjs +16 -0
- package/dist/assistant-text-phase-C20rxWwP.mjs +55 -0
- package/dist/{azure-openai-responses-C5bZRfAP.mjs → azure-openai-responses-Crpa40QR.mjs} +5 -5
- package/dist/{base64-CEFBpSkN.mjs → base64-D-su8YVo.mjs} +1 -27
- package/dist/{diagnostics-DfFyKeX_.mjs → diagnostics-dV98PqIy.mjs} +96 -21
- package/dist/diagnostics.d.mts +3 -1
- package/dist/diagnostics.mjs +3 -3
- package/dist/{event-stream-BhT5T1Ay.d.mts → event-stream-C1Z2piyk.d.mts} +11 -3
- package/dist/{event-stream-BgDvQeum.mjs → event-stream-D8PARQfL.mjs} +45 -1
- package/dist/event-stream-I_GlBsuZ.d.mts +1 -0
- package/dist/event-stream.d.mts +2 -2
- package/dist/event-stream.mjs +1 -1
- package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-B37TB3rB.mjs} +3 -10
- package/dist/github-copilot-request-facts-BTEBMeOv.mjs +16 -0
- package/dist/{google-4qeuE8iX.mjs → google-BDPriaVe.mjs} +10 -10
- package/dist/google-messages-CVn9eFpF.mjs +449 -0
- package/dist/google-shared-BedY23XS.mjs +185 -0
- package/dist/{google-vertex-O9BcnB6X.mjs → google-vertex-DMz8XQCn.mjs} +7 -6
- package/dist/{host-CEvLw30U.mjs → host-CWuF-sS3.mjs} +44 -39
- package/dist/{host-DjzGmdZ2.d.mts → host-DK3wmS3e.d.mts} +3 -3
- package/dist/host-policy-CAopLRKA.mjs +37 -0
- package/dist/{index-FnHM2FcI.d.mts → index-CQ6LTHw8.d.mts} +3 -3
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +4 -4
- package/dist/internal/anthropic.d.mts +7 -7
- package/dist/internal/anthropic.mjs +4 -4
- package/dist/internal/google-model-family.d.mts +5 -0
- package/dist/internal/google-model-family.mjs +15 -0
- package/dist/internal/openai-responses-payload-policy.d.mts +1 -1
- package/dist/internal/openai-responses-payload-policy.mjs +1 -1
- package/dist/internal/openai.d.mts +8 -103
- package/dist/internal/openai.mjs +10 -10
- package/dist/internal/retry-after.d.mts +2 -4
- package/dist/internal/retry-after.mjs +57 -8
- package/dist/internal/runtime.d.mts +7 -6
- package/dist/internal/runtime.mjs +8 -7
- package/dist/internal/shared.d.mts +14 -3
- package/dist/internal/shared.mjs +6 -4
- package/dist/internal/tool-schema.d.mts +63 -0
- package/dist/internal/tool-schema.mjs +3 -0
- package/dist/{json-parse-BuAJEbdW.mjs → json-parse-Dw_hnxsA.mjs} +1 -1
- package/dist/{mistral-Tb6oalqH.mjs → mistral--m-Jm6VZ.mjs} +13 -37
- package/dist/model-transport-url-DKocrEsb.d.mts +28 -0
- package/dist/{openai-chatgpt-responses-yUXjPNfu.mjs → openai-chatgpt-responses-nDZccFW-.mjs} +48 -38
- package/dist/openai-completions-KuoZyx0d.mjs +187 -0
- package/dist/{openai-completions-compat-CpjYUArk.d.mts → openai-completions-compat-CXn3T1we.d.mts} +26 -4
- package/dist/{openai-completions-stream-BsrBe3Gg.mjs → openai-completions-stream-BQk3SkLD.mjs} +622 -452
- package/dist/openai-prompt-cache-BI0rkM-5.mjs +220 -0
- package/dist/openai-prompt-cache-rrutvqxq.d.mts +16 -0
- package/dist/openai-provider-client-ha_WxTyj.mjs +24 -0
- package/dist/openai-reasoning-effort-BK7FbcLT.mjs +167 -0
- package/dist/{openai-responses-CCL41ALM.mjs → openai-responses-D99dOzKI.mjs} +14 -29
- package/dist/{openai-responses-compaction-window-BMVHFOtq.mjs → openai-responses-compaction-window-D5jbzCi3.mjs} +7 -170
- package/dist/{openai-responses-contracts-rF5DDRNS.d.mts → openai-responses-contracts-B55afwRo.d.mts} +3 -3
- package/dist/{openai-responses-prompt-observer-internal-D0bhBfgL.mjs → openai-responses-prompt-observer-internal-tApyTLVu.mjs} +3 -3
- package/dist/{openai-responses-shared-Bmma_3Qc.mjs → openai-responses-shared-ZyQEzS5i.mjs} +44 -115
- package/dist/openai-tool-projection-793cE3QX.d.mts +37 -0
- package/dist/{openai-tool-schema-_pTAJqKF.mjs → openai-tool-schema-CzjyYXun.mjs} +38 -556
- package/dist/openai-tool-schema-ynZBgqW-.d.mts +38 -0
- package/dist/openai-transport-params-DNasp2fU.mjs +674 -0
- package/dist/{provider-error-9TraxGvt.mjs → provider-error-C6TbKiey.mjs} +23 -6
- package/dist/{provider-options-Bcc_p-TU.d.mts → provider-options-BXr9Ec83.d.mts} +4 -39
- package/dist/{provider-transcript-transform-BaMbI1hr.mjs → provider-transcript-transform-pPmUIwKt.mjs} +1 -1
- package/dist/provider-types-CAV0Og3m.d.mts +29 -0
- package/dist/provider-types.d.mts +6 -31
- package/dist/providers.d.mts +2 -2
- package/dist/providers.mjs +11 -11
- package/dist/{reasoning-tag-text-partitioner-DLCNXki6.mjs → reasoning-tag-text-partitioner-BQBi4B9d.mjs} +19 -12
- package/dist/record-coerce-DwRYMj3t.mjs +32 -0
- package/dist/retry-after-CdCURCVg.d.mts +15 -0
- package/dist/{sanitize-unicode-D6xUvZaS.mjs → sanitize-unicode-Bb-v9meu.mjs} +1 -1
- package/dist/session-affinity-CCH7eYdB.mjs +20 -0
- package/dist/{simple-options-BjHCCh4v.mjs → simple-options-tcKOqnpF.mjs} +3 -3
- package/dist/{src-2qBGKg8O.mjs → src-B2Q_6G8V.mjs} +1 -1
- package/dist/{stream-first-event-timeout-DcNjoFQE.mjs → stream-first-event-timeout-2hfrquuz.mjs} +1 -1
- package/dist/string-coerce-fsri9iCu.mjs +34 -0
- package/dist/{string-normalization--fwJ4S2q.mjs → string-normalization-CmLIasuf.mjs} +1 -1
- package/dist/{tool-schema-json-projection-mJhXDcyz.mjs → tool-schema-json-projection-ClptDdAO.mjs} +2 -38
- package/dist/{transport-stream-shared-CZqMhfIw.mjs → transport-stream-shared-Cu3ZPhNW.mjs} +5 -5
- package/dist/{transport-stream-shared-xnaqxmbP.d.mts → transport-stream-shared-DOxpGJ-H.d.mts} +4 -4
- package/dist/transport-utils-CCooe-cr.mjs +121 -0
- package/dist/transports.d.mts +113 -41
- package/dist/transports.mjs +162 -1276
- package/dist/types-BADKjDBI.d.mts +1 -0
- package/dist/{types-CJ1-Ht7A.d.mts → types-Dy1q0CSu.d.mts} +72 -57
- package/dist/types.d.mts +5 -5
- package/dist/types.mjs +3 -3
- package/dist/utf16-slice-CvGodqok.mjs +29 -0
- package/dist/{validation-CJZtym2g.mjs → validation-BDzVDnTs.mjs} +9 -1
- package/dist/{validation-AKZBDGQd.d.mts → validation-CaFUZN9B.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +13 -3
- package/dist/anthropic-BDdqdVLK.mjs +0 -886
- package/dist/event-stream-zctLx0yr.d.mts +0 -1
- package/dist/google-shared-CWeG8RIl.mjs +0 -636
- package/dist/google-thinking-level-C-V3tecN.mjs +0 -9
- package/dist/openai-completions-BIUV3RDT.mjs +0 -403
- package/dist/openai-prompt-cache-CGnVB74a.mjs +0 -21
- package/dist/openai-prompt-cache-CNoIfHYC.d.mts +0 -16
- package/dist/transport-utils-7il795_9.mjs +0 -138
- package/dist/types-3Lnm-QSJ.d.mts +0 -1
- package/dist/utf16-slice-qz3nsy87.mjs +0 -84
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import "./event-stream-BhT5T1Ay.mjs";
|
|
@@ -1,636 +0,0 @@
|
|
|
1
|
-
import { i as clampThinkingLevel, r as calculateCost, t as sanitizeSurrogates } from "./sanitize-unicode-D6xUvZaS.mjs";
|
|
2
|
-
import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload } from "./host-CEvLw30U.mjs";
|
|
3
|
-
import { d as stripSystemPromptCacheBoundary, m as sortPromptCacheToolsByName } from "./simple-options-BjHCCh4v.mjs";
|
|
4
|
-
import { _ as transportAbortError, n as coerceTransportToolCallArguments, p as notifyProviderStreamOpened, t as assignTransportErrorDetails } from "./transport-stream-shared-CZqMhfIw.mjs";
|
|
5
|
-
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
6
|
-
import { t as googleFlashSupportsMinimalThinking } from "./google-thinking-level-C-V3tecN.mjs";
|
|
7
|
-
import { t as transformProviderMessages } from "./provider-transcript-transform-BaMbI1hr.mjs";
|
|
8
|
-
import { FinishReason, FunctionCallingConfigMode, ThinkingLevel } from "@google/genai";
|
|
9
|
-
//#region packages/ai/src/providers/google-shared.ts
|
|
10
|
-
/**
|
|
11
|
-
* Shared utilities for Google Generative AI and Google Vertex providers.
|
|
12
|
-
*/
|
|
13
|
-
const GOOGLE_MODEL_RESOURCE_PREFIX = /^(?:(?:projects\/[^/]+\/locations\/[^/]+\/)?publishers\/google\/models\/|google\/|models\/)/u;
|
|
14
|
-
/**
|
|
15
|
-
* Determines whether a streamed Gemini `Part` should be treated as "thinking".
|
|
16
|
-
*
|
|
17
|
-
* Protocol note (Gemini / Vertex AI thought signatures):
|
|
18
|
-
* - `thought: true` is the definitive marker for thinking content (thought summaries).
|
|
19
|
-
* - `thoughtSignature` is an encrypted representation of the model's internal thought process
|
|
20
|
-
* used to preserve reasoning context across multi-turn interactions.
|
|
21
|
-
* - `thoughtSignature` can appear on ANY part type (text, functionCall, etc.) - it does NOT
|
|
22
|
-
* indicate the part itself is thinking content.
|
|
23
|
-
* - For non-functionCall responses, the signature appears on the last part for context replay.
|
|
24
|
-
* - When persisting/replaying model outputs, signature-bearing parts must be preserved as-is;
|
|
25
|
-
* do not merge/move signatures across parts.
|
|
26
|
-
*
|
|
27
|
-
* See: https://ai.google.dev/gemini-api/docs/thought-signatures
|
|
28
|
-
*/
|
|
29
|
-
function isThinkingPart(part) {
|
|
30
|
-
return part.thought === true;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Retain thought signatures during streaming.
|
|
34
|
-
*
|
|
35
|
-
* Some backends only send `thoughtSignature` on the first delta for a given part/block; later deltas may omit it.
|
|
36
|
-
* This helper preserves the last non-empty signature for the current block.
|
|
37
|
-
*
|
|
38
|
-
* Note: this does NOT merge or move signatures across distinct response parts. It only prevents
|
|
39
|
-
* a signature from being overwritten with `undefined` within the same streamed block.
|
|
40
|
-
* @internal Directly tested provider implementation detail.
|
|
41
|
-
*/
|
|
42
|
-
function retainThoughtSignature(existing, incoming) {
|
|
43
|
-
if (typeof incoming === "string" && incoming.length > 0) return incoming;
|
|
44
|
-
return existing;
|
|
45
|
-
}
|
|
46
|
-
const base64SignaturePattern = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
47
|
-
function isValidThoughtSignature(signature) {
|
|
48
|
-
if (!signature) return false;
|
|
49
|
-
if (signature.length % 4 !== 0) return false;
|
|
50
|
-
return base64SignaturePattern.test(signature);
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Only keep signatures from the same provider/model and with valid base64.
|
|
54
|
-
*/
|
|
55
|
-
function resolveThoughtSignature(isSameProviderAndModel, signature) {
|
|
56
|
-
return isSameProviderAndModel && isValidThoughtSignature(signature) ? signature : void 0;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Models via Google APIs that require explicit tool call IDs in function calls/responses.
|
|
60
|
-
* @internal Directly tested provider implementation detail.
|
|
61
|
-
*/
|
|
62
|
-
function requiresToolCallId(modelId) {
|
|
63
|
-
return modelId.startsWith("claude-") || modelId.startsWith("gpt-oss-");
|
|
64
|
-
}
|
|
65
|
-
function getGeminiMajorVersion(modelId) {
|
|
66
|
-
const match = modelId.toLowerCase().match(/(?:^|\/)gemini(?:-live)?-(\d+)/);
|
|
67
|
-
if (!match) return;
|
|
68
|
-
const majorVersion = match.at(1);
|
|
69
|
-
return majorVersion === void 0 ? void 0 : Number.parseInt(majorVersion, 10);
|
|
70
|
-
}
|
|
71
|
-
function supportsMultimodalFunctionResponse(modelId) {
|
|
72
|
-
const geminiMajorVersion = getGeminiMajorVersion(modelId);
|
|
73
|
-
if (geminiMajorVersion !== void 0) return geminiMajorVersion >= 3;
|
|
74
|
-
return true;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Convert internal messages to Gemini Content[] format.
|
|
78
|
-
* @internal Directly tested provider implementation detail.
|
|
79
|
-
*/
|
|
80
|
-
function convertMessages(model, context) {
|
|
81
|
-
const contents = [];
|
|
82
|
-
const normalizeToolCallId = (id) => {
|
|
83
|
-
if (!requiresToolCallId(model.id)) return id;
|
|
84
|
-
return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
|
|
85
|
-
};
|
|
86
|
-
const transformedMessages = transformProviderMessages(context.messages, model, normalizeToolCallId);
|
|
87
|
-
const requiresToolCallThoughtSignature = model.provider !== "google-gemini-cli" && (isGemini3ProModel(model) || isGemini3FlashModel(model));
|
|
88
|
-
const pendingToolResultImageTurns = [];
|
|
89
|
-
const sameRouteToolCallIds = /* @__PURE__ */ new Set();
|
|
90
|
-
let activeToolResultParts;
|
|
91
|
-
const flushToolResultRun = () => {
|
|
92
|
-
contents.push(...pendingToolResultImageTurns);
|
|
93
|
-
pendingToolResultImageTurns.length = 0;
|
|
94
|
-
activeToolResultParts = void 0;
|
|
95
|
-
};
|
|
96
|
-
for (const msg of transformedMessages) {
|
|
97
|
-
if (msg.role !== "toolResult") flushToolResultRun();
|
|
98
|
-
if (msg.role === "user") {
|
|
99
|
-
if (typeof msg.content === "string") contents.push({
|
|
100
|
-
role: "user",
|
|
101
|
-
parts: [{ text: sanitizeSurrogates(msg.content) || " " }]
|
|
102
|
-
});
|
|
103
|
-
else {
|
|
104
|
-
const parts = msg.content.map((item) => {
|
|
105
|
-
if (item.type === "text") return { text: sanitizeSurrogates(item.text) || " " };
|
|
106
|
-
return { inlineData: {
|
|
107
|
-
mimeType: item.mimeType,
|
|
108
|
-
data: item.data
|
|
109
|
-
} };
|
|
110
|
-
});
|
|
111
|
-
if (parts.length === 0) parts.push({ text: " " });
|
|
112
|
-
contents.push({
|
|
113
|
-
role: "user",
|
|
114
|
-
parts
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
} else if (msg.role === "assistant") {
|
|
118
|
-
const parts = [];
|
|
119
|
-
let sawFunctionCall = false;
|
|
120
|
-
const isSameProviderAndModel = msg.provider === model.provider && msg.api === model.api && msg.model === model.id;
|
|
121
|
-
for (const block of msg.content) if (block.type === "text") {
|
|
122
|
-
const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.textSignature);
|
|
123
|
-
if ((!block.text || block.text.trim() === "") && !thoughtSignature) continue;
|
|
124
|
-
parts.push({
|
|
125
|
-
text: sanitizeSurrogates(block.text),
|
|
126
|
-
...thoughtSignature && { thoughtSignature }
|
|
127
|
-
});
|
|
128
|
-
} else if (block.type === "thinking") {
|
|
129
|
-
const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thinkingSignature);
|
|
130
|
-
if ((!block.thinking || block.thinking.trim() === "") && !thoughtSignature) continue;
|
|
131
|
-
if (isSameProviderAndModel) parts.push({
|
|
132
|
-
thought: true,
|
|
133
|
-
text: sanitizeSurrogates(block.thinking),
|
|
134
|
-
...thoughtSignature && { thoughtSignature }
|
|
135
|
-
});
|
|
136
|
-
else parts.push({ text: sanitizeSurrogates(block.thinking) });
|
|
137
|
-
} else if (block.type === "toolCall") {
|
|
138
|
-
if (isSameProviderAndModel && model.provider !== "google-gemini-cli") sameRouteToolCallIds.add(block.id);
|
|
139
|
-
const args = coerceTransportToolCallArguments(block.arguments);
|
|
140
|
-
const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thoughtSignature) ?? (!sawFunctionCall && requiresToolCallThoughtSignature ? "skip_thought_signature_validator" : void 0);
|
|
141
|
-
sawFunctionCall = true;
|
|
142
|
-
const part = {
|
|
143
|
-
functionCall: {
|
|
144
|
-
name: block.name,
|
|
145
|
-
args,
|
|
146
|
-
...sameRouteToolCallIds.has(block.id) || requiresToolCallId(model.id) ? { id: block.id } : {}
|
|
147
|
-
},
|
|
148
|
-
...thoughtSignature && { thoughtSignature }
|
|
149
|
-
};
|
|
150
|
-
parts.push(part);
|
|
151
|
-
}
|
|
152
|
-
if (parts.length === 0) continue;
|
|
153
|
-
contents.push({
|
|
154
|
-
role: "model",
|
|
155
|
-
parts
|
|
156
|
-
});
|
|
157
|
-
} else if (msg.role === "toolResult") {
|
|
158
|
-
const textResult = extractToolResultText(msg.content);
|
|
159
|
-
const imageContent = model.input.includes("image") ? msg.content.filter(isImageWithMediaPayload) : [];
|
|
160
|
-
const hasText = textResult.length > 0;
|
|
161
|
-
const hasImages = imageContent.length > 0;
|
|
162
|
-
const mediaPlaceholder = describeToolResultMediaPlaceholder(msg.content);
|
|
163
|
-
const modelSupportsMultimodalFunctionResponse = supportsMultimodalFunctionResponse(model.id);
|
|
164
|
-
const responseValue = hasText ? sanitizeSurrogates(textResult) : mediaPlaceholder ?? "";
|
|
165
|
-
const imageParts = imageContent.map((imageBlock) => ({ inlineData: {
|
|
166
|
-
mimeType: imageBlock.mimeType,
|
|
167
|
-
data: imageBlock.data
|
|
168
|
-
} }));
|
|
169
|
-
const includeId = sameRouteToolCallIds.has(msg.toolCallId) || requiresToolCallId(model.id);
|
|
170
|
-
const functionResponsePart = { functionResponse: {
|
|
171
|
-
name: msg.toolName,
|
|
172
|
-
response: msg.isError ? { error: responseValue } : { output: responseValue },
|
|
173
|
-
...hasImages && modelSupportsMultimodalFunctionResponse && { parts: imageParts },
|
|
174
|
-
...includeId ? { id: msg.toolCallId } : {}
|
|
175
|
-
} };
|
|
176
|
-
if (activeToolResultParts) activeToolResultParts.push(functionResponsePart);
|
|
177
|
-
else {
|
|
178
|
-
activeToolResultParts = [functionResponsePart];
|
|
179
|
-
contents.push({
|
|
180
|
-
role: "user",
|
|
181
|
-
parts: activeToolResultParts
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
if (hasImages && !modelSupportsMultimodalFunctionResponse) pendingToolResultImageTurns.push({
|
|
185
|
-
role: "user",
|
|
186
|
-
parts: [{ text: "Tool result image:" }, ...imageParts]
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
flushToolResultRun();
|
|
191
|
-
if (contents.length === 0) contents.push({
|
|
192
|
-
role: "user",
|
|
193
|
-
parts: [{ text: " " }]
|
|
194
|
-
});
|
|
195
|
-
return contents;
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Convert tools to Gemini function declarations format.
|
|
199
|
-
* @internal Directly tested provider implementation detail.
|
|
200
|
-
*/
|
|
201
|
-
function convertTools(tools) {
|
|
202
|
-
if (tools.length === 0) return;
|
|
203
|
-
return [{ functionDeclarations: sortPromptCacheToolsByName(tools).map((tool) => ({
|
|
204
|
-
name: tool.name,
|
|
205
|
-
description: tool.description,
|
|
206
|
-
parametersJsonSchema: tool.parameters
|
|
207
|
-
})) }];
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Map tool choice string to Gemini FunctionCallingConfigMode.
|
|
211
|
-
* @internal Directly tested provider implementation detail.
|
|
212
|
-
*/
|
|
213
|
-
function mapToolChoice(choice) {
|
|
214
|
-
switch (choice) {
|
|
215
|
-
case "auto": return FunctionCallingConfigMode.AUTO;
|
|
216
|
-
case "none": return FunctionCallingConfigMode.NONE;
|
|
217
|
-
case "any": return FunctionCallingConfigMode.ANY;
|
|
218
|
-
default: return FunctionCallingConfigMode.AUTO;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
function createGoogleAssistantOutput(model, api = model.api) {
|
|
222
|
-
return {
|
|
223
|
-
role: "assistant",
|
|
224
|
-
content: [],
|
|
225
|
-
api,
|
|
226
|
-
provider: model.provider,
|
|
227
|
-
model: model.id,
|
|
228
|
-
usage: {
|
|
229
|
-
input: 0,
|
|
230
|
-
output: 0,
|
|
231
|
-
cacheRead: 0,
|
|
232
|
-
cacheWrite: 0,
|
|
233
|
-
totalTokens: 0,
|
|
234
|
-
cost: {
|
|
235
|
-
input: 0,
|
|
236
|
-
output: 0,
|
|
237
|
-
cacheRead: 0,
|
|
238
|
-
cacheWrite: 0,
|
|
239
|
-
total: 0
|
|
240
|
-
}
|
|
241
|
-
},
|
|
242
|
-
stopReason: "stop",
|
|
243
|
-
timestamp: Date.now()
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
async function runGoogleGenerateContentLifecycle(params) {
|
|
247
|
-
const { stream, model, output, options } = params;
|
|
248
|
-
try {
|
|
249
|
-
const client = params.createClient();
|
|
250
|
-
let requestParams = params.buildParams();
|
|
251
|
-
const nextParams = await options?.onPayload?.(requestParams, model);
|
|
252
|
-
if (nextParams !== void 0) requestParams = nextParams;
|
|
253
|
-
const googleIterator = (await client.models.generateContentStream(requestParams))[Symbol.asyncIterator]();
|
|
254
|
-
await notifyProviderStreamOpened({
|
|
255
|
-
options,
|
|
256
|
-
cancelStream: async () => {
|
|
257
|
-
await googleIterator.return?.();
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
await consumeGoogleGenerateContentStream({
|
|
261
|
-
chunks: { [Symbol.asyncIterator]: () => googleIterator },
|
|
262
|
-
model,
|
|
263
|
-
output,
|
|
264
|
-
stream,
|
|
265
|
-
signal: options?.signal,
|
|
266
|
-
nextToolCallId: params.nextToolCallId
|
|
267
|
-
});
|
|
268
|
-
} catch (error) {
|
|
269
|
-
for (const block of output.content) if ("index" in block) delete block.index;
|
|
270
|
-
const failure = options?.signal?.aborted ? transportAbortError(options.signal) : error;
|
|
271
|
-
assignTransportErrorDetails(output, failure, options?.signal);
|
|
272
|
-
stream.push({
|
|
273
|
-
type: "error",
|
|
274
|
-
reason: output.stopReason === "aborted" ? "aborted" : "error",
|
|
275
|
-
error: output
|
|
276
|
-
});
|
|
277
|
-
stream.end();
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
function buildGoogleGenerateContentParams(model, context, options = {}) {
|
|
281
|
-
const contents = convertMessages(model, context);
|
|
282
|
-
const generationConfig = {};
|
|
283
|
-
if (options.temperature !== void 0) generationConfig.temperature = options.temperature;
|
|
284
|
-
if (options.maxTokens !== void 0) generationConfig.maxOutputTokens = options.maxTokens;
|
|
285
|
-
if (options.stop !== void 0 && options.stop.length > 0) generationConfig.stopSequences = options.stop;
|
|
286
|
-
const config = {
|
|
287
|
-
...Object.keys(generationConfig).length > 0 && generationConfig,
|
|
288
|
-
...context.systemPrompt && { systemInstruction: sanitizeSurrogates(stripSystemPromptCacheBoundary(context.systemPrompt)) },
|
|
289
|
-
...context.tools && context.tools.length > 0 && { tools: convertTools(context.tools) }
|
|
290
|
-
};
|
|
291
|
-
if (context.tools && context.tools.length > 0 && options.toolChoice) config.toolConfig = { functionCallingConfig: { mode: mapToolChoice(options.toolChoice) } };
|
|
292
|
-
else config.toolConfig = void 0;
|
|
293
|
-
if (options.thinking?.enabled && model.reasoning) {
|
|
294
|
-
const thinkingConfig = { includeThoughts: true };
|
|
295
|
-
if (options.thinking.level !== void 0) thinkingConfig.thinkingLevel = ThinkingLevel[options.thinking.level];
|
|
296
|
-
else if (options.thinking.budgetTokens !== void 0) thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
|
|
297
|
-
config.thinkingConfig = thinkingConfig;
|
|
298
|
-
} else if (model.reasoning && options.thinking && !options.thinking.enabled) {
|
|
299
|
-
const disabledThinkingConfig = getDisabledGoogleThinkingConfig(model);
|
|
300
|
-
if (Object.keys(disabledThinkingConfig).length > 0) config.thinkingConfig = disabledThinkingConfig;
|
|
301
|
-
}
|
|
302
|
-
if (options.signal) {
|
|
303
|
-
if (options.signal.aborted) throw new Error("Request aborted");
|
|
304
|
-
config.abortSignal = options.signal;
|
|
305
|
-
}
|
|
306
|
-
return {
|
|
307
|
-
model: model.id,
|
|
308
|
-
contents,
|
|
309
|
-
config
|
|
310
|
-
};
|
|
311
|
-
}
|
|
312
|
-
function isAdaptiveGoogleReasoningLevel(value) {
|
|
313
|
-
return value === "adaptive";
|
|
314
|
-
}
|
|
315
|
-
function buildGoogleSimpleThinking(model, options, config) {
|
|
316
|
-
if (!options?.reasoning || options.reasoning === "off") return { enabled: false };
|
|
317
|
-
if (isAdaptiveGoogleReasoningLevel(options.reasoning)) {
|
|
318
|
-
if (!model.reasoning) return { enabled: false };
|
|
319
|
-
if (isGemma4Model(model)) return {
|
|
320
|
-
enabled: true,
|
|
321
|
-
level: ThinkingLevel.HIGH
|
|
322
|
-
};
|
|
323
|
-
return isGemini3ProModel(model) || isGemini3FlashModel(model) ? { enabled: true } : {
|
|
324
|
-
enabled: true,
|
|
325
|
-
budgetTokens: -1
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
const clampedReasoning = clampThinkingLevel(model, options.reasoning);
|
|
329
|
-
if (clampedReasoning === "off") return { enabled: false };
|
|
330
|
-
const effort = clampedReasoning === "max" ? "high" : clampedReasoning;
|
|
331
|
-
if (isGemini3ProModel(model) || isGemini3FlashModel(model) || config?.includeGemma4ThinkingLevel && isGemma4Model(model)) return {
|
|
332
|
-
enabled: true,
|
|
333
|
-
level: getGoogleThinkingLevel(effort, model, { includeGemma4: config?.includeGemma4ThinkingLevel })
|
|
334
|
-
};
|
|
335
|
-
return {
|
|
336
|
-
enabled: true,
|
|
337
|
-
budgetTokens: getGoogleBudget(model, effort, options.thinkingBudgets, { useFlashLiteBudgets: config?.useFlashLiteBudgets })
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
function getDisabledGoogleThinkingConfig(model) {
|
|
341
|
-
if (isGemini3ProModel(model)) return { thinkingLevel: ThinkingLevel.LOW };
|
|
342
|
-
if (isGemini3FlashModel(model)) return { thinkingLevel: googleFlashSupportsMinimalThinking(model.id) ? ThinkingLevel.MINIMAL : ThinkingLevel.LOW };
|
|
343
|
-
if (isGemma4Model(model) || model.id.toLowerCase().includes("gemini-2.5-pro")) return {};
|
|
344
|
-
return { thinkingBudget: 0 };
|
|
345
|
-
}
|
|
346
|
-
/** @internal Directly tested provider implementation detail. */
|
|
347
|
-
function isGemma4Model(model) {
|
|
348
|
-
return /gemma-?4/.test(model.id.toLowerCase());
|
|
349
|
-
}
|
|
350
|
-
function isGemini3ProModel(model) {
|
|
351
|
-
return /gemini-(?:3(?:\.\d+)?-pro|pro-latest)/.test(model.id.toLowerCase());
|
|
352
|
-
}
|
|
353
|
-
function isGemini3FlashModel(model) {
|
|
354
|
-
return /gemini-(?:3(?:\.\d+)?-flash|flash(?:-lite)?-latest)/.test(model.id.toLowerCase());
|
|
355
|
-
}
|
|
356
|
-
function getGoogleThinkingLevel(effort, model, config) {
|
|
357
|
-
if (isGemini3ProModel(model)) switch (effort) {
|
|
358
|
-
case "minimal":
|
|
359
|
-
case "low": return ThinkingLevel.LOW;
|
|
360
|
-
case "medium":
|
|
361
|
-
case "high": return ThinkingLevel.HIGH;
|
|
362
|
-
}
|
|
363
|
-
if (config?.includeGemma4 && isGemma4Model(model)) switch (effort) {
|
|
364
|
-
case "minimal":
|
|
365
|
-
case "low": return ThinkingLevel.MINIMAL;
|
|
366
|
-
case "medium":
|
|
367
|
-
case "high": return ThinkingLevel.HIGH;
|
|
368
|
-
}
|
|
369
|
-
switch (effort) {
|
|
370
|
-
case "minimal": return isGemini3FlashModel(model) && !googleFlashSupportsMinimalThinking(model.id) ? ThinkingLevel.LOW : ThinkingLevel.MINIMAL;
|
|
371
|
-
case "low": return ThinkingLevel.LOW;
|
|
372
|
-
case "medium": return ThinkingLevel.MEDIUM;
|
|
373
|
-
case "high": return ThinkingLevel.HIGH;
|
|
374
|
-
}
|
|
375
|
-
return ThinkingLevel.HIGH;
|
|
376
|
-
}
|
|
377
|
-
function getGoogleBudget(model, effort, customBudgets, config) {
|
|
378
|
-
if (customBudgets?.[effort] !== void 0) return customBudgets[effort];
|
|
379
|
-
if (model.id.includes("2.5-pro")) return {
|
|
380
|
-
minimal: 128,
|
|
381
|
-
low: 2048,
|
|
382
|
-
medium: 8192,
|
|
383
|
-
high: 32768
|
|
384
|
-
}[effort];
|
|
385
|
-
if (config?.useFlashLiteBudgets && model.id.includes("2.5-flash-lite")) return {
|
|
386
|
-
minimal: 512,
|
|
387
|
-
low: 2048,
|
|
388
|
-
medium: 8192,
|
|
389
|
-
high: 24576
|
|
390
|
-
}[effort];
|
|
391
|
-
if (model.id.includes("2.5-flash")) return {
|
|
392
|
-
minimal: 128,
|
|
393
|
-
low: 2048,
|
|
394
|
-
medium: 8192,
|
|
395
|
-
high: 24576
|
|
396
|
-
}[effort];
|
|
397
|
-
return -1;
|
|
398
|
-
}
|
|
399
|
-
/**
|
|
400
|
-
* Map Gemini FinishReason to our StopReason.
|
|
401
|
-
* @internal Directly tested provider implementation detail.
|
|
402
|
-
*/
|
|
403
|
-
function mapStopReason(reason) {
|
|
404
|
-
switch (reason) {
|
|
405
|
-
case FinishReason.STOP: return "stop";
|
|
406
|
-
case FinishReason.MAX_TOKENS: return "length";
|
|
407
|
-
case FinishReason.BLOCKLIST:
|
|
408
|
-
case FinishReason.PROHIBITED_CONTENT:
|
|
409
|
-
case FinishReason.SPII:
|
|
410
|
-
case FinishReason.SAFETY:
|
|
411
|
-
case FinishReason.IMAGE_SAFETY:
|
|
412
|
-
case FinishReason.IMAGE_PROHIBITED_CONTENT:
|
|
413
|
-
case FinishReason.IMAGE_RECITATION:
|
|
414
|
-
case FinishReason.IMAGE_OTHER:
|
|
415
|
-
case FinishReason.RECITATION:
|
|
416
|
-
case FinishReason.FINISH_REASON_UNSPECIFIED:
|
|
417
|
-
case FinishReason.OTHER:
|
|
418
|
-
case FinishReason.LANGUAGE:
|
|
419
|
-
case FinishReason.MALFORMED_FUNCTION_CALL:
|
|
420
|
-
case FinishReason.TOO_MANY_TOOL_CALLS:
|
|
421
|
-
case FinishReason.UNEXPECTED_TOOL_CALL:
|
|
422
|
-
case FinishReason.NO_IMAGE: return "error";
|
|
423
|
-
default: throw new Error(`Unhandled stop reason: ${String(reason)}`);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
/** @internal Directly tested provider implementation detail. */
|
|
427
|
-
async function consumeGoogleGenerateContentStream(params) {
|
|
428
|
-
params.stream.push({
|
|
429
|
-
type: "start",
|
|
430
|
-
partial: params.output
|
|
431
|
-
});
|
|
432
|
-
let currentBlock = null;
|
|
433
|
-
const blocks = params.output.content;
|
|
434
|
-
let sawTerminalReason = false;
|
|
435
|
-
let terminalGenerationError;
|
|
436
|
-
const knownUsage = {
|
|
437
|
-
promptTokenCount: 0,
|
|
438
|
-
cachedContentTokenCount: 0,
|
|
439
|
-
toolUsePromptTokenCount: 0,
|
|
440
|
-
candidatesTokenCount: 0,
|
|
441
|
-
thoughtsTokenCount: 0
|
|
442
|
-
};
|
|
443
|
-
const toolCallIds = /* @__PURE__ */ new Set();
|
|
444
|
-
for (const block of blocks) if (block.type === "toolCall") toolCallIds.add(block.id);
|
|
445
|
-
const blockIndex = () => blocks.length - 1;
|
|
446
|
-
const endCurrentBlock = () => {
|
|
447
|
-
if (!currentBlock) return;
|
|
448
|
-
if (currentBlock.type === "text") params.stream.push({
|
|
449
|
-
type: "text_end",
|
|
450
|
-
contentIndex: blockIndex(),
|
|
451
|
-
content: currentBlock.text,
|
|
452
|
-
partial: params.output
|
|
453
|
-
});
|
|
454
|
-
else params.stream.push({
|
|
455
|
-
type: "thinking_end",
|
|
456
|
-
contentIndex: blockIndex(),
|
|
457
|
-
content: currentBlock.thinking,
|
|
458
|
-
partial: params.output
|
|
459
|
-
});
|
|
460
|
-
currentBlock = null;
|
|
461
|
-
};
|
|
462
|
-
for await (const chunk of params.chunks) {
|
|
463
|
-
notifyLlmRequestActivity(params.signal);
|
|
464
|
-
params.output.responseId ||= chunk.responseId;
|
|
465
|
-
const responseModel = chunk.modelVersion?.trim();
|
|
466
|
-
if (responseModel && params.model.id.replace(GOOGLE_MODEL_RESOURCE_PREFIX, "") !== responseModel.replace(GOOGLE_MODEL_RESOURCE_PREFIX, "")) params.output.responseModel ||= responseModel;
|
|
467
|
-
if (chunk.usageMetadata) {
|
|
468
|
-
for (const field of Object.keys(knownUsage)) {
|
|
469
|
-
const value = chunk.usageMetadata[field];
|
|
470
|
-
if (typeof value === "number") knownUsage[field] = value;
|
|
471
|
-
}
|
|
472
|
-
const promptTokens = knownUsage.promptTokenCount;
|
|
473
|
-
const cacheRead = knownUsage.cachedContentTokenCount;
|
|
474
|
-
const toolUsePromptTokens = knownUsage.toolUsePromptTokenCount;
|
|
475
|
-
const outputTokens = knownUsage.candidatesTokenCount + knownUsage.thoughtsTokenCount;
|
|
476
|
-
params.output.usage = {
|
|
477
|
-
input: Math.max(0, promptTokens - cacheRead) + toolUsePromptTokens,
|
|
478
|
-
output: outputTokens,
|
|
479
|
-
cacheRead,
|
|
480
|
-
cacheWrite: 0,
|
|
481
|
-
totalTokens: chunk.usageMetadata.totalTokenCount ?? promptTokens + outputTokens + toolUsePromptTokens,
|
|
482
|
-
cost: {
|
|
483
|
-
input: 0,
|
|
484
|
-
output: 0,
|
|
485
|
-
cacheRead: 0,
|
|
486
|
-
cacheWrite: 0,
|
|
487
|
-
total: 0
|
|
488
|
-
}
|
|
489
|
-
};
|
|
490
|
-
calculateCost(params.model, params.output.usage);
|
|
491
|
-
}
|
|
492
|
-
const candidate = chunk.candidates?.[0];
|
|
493
|
-
const promptFeedback = chunk.promptFeedback;
|
|
494
|
-
if (!candidate && promptFeedback) {
|
|
495
|
-
const blockReason = promptFeedback.blockReason ?? "PROMPT_BLOCKED";
|
|
496
|
-
const blockMessage = promptFeedback.blockReasonMessage?.trim();
|
|
497
|
-
params.output.errorCode = blockReason;
|
|
498
|
-
params.output.errorType = "google_prompt_blocked";
|
|
499
|
-
throw new Error(`Google prompt blocked (${blockReason})${blockMessage ? `: ${blockMessage}` : ""}`);
|
|
500
|
-
}
|
|
501
|
-
if (candidate?.content?.parts) for (const [partIndex, part] of candidate.content.parts.entries()) {
|
|
502
|
-
const text = part.text;
|
|
503
|
-
const hasText = typeof text === "string";
|
|
504
|
-
const hasThoughtSignature = typeof part.thoughtSignature === "string" && part.thoughtSignature.length > 0;
|
|
505
|
-
const signatureOnly = hasThoughtSignature && (!hasText || text.length === 0) && Object.keys(part).every((key) => key === "thought" || key === "thoughtSignature" || key === "text");
|
|
506
|
-
if (signatureOnly) {
|
|
507
|
-
if (!hasText && part.thought !== true) {
|
|
508
|
-
const latestBlock = blocks.at(-1);
|
|
509
|
-
if (partIndex === 0 && latestBlock?.type === "toolCall" && !latestBlock.thoughtSignature) {
|
|
510
|
-
latestBlock.thoughtSignature = retainThoughtSignature(latestBlock.thoughtSignature, part.thoughtSignature);
|
|
511
|
-
continue;
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
endCurrentBlock();
|
|
515
|
-
}
|
|
516
|
-
if (hasText || signatureOnly) {
|
|
517
|
-
if (currentBlock && (hasThoughtSignature || partIndex > 0)) {
|
|
518
|
-
const currentSignature = currentBlock.type === "thinking" ? currentBlock.thinkingSignature : currentBlock.textSignature;
|
|
519
|
-
if ((currentBlock.type === "thinking" ? currentBlock.thinking : currentBlock.text).length > 0 && (currentSignature !== part.thoughtSignature || partIndex > 0 && (currentSignature || hasThoughtSignature))) endCurrentBlock();
|
|
520
|
-
}
|
|
521
|
-
const isThinking = isThinkingPart(part);
|
|
522
|
-
if (!currentBlock || isThinking && currentBlock.type !== "thinking" || !isThinking && currentBlock.type !== "text") {
|
|
523
|
-
endCurrentBlock();
|
|
524
|
-
if (isThinking) {
|
|
525
|
-
currentBlock = {
|
|
526
|
-
type: "thinking",
|
|
527
|
-
thinking: "",
|
|
528
|
-
thinkingSignature: void 0
|
|
529
|
-
};
|
|
530
|
-
params.output.content.push(currentBlock);
|
|
531
|
-
params.stream.push({
|
|
532
|
-
type: "thinking_start",
|
|
533
|
-
contentIndex: blockIndex(),
|
|
534
|
-
partial: params.output
|
|
535
|
-
});
|
|
536
|
-
} else {
|
|
537
|
-
currentBlock = {
|
|
538
|
-
type: "text",
|
|
539
|
-
text: ""
|
|
540
|
-
};
|
|
541
|
-
params.output.content.push(currentBlock);
|
|
542
|
-
params.stream.push({
|
|
543
|
-
type: "text_start",
|
|
544
|
-
contentIndex: blockIndex(),
|
|
545
|
-
partial: params.output
|
|
546
|
-
});
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
const delta = hasText ? text : "";
|
|
550
|
-
if (currentBlock.type === "thinking") {
|
|
551
|
-
currentBlock.thinking += delta;
|
|
552
|
-
currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);
|
|
553
|
-
params.stream.push({
|
|
554
|
-
type: "thinking_delta",
|
|
555
|
-
contentIndex: blockIndex(),
|
|
556
|
-
delta,
|
|
557
|
-
partial: params.output
|
|
558
|
-
});
|
|
559
|
-
} else {
|
|
560
|
-
currentBlock.text += delta;
|
|
561
|
-
currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);
|
|
562
|
-
params.stream.push({
|
|
563
|
-
type: "text_delta",
|
|
564
|
-
contentIndex: blockIndex(),
|
|
565
|
-
delta,
|
|
566
|
-
partial: params.output
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
if (signatureOnly) endCurrentBlock();
|
|
570
|
-
}
|
|
571
|
-
if (part.functionCall) {
|
|
572
|
-
endCurrentBlock();
|
|
573
|
-
const providedId = part.functionCall.id;
|
|
574
|
-
const toolCall = {
|
|
575
|
-
type: "toolCall",
|
|
576
|
-
id: !providedId || toolCallIds.has(providedId) ? params.nextToolCallId(part.functionCall.name) : providedId,
|
|
577
|
-
name: part.functionCall.name || "",
|
|
578
|
-
arguments: part.functionCall.args ?? {},
|
|
579
|
-
...part.thoughtSignature && { thoughtSignature: part.thoughtSignature }
|
|
580
|
-
};
|
|
581
|
-
params.output.content.push(toolCall);
|
|
582
|
-
toolCallIds.add(toolCall.id);
|
|
583
|
-
params.stream.push({
|
|
584
|
-
type: "toolcall_start",
|
|
585
|
-
contentIndex: blockIndex(),
|
|
586
|
-
partial: params.output
|
|
587
|
-
});
|
|
588
|
-
params.stream.push({
|
|
589
|
-
type: "toolcall_delta",
|
|
590
|
-
contentIndex: blockIndex(),
|
|
591
|
-
delta: JSON.stringify(toolCall.arguments),
|
|
592
|
-
partial: params.output
|
|
593
|
-
});
|
|
594
|
-
params.stream.push({
|
|
595
|
-
type: "toolcall_end",
|
|
596
|
-
contentIndex: blockIndex(),
|
|
597
|
-
toolCall,
|
|
598
|
-
partial: params.output
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
if (candidate?.finishReason && candidate.finishReason !== FinishReason.FINISH_REASON_UNSPECIFIED) {
|
|
603
|
-
sawTerminalReason = true;
|
|
604
|
-
params.output.stopReason = mapStopReason(candidate.finishReason);
|
|
605
|
-
if (params.output.stopReason === "error") {
|
|
606
|
-
const finishMessage = candidate.finishMessage?.trim();
|
|
607
|
-
terminalGenerationError = Object.assign(/* @__PURE__ */ new Error(`Google generation stopped (${candidate.finishReason})${finishMessage ? `: ${finishMessage}` : ""}`), {
|
|
608
|
-
code: candidate.finishReason,
|
|
609
|
-
type: "google_generation_failed"
|
|
610
|
-
});
|
|
611
|
-
}
|
|
612
|
-
if (params.output.stopReason === "stop" && params.output.content.some((block) => block.type === "toolCall")) params.output.stopReason = "toolUse";
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
endCurrentBlock();
|
|
616
|
-
if (params.signal?.aborted) throw transportAbortError(params.signal);
|
|
617
|
-
if (terminalGenerationError) {
|
|
618
|
-
params.output.errorCode = terminalGenerationError.code;
|
|
619
|
-
params.output.errorType = terminalGenerationError.type;
|
|
620
|
-
throw terminalGenerationError;
|
|
621
|
-
}
|
|
622
|
-
if (!sawTerminalReason) {
|
|
623
|
-
params.output.errorCode = "STREAM_INCOMPLETE";
|
|
624
|
-
params.output.errorType = "google_incomplete_stream";
|
|
625
|
-
throw new Error("Google stream ended before a terminal finish reason");
|
|
626
|
-
}
|
|
627
|
-
if (params.output.stopReason === "aborted" || params.output.stopReason === "error") throw new Error("An unknown error occurred");
|
|
628
|
-
params.stream.push({
|
|
629
|
-
type: "done",
|
|
630
|
-
reason: params.output.stopReason,
|
|
631
|
-
message: params.output
|
|
632
|
-
});
|
|
633
|
-
params.stream.end();
|
|
634
|
-
}
|
|
635
|
-
//#endregion
|
|
636
|
-
export { runGoogleGenerateContentLifecycle as i, buildGoogleSimpleThinking as n, createGoogleAssistantOutput as r, buildGoogleGenerateContentParams as t };
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region packages/ai/src/transports/google-thinking-level.ts
|
|
2
|
-
/** Returns whether a Gemini Flash model accepts the MINIMAL thinking level. */
|
|
3
|
-
function googleFlashSupportsMinimalThinking(modelId) {
|
|
4
|
-
const match = modelId.toLowerCase().match(/(?:^|\/)gemini-3\.(\d+)-flash(?:-|$)/);
|
|
5
|
-
if (!match) return true;
|
|
6
|
-
return Number.parseInt(match[1] ?? "0", 10) < 7;
|
|
7
|
-
}
|
|
8
|
-
//#endregion
|
|
9
|
-
export { googleFlashSupportsMinimalThinking as t };
|