@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.
Files changed (91) hide show
  1. package/dist/{anthropic-CH4UUnZr.mjs → anthropic-B6dLpq5L.mjs} +55 -203
  2. package/dist/{src-QkygScBs.mjs → anthropic-JsNA5KCu.mjs} +0 -1
  3. package/dist/anthropic-compaction-replay-8lJNKXOE.mjs +840 -0
  4. package/dist/anthropic-payload-policy-CiEuQS72.d.mts +49 -0
  5. package/dist/{api-registry-DlMgPR39.d.mts → api-registry-k3zTz0cV.d.mts} +1 -1
  6. package/dist/{azure-openai-responses-CImcwB83.mjs → azure-openai-responses-mxIOtUnn.mjs} +23 -29
  7. package/dist/diagnostics.d.mts +24 -1
  8. package/dist/diagnostics.mjs +2 -1
  9. package/dist/{event-stream-YjaPW20U.d.mts → event-stream-BP6AWT8j.d.mts} +4 -1
  10. package/dist/{event-stream-D8n2uFee.mjs → event-stream-uSMZJ3FA.mjs} +26 -5
  11. package/dist/event-stream.d.mts +1 -1
  12. package/dist/event-stream.mjs +1 -1
  13. package/dist/{google-CtSg0iTS.mjs → google-C7h2QzDX.mjs} +5 -5
  14. package/dist/{google-shared-DNBz5rcD.mjs → google-shared-B0Qr9OR7.mjs} +146 -89
  15. package/dist/google-thinking-level-C-V3tecN.mjs +9 -0
  16. package/dist/{google-vertex-31f1uS9L.mjs → google-vertex-Bhc3TjDl.mjs} +11 -7
  17. package/dist/{llm-request-activity-BjtkplhG.mjs → headers-DdOQtGuU.mjs} +9 -1
  18. package/dist/host-DTqNc7ad.mjs +466 -0
  19. package/dist/{host-B9GUmcra.d.mts → host-vWgMMhiJ.d.mts} +9 -4
  20. package/dist/index.d.mts +6 -6
  21. package/dist/index.mjs +7 -5
  22. package/dist/internal/anthropic.d.mts +29 -5
  23. package/dist/internal/anthropic.mjs +5 -5
  24. package/dist/internal/openai-responses-payload-policy.d.mts +3 -0
  25. package/dist/internal/openai-responses-payload-policy.mjs +3 -0
  26. package/dist/internal/openai.d.mts +6 -6
  27. package/dist/internal/openai.mjs +8 -7
  28. package/dist/internal/runtime.d.mts +17 -5
  29. package/dist/internal/runtime.mjs +85 -73
  30. package/dist/internal/shared.d.mts +1 -6
  31. package/dist/internal/shared.mjs +3 -5
  32. package/dist/{json-parse-BvXNt1-7.mjs → json-parse-CDnesDM_.mjs} +4 -6
  33. package/dist/{mistral-CWmpvWYh.mjs → mistral-CEWoQI_g.mjs} +45 -48
  34. package/dist/number-coercion-H9qHik3g.mjs +71 -0
  35. package/dist/openai-chatgpt-jwt-KWcgd0d_.mjs +19 -0
  36. package/dist/{openai-chatgpt-responses-B84Ibtrd.mjs → openai-chatgpt-responses-CrPmqERt.mjs} +284 -240
  37. package/dist/{openai-completions-DsOxhOD1.mjs → openai-completions-BPnt4Sml.mjs} +65 -99
  38. package/dist/{openai-completions-compat-DBWjXoMZ.d.mts → openai-completions-compat-Dt3dcawL.d.mts} +2 -2
  39. package/dist/{openai-responses-BT7A3sLu.mjs → openai-responses-DhIKtOup.mjs} +18 -41
  40. package/dist/openai-responses-contracts-CyfIkQi5.mjs +253 -0
  41. package/dist/openai-responses-contracts-XpZJxrRG.d.mts +68 -0
  42. package/dist/openai-responses-payload-policy-BDxV-W0c.mjs +206 -0
  43. package/dist/openai-responses-payload-policy-BSs371VM.d.mts +40 -0
  44. package/dist/openai-responses-prompt-observer-internal-DgNTYnRY.mjs +46 -0
  45. package/dist/{openai-responses-stream-internal-Cw5txaGW.mjs → openai-responses-shared-DXIt3iY5.mjs} +1406 -940
  46. package/dist/{openai-reasoning-compat-YgeLncHw.mjs → openai-stop-reason-BkFkqqK0.mjs} +204 -37
  47. package/dist/openai-tool-projection-CY04OcvQ.mjs +338 -0
  48. package/dist/provider-error-BUwEnjXq.mjs +429 -0
  49. package/dist/provider-error-CzNw4BWX.d.mts +12 -0
  50. package/dist/{provider-options-D8bB3z9b.d.mts → provider-options-B96RdNpH.d.mts} +9 -3
  51. package/dist/provider-transcript-transform-ePx-Bbfr.mjs +155 -0
  52. package/dist/provider-types.d.mts +31 -0
  53. package/dist/provider-types.mjs +8 -0
  54. package/dist/providers.d.mts +1 -1
  55. package/dist/providers.mjs +17 -19
  56. package/dist/{reasoning-tag-text-partitioner-CGDyLWUR.mjs → reasoning-tag-text-partitioner-rnPwX2pg.mjs} +14 -8
  57. package/dist/record-coerce-DdXsgUd_.mjs +23 -0
  58. package/dist/sanitize-unicode-BYqrYtC_.mjs +90 -0
  59. package/dist/session-resources-CkR4WWy1.mjs +21 -0
  60. package/dist/simple-options-D58D5Kvw.mjs +117 -0
  61. package/dist/src-D2H6yKkH.mjs +2 -0
  62. package/dist/{stream-first-event-timeout-BBys9hSb.mjs → stream-first-event-timeout-MK28puvq.mjs} +2 -2
  63. package/dist/string-coerce-fsri9iCu.mjs +34 -0
  64. package/dist/{tool-schema-json-projection-BwNu3nDi.mjs → tool-schema-json-projection-q5d7QX5c.mjs} +32 -7
  65. package/dist/transport-utils-DJqkxbhC.mjs +138 -0
  66. package/dist/transports.d.mts +166 -241
  67. package/dist/transports.mjs +1979 -1825
  68. package/dist/types-BDdaOVi2.mjs +6 -0
  69. package/dist/{types-bzp5k29J.d.mts → types-BHNrPS1l.d.mts} +23 -1
  70. package/dist/types.d.mts +4 -4
  71. package/dist/types.mjs +6 -4
  72. package/dist/utf16-slice-CvGodqok.mjs +29 -0
  73. package/dist/{validation-DAa_yFOM.mjs → validation-B61OhAio.mjs} +6 -6
  74. package/dist/{validation-B-j7cOYp.d.mts → validation-DT9SrFn3.d.mts} +1 -1
  75. package/dist/validation.d.mts +1 -1
  76. package/dist/validation.mjs +1 -1
  77. package/package.json +15 -1
  78. package/dist/anthropic-usage-DWU-x8MI.mjs +0 -459
  79. package/dist/error-coercion-DgxlWC0n.mjs +0 -15
  80. package/dist/headers-B_e4-1J0.mjs +0 -9
  81. package/dist/host-Dog2WQiR.mjs +0 -369
  82. package/dist/number-coercion-DvG7SNMg.mjs +0 -129
  83. package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +0 -39
  84. package/dist/openai-responses-shared-pXl6Wd8S.mjs +0 -392
  85. package/dist/openai-tool-projection-OhX64DoP.mjs +0 -215
  86. package/dist/provider-error-CAEvRjry.mjs +0 -47
  87. package/dist/sanitize-unicode-DT5o51ur.mjs +0 -26
  88. package/dist/simple-options-9lhRrN73.mjs +0 -50
  89. package/dist/tool-result-text-CTpIRbYd.mjs +0 -225
  90. package/dist/transform-messages-C8mBqZxF.mjs +0 -2
  91. package/dist/transport-stream-shared-D81p90xq.mjs +0 -297
