@openclaw/ai 2026.7.2-beta.7 → 2026.8.1-beta.2
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/dist/{anthropic-CH4UUnZr.mjs → anthropic-B6dLpq5L.mjs} +55 -203
- package/dist/{src-QkygScBs.mjs → anthropic-JsNA5KCu.mjs} +0 -1
- package/dist/anthropic-compaction-replay-8lJNKXOE.mjs +840 -0
- package/dist/anthropic-payload-policy-CiEuQS72.d.mts +49 -0
- package/dist/{api-registry-DlMgPR39.d.mts → api-registry-k3zTz0cV.d.mts} +1 -1
- package/dist/{azure-openai-responses-CImcwB83.mjs → azure-openai-responses-mxIOtUnn.mjs} +23 -29
- package/dist/diagnostics.d.mts +24 -1
- package/dist/diagnostics.mjs +2 -1
- package/dist/{event-stream-YjaPW20U.d.mts → event-stream-BP6AWT8j.d.mts} +4 -1
- package/dist/{event-stream-D8n2uFee.mjs → event-stream-uSMZJ3FA.mjs} +26 -5
- package/dist/event-stream.d.mts +1 -1
- package/dist/event-stream.mjs +1 -1
- package/dist/{google-CtSg0iTS.mjs → google-C7h2QzDX.mjs} +5 -5
- package/dist/{google-shared-DNBz5rcD.mjs → google-shared-B0Qr9OR7.mjs} +146 -89
- package/dist/google-thinking-level-C-V3tecN.mjs +9 -0
- package/dist/{google-vertex-31f1uS9L.mjs → google-vertex-Bhc3TjDl.mjs} +11 -7
- package/dist/{llm-request-activity-BjtkplhG.mjs → headers-DdOQtGuU.mjs} +9 -1
- package/dist/host-DTqNc7ad.mjs +466 -0
- package/dist/{host-B9GUmcra.d.mts → host-vWgMMhiJ.d.mts} +9 -4
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +7 -5
- package/dist/internal/anthropic.d.mts +29 -5
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/openai-responses-payload-policy.d.mts +3 -0
- package/dist/internal/openai-responses-payload-policy.mjs +3 -0
- package/dist/internal/openai.d.mts +6 -6
- package/dist/internal/openai.mjs +8 -7
- package/dist/internal/runtime.d.mts +17 -5
- package/dist/internal/runtime.mjs +85 -73
- package/dist/internal/shared.d.mts +1 -6
- package/dist/internal/shared.mjs +3 -5
- package/dist/{json-parse-BvXNt1-7.mjs → json-parse-CDnesDM_.mjs} +4 -6
- package/dist/{mistral-CWmpvWYh.mjs → mistral-CEWoQI_g.mjs} +45 -48
- package/dist/number-coercion-H9qHik3g.mjs +71 -0
- package/dist/openai-chatgpt-jwt-KWcgd0d_.mjs +19 -0
- package/dist/{openai-chatgpt-responses-B84Ibtrd.mjs → openai-chatgpt-responses-CrPmqERt.mjs} +284 -240
- package/dist/{openai-completions-DsOxhOD1.mjs → openai-completions-BPnt4Sml.mjs} +65 -99
- package/dist/{openai-completions-compat-DBWjXoMZ.d.mts → openai-completions-compat-Dt3dcawL.d.mts} +2 -2
- package/dist/{openai-responses-BT7A3sLu.mjs → openai-responses-DhIKtOup.mjs} +18 -41
- package/dist/openai-responses-contracts-CyfIkQi5.mjs +253 -0
- package/dist/openai-responses-contracts-XpZJxrRG.d.mts +68 -0
- package/dist/openai-responses-payload-policy-BDxV-W0c.mjs +206 -0
- package/dist/openai-responses-payload-policy-BSs371VM.d.mts +40 -0
- package/dist/openai-responses-prompt-observer-internal-DgNTYnRY.mjs +46 -0
- package/dist/{openai-responses-stream-internal-Cw5txaGW.mjs → openai-responses-shared-DXIt3iY5.mjs} +1406 -940
- package/dist/{openai-reasoning-compat-YgeLncHw.mjs → openai-stop-reason-BkFkqqK0.mjs} +204 -37
- package/dist/openai-tool-projection-CY04OcvQ.mjs +338 -0
- package/dist/provider-error-BUwEnjXq.mjs +429 -0
- package/dist/provider-error-CzNw4BWX.d.mts +12 -0
- package/dist/{provider-options-D8bB3z9b.d.mts → provider-options-B96RdNpH.d.mts} +9 -3
- package/dist/provider-transcript-transform-ePx-Bbfr.mjs +155 -0
- package/dist/provider-types.d.mts +31 -0
- package/dist/provider-types.mjs +8 -0
- package/dist/providers.d.mts +1 -1
- package/dist/providers.mjs +17 -19
- package/dist/{reasoning-tag-text-partitioner-CGDyLWUR.mjs → reasoning-tag-text-partitioner-rnPwX2pg.mjs} +14 -8
- package/dist/record-coerce-DdXsgUd_.mjs +23 -0
- package/dist/sanitize-unicode-BYqrYtC_.mjs +90 -0
- package/dist/session-resources-CkR4WWy1.mjs +21 -0
- package/dist/simple-options-D58D5Kvw.mjs +117 -0
- package/dist/src-D2H6yKkH.mjs +2 -0
- package/dist/{stream-first-event-timeout-BBys9hSb.mjs → stream-first-event-timeout-MK28puvq.mjs} +2 -2
- package/dist/string-coerce-fsri9iCu.mjs +34 -0
- package/dist/{tool-schema-json-projection-BwNu3nDi.mjs → tool-schema-json-projection-q5d7QX5c.mjs} +32 -7
- package/dist/transport-utils-DJqkxbhC.mjs +138 -0
- package/dist/transports.d.mts +166 -241
- package/dist/transports.mjs +1979 -1825
- package/dist/types-BDdaOVi2.mjs +6 -0
- package/dist/{types-bzp5k29J.d.mts → types-BHNrPS1l.d.mts} +23 -1
- package/dist/types.d.mts +4 -4
- package/dist/types.mjs +6 -4
- package/dist/utf16-slice-CvGodqok.mjs +29 -0
- package/dist/{validation-DAa_yFOM.mjs → validation-B61OhAio.mjs} +6 -6
- package/dist/{validation-B-j7cOYp.d.mts → validation-DT9SrFn3.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +15 -1
- package/dist/anthropic-usage-DWU-x8MI.mjs +0 -459
- package/dist/error-coercion-DgxlWC0n.mjs +0 -15
- package/dist/headers-B_e4-1J0.mjs +0 -9
- package/dist/host-Dog2WQiR.mjs +0 -369
- package/dist/number-coercion-DvG7SNMg.mjs +0 -129
- package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +0 -39
- package/dist/openai-responses-shared-pXl6Wd8S.mjs +0 -392
- package/dist/openai-tool-projection-OhX64DoP.mjs +0 -215
- package/dist/provider-error-CAEvRjry.mjs +0 -47
- package/dist/sanitize-unicode-DT5o51ur.mjs +0 -26
- package/dist/simple-options-9lhRrN73.mjs +0 -50
- package/dist/tool-result-text-CTpIRbYd.mjs +0 -225
- package/dist/transform-messages-C8mBqZxF.mjs +0 -2
- package/dist/transport-stream-shared-D81p90xq.mjs +0 -297
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { i as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { t as formatProviderError } from "./provider-error-CAEvRjry.mjs";
|
|
7
|
-
import "./transform-messages-C8mBqZxF.mjs";
|
|
1
|
+
import { i as clampThinkingLevel, r as calculateCost, t as sanitizeSurrogates } from "./sanitize-unicode-BYqrYtC_.mjs";
|
|
2
|
+
import { a as describeToolResultMediaPlaceholder, l as isImageWithMediaPayload, s as extractToolResultText } from "./host-DTqNc7ad.mjs";
|
|
3
|
+
import { f as sortPromptCacheToolsByName, l as stripSystemPromptCacheBoundary } from "./simple-options-D58D5Kvw.mjs";
|
|
4
|
+
import { f as transportAbortError, n as assignTransportErrorDetails, r as coerceTransportToolCallArguments, t as transformProviderMessages } from "./provider-transcript-transform-ePx-Bbfr.mjs";
|
|
5
|
+
import { t as googleFlashSupportsMinimalThinking } from "./google-thinking-level-C-V3tecN.mjs";
|
|
8
6
|
import { FinishReason, FunctionCallingConfigMode, ThinkingLevel } from "@google/genai";
|
|
9
7
|
//#region packages/ai/src/providers/google-shared.ts
|
|
10
8
|
/**
|
|
@@ -82,7 +80,8 @@ function convertMessages(model, context) {
|
|
|
82
80
|
if (!requiresToolCallId(model.id)) return id;
|
|
83
81
|
return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
|
|
84
82
|
};
|
|
85
|
-
const transformedMessages =
|
|
83
|
+
const transformedMessages = transformProviderMessages(context.messages, model, normalizeToolCallId);
|
|
84
|
+
const requiresToolCallThoughtSignature = model.provider !== "google-gemini-cli" && (isGemini3ProModel(model) || isGemini3FlashModel(model));
|
|
86
85
|
const pendingToolResultImageTurns = [];
|
|
87
86
|
let activeToolResultParts;
|
|
88
87
|
const flushToolResultRun = () => {
|
|
@@ -94,17 +93,17 @@ function convertMessages(model, context) {
|
|
|
94
93
|
if (msg.role !== "toolResult") flushToolResultRun();
|
|
95
94
|
if (msg.role === "user") if (typeof msg.content === "string") contents.push({
|
|
96
95
|
role: "user",
|
|
97
|
-
parts: [{ text: sanitizeSurrogates(msg.content) }]
|
|
96
|
+
parts: [{ text: sanitizeSurrogates(msg.content) || " " }]
|
|
98
97
|
});
|
|
99
98
|
else {
|
|
100
99
|
const parts = msg.content.map((item) => {
|
|
101
|
-
if (item.type === "text") return { text: sanitizeSurrogates(item.text) };
|
|
100
|
+
if (item.type === "text") return { text: sanitizeSurrogates(item.text) || " " };
|
|
102
101
|
return { inlineData: {
|
|
103
102
|
mimeType: item.mimeType,
|
|
104
103
|
data: item.data
|
|
105
104
|
} };
|
|
106
105
|
});
|
|
107
|
-
if (parts.length === 0)
|
|
106
|
+
if (parts.length === 0) parts.push({ text: " " });
|
|
108
107
|
contents.push({
|
|
109
108
|
role: "user",
|
|
110
109
|
parts
|
|
@@ -112,30 +111,32 @@ function convertMessages(model, context) {
|
|
|
112
111
|
}
|
|
113
112
|
else if (msg.role === "assistant") {
|
|
114
113
|
const parts = [];
|
|
115
|
-
|
|
114
|
+
let sawFunctionCall = false;
|
|
115
|
+
const isSameProviderAndModel = msg.provider === model.provider && msg.api === model.api && msg.model === model.id;
|
|
116
116
|
for (const block of msg.content) if (block.type === "text") {
|
|
117
|
-
if (!block.text || block.text.trim() === "") continue;
|
|
118
117
|
const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.textSignature);
|
|
118
|
+
if ((!block.text || block.text.trim() === "") && !thoughtSignature) continue;
|
|
119
119
|
parts.push({
|
|
120
120
|
text: sanitizeSurrogates(block.text),
|
|
121
121
|
...thoughtSignature && { thoughtSignature }
|
|
122
122
|
});
|
|
123
123
|
} else if (block.type === "thinking") {
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
} else parts.push({ text: sanitizeSurrogates(block.thinking) });
|
|
124
|
+
const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thinkingSignature);
|
|
125
|
+
if ((!block.thinking || block.thinking.trim() === "") && !thoughtSignature) continue;
|
|
126
|
+
if (isSameProviderAndModel) parts.push({
|
|
127
|
+
thought: true,
|
|
128
|
+
text: sanitizeSurrogates(block.thinking),
|
|
129
|
+
...thoughtSignature && { thoughtSignature }
|
|
130
|
+
});
|
|
131
|
+
else parts.push({ text: sanitizeSurrogates(block.thinking) });
|
|
133
132
|
} else if (block.type === "toolCall") {
|
|
134
|
-
const
|
|
133
|
+
const args = coerceTransportToolCallArguments(block.arguments);
|
|
134
|
+
const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thoughtSignature) ?? (!sawFunctionCall && requiresToolCallThoughtSignature ? "skip_thought_signature_validator" : void 0);
|
|
135
|
+
sawFunctionCall = true;
|
|
135
136
|
const part = {
|
|
136
137
|
functionCall: {
|
|
137
138
|
name: block.name,
|
|
138
|
-
args
|
|
139
|
+
args,
|
|
139
140
|
...requiresToolCallId(model.id) ? { id: block.id } : {}
|
|
140
141
|
},
|
|
141
142
|
...thoughtSignature && { thoughtSignature }
|
|
@@ -181,45 +182,22 @@ function convertMessages(model, context) {
|
|
|
181
182
|
}
|
|
182
183
|
}
|
|
183
184
|
flushToolResultRun();
|
|
185
|
+
if (contents.length === 0) contents.push({
|
|
186
|
+
role: "user",
|
|
187
|
+
parts: [{ text: " " }]
|
|
188
|
+
});
|
|
184
189
|
return contents;
|
|
185
190
|
}
|
|
186
|
-
const JSON_SCHEMA_META_DECLARATIONS = /* @__PURE__ */ new Set([
|
|
187
|
-
"$schema",
|
|
188
|
-
"$id",
|
|
189
|
-
"$anchor",
|
|
190
|
-
"$dynamicAnchor",
|
|
191
|
-
"$vocabulary",
|
|
192
|
-
"$comment",
|
|
193
|
-
"$defs",
|
|
194
|
-
"definitions"
|
|
195
|
-
]);
|
|
196
|
-
/**
|
|
197
|
-
* Strip meta-declarations from a schema obj
|
|
198
|
-
*/
|
|
199
|
-
function sanitizeForOpenApi(schema) {
|
|
200
|
-
if (typeof schema !== "object" || schema === null || Array.isArray(schema)) return schema;
|
|
201
|
-
const result = {};
|
|
202
|
-
for (const [key, value] of Object.entries(schema)) {
|
|
203
|
-
if (JSON_SCHEMA_META_DECLARATIONS.has(key)) continue;
|
|
204
|
-
result[key] = sanitizeForOpenApi(value);
|
|
205
|
-
}
|
|
206
|
-
return result;
|
|
207
|
-
}
|
|
208
191
|
/**
|
|
209
192
|
* Convert tools to Gemini function declarations format.
|
|
210
|
-
*
|
|
211
|
-
* By default uses `parametersJsonSchema` which supports full JSON Schema (including
|
|
212
|
-
* anyOf, oneOf, const, etc.). Set `useParameters` to true to use the legacy `parameters`
|
|
213
|
-
* field instead (OpenAPI 3.03 Schema). This is needed for Cloud Code Assist with Claude
|
|
214
|
-
* models, where the API translates `parameters` into Anthropic's `input_schema`.
|
|
215
193
|
* @internal Directly tested provider implementation detail.
|
|
216
194
|
*/
|
|
217
|
-
function convertTools(tools
|
|
195
|
+
function convertTools(tools) {
|
|
218
196
|
if (tools.length === 0) return;
|
|
219
|
-
return [{ functionDeclarations: tools.map((tool) => ({
|
|
197
|
+
return [{ functionDeclarations: sortPromptCacheToolsByName(tools).map((tool) => ({
|
|
220
198
|
name: tool.name,
|
|
221
199
|
description: tool.description,
|
|
222
|
-
|
|
200
|
+
parametersJsonSchema: tool.parameters
|
|
223
201
|
})) }];
|
|
224
202
|
}
|
|
225
203
|
/**
|
|
@@ -276,17 +254,16 @@ async function runGoogleGenerateContentLifecycle(params) {
|
|
|
276
254
|
});
|
|
277
255
|
} catch (error) {
|
|
278
256
|
for (const block of output.content) if ("index" in block) delete block.index;
|
|
279
|
-
output
|
|
280
|
-
output.errorMessage = formatProviderError(error);
|
|
257
|
+
assignTransportErrorDetails(output, options?.signal?.aborted ? transportAbortError(options.signal) : error, options?.signal);
|
|
281
258
|
stream.push({
|
|
282
259
|
type: "error",
|
|
283
|
-
reason: output.stopReason,
|
|
260
|
+
reason: output.stopReason === "aborted" ? "aborted" : "error",
|
|
284
261
|
error: output
|
|
285
262
|
});
|
|
286
263
|
stream.end();
|
|
287
264
|
}
|
|
288
265
|
}
|
|
289
|
-
function buildGoogleGenerateContentParams(model, context, options = {}
|
|
266
|
+
function buildGoogleGenerateContentParams(model, context, options = {}) {
|
|
290
267
|
const contents = convertMessages(model, context);
|
|
291
268
|
const generationConfig = {};
|
|
292
269
|
if (options.temperature !== void 0) generationConfig.temperature = options.temperature;
|
|
@@ -304,7 +281,10 @@ function buildGoogleGenerateContentParams(model, context, options = {}, configHo
|
|
|
304
281
|
if (options.thinking.level !== void 0) thinkingConfig.thinkingLevel = ThinkingLevel[options.thinking.level];
|
|
305
282
|
else if (options.thinking.budgetTokens !== void 0) thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
|
|
306
283
|
config.thinkingConfig = thinkingConfig;
|
|
307
|
-
} else if (model.reasoning && options.thinking && !options.thinking.enabled)
|
|
284
|
+
} else if (model.reasoning && options.thinking && !options.thinking.enabled) {
|
|
285
|
+
const disabledThinkingConfig = getDisabledGoogleThinkingConfig(model);
|
|
286
|
+
if (Object.keys(disabledThinkingConfig).length > 0) config.thinkingConfig = disabledThinkingConfig;
|
|
287
|
+
}
|
|
308
288
|
if (options.signal) {
|
|
309
289
|
if (options.signal.aborted) throw new Error("Request aborted");
|
|
310
290
|
config.abortSignal = options.signal;
|
|
@@ -315,8 +295,22 @@ function buildGoogleGenerateContentParams(model, context, options = {}, configHo
|
|
|
315
295
|
config
|
|
316
296
|
};
|
|
317
297
|
}
|
|
298
|
+
function isAdaptiveGoogleReasoningLevel(value) {
|
|
299
|
+
return value === "adaptive";
|
|
300
|
+
}
|
|
318
301
|
function buildGoogleSimpleThinking(model, options, config) {
|
|
319
302
|
if (!options?.reasoning || options.reasoning === "off") return { enabled: false };
|
|
303
|
+
if (isAdaptiveGoogleReasoningLevel(options.reasoning)) {
|
|
304
|
+
if (!model.reasoning) return { enabled: false };
|
|
305
|
+
if (isGemma4Model(model)) return {
|
|
306
|
+
enabled: true,
|
|
307
|
+
level: ThinkingLevel.HIGH
|
|
308
|
+
};
|
|
309
|
+
return isGemini3ProModel(model) || isGemini3FlashModel(model) ? { enabled: true } : {
|
|
310
|
+
enabled: true,
|
|
311
|
+
budgetTokens: -1
|
|
312
|
+
};
|
|
313
|
+
}
|
|
320
314
|
const clampedReasoning = clampThinkingLevel(model, options.reasoning);
|
|
321
315
|
if (clampedReasoning === "off") return { enabled: false };
|
|
322
316
|
const effort = clampedReasoning === "max" ? "high" : clampedReasoning;
|
|
@@ -329,10 +323,10 @@ function buildGoogleSimpleThinking(model, options, config) {
|
|
|
329
323
|
budgetTokens: getGoogleBudget(model, effort, options.thinkingBudgets, { useFlashLiteBudgets: config?.useFlashLiteBudgets })
|
|
330
324
|
};
|
|
331
325
|
}
|
|
332
|
-
function getDisabledGoogleThinkingConfig(model
|
|
326
|
+
function getDisabledGoogleThinkingConfig(model) {
|
|
333
327
|
if (isGemini3ProModel(model)) return { thinkingLevel: ThinkingLevel.LOW };
|
|
334
|
-
if (isGemini3FlashModel(model)) return { thinkingLevel: ThinkingLevel.MINIMAL };
|
|
335
|
-
if (
|
|
328
|
+
if (isGemini3FlashModel(model)) return { thinkingLevel: googleFlashSupportsMinimalThinking(model.id) ? ThinkingLevel.MINIMAL : ThinkingLevel.LOW };
|
|
329
|
+
if (isGemma4Model(model) || model.id.toLowerCase().includes("gemini-2.5-pro")) return {};
|
|
336
330
|
return { thinkingBudget: 0 };
|
|
337
331
|
}
|
|
338
332
|
/** @internal Directly tested provider implementation detail. */
|
|
@@ -340,10 +334,10 @@ function isGemma4Model(model) {
|
|
|
340
334
|
return /gemma-?4/.test(model.id.toLowerCase());
|
|
341
335
|
}
|
|
342
336
|
function isGemini3ProModel(model) {
|
|
343
|
-
return /gemini-3(?:\.\d+)?-pro/.test(model.id.toLowerCase());
|
|
337
|
+
return /gemini-(?:3(?:\.\d+)?-pro|pro-latest)/.test(model.id.toLowerCase());
|
|
344
338
|
}
|
|
345
339
|
function isGemini3FlashModel(model) {
|
|
346
|
-
return /gemini-3(?:\.\d+)?-flash/.test(model.id.toLowerCase());
|
|
340
|
+
return /gemini-(?:3(?:\.\d+)?-flash|flash(?:-lite)?-latest)/.test(model.id.toLowerCase());
|
|
347
341
|
}
|
|
348
342
|
function getGoogleThinkingLevel(effort, model, config) {
|
|
349
343
|
if (isGemini3ProModel(model)) switch (effort) {
|
|
@@ -359,7 +353,7 @@ function getGoogleThinkingLevel(effort, model, config) {
|
|
|
359
353
|
case "high": return ThinkingLevel.HIGH;
|
|
360
354
|
}
|
|
361
355
|
switch (effort) {
|
|
362
|
-
case "minimal": return ThinkingLevel.MINIMAL;
|
|
356
|
+
case "minimal": return isGemini3FlashModel(model) && !googleFlashSupportsMinimalThinking(model.id) ? ThinkingLevel.LOW : ThinkingLevel.MINIMAL;
|
|
363
357
|
case "low": return ThinkingLevel.LOW;
|
|
364
358
|
case "medium": return ThinkingLevel.MEDIUM;
|
|
365
359
|
case "high": return ThinkingLevel.HIGH;
|
|
@@ -422,6 +416,15 @@ async function consumeGoogleGenerateContentStream(params) {
|
|
|
422
416
|
});
|
|
423
417
|
let currentBlock = null;
|
|
424
418
|
const blocks = params.output.content;
|
|
419
|
+
let sawTerminalReason = false;
|
|
420
|
+
let terminalGenerationError;
|
|
421
|
+
const knownUsage = {
|
|
422
|
+
promptTokenCount: 0,
|
|
423
|
+
cachedContentTokenCount: 0,
|
|
424
|
+
toolUsePromptTokenCount: 0,
|
|
425
|
+
candidatesTokenCount: 0,
|
|
426
|
+
thoughtsTokenCount: 0
|
|
427
|
+
};
|
|
425
428
|
const toolCallIds = /* @__PURE__ */ new Set();
|
|
426
429
|
for (const block of blocks) if (block.type === "toolCall") toolCallIds.add(block.id);
|
|
427
430
|
const blockIndex = () => blocks.length - 1;
|
|
@@ -443,9 +446,60 @@ async function consumeGoogleGenerateContentStream(params) {
|
|
|
443
446
|
};
|
|
444
447
|
for await (const chunk of params.chunks) {
|
|
445
448
|
params.output.responseId ||= chunk.responseId;
|
|
449
|
+
if (chunk.usageMetadata) {
|
|
450
|
+
for (const field of Object.keys(knownUsage)) {
|
|
451
|
+
const value = chunk.usageMetadata[field];
|
|
452
|
+
if (typeof value === "number") knownUsage[field] = value;
|
|
453
|
+
}
|
|
454
|
+
const promptTokens = knownUsage.promptTokenCount;
|
|
455
|
+
const cacheRead = knownUsage.cachedContentTokenCount;
|
|
456
|
+
const toolUsePromptTokens = knownUsage.toolUsePromptTokenCount;
|
|
457
|
+
const outputTokens = knownUsage.candidatesTokenCount + knownUsage.thoughtsTokenCount;
|
|
458
|
+
params.output.usage = {
|
|
459
|
+
input: Math.max(0, promptTokens - cacheRead) + toolUsePromptTokens,
|
|
460
|
+
output: outputTokens,
|
|
461
|
+
cacheRead,
|
|
462
|
+
cacheWrite: 0,
|
|
463
|
+
totalTokens: chunk.usageMetadata.totalTokenCount ?? promptTokens + outputTokens + toolUsePromptTokens,
|
|
464
|
+
cost: {
|
|
465
|
+
input: 0,
|
|
466
|
+
output: 0,
|
|
467
|
+
cacheRead: 0,
|
|
468
|
+
cacheWrite: 0,
|
|
469
|
+
total: 0
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
calculateCost(params.model, params.output.usage);
|
|
473
|
+
}
|
|
446
474
|
const candidate = chunk.candidates?.[0];
|
|
447
|
-
|
|
448
|
-
|
|
475
|
+
const promptFeedback = chunk.promptFeedback;
|
|
476
|
+
if (!candidate && promptFeedback) {
|
|
477
|
+
const blockReason = promptFeedback.blockReason ?? "PROMPT_BLOCKED";
|
|
478
|
+
const blockMessage = promptFeedback.blockReasonMessage?.trim();
|
|
479
|
+
params.output.errorCode = blockReason;
|
|
480
|
+
params.output.errorType = "google_prompt_blocked";
|
|
481
|
+
throw new Error(`Google prompt blocked (${blockReason})${blockMessage ? `: ${blockMessage}` : ""}`);
|
|
482
|
+
}
|
|
483
|
+
if (candidate?.content?.parts) for (const [partIndex, part] of candidate.content.parts.entries()) {
|
|
484
|
+
const text = part.text;
|
|
485
|
+
const hasText = typeof text === "string";
|
|
486
|
+
const hasThoughtSignature = typeof part.thoughtSignature === "string" && part.thoughtSignature.length > 0;
|
|
487
|
+
const signatureOnly = hasThoughtSignature && (!hasText || text.length === 0) && Object.keys(part).every((key) => key === "thought" || key === "thoughtSignature" || key === "text");
|
|
488
|
+
if (signatureOnly) {
|
|
489
|
+
if (!hasText && part.thought !== true) {
|
|
490
|
+
const latestBlock = blocks.at(-1);
|
|
491
|
+
if (partIndex === 0 && latestBlock?.type === "toolCall" && !latestBlock.thoughtSignature) {
|
|
492
|
+
latestBlock.thoughtSignature = retainThoughtSignature(latestBlock.thoughtSignature, part.thoughtSignature);
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
endCurrentBlock();
|
|
497
|
+
}
|
|
498
|
+
if (hasText || signatureOnly) {
|
|
499
|
+
if (currentBlock && (hasThoughtSignature || partIndex > 0)) {
|
|
500
|
+
const currentSignature = currentBlock.type === "thinking" ? currentBlock.thinkingSignature : currentBlock.textSignature;
|
|
501
|
+
if ((currentBlock.type === "thinking" ? currentBlock.thinking : currentBlock.text).length > 0 && (currentSignature !== part.thoughtSignature || partIndex > 0 && (currentSignature || hasThoughtSignature))) endCurrentBlock();
|
|
502
|
+
}
|
|
449
503
|
const isThinking = isThinkingPart(part);
|
|
450
504
|
if (!currentBlock || isThinking && currentBlock.type !== "thinking" || !isThinking && currentBlock.type !== "text") {
|
|
451
505
|
endCurrentBlock();
|
|
@@ -474,25 +528,27 @@ async function consumeGoogleGenerateContentStream(params) {
|
|
|
474
528
|
});
|
|
475
529
|
}
|
|
476
530
|
}
|
|
531
|
+
const delta = hasText ? text : "";
|
|
477
532
|
if (currentBlock.type === "thinking") {
|
|
478
|
-
currentBlock.thinking +=
|
|
533
|
+
currentBlock.thinking += delta;
|
|
479
534
|
currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);
|
|
480
535
|
params.stream.push({
|
|
481
536
|
type: "thinking_delta",
|
|
482
537
|
contentIndex: blockIndex(),
|
|
483
|
-
delta
|
|
538
|
+
delta,
|
|
484
539
|
partial: params.output
|
|
485
540
|
});
|
|
486
541
|
} else {
|
|
487
|
-
currentBlock.text +=
|
|
542
|
+
currentBlock.text += delta;
|
|
488
543
|
currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);
|
|
489
544
|
params.stream.push({
|
|
490
545
|
type: "text_delta",
|
|
491
546
|
contentIndex: blockIndex(),
|
|
492
|
-
delta
|
|
547
|
+
delta,
|
|
493
548
|
partial: params.output
|
|
494
549
|
});
|
|
495
550
|
}
|
|
551
|
+
if (signatureOnly) endCurrentBlock();
|
|
496
552
|
}
|
|
497
553
|
if (part.functionCall) {
|
|
498
554
|
endCurrentBlock();
|
|
@@ -526,29 +582,30 @@ async function consumeGoogleGenerateContentStream(params) {
|
|
|
526
582
|
}
|
|
527
583
|
}
|
|
528
584
|
if (candidate?.finishReason) {
|
|
585
|
+
sawTerminalReason = true;
|
|
529
586
|
params.output.stopReason = mapStopReason(candidate.finishReason);
|
|
587
|
+
if (params.output.stopReason === "error") {
|
|
588
|
+
const finishMessage = candidate.finishMessage?.trim();
|
|
589
|
+
terminalGenerationError = Object.assign(/* @__PURE__ */ new Error(`Google generation stopped (${candidate.finishReason})${finishMessage ? `: ${finishMessage}` : ""}`), {
|
|
590
|
+
code: candidate.finishReason,
|
|
591
|
+
type: "google_generation_failed"
|
|
592
|
+
});
|
|
593
|
+
}
|
|
530
594
|
if (params.output.stopReason === "stop" && params.output.content.some((block) => block.type === "toolCall")) params.output.stopReason = "toolUse";
|
|
531
595
|
}
|
|
532
|
-
if (chunk.usageMetadata) {
|
|
533
|
-
params.output.usage = {
|
|
534
|
-
input: (chunk.usageMetadata.promptTokenCount || 0) - (chunk.usageMetadata.cachedContentTokenCount || 0),
|
|
535
|
-
output: (chunk.usageMetadata.candidatesTokenCount || 0) + (chunk.usageMetadata.thoughtsTokenCount || 0),
|
|
536
|
-
cacheRead: chunk.usageMetadata.cachedContentTokenCount || 0,
|
|
537
|
-
cacheWrite: 0,
|
|
538
|
-
totalTokens: chunk.usageMetadata.totalTokenCount || 0,
|
|
539
|
-
cost: {
|
|
540
|
-
input: 0,
|
|
541
|
-
output: 0,
|
|
542
|
-
cacheRead: 0,
|
|
543
|
-
cacheWrite: 0,
|
|
544
|
-
total: 0
|
|
545
|
-
}
|
|
546
|
-
};
|
|
547
|
-
calculateCost(params.model, params.output.usage);
|
|
548
|
-
}
|
|
549
596
|
}
|
|
550
597
|
endCurrentBlock();
|
|
551
598
|
if (params.signal?.aborted) throw transportAbortError(params.signal);
|
|
599
|
+
if (terminalGenerationError) {
|
|
600
|
+
params.output.errorCode = terminalGenerationError.code;
|
|
601
|
+
params.output.errorType = terminalGenerationError.type;
|
|
602
|
+
throw terminalGenerationError;
|
|
603
|
+
}
|
|
604
|
+
if (!sawTerminalReason) {
|
|
605
|
+
params.output.errorCode = "STREAM_INCOMPLETE";
|
|
606
|
+
params.output.errorType = "google_incomplete_stream";
|
|
607
|
+
throw new Error("Google stream ended before a terminal finish reason");
|
|
608
|
+
}
|
|
552
609
|
if (params.output.stopReason === "aborted" || params.output.stopReason === "error") throw new Error("An unknown error occurred");
|
|
553
610
|
params.stream.push({
|
|
554
611
|
type: "done",
|
|
@@ -558,4 +615,4 @@ async function consumeGoogleGenerateContentStream(params) {
|
|
|
558
615
|
params.stream.end();
|
|
559
616
|
}
|
|
560
617
|
//#endregion
|
|
561
|
-
export { runGoogleGenerateContentLifecycle as
|
|
618
|
+
export { runGoogleGenerateContentLifecycle as i, buildGoogleSimpleThinking as n, createGoogleAssistantOutput as r, buildGoogleGenerateContentParams as t };
|
|
@@ -0,0 +1,9 @@
|
|
|
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 };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { t as AssistantMessageEventStream } from "./event-stream-
|
|
2
|
-
import {
|
|
3
|
-
import { n as
|
|
4
|
-
import {
|
|
1
|
+
import { t as AssistantMessageEventStream } from "./event-stream-uSMZJ3FA.mjs";
|
|
2
|
+
import { a as normalizeOptionalString } from "./string-coerce-fsri9iCu.mjs";
|
|
3
|
+
import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-DTqNc7ad.mjs";
|
|
4
|
+
import { n as buildBaseOptions } from "./simple-options-D58D5Kvw.mjs";
|
|
5
|
+
import { i as runGoogleGenerateContentLifecycle, n as buildGoogleSimpleThinking, r as createGoogleAssistantOutput, t as buildGoogleGenerateContentParams } from "./google-shared-B0Qr9OR7.mjs";
|
|
5
6
|
import { GoogleGenAI, ResourceScope } from "@google/genai";
|
|
6
7
|
//#region packages/ai/src/providers/google-vertex.ts
|
|
7
8
|
const API_VERSION = "v1";
|
|
@@ -27,7 +28,10 @@ const streamSimpleGoogleVertex = (model, context, options) => {
|
|
|
27
28
|
const base = buildBaseOptions(model, options, void 0);
|
|
28
29
|
return streamGoogleVertex(model, context, {
|
|
29
30
|
...base,
|
|
30
|
-
thinking: buildGoogleSimpleThinking(model, options
|
|
31
|
+
thinking: buildGoogleSimpleThinking(model, options, {
|
|
32
|
+
includeGemma4ThinkingLevel: true,
|
|
33
|
+
useFlashLiteBudgets: true
|
|
34
|
+
})
|
|
31
35
|
});
|
|
32
36
|
};
|
|
33
37
|
function createClient(model, project, location, optionsHeaders) {
|
|
@@ -82,12 +86,12 @@ function isPlaceholderApiKey(apiKey) {
|
|
|
82
86
|
return /^<[^>]+>$/.test(apiKey);
|
|
83
87
|
}
|
|
84
88
|
function resolveProject(options) {
|
|
85
|
-
const project = options?.project || process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
|
|
89
|
+
const project = normalizeOptionalString(options?.project) || normalizeOptionalString(process.env.GOOGLE_CLOUD_PROJECT) || normalizeOptionalString(process.env.GCLOUD_PROJECT);
|
|
86
90
|
if (!project) throw new Error("Vertex AI requires a project ID. Set GOOGLE_CLOUD_PROJECT/GCLOUD_PROJECT or pass project in options.");
|
|
87
91
|
return project;
|
|
88
92
|
}
|
|
89
93
|
function resolveLocation(options) {
|
|
90
|
-
const location = options?.location || process.env.GOOGLE_CLOUD_LOCATION;
|
|
94
|
+
const location = normalizeOptionalString(options?.location) || normalizeOptionalString(process.env.GOOGLE_CLOUD_LOCATION);
|
|
91
95
|
if (!location) throw new Error("Vertex AI requires a location. Set GOOGLE_CLOUD_LOCATION or pass location in options.");
|
|
92
96
|
return location;
|
|
93
97
|
}
|
|
@@ -14,4 +14,12 @@ function onLlmRequestActivity(signal, listener) {
|
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
//#endregion
|
|
17
|
-
|
|
17
|
+
//#region packages/ai/src/utils/headers.ts
|
|
18
|
+
/** Converts a Headers object to a plain record for provider request handling. */
|
|
19
|
+
function headersToRecord(headers) {
|
|
20
|
+
const result = {};
|
|
21
|
+
for (const [key, value] of headers.entries()) result[key] = value;
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { notifyLlmRequestActivity as n, onLlmRequestActivity as r, headersToRecord as t };
|