@openclaw/ai 2026.9.1 → 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.
Files changed (111) hide show
  1. package/README.md +3 -2
  2. package/dist/anthropic-CZy5U0NY.mjs +376 -0
  3. package/dist/anthropic-payload-policy-wuRCb6MH.d.mts +85 -0
  4. package/dist/anthropic-stream-reducer-B_yo_7pf.mjs +1669 -0
  5. package/dist/{api-registry-Cs6HGNqY.d.mts → api-registry-CB1-1oQ2.d.mts} +2 -2
  6. package/dist/assistant-output-iqnlJCV2.mjs +16 -0
  7. package/dist/assistant-text-phase-C20rxWwP.mjs +55 -0
  8. package/dist/{azure-openai-responses-CN4Fy5zV.mjs → azure-openai-responses-Crpa40QR.mjs} +5 -5
  9. package/dist/{base64-CEFBpSkN.mjs → base64-D-su8YVo.mjs} +1 -27
  10. package/dist/{diagnostics-KhXK-QJI.mjs → diagnostics-dV98PqIy.mjs} +96 -21
  11. package/dist/diagnostics.d.mts +3 -1
  12. package/dist/diagnostics.mjs +3 -3
  13. package/dist/{event-stream-vK_7r3bj.d.mts → event-stream-C1Z2piyk.d.mts} +11 -3
  14. package/dist/{event-stream-uSMZJ3FA.mjs → event-stream-D8PARQfL.mjs} +48 -10
  15. package/dist/event-stream-I_GlBsuZ.d.mts +1 -0
  16. package/dist/event-stream.d.mts +2 -2
  17. package/dist/event-stream.mjs +1 -1
  18. package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-B37TB3rB.mjs} +3 -10
  19. package/dist/github-copilot-request-facts-BTEBMeOv.mjs +16 -0
  20. package/dist/{google-CC-nrwXg.mjs → google-BDPriaVe.mjs} +10 -10
  21. package/dist/google-messages-CVn9eFpF.mjs +449 -0
  22. package/dist/google-shared-BedY23XS.mjs +185 -0
  23. package/dist/{google-vertex-DCr0pyzQ.mjs → google-vertex-DMz8XQCn.mjs} +7 -6
  24. package/dist/{host-BIaiBURL.mjs → host-CWuF-sS3.mjs} +84 -34
  25. package/dist/{host-BztR4tQj.d.mts → host-DK3wmS3e.d.mts} +3 -3
  26. package/dist/host-policy-CAopLRKA.mjs +37 -0
  27. package/dist/{index-AfaxKT8w.d.mts → index-CQ6LTHw8.d.mts} +11 -5
  28. package/dist/index.d.mts +7 -7
  29. package/dist/index.mjs +5 -5
  30. package/dist/internal/anthropic.d.mts +14 -11
  31. package/dist/internal/anthropic.mjs +5 -5
  32. package/dist/internal/google-model-family.d.mts +5 -0
  33. package/dist/internal/google-model-family.mjs +15 -0
  34. package/dist/internal/openai-responses-payload-policy.d.mts +1 -1
  35. package/dist/internal/openai-responses-payload-policy.mjs +1 -1
  36. package/dist/internal/openai.d.mts +8 -103
  37. package/dist/internal/openai.mjs +10 -10
  38. package/dist/internal/retry-after.d.mts +2 -4
  39. package/dist/internal/retry-after.mjs +57 -8
  40. package/dist/internal/runtime.d.mts +7 -6
  41. package/dist/internal/runtime.mjs +8 -7
  42. package/dist/internal/shared.d.mts +14 -3
  43. package/dist/internal/shared.mjs +6 -4
  44. package/dist/internal/tool-schema.d.mts +63 -0
  45. package/dist/internal/tool-schema.mjs +3 -0
  46. package/dist/{json-parse-BuAJEbdW.mjs → json-parse-Dw_hnxsA.mjs} +1 -1
  47. package/dist/{mistral-B7etBd_H.mjs → mistral--m-Jm6VZ.mjs} +16 -38
  48. package/dist/model-transport-url-DKocrEsb.d.mts +28 -0
  49. package/dist/{openai-chatgpt-responses-BAJ4gq3i.mjs → openai-chatgpt-responses-nDZccFW-.mjs} +62 -54
  50. package/dist/openai-completions-KuoZyx0d.mjs +187 -0
  51. package/dist/{openai-completions-compat-4IjSBpr6.d.mts → openai-completions-compat-CXn3T1we.d.mts} +26 -4
  52. package/dist/{openai-completions-stream-DZjwK8vp.mjs → openai-completions-stream-BQk3SkLD.mjs} +621 -451
  53. package/dist/openai-prompt-cache-BI0rkM-5.mjs +220 -0
  54. package/dist/openai-prompt-cache-rrutvqxq.d.mts +16 -0
  55. package/dist/openai-provider-client-ha_WxTyj.mjs +24 -0
  56. package/dist/openai-reasoning-effort-BK7FbcLT.mjs +167 -0
  57. package/dist/{openai-responses-BEUlxfDu.mjs → openai-responses-D99dOzKI.mjs} +14 -32
  58. package/dist/{openai-responses-compaction-window-DO7yV7az.mjs → openai-responses-compaction-window-D5jbzCi3.mjs} +7 -159
  59. package/dist/{openai-responses-contracts-bPzSN_Ba.d.mts → openai-responses-contracts-B55afwRo.d.mts} +12 -4
  60. package/dist/{openai-responses-prompt-observer-internal-C7x4IK7r.mjs → openai-responses-prompt-observer-internal-tApyTLVu.mjs} +3 -3
  61. package/dist/{openai-responses-shared-DiAdpNAM.mjs → openai-responses-shared-ZyQEzS5i.mjs} +217 -212
  62. package/dist/openai-tool-projection-793cE3QX.d.mts +37 -0
  63. package/dist/{openai-tool-schema-BMiHFH36.mjs → openai-tool-schema-CzjyYXun.mjs} +53 -583
  64. package/dist/openai-tool-schema-ynZBgqW-.d.mts +38 -0
  65. package/dist/openai-transport-params-DNasp2fU.mjs +674 -0
  66. package/dist/{provider-error-B6EGq6gg.mjs → provider-error-C6TbKiey.mjs} +29 -13
  67. package/dist/{provider-options-CxFPtvh7.d.mts → provider-options-BXr9Ec83.d.mts} +19 -42
  68. package/dist/provider-replay-context-BuSUaAk5.mjs +21 -0
  69. package/dist/{provider-transcript-transform-WvJmFUAf.mjs → provider-transcript-transform-pPmUIwKt.mjs} +1 -1
  70. package/dist/provider-types-CAV0Og3m.d.mts +29 -0
  71. package/dist/provider-types.d.mts +6 -31
  72. package/dist/providers.d.mts +2 -2
  73. package/dist/providers.mjs +11 -11
  74. package/dist/{reasoning-tag-text-partitioner-C-4uedDb.mjs → reasoning-tag-text-partitioner-BQBi4B9d.mjs} +90 -35
  75. package/dist/record-coerce-DwRYMj3t.mjs +32 -0
  76. package/dist/retry-after-CdCURCVg.d.mts +15 -0
  77. package/dist/{sanitize-unicode-S6binQG-.mjs → sanitize-unicode-Bb-v9meu.mjs} +1 -1
  78. package/dist/session-affinity-CCH7eYdB.mjs +20 -0
  79. package/dist/{simple-options-0PLDyJ-d.mjs → simple-options-tcKOqnpF.mjs} +3 -3
  80. package/dist/{src-C8U7lkoa.mjs → src-B2Q_6G8V.mjs} +10 -2
  81. package/dist/{stream-first-event-timeout-DcNjoFQE.mjs → stream-first-event-timeout-2hfrquuz.mjs} +1 -1
  82. package/dist/string-coerce-fsri9iCu.mjs +34 -0
  83. package/dist/{string-normalization--fwJ4S2q.mjs → string-normalization-CmLIasuf.mjs} +1 -1
  84. package/dist/{tool-schema-json-projection-BtZiml7r.mjs → tool-schema-json-projection-ClptDdAO.mjs} +2 -38
  85. package/dist/{transport-stream-shared-CytPVLIg.mjs → transport-stream-shared-Cu3ZPhNW.mjs} +5 -5
  86. package/dist/{transport-stream-shared-BrvFTkoO.d.mts → transport-stream-shared-DOxpGJ-H.d.mts} +4 -4
  87. package/dist/transport-utils-CCooe-cr.mjs +121 -0
  88. package/dist/transports.d.mts +114 -41
  89. package/dist/transports.mjs +796 -1596
  90. package/dist/types-BADKjDBI.d.mts +1 -0
  91. package/dist/{types-DbrhszyQ.d.mts → types-Dy1q0CSu.d.mts} +101 -64
  92. package/dist/types.d.mts +6 -6
  93. package/dist/types.mjs +4 -4
  94. package/dist/utf16-slice-CvGodqok.mjs +29 -0
  95. package/dist/{validation-CJZtym2g.mjs → validation-BDzVDnTs.mjs} +9 -1
  96. package/dist/{validation-BOwtcl9X.d.mts → validation-CaFUZN9B.d.mts} +1 -1
  97. package/dist/validation.d.mts +1 -1
  98. package/dist/validation.mjs +1 -1
  99. package/package.json +14 -4
  100. package/dist/anthropic-compaction-replay-OMJZ0uyo.mjs +0 -838
  101. package/dist/anthropic-hk7F7ptG.mjs +0 -883
  102. package/dist/anthropic-payload-policy-DBT1itQ-.d.mts +0 -51
  103. package/dist/event-stream-DeDhbCc5.d.mts +0 -1
  104. package/dist/google-shared-CjPY0hZM.mjs +0 -634
  105. package/dist/google-thinking-level-C-V3tecN.mjs +0 -9
  106. package/dist/openai-completions-D0QZ0AyB.mjs +0 -403
  107. package/dist/openai-prompt-cache-2uo_1OR1.d.mts +0 -7
  108. package/dist/openai-prompt-cache-mZTCdRPo.mjs +0 -12
  109. package/dist/transport-utils-CtuS1Upe.mjs +0 -138
  110. package/dist/types-B5EFUmXs.d.mts +0 -1
  111. package/dist/utf16-slice-qz3nsy87.mjs +0 -84
@@ -0,0 +1,449 @@
1
+ import { r as appendAssistantThinking } from "./event-stream-D8PARQfL.mjs";
2
+ import { r as calculateCost, t as sanitizeSurrogates } from "./sanitize-unicode-Bb-v9meu.mjs";
3
+ import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload } from "./host-CWuF-sS3.mjs";
4
+ import { m as sortPromptCacheToolsByName } from "./simple-options-tcKOqnpF.mjs";
5
+ import { _ as transportAbortError, g as sanitizeTransportPayloadText, n as coerceTransportToolCallArguments } from "./transport-stream-shared-Cu3ZPhNW.mjs";
6
+ import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
7
+ //#region packages/ai/src/transports/google-thinking-level.ts
8
+ /** Returns whether a Gemini Flash model accepts the MINIMAL thinking level. */
9
+ function googleFlashSupportsMinimalThinking(modelId) {
10
+ const match = modelId.toLowerCase().match(/(?:^|\/)gemini-3\.(\d+)-flash(?:-|$)/);
11
+ if (!match) return true;
12
+ return Number.parseInt(match[1] ?? "0", 10) < 7;
13
+ }
14
+ //#endregion
15
+ //#region packages/ai/src/providers/google-stream.ts
16
+ const GOOGLE_MODEL_RESOURCE_PREFIX = /^(?:(?:projects\/[^/]+\/locations\/[^/]+\/)?publishers\/google\/models\/|google\/|models\/)/u;
17
+ function retainThoughtSignature(existing, incoming) {
18
+ if (typeof incoming === "string" && incoming.length > 0) return incoming;
19
+ return existing;
20
+ }
21
+ const stopReasons = new Map(Object.entries({
22
+ STOP: "stop",
23
+ MAX_TOKENS: "length",
24
+ BLOCKLIST: "error",
25
+ PROHIBITED_CONTENT: "error",
26
+ SPII: "error",
27
+ SAFETY: "error",
28
+ IMAGE_SAFETY: "error",
29
+ IMAGE_PROHIBITED_CONTENT: "error",
30
+ IMAGE_RECITATION: "error",
31
+ IMAGE_OTHER: "error",
32
+ RECITATION: "error",
33
+ FINISH_REASON_UNSPECIFIED: "error",
34
+ OTHER: "error",
35
+ LANGUAGE: "error",
36
+ MALFORMED_FUNCTION_CALL: "error",
37
+ TOO_MANY_TOOL_CALLS: "error",
38
+ UNEXPECTED_TOOL_CALL: "error",
39
+ NO_IMAGE: "error"
40
+ }));
41
+ function mapStopReason(reason) {
42
+ const mapped = stopReasons.get(reason);
43
+ if (!mapped) throw new Error(`Unhandled stop reason: ${reason}`);
44
+ return mapped;
45
+ }
46
+ /** @internal Directly tested provider implementation detail. */
47
+ async function consumeGoogleGenerateContentStream(params) {
48
+ const preserveParts = params.profile !== "managed";
49
+ const normalizeModelId = params.normalizeModelId ?? ((id) => id.replace(GOOGLE_MODEL_RESOURCE_PREFIX, ""));
50
+ params.stream.push({
51
+ type: "start",
52
+ partial: params.output
53
+ });
54
+ let currentBlock = null;
55
+ const blocks = params.output.content;
56
+ let sawTerminalReason = false;
57
+ let terminalGenerationError;
58
+ const knownUsage = {
59
+ promptTokenCount: 0,
60
+ cachedContentTokenCount: 0,
61
+ toolUsePromptTokenCount: 0,
62
+ candidatesTokenCount: 0,
63
+ thoughtsTokenCount: 0
64
+ };
65
+ const toolCallIds = /* @__PURE__ */ new Set();
66
+ for (const block of blocks) if (block.type === "toolCall") toolCallIds.add(block.id);
67
+ const blockIndex = () => blocks.length - 1;
68
+ const endCurrentBlock = () => {
69
+ if (!currentBlock) return;
70
+ if (currentBlock.type === "text") params.stream.push({
71
+ type: "text_end",
72
+ contentIndex: blockIndex(),
73
+ content: currentBlock.text,
74
+ partial: params.output
75
+ });
76
+ else params.stream.push({
77
+ type: "thinking_end",
78
+ contentIndex: blockIndex(),
79
+ content: currentBlock.thinking,
80
+ partial: params.output
81
+ });
82
+ currentBlock = null;
83
+ };
84
+ for await (const chunk of params.chunks) {
85
+ notifyLlmRequestActivity(params.signal);
86
+ params.output.responseId ||= chunk.responseId;
87
+ const responseModel = chunk.modelVersion?.trim();
88
+ if (responseModel && normalizeModelId(params.model.id) !== normalizeModelId(responseModel)) params.output.responseModel ||= responseModel;
89
+ if (chunk.usageMetadata) {
90
+ for (const field of [
91
+ "promptTokenCount",
92
+ "cachedContentTokenCount",
93
+ "toolUsePromptTokenCount",
94
+ "candidatesTokenCount",
95
+ "thoughtsTokenCount"
96
+ ]) {
97
+ const value = chunk.usageMetadata[field];
98
+ if (typeof value === "number") knownUsage[field] = value;
99
+ }
100
+ const promptTokens = knownUsage.promptTokenCount;
101
+ const cacheRead = knownUsage.cachedContentTokenCount;
102
+ const toolUsePromptTokens = knownUsage.toolUsePromptTokenCount;
103
+ const outputTokens = knownUsage.candidatesTokenCount + knownUsage.thoughtsTokenCount;
104
+ params.output.usage = {
105
+ input: Math.max(0, promptTokens - cacheRead) + toolUsePromptTokens,
106
+ output: outputTokens,
107
+ cacheRead,
108
+ cacheWrite: 0,
109
+ totalTokens: chunk.usageMetadata.totalTokenCount ?? promptTokens + outputTokens + toolUsePromptTokens,
110
+ cost: {
111
+ input: 0,
112
+ output: 0,
113
+ cacheRead: 0,
114
+ cacheWrite: 0,
115
+ total: 0
116
+ }
117
+ };
118
+ calculateCost(params.model, params.output.usage);
119
+ }
120
+ const candidate = chunk.candidates?.[0];
121
+ const promptFeedback = chunk.promptFeedback;
122
+ if (!candidate && promptFeedback) {
123
+ const blockReason = (preserveParts ? promptFeedback.blockReason : promptFeedback.blockReason?.trim() || void 0) ?? "PROMPT_BLOCKED";
124
+ const blockMessage = promptFeedback.blockReasonMessage?.trim();
125
+ if (preserveParts) {
126
+ params.output.errorCode = blockReason;
127
+ params.output.errorType = "google_prompt_blocked";
128
+ }
129
+ throw Object.assign(/* @__PURE__ */ new Error(`Google prompt blocked (${blockReason})${blockMessage ? `: ${blockMessage}` : ""}`), {
130
+ code: blockReason,
131
+ type: "google_prompt_blocked"
132
+ });
133
+ }
134
+ if (candidate?.content?.parts) for (const [partIndex, part] of candidate.content.parts.entries()) {
135
+ const text = part.text;
136
+ const hasText = typeof text === "string";
137
+ const hasThoughtSignature = typeof part.thoughtSignature === "string" && part.thoughtSignature.length > 0;
138
+ const signatureOnly = preserveParts && hasThoughtSignature && (!hasText || text.length === 0) && Object.keys(part).every((key) => key === "thought" || key === "thoughtSignature" || key === "text");
139
+ if (signatureOnly || !preserveParts && hasThoughtSignature && !part.functionCall) {
140
+ if (!hasText && part.thought !== true) {
141
+ const latestBlock = blocks.at(-1);
142
+ if (latestBlock?.type === "toolCall" && (!preserveParts || partIndex === 0 && !latestBlock.thoughtSignature)) {
143
+ latestBlock.thoughtSignature = retainThoughtSignature(latestBlock.thoughtSignature, part.thoughtSignature);
144
+ continue;
145
+ }
146
+ }
147
+ if (preserveParts) endCurrentBlock();
148
+ }
149
+ if (hasText || signatureOnly || !preserveParts && hasThoughtSignature && !part.functionCall) {
150
+ if (preserveParts && currentBlock && (hasThoughtSignature || partIndex > 0)) {
151
+ const currentSignature = currentBlock.type === "thinking" ? currentBlock.thinkingSignature : currentBlock.textSignature;
152
+ if ((currentBlock.type === "thinking" ? currentBlock.thinking : currentBlock.text).length > 0 && (currentSignature !== part.thoughtSignature || partIndex > 0 && (currentSignature || hasThoughtSignature))) endCurrentBlock();
153
+ }
154
+ const isThinking = part.thought === true || !preserveParts && !hasText;
155
+ if (!currentBlock || isThinking && currentBlock.type !== "thinking" || !isThinking && currentBlock.type !== "text") {
156
+ endCurrentBlock();
157
+ if (isThinking) {
158
+ currentBlock = {
159
+ type: "thinking",
160
+ thinking: "",
161
+ ...preserveParts ? { thinkingSignature: void 0 } : {}
162
+ };
163
+ params.output.content.push(currentBlock);
164
+ params.stream.push({
165
+ type: "thinking_start",
166
+ contentIndex: blockIndex(),
167
+ partial: params.output
168
+ });
169
+ } else {
170
+ currentBlock = {
171
+ type: "text",
172
+ text: ""
173
+ };
174
+ params.output.content.push(currentBlock);
175
+ params.stream.push({
176
+ type: "text_start",
177
+ contentIndex: blockIndex(),
178
+ partial: params.output
179
+ });
180
+ }
181
+ }
182
+ const delta = hasText ? text : "";
183
+ if (currentBlock.type === "thinking") {
184
+ appendAssistantThinking(currentBlock, delta);
185
+ currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);
186
+ params.stream.push({
187
+ type: "thinking_delta",
188
+ contentIndex: blockIndex(),
189
+ delta,
190
+ partial: params.output
191
+ });
192
+ } else {
193
+ currentBlock.text += delta;
194
+ currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);
195
+ params.stream.push({
196
+ type: "text_delta",
197
+ contentIndex: blockIndex(),
198
+ delta,
199
+ partial: params.output
200
+ });
201
+ }
202
+ if (signatureOnly) endCurrentBlock();
203
+ }
204
+ if (part.functionCall) {
205
+ endCurrentBlock();
206
+ const providedId = part.functionCall.id;
207
+ const toolCall = {
208
+ type: "toolCall",
209
+ id: !providedId || toolCallIds.has(providedId) ? params.nextToolCallId(part.functionCall.name) : providedId,
210
+ name: part.functionCall.name || "",
211
+ arguments: part.functionCall.args ?? {},
212
+ ...part.thoughtSignature && { thoughtSignature: part.thoughtSignature }
213
+ };
214
+ params.output.content.push(toolCall);
215
+ toolCallIds.add(toolCall.id);
216
+ params.stream.push({
217
+ type: "toolcall_start",
218
+ contentIndex: blockIndex(),
219
+ partial: params.output
220
+ });
221
+ params.stream.push({
222
+ type: "toolcall_delta",
223
+ contentIndex: blockIndex(),
224
+ delta: JSON.stringify(toolCall.arguments),
225
+ partial: params.output
226
+ });
227
+ params.stream.push({
228
+ type: "toolcall_end",
229
+ contentIndex: blockIndex(),
230
+ toolCall,
231
+ partial: params.output
232
+ });
233
+ }
234
+ }
235
+ if (candidate?.finishReason && candidate.finishReason !== "FINISH_REASON_UNSPECIFIED") {
236
+ sawTerminalReason = true;
237
+ params.output.stopReason = (params.resolveStopReason ?? mapStopReason)(candidate.finishReason);
238
+ if (params.output.stopReason === "error") {
239
+ const finishMessage = candidate.finishMessage?.trim();
240
+ terminalGenerationError = Object.assign(/* @__PURE__ */ new Error(`Google generation stopped (${candidate.finishReason})${finishMessage ? `: ${finishMessage}` : ""}`), {
241
+ code: candidate.finishReason,
242
+ type: "google_generation_failed"
243
+ });
244
+ }
245
+ if (params.output.stopReason === "stop" && params.output.content.some((block) => block.type === "toolCall")) params.output.stopReason = "toolUse";
246
+ }
247
+ }
248
+ endCurrentBlock();
249
+ if (params.signal?.aborted) throw transportAbortError(params.signal);
250
+ if (terminalGenerationError) {
251
+ if (preserveParts) {
252
+ params.output.errorCode = terminalGenerationError.code;
253
+ params.output.errorType = terminalGenerationError.type;
254
+ }
255
+ throw terminalGenerationError;
256
+ }
257
+ if (!sawTerminalReason) {
258
+ if (preserveParts) {
259
+ params.output.errorCode = "STREAM_INCOMPLETE";
260
+ params.output.errorType = "google_incomplete_stream";
261
+ }
262
+ throw Object.assign(/* @__PURE__ */ new Error("Google stream ended before a terminal finish reason"), {
263
+ code: "STREAM_INCOMPLETE",
264
+ type: "google_incomplete_stream"
265
+ });
266
+ }
267
+ if (params.output.stopReason === "aborted" || params.output.stopReason === "error") throw new Error("An unknown error occurred");
268
+ params.stream.push({
269
+ type: "done",
270
+ reason: params.output.stopReason,
271
+ message: params.output
272
+ });
273
+ params.stream.end();
274
+ }
275
+ //#endregion
276
+ //#region packages/ai/src/providers/google-messages.ts
277
+ const GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP = "skip_thought_signature_validator";
278
+ function resolveThoughtSignature(value) {
279
+ return value && value.length % 4 === 0 && /^[A-Za-z0-9+/]+={0,2}$/.test(value) ? value : void 0;
280
+ }
281
+ function stableStringifyGoogleToolCallValue(value) {
282
+ if (Array.isArray(value)) return `[${value.map((item) => stableStringifyGoogleToolCallValue(item)).join(",")}]`;
283
+ if (value && typeof value === "object") return `{${Object.keys(value).toSorted().map((key) => `${JSON.stringify(key)}:${stableStringifyGoogleToolCallValue(Reflect.get(value, key))}`).join(",")}}`;
284
+ return JSON.stringify(value);
285
+ }
286
+ function sanitizeGeminiThoughtSignature(value) {
287
+ if (typeof value !== "string") return;
288
+ const trimmed = value.trim();
289
+ return trimmed && /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(trimmed) ? trimmed : void 0;
290
+ }
291
+ function toolCallThoughtSignatureReplayKey(id, name, args) {
292
+ return [
293
+ id,
294
+ name,
295
+ stableStringifyGoogleToolCallValue(args)
296
+ ].join("\0");
297
+ }
298
+ function requiresGoogleToolCallId(modelId) {
299
+ return modelId.startsWith("claude-") || modelId.startsWith("gpt-oss-");
300
+ }
301
+ function getGeminiMajorVersion(modelId) {
302
+ const match = modelId.toLowerCase().match(/(?:^|\/)gemini(?:-live)?-(\d+)/);
303
+ if (!match) return;
304
+ const majorVersion = match.at(1);
305
+ return majorVersion === void 0 ? void 0 : Number.parseInt(majorVersion, 10);
306
+ }
307
+ function supportsMultimodalFunctionResponse(modelId) {
308
+ const geminiMajorVersion = getGeminiMajorVersion(modelId);
309
+ if (geminiMajorVersion !== void 0) return geminiMajorVersion >= 3;
310
+ return true;
311
+ }
312
+ /** Project a prepared transcript; route repair and trusted video admission remain caller-owned. */
313
+ function projectGoogleMessages(params) {
314
+ const { model, messages: transformedMessages } = params;
315
+ const managed = params.replay === "managed";
316
+ const sanitizeText = managed ? sanitizeTransportPayloadText : sanitizeSurrogates;
317
+ const signature = managed ? sanitizeGeminiThoughtSignature : resolveThoughtSignature;
318
+ const replaySignatures = /* @__PURE__ */ new Map();
319
+ const contents = [];
320
+ const pendingToolResultImageTurns = [];
321
+ const sameRouteToolCallIds = /* @__PURE__ */ new Set();
322
+ let activeToolResultParts;
323
+ const flushToolResultRun = () => {
324
+ contents.push(...pendingToolResultImageTurns);
325
+ pendingToolResultImageTurns.length = 0;
326
+ activeToolResultParts = void 0;
327
+ };
328
+ for (const msg of transformedMessages) {
329
+ if (msg.role !== "toolResult") flushToolResultRun();
330
+ if (msg.role === "user") {
331
+ if (typeof msg.content === "string") contents.push({
332
+ role: "user",
333
+ parts: [{ text: sanitizeText(msg.content) || " " }]
334
+ });
335
+ else {
336
+ const parts = msg.content.map((item) => {
337
+ if (item.type === "text") return { text: sanitizeText(item.text) || " " };
338
+ if (managed && item.type === "video") return params.videoPart?.(item) ?? { text: "(video omitted: native video slot unavailable)" };
339
+ return { inlineData: {
340
+ mimeType: item.mimeType,
341
+ data: item.data
342
+ } };
343
+ });
344
+ const visibleParts = managed && !model.input.includes("image") ? parts.filter((part) => !part.inlineData) : parts;
345
+ if (visibleParts.length === 0) visibleParts.push({ text: " " });
346
+ contents.push({
347
+ role: "user",
348
+ parts: visibleParts
349
+ });
350
+ }
351
+ } else if (msg.role === "assistant") {
352
+ const parts = [];
353
+ let sawFunctionCall = false;
354
+ const nextReplaySignatures = /* @__PURE__ */ new Map();
355
+ const isSameProviderAndModel = msg.provider === model.provider && msg.api === model.api && msg.model === model.id;
356
+ for (const block of msg.content) if (block.type === "text") {
357
+ const thoughtSignature = isSameProviderAndModel ? signature(block.textSignature) : void 0;
358
+ if ((!block.text || block.text.trim() === "") && (managed || !thoughtSignature)) continue;
359
+ parts.push({
360
+ text: sanitizeText(block.text),
361
+ ...thoughtSignature && { thoughtSignature }
362
+ });
363
+ } else if (block.type === "thinking") {
364
+ const thoughtSignature = isSameProviderAndModel ? signature(block.thinkingSignature) : void 0;
365
+ if ((!block.thinking || block.thinking.trim() === "") && (managed || !thoughtSignature)) continue;
366
+ if (isSameProviderAndModel) parts.push({
367
+ thought: true,
368
+ text: sanitizeText(block.thinking),
369
+ ...thoughtSignature && { thoughtSignature }
370
+ });
371
+ else parts.push({ text: sanitizeText(block.thinking) });
372
+ } else if (block.type === "toolCall") {
373
+ if (isSameProviderAndModel && (managed || model.provider !== "google-gemini-cli")) sameRouteToolCallIds.add(block.id);
374
+ const args = coerceTransportToolCallArguments(block.arguments);
375
+ const ownSignature = isSameProviderAndModel ? signature(block.thoughtSignature) : void 0;
376
+ const replayKey = managed && (ownSignature || params.requiresToolCallSignature && isSameProviderAndModel && replaySignatures.size > 0) ? toolCallThoughtSignatureReplayKey(block.id, block.name, args) : "";
377
+ if (managed && ownSignature) nextReplaySignatures.set(replayKey, ownSignature);
378
+ const thoughtSignature = ownSignature ?? (managed && params.requiresToolCallSignature && isSameProviderAndModel ? replaySignatures.get(replayKey) : void 0) ?? (params.requiresToolCallSignature && (managed || !sawFunctionCall) ? GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP : void 0);
379
+ sawFunctionCall = true;
380
+ const part = {
381
+ functionCall: {
382
+ name: block.name,
383
+ args,
384
+ ...(managed ? isSameProviderAndModel : sameRouteToolCallIds.has(block.id)) || requiresGoogleToolCallId(model.id) ? { id: block.id } : {}
385
+ },
386
+ ...thoughtSignature && { thoughtSignature }
387
+ };
388
+ parts.push(part);
389
+ }
390
+ for (const [key, value] of nextReplaySignatures) replaySignatures.set(key, value);
391
+ if (parts.length === 0) continue;
392
+ contents.push({
393
+ role: "model",
394
+ parts
395
+ });
396
+ } else if (msg.role === "toolResult") {
397
+ const textResult = extractToolResultText(msg.content);
398
+ const imageContent = model.input.includes("image") ? msg.content.filter((item) => managed ? item.type === "image" && describeToolResultMediaPlaceholder([item]) !== void 0 : isImageWithMediaPayload(item)) : [];
399
+ const hasText = textResult.length > 0;
400
+ const hasImages = imageContent.length > 0;
401
+ const mediaPlaceholder = describeToolResultMediaPlaceholder(msg.content);
402
+ const modelSupportsMultimodalFunctionResponse = supportsMultimodalFunctionResponse(model.id);
403
+ const responseValue = hasText ? sanitizeText(textResult) : mediaPlaceholder ?? "";
404
+ const imageParts = imageContent.map((imageBlock) => ({ inlineData: {
405
+ mimeType: imageBlock.mimeType,
406
+ data: imageBlock.data
407
+ } }));
408
+ const includeId = sameRouteToolCallIds.has(msg.toolCallId) || requiresGoogleToolCallId(model.id);
409
+ const functionResponsePart = { functionResponse: {
410
+ name: msg.toolName,
411
+ response: msg.isError ? { error: responseValue } : { output: responseValue },
412
+ ...hasImages && modelSupportsMultimodalFunctionResponse && { parts: imageParts },
413
+ ...includeId ? { id: msg.toolCallId } : {}
414
+ } };
415
+ if (activeToolResultParts) activeToolResultParts.push(functionResponsePart);
416
+ else {
417
+ activeToolResultParts = [functionResponsePart];
418
+ contents.push({
419
+ role: "user",
420
+ parts: activeToolResultParts
421
+ });
422
+ }
423
+ if (hasImages && !modelSupportsMultimodalFunctionResponse) pendingToolResultImageTurns.push({
424
+ role: "user",
425
+ parts: [{ text: "Tool result image:" }, ...imageParts]
426
+ });
427
+ }
428
+ }
429
+ flushToolResultRun();
430
+ if (contents.length === 0) contents.push({
431
+ role: "user",
432
+ parts: [{ text: " " }]
433
+ });
434
+ return contents;
435
+ }
436
+ /**
437
+ * Convert tools to Gemini function declarations format.
438
+ * @internal Directly tested provider implementation detail.
439
+ */
440
+ function convertGoogleTools(tools) {
441
+ if (tools.length === 0) return;
442
+ return [{ functionDeclarations: sortPromptCacheToolsByName(tools).map((tool) => ({
443
+ name: tool.name,
444
+ description: tool.description,
445
+ parametersJsonSchema: tool.parameters
446
+ })) }];
447
+ }
448
+ //#endregion
449
+ export { googleFlashSupportsMinimalThinking as a, consumeGoogleGenerateContentStream as i, projectGoogleMessages as n, requiresGoogleToolCallId as r, convertGoogleTools as t };
@@ -0,0 +1,185 @@
1
+ import { i as clampThinkingLevel, t as sanitizeSurrogates } from "./sanitize-unicode-Bb-v9meu.mjs";
2
+ import { d as stripSystemPromptCacheBoundary } from "./simple-options-tcKOqnpF.mjs";
3
+ import { _ as transportAbortError, p as notifyProviderStreamOpened, t as assignTransportErrorDetails } from "./transport-stream-shared-Cu3ZPhNW.mjs";
4
+ import { a as googleFlashSupportsMinimalThinking, i as consumeGoogleGenerateContentStream, n as projectGoogleMessages, r as requiresGoogleToolCallId, t as convertGoogleTools } from "./google-messages-CVn9eFpF.mjs";
5
+ import { t as transformProviderMessages } from "./provider-transcript-transform-pPmUIwKt.mjs";
6
+ import { FunctionCallingConfigMode, ThinkingLevel } from "@google/genai";
7
+ //#region packages/ai/src/providers/google-shared.ts
8
+ /**
9
+ * Shared utilities for Google Generative AI and Google Vertex providers.
10
+ */
11
+ function convertMessages(model, context) {
12
+ return projectGoogleMessages({
13
+ model,
14
+ messages: transformProviderMessages(context.messages, model, (id) => requiresGoogleToolCallId(model.id) ? id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64) : id),
15
+ replay: "signed-parts",
16
+ requiresToolCallSignature: model.provider !== "google-gemini-cli" && (isGemini3ProModel(model) || isGemini3FlashModel(model))
17
+ });
18
+ }
19
+ /**
20
+ * Map tool choice string to Gemini FunctionCallingConfigMode.
21
+ * @internal Directly tested provider implementation detail.
22
+ */
23
+ function mapToolChoice(choice) {
24
+ switch (choice) {
25
+ case "auto": return FunctionCallingConfigMode.AUTO;
26
+ case "none": return FunctionCallingConfigMode.NONE;
27
+ case "any": return FunctionCallingConfigMode.ANY;
28
+ default: return FunctionCallingConfigMode.AUTO;
29
+ }
30
+ }
31
+ async function runGoogleGenerateContentLifecycle(params) {
32
+ const { stream, model, output, options } = params;
33
+ try {
34
+ const client = params.createClient();
35
+ let requestParams = params.buildParams();
36
+ const nextParams = await options?.onPayload?.(requestParams, model);
37
+ if (nextParams !== void 0) requestParams = nextParams;
38
+ const googleIterator = (await client.models.generateContentStream(requestParams))[Symbol.asyncIterator]();
39
+ await notifyProviderStreamOpened({
40
+ options,
41
+ cancelStream: async () => {
42
+ await googleIterator.return?.();
43
+ }
44
+ });
45
+ await consumeGoogleGenerateContentStream({
46
+ chunks: { [Symbol.asyncIterator]: () => googleIterator },
47
+ model,
48
+ output,
49
+ stream,
50
+ signal: options?.signal,
51
+ nextToolCallId: params.nextToolCallId
52
+ });
53
+ } catch (error) {
54
+ for (const block of output.content) if ("index" in block) delete block.index;
55
+ const failure = options?.signal?.aborted ? transportAbortError(options.signal) : error;
56
+ assignTransportErrorDetails(output, failure, options?.signal);
57
+ stream.push({
58
+ type: "error",
59
+ reason: output.stopReason === "aborted" ? "aborted" : "error",
60
+ error: output
61
+ });
62
+ stream.end();
63
+ }
64
+ }
65
+ function buildGoogleGenerateContentParams(model, context, options = {}) {
66
+ const contents = convertMessages(model, context);
67
+ const generationConfig = {};
68
+ if (options.temperature !== void 0) generationConfig.temperature = options.temperature;
69
+ if (options.maxTokens !== void 0) generationConfig.maxOutputTokens = options.maxTokens;
70
+ if (options.stop !== void 0 && options.stop.length > 0) generationConfig.stopSequences = options.stop;
71
+ const config = {
72
+ ...Object.keys(generationConfig).length > 0 && generationConfig,
73
+ ...context.systemPrompt && { systemInstruction: sanitizeSurrogates(stripSystemPromptCacheBoundary(context.systemPrompt)) },
74
+ ...context.tools && context.tools.length > 0 && { tools: convertGoogleTools(context.tools) }
75
+ };
76
+ if (context.tools && context.tools.length > 0 && options.toolChoice) config.toolConfig = { functionCallingConfig: { mode: mapToolChoice(options.toolChoice) } };
77
+ else config.toolConfig = void 0;
78
+ if (options.thinking?.enabled && model.reasoning) {
79
+ const thinkingConfig = { includeThoughts: true };
80
+ if (options.thinking.level !== void 0) thinkingConfig.thinkingLevel = ThinkingLevel[options.thinking.level];
81
+ else if (options.thinking.budgetTokens !== void 0) thinkingConfig.thinkingBudget = options.thinking.budgetTokens;
82
+ config.thinkingConfig = thinkingConfig;
83
+ } else if (model.reasoning && options.thinking && !options.thinking.enabled) {
84
+ const disabledThinkingConfig = getDisabledGoogleThinkingConfig(model);
85
+ if (Object.keys(disabledThinkingConfig).length > 0) config.thinkingConfig = disabledThinkingConfig;
86
+ }
87
+ if (options.signal) {
88
+ if (options.signal.aborted) throw new Error("Request aborted");
89
+ config.abortSignal = options.signal;
90
+ }
91
+ return {
92
+ model: model.id,
93
+ contents,
94
+ config
95
+ };
96
+ }
97
+ function isAdaptiveGoogleReasoningLevel(value) {
98
+ return value === "adaptive";
99
+ }
100
+ function buildGoogleSimpleThinking(model, options, config) {
101
+ if (!options?.reasoning || options.reasoning === "off") return { enabled: false };
102
+ if (isAdaptiveGoogleReasoningLevel(options.reasoning)) {
103
+ if (!model.reasoning) return { enabled: false };
104
+ if (isGemma4Model(model)) return {
105
+ enabled: true,
106
+ level: ThinkingLevel.HIGH
107
+ };
108
+ return isGemini3ProModel(model) || isGemini3FlashModel(model) ? { enabled: true } : {
109
+ enabled: true,
110
+ budgetTokens: -1
111
+ };
112
+ }
113
+ const clampedReasoning = clampThinkingLevel(model, options.reasoning);
114
+ if (clampedReasoning === "off") return { enabled: false };
115
+ const effort = clampedReasoning === "max" ? "high" : clampedReasoning;
116
+ if (isGemini3ProModel(model) || isGemini3FlashModel(model) || config?.includeGemma4ThinkingLevel && isGemma4Model(model)) return {
117
+ enabled: true,
118
+ level: getGoogleThinkingLevel(effort, model, { includeGemma4: config?.includeGemma4ThinkingLevel })
119
+ };
120
+ return {
121
+ enabled: true,
122
+ budgetTokens: getGoogleBudget(model, effort, options.thinkingBudgets, { useFlashLiteBudgets: config?.useFlashLiteBudgets })
123
+ };
124
+ }
125
+ function getDisabledGoogleThinkingConfig(model) {
126
+ if (isGemini3ProModel(model)) return { thinkingLevel: ThinkingLevel.LOW };
127
+ if (isGemini3FlashModel(model)) return { thinkingLevel: googleFlashSupportsMinimalThinking(model.id) ? ThinkingLevel.MINIMAL : ThinkingLevel.LOW };
128
+ if (isGemma4Model(model) || model.id.toLowerCase().includes("gemini-2.5-pro")) return {};
129
+ return { thinkingBudget: 0 };
130
+ }
131
+ /** @internal Directly tested provider implementation detail. */
132
+ function isGemma4Model(model) {
133
+ return /gemma-?4/.test(model.id.toLowerCase());
134
+ }
135
+ function isGemini3ProModel(model) {
136
+ return /gemini-(?:3(?:\.\d+)?-pro|pro-latest)/.test(model.id.toLowerCase());
137
+ }
138
+ function isGemini3FlashModel(model) {
139
+ return /gemini-(?:3(?:\.\d+)?-flash|flash(?:-lite)?-latest)/.test(model.id.toLowerCase());
140
+ }
141
+ function getGoogleThinkingLevel(effort, model, config) {
142
+ if (isGemini3ProModel(model)) switch (effort) {
143
+ case "minimal":
144
+ case "low": return ThinkingLevel.LOW;
145
+ case "medium":
146
+ case "high": return ThinkingLevel.HIGH;
147
+ }
148
+ if (config?.includeGemma4 && isGemma4Model(model)) switch (effort) {
149
+ case "minimal":
150
+ case "low": return ThinkingLevel.MINIMAL;
151
+ case "medium":
152
+ case "high": return ThinkingLevel.HIGH;
153
+ }
154
+ switch (effort) {
155
+ case "minimal": return isGemini3FlashModel(model) && !googleFlashSupportsMinimalThinking(model.id) ? ThinkingLevel.LOW : ThinkingLevel.MINIMAL;
156
+ case "low": return ThinkingLevel.LOW;
157
+ case "medium": return ThinkingLevel.MEDIUM;
158
+ case "high": return ThinkingLevel.HIGH;
159
+ }
160
+ return ThinkingLevel.HIGH;
161
+ }
162
+ function getGoogleBudget(model, effort, customBudgets, config) {
163
+ if (customBudgets?.[effort] !== void 0) return customBudgets[effort];
164
+ if (model.id.includes("2.5-pro")) return {
165
+ minimal: 128,
166
+ low: 2048,
167
+ medium: 8192,
168
+ high: 32768
169
+ }[effort];
170
+ if (config?.useFlashLiteBudgets && model.id.includes("2.5-flash-lite")) return {
171
+ minimal: 512,
172
+ low: 2048,
173
+ medium: 8192,
174
+ high: 24576
175
+ }[effort];
176
+ if (model.id.includes("2.5-flash")) return {
177
+ minimal: 128,
178
+ low: 2048,
179
+ medium: 8192,
180
+ high: 24576
181
+ }[effort];
182
+ return -1;
183
+ }
184
+ //#endregion
185
+ export { buildGoogleSimpleThinking as n, runGoogleGenerateContentLifecycle as r, buildGoogleGenerateContentParams as t };
@@ -1,8 +1,9 @@
1
- import { t as AssistantMessageEventStream } from "./event-stream-uSMZJ3FA.mjs";
2
- import { d as normalizeOptionalString } from "./utf16-slice-qz3nsy87.mjs";
3
- import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-BIaiBURL.mjs";
4
- import { n as buildBaseOptions } from "./simple-options-0PLDyJ-d.mjs";
5
- import { i as runGoogleGenerateContentLifecycle, n as buildGoogleSimpleThinking, r as createGoogleAssistantOutput, t as buildGoogleGenerateContentParams } from "./google-shared-CjPY0hZM.mjs";
1
+ import { t as AssistantMessageEventStream } from "./event-stream-D8PARQfL.mjs";
2
+ import { a as normalizeOptionalString } from "./string-coerce-fsri9iCu.mjs";
3
+ import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-CWuF-sS3.mjs";
4
+ import { n as buildBaseOptions } from "./simple-options-tcKOqnpF.mjs";
5
+ import { t as createAssistantOutput } from "./assistant-output-iqnlJCV2.mjs";
6
+ import { n as buildGoogleSimpleThinking, r as runGoogleGenerateContentLifecycle, t as buildGoogleGenerateContentParams } from "./google-shared-BedY23XS.mjs";
6
7
  import { GoogleGenAI, ResourceScope } from "@google/genai";
7
8
  //#region packages/ai/src/providers/google-vertex.ts
8
9
  const API_VERSION = "v1";
@@ -10,7 +11,7 @@ const GCP_VERTEX_CREDENTIALS_MARKER = "gcp-vertex-credentials";
10
11
  let toolCallCounter = 0;
11
12
  const streamGoogleVertex = (model, context, options) => {
12
13
  const stream = new AssistantMessageEventStream();
13
- const output = createGoogleAssistantOutput(model, "google-vertex");
14
+ const output = createAssistantOutput(model, "google-vertex");
14
15
  runGoogleGenerateContentLifecycle({
15
16
  stream,
16
17
  model,