@@ -1,10 +1,8 @@
1
- import { i as transformMessages } from "./host-Dog2WQiR.mjs";
2
- import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
3
- import { a as isImageWithMediaPayload, d as stripSystemPromptCacheBoundary, r as extractToolResultText, t as describeToolResultMediaPlaceholder } from "./tool-result-text-CTpIRbYd.mjs";
4
- import { c as calculateCost, l as clampThinkingLevel } from "./number-coercion-DvG7SNMg.mjs";
5
- import { d as transportAbortError } from "./transport-stream-shared-D81p90xq.mjs";
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 = transformMessages(context.messages, model, normalizeToolCallId);
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) continue;
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
- const isSameProviderAndModel = msg.provider === model.provider && msg.model === model.id;
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
- if (!block.thinking || block.thinking.trim() === "") continue;
125
- if (isSameProviderAndModel) {
126
- const thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thinkingSignature);
127
- parts.push({
128
- thought: true,
129
- text: sanitizeSurrogates(block.thinking),
130
- ...thoughtSignature && { thoughtSignature }
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 thoughtSignature = resolveThoughtSignature(isSameProviderAndModel, block.thoughtSignature);
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: block.arguments ?? {},
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, useParameters = false) {
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
- ...useParameters ? { parameters: sanitizeForOpenApi(tool.parameters) } : { parametersJsonSchema: tool.parameters }
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.stopReason = options?.signal?.aborted ? "aborted" : "error";
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 = {}, configHooks) {
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) config.thinkingConfig = configHooks?.getDisabledThinkingConfig ? configHooks.getDisabledThinkingConfig(model) : getDisabledGoogleThinkingConfig(model);
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, config) {
326
+ function getDisabledGoogleThinkingConfig(model) {
333
327
  if (isGemini3ProModel(model)) return { thinkingLevel: ThinkingLevel.LOW };
334
- if (isGemini3FlashModel(model)) return { thinkingLevel: ThinkingLevel.MINIMAL };
335
- if (config?.includeGemma4 && isGemma4Model(model)) return { thinkingLevel: ThinkingLevel.MINIMAL };
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
- if (candidate?.content?.parts) for (const part of candidate.content.parts) {
448
- if (part.text !== void 0) {
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 += part.text;
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: part.text,
538
+ delta,
484
539
  partial: params.output
485
540
  });
486
541
  } else {
487
- currentBlock.text += part.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: part.text,
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 a, getDisabledGoogleThinkingConfig as i, buildGoogleSimpleThinking as n, createGoogleAssistantOutput as r, buildGoogleGenerateContentParams as t };
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-D8n2uFee.mjs";
2
- import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-Dog2WQiR.mjs";
3
- import { n as buildBaseOptions } from "./simple-options-9lhRrN73.mjs";
4
- import { a as runGoogleGenerateContentLifecycle, n as buildGoogleSimpleThinking, r as createGoogleAssistantOutput, t as buildGoogleGenerateContentParams } from "./google-shared-DNBz5rcD.mjs";
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
- export { onLlmRequestActivity as n, notifyLlmRequestActivity as t };
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 };