@openclaw/ai 2026.7.2-beta.5 → 2026.7.2-beta.7

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 (47) hide show
  1. package/dist/{anthropic-CQVj3le6.mjs → anthropic-CH4UUnZr.mjs} +14 -463
  2. package/dist/anthropic-usage-DWU-x8MI.mjs +459 -0
  3. package/dist/{azure-openai-responses-DIYgsqFM.mjs → azure-openai-responses-CImcwB83.mjs} +4 -3
  4. package/dist/azure-openai-responses-client-compat-C7K7QfUE.mjs +62 -0
  5. package/dist/cache-retention-0x979a5V.mjs +12 -0
  6. package/dist/deferred-event-buffer-DAvyP7qA.mjs +19 -0
  7. package/dist/github-copilot-headers-NCJtz9i0.mjs +37 -0
  8. package/dist/{google-f-A8xrae.mjs → google-CtSg0iTS.mjs} +3 -3
  9. package/dist/{google-shared-J6qvYINH.mjs → google-shared-DNBz5rcD.mjs} +5 -3
  10. package/dist/{google-vertex-D3yMVXIY.mjs → google-vertex-31f1uS9L.mjs} +3 -3
  11. package/dist/host-Dog2WQiR.mjs +369 -0
  12. package/dist/index.mjs +1 -1
  13. package/dist/internal/anthropic.d.mts +3 -53
  14. package/dist/internal/anthropic.mjs +3 -2
  15. package/dist/internal/openai.d.mts +259 -2
  16. package/dist/internal/openai.mjs +8 -4
  17. package/dist/internal/runtime.mjs +6 -4
  18. package/dist/internal/shared.d.mts +1 -1
  19. package/dist/internal/shared.mjs +5 -1
  20. package/dist/{llm-request-activity-CehVkZP-.mjs → llm-request-activity-BjtkplhG.mjs} +1 -19
  21. package/dist/{mistral-CKV-TOQj.mjs → mistral-CWmpvWYh.mjs} +5 -3
  22. package/dist/{openai-chatgpt-responses-CedIj0hk.mjs → openai-chatgpt-responses-B84Ibtrd.mjs} +18 -13
  23. package/dist/openai-completions-DsOxhOD1.mjs +630 -0
  24. package/dist/openai-completions-compat-DBWjXoMZ.d.mts +43 -0
  25. package/dist/openai-reasoning-compat-YgeLncHw.mjs +396 -0
  26. package/dist/openai-responses-BT7A3sLu.mjs +138 -0
  27. package/dist/openai-responses-shared-pXl6Wd8S.mjs +392 -0
  28. package/dist/{openai-D3PD6PE-.mjs → openai-responses-stream-internal-Cw5txaGW.mjs} +1409 -1863
  29. package/dist/openai-tool-projection-OhX64DoP.mjs +215 -0
  30. package/dist/{provider-error-apVOZI6G.mjs → provider-error-CAEvRjry.mjs} +1 -1
  31. package/dist/provider-options-D8bB3z9b.d.mts +144 -0
  32. package/dist/providers.mjs +8 -8
  33. package/dist/{stream-first-event-timeout-C3OgBjIk.mjs → reasoning-tag-text-partitioner-CGDyLWUR.mjs} +1 -86
  34. package/dist/simple-options-9lhRrN73.mjs +50 -0
  35. package/dist/stream-first-event-timeout-BBys9hSb.mjs +86 -0
  36. package/dist/tls-certificate-errors-DXSpluKI.mjs +93 -0
  37. package/dist/tool-result-text-CTpIRbYd.mjs +225 -0
  38. package/dist/{github-copilot-headers-BCoBNmL7.mjs → tool-schema-json-projection-BwNu3nDi.mjs} +1 -48
  39. package/dist/transform-messages-C8mBqZxF.mjs +2 -0
  40. package/dist/{transport-stream-shared-BbMELSI4.mjs → transport-stream-shared-D81p90xq.mjs} +4 -4
  41. package/dist/transports.d.mts +13 -33
  42. package/dist/transports.mjs +75 -34
  43. package/package.json +4 -4
  44. package/dist/host-XYGZcgO8.mjs +0 -98
  45. package/dist/openai-BPor_3WI.d.mts +0 -358
  46. package/dist/openai-completions-CiSutyu0.mjs +0 -1223
  47. package/dist/shared-CdjNZd35.mjs +0 -634
@@ -0,0 +1,459 @@
1
+ import { o as resolveClaudeFable5ModelIdentity, s as resolveClaudeModelIdentity, u as resolveClaudeOpus5ModelIdentity } from "./src-QkygScBs.mjs";
2
+ import { g as isRecord, n as getAiTransportHost } from "./host-Dog2WQiR.mjs";
3
+ import { m as sortPromptCacheToolsByName } from "./tool-result-text-CTpIRbYd.mjs";
4
+ import { t as projectRuntimeToolInputSchema } from "./tool-schema-json-projection-BwNu3nDi.mjs";
5
+ //#region packages/media-core/src/base64.ts
6
+ /** Estimates decoded bytes without allocating a cleaned copy of the base64 payload. */
7
+ function estimateBase64DecodedBytes(base64) {
8
+ let effectiveLen = 0;
9
+ for (let i = 0; i < base64.length; i += 1) {
10
+ if (base64.charCodeAt(i) <= 32) continue;
11
+ effectiveLen += 1;
12
+ }
13
+ if (effectiveLen === 0) return 0;
14
+ let padding = 0;
15
+ let end = base64.length - 1;
16
+ while (end >= 0 && base64.charCodeAt(end) <= 32) end -= 1;
17
+ if (end >= 0 && base64[end] === "=") {
18
+ padding = 1;
19
+ end -= 1;
20
+ while (end >= 0 && base64.charCodeAt(end) <= 32) end -= 1;
21
+ if (end >= 0 && base64[end] === "=") padding = 2;
22
+ }
23
+ const estimated = Math.floor(effectiveLen * 3 / 4) - padding;
24
+ return Math.max(0, estimated);
25
+ }
26
+ const CANONICALIZE_BASE64_CHUNK_SIZE = 8192;
27
+ function isBase64DataChar(code) {
28
+ return code >= 65 && code <= 90 || code >= 97 && code <= 122 || code >= 48 && code <= 57 || code === 43 || code === 47;
29
+ }
30
+ function base64DataValue(code) {
31
+ if (code >= 65 && code <= 90) return code - 65;
32
+ if (code >= 97 && code <= 122) return code - 97 + 26;
33
+ if (code >= 48 && code <= 57) return code - 48 + 52;
34
+ return code === 43 ? 62 : 63;
35
+ }
36
+ /**
37
+ * Normalizes and validates a base64 string, returning canonical no-whitespace
38
+ * base64 only when the input has valid alphabet, padding, and length.
39
+ */
40
+ function canonicalizeBase64(base64) {
41
+ const chunks = [];
42
+ let current = "";
43
+ let cleanedLength = 0;
44
+ let padding = 0;
45
+ let sawPadding = false;
46
+ let lastDataCode = 0;
47
+ const append = (char) => {
48
+ current += char;
49
+ cleanedLength += 1;
50
+ if (current.length >= CANONICALIZE_BASE64_CHUNK_SIZE) {
51
+ chunks.push(current);
52
+ current = "";
53
+ }
54
+ };
55
+ for (let i = 0; i < base64.length; i += 1) {
56
+ const code = base64.charCodeAt(i);
57
+ if (code <= 32) continue;
58
+ if (code === 61) {
59
+ padding += 1;
60
+ if (padding > 2) return;
61
+ sawPadding = true;
62
+ append("=");
63
+ continue;
64
+ }
65
+ if (sawPadding || !isBase64DataChar(code)) return;
66
+ lastDataCode = code;
67
+ append(base64[i] ?? "");
68
+ }
69
+ if (cleanedLength === 0) return;
70
+ const remainder = cleanedLength % 4;
71
+ if (remainder !== 0) {
72
+ if (sawPadding || remainder === 1) return;
73
+ current += "=".repeat(4 - remainder);
74
+ }
75
+ const effectivePadding = remainder === 0 ? padding : 4 - remainder;
76
+ const padBitMask = effectivePadding === 2 ? 15 : effectivePadding === 1 ? 3 : 0;
77
+ if (padBitMask !== 0 && (base64DataValue(lastDataCode) & padBitMask) !== 0) return;
78
+ if (current) chunks.push(current);
79
+ return chunks.join("");
80
+ }
81
+ //#endregion
82
+ //#region packages/ai/src/internal/anthropic-inline-images.ts
83
+ const ANTHROPIC_IMAGE_MEDIA_TYPE_SET = /* @__PURE__ */ new Set([
84
+ "image/jpeg",
85
+ "image/png",
86
+ "image/gif",
87
+ "image/webp"
88
+ ]);
89
+ const ANTHROPIC_INLINE_IMAGES_DECODE_SAFETY_BYTES = 64 * 1024 * 1024;
90
+ function createAnthropicInlineImageBudget() {
91
+ return { totalBytes: 0 };
92
+ }
93
+ function resolveAnthropicImageMediaType(value) {
94
+ if (ANTHROPIC_IMAGE_MEDIA_TYPE_SET.has(value)) return value;
95
+ throw new Error(`Unsupported Anthropic image media type after normalization: ${value}`);
96
+ }
97
+ async function normalizeAnthropicInlineContent(content, budget) {
98
+ if (!content.some((block) => block.type === "image")) return content.filter((block) => block.type === "text");
99
+ const inputBytes = content.reduce((total, block) => block.type === "image" ? total + estimateBase64DecodedBytes(block.data) : total, 0);
100
+ if (budget.totalBytes + inputBytes > ANTHROPIC_INLINE_IMAGES_DECODE_SAFETY_BYTES) throw new Error("Anthropic inline images exceed the 64 MB aggregate decoded safety limit.");
101
+ const normalized = [];
102
+ for (const block of content) {
103
+ if (block.type !== "image") {
104
+ normalized.push(block);
105
+ continue;
106
+ }
107
+ const normalizedBlocks = await getAiTransportHost().normalizeAnthropicInlineContentBlocks([block]);
108
+ const outputBytes = normalizedBlocks.reduce((total, normalizedBlock) => normalizedBlock.type === "image" ? total + estimateBase64DecodedBytes(normalizedBlock.data) : total, 0);
109
+ if (budget.totalBytes + outputBytes > ANTHROPIC_INLINE_IMAGES_DECODE_SAFETY_BYTES) throw new Error("Anthropic inline images exceed the 64 MB aggregate decoded safety limit.");
110
+ budget.totalBytes += outputBytes;
111
+ normalized.push(...normalizedBlocks);
112
+ }
113
+ return normalized;
114
+ }
115
+ //#endregion
116
+ //#region packages/ai/src/providers/anthropic-auth-headers.ts
117
+ function usesFoundryBearerAuth(model) {
118
+ return model.provider === "microsoft-foundry" && (model.authHeader === true || hasBearerAuthorizationHeader(model.headers));
119
+ }
120
+ function hasBearerAuthorizationHeader(headers) {
121
+ if (!headers) return false;
122
+ return Object.entries(headers).some(([key, value]) => key.toLowerCase() === "authorization" && /^bearer\s+\S+/i.test(value.trim()));
123
+ }
124
+ function omitFoundryBearerCredentialHeaders(headers) {
125
+ if (!headers) return;
126
+ const next = {};
127
+ for (const [key, value] of Object.entries(headers)) {
128
+ const lower = key.toLowerCase();
129
+ if (lower === "authorization" || lower === "x-api-key" || lower === "api-key") continue;
130
+ next[key] = value;
131
+ }
132
+ return Object.keys(next).length > 0 ? next : void 0;
133
+ }
134
+ //#endregion
135
+ //#region packages/ai/src/providers/anthropic-refusal.ts
136
+ function readNullableString(value) {
137
+ return typeof value === "string" && value.trim() ? value.trim() : null;
138
+ }
139
+ function readAnthropicRefusalDetails(value) {
140
+ if (!value || typeof value !== "object") return {
141
+ category: null,
142
+ explanation: null
143
+ };
144
+ const details = value;
145
+ return {
146
+ category: readNullableString(details.category),
147
+ explanation: readNullableString(details.explanation)
148
+ };
149
+ }
150
+ function formatAnthropicRefusalMessage(details) {
151
+ return `Anthropic refusal${details.category ? ` (category: ${details.category})` : ""}${details.explanation ? `: ${details.explanation}` : "."}`;
152
+ }
153
+ function applyAnthropicRefusal(output, stopDetails, provider) {
154
+ const details = readAnthropicRefusalDetails(stopDetails);
155
+ output.stopReason = "error";
156
+ output.errorMessage = formatAnthropicRefusalMessage(details);
157
+ output.diagnostics = [...output.diagnostics ?? [], {
158
+ type: "provider_refusal",
159
+ timestamp: Date.now(),
160
+ details: {
161
+ provider,
162
+ category: details.category,
163
+ explanation: details.explanation
164
+ }
165
+ }];
166
+ }
167
+ //#endregion
168
+ //#region packages/ai/src/providers/anthropic-server-fallback.ts
169
+ /** Anthropic beta that re-serves safety refusals on an allowed fallback model. */
170
+ const ANTHROPIC_SERVER_SIDE_FALLBACK_BETA = "server-side-fallback-2026-07-01";
171
+ /** Let Anthropic select the recommended model for each refusal category. */
172
+ const ANTHROPIC_SERVER_SIDE_FALLBACKS = "default";
173
+ const CLAUDE_OPUS_FALLBACK_MODEL_COST = {
174
+ input: 5,
175
+ output: 25,
176
+ cacheRead: .5,
177
+ cacheWrite: 6.25
178
+ };
179
+ function resolveFallbackModelIdentity(modelId) {
180
+ if (!modelId?.trim()) return null;
181
+ const ref = { id: modelId };
182
+ const normalized = resolveClaudeModelIdentity(ref);
183
+ if (normalized === "opus" || normalized === "opus-5" || resolveClaudeOpus5ModelIdentity(ref)) return "claude-opus-5";
184
+ if (resolveClaudeFable5ModelIdentity(ref)) return "claude-fable-5";
185
+ if (/^claude-opus-4-8(?=$|[^a-z0-9])/.test(normalized)) return "claude-opus-4-8";
186
+ return normalized || null;
187
+ }
188
+ function isClaudeOpusFallbackModel(modelId) {
189
+ return modelId === "claude-opus-5" || modelId === "claude-opus-4-8";
190
+ }
191
+ /** Resolve billed rates from the serving model reported by Anthropic's fallback stream. */
192
+ function resolveAnthropicFallbackServingModelCost(params) {
193
+ const requestedModelId = resolveFallbackModelIdentity(params.requestedModelId);
194
+ const servingModelId = resolveFallbackModelIdentity(params.servingModelId);
195
+ if (!servingModelId || servingModelId === requestedModelId || !isClaudeOpusFallbackModel(servingModelId)) return params.requestedCost;
196
+ if (requestedModelId && isClaudeOpusFallbackModel(requestedModelId)) return params.requestedCost;
197
+ return CLAUDE_OPUS_FALLBACK_MODEL_COST;
198
+ }
199
+ function readBoundaryModel(value) {
200
+ if (!value || typeof value !== "object") return null;
201
+ const model = value.model;
202
+ return typeof model === "string" && model.trim() ? model : null;
203
+ }
204
+ /** Reads a `fallback` content block marking where one model's output gives way to the next. */
205
+ function readAnthropicFallbackBoundary(block) {
206
+ if (!block || typeof block !== "object") return null;
207
+ const record = block;
208
+ if (record.type !== "fallback") return null;
209
+ return {
210
+ fromModel: readBoundaryModel(record.from),
211
+ toModel: readBoundaryModel(record.to)
212
+ };
213
+ }
214
+ /**
215
+ * Drops pre-fallback thinking/tool calls while preserving the text prefix that
216
+ * the serving model continued. Dropped tool calls must never execute or replay.
217
+ */
218
+ function applyAnthropicFallbackBoundary(params) {
219
+ const { output, boundary } = params;
220
+ const survivors = output.content.filter((block) => block.type === "text");
221
+ for (const survivor of survivors) delete survivor.textSignature;
222
+ output.content.splice(0, output.content.length, ...survivors);
223
+ if (boundary.toModel) output.responseModel = boundary.toModel;
224
+ output.diagnostics = [...output.diagnostics ?? [], {
225
+ type: "provider_fallback",
226
+ timestamp: Date.now(),
227
+ details: {
228
+ provider: params.provider,
229
+ fromModel: boundary.fromModel,
230
+ toModel: boundary.toModel
231
+ }
232
+ }];
233
+ }
234
+ //#endregion
235
+ //#region packages/ai/src/providers/anthropic-thinking-replay.ts
236
+ const ANTHROPIC_OMITTED_REASONING_TEXT = "[assistant reasoning omitted]";
237
+ function asReplayMessage(value) {
238
+ return value && typeof value === "object" ? value : void 0;
239
+ }
240
+ /**
241
+ * Anthropic tool results continue the preceding assistant turn. Preserve that
242
+ * turn's signed thinking even when the next request disables new thinking.
243
+ */
244
+ function findActiveAnthropicToolTurnAssistantIndex(messages) {
245
+ const toolResultIds = /* @__PURE__ */ new Set();
246
+ let index = messages.length - 1;
247
+ while (index >= 0) {
248
+ const message = asReplayMessage(messages[index]);
249
+ if (message?.role !== "toolResult") break;
250
+ if (typeof message.toolCallId === "string") toolResultIds.add(message.toolCallId);
251
+ index -= 1;
252
+ }
253
+ if (toolResultIds.size === 0) return -1;
254
+ const assistant = asReplayMessage(messages[index]);
255
+ if (assistant?.role !== "assistant" || !Array.isArray(assistant.content)) return -1;
256
+ const toolCallIds = /* @__PURE__ */ new Set();
257
+ for (const block of assistant.content) {
258
+ if (!block || typeof block !== "object") continue;
259
+ const record = block;
260
+ if ((record.type === "toolCall" || record.type === "tool_use" || record.type === "function_call") && typeof record.id === "string") toolCallIds.add(record.id);
261
+ }
262
+ return [...toolResultIds].every((toolCallId) => toolCallIds.has(toolCallId)) ? index : -1;
263
+ }
264
+ //#endregion
265
+ //#region packages/ai/src/providers/anthropic-tool-projection.ts
266
+ function isProviderSupportedViolation(violation) {
267
+ return violation.endsWith(".$dynamicRef") || violation.endsWith(".$dynamicAnchor");
268
+ }
269
+ const schemaValueKeywords = /* @__PURE__ */ new Set([
270
+ "additionalProperties",
271
+ "contains",
272
+ "contentSchema",
273
+ "else",
274
+ "if",
275
+ "items",
276
+ "not",
277
+ "propertyNames",
278
+ "then",
279
+ "unevaluatedItems",
280
+ "unevaluatedProperties"
281
+ ]);
282
+ const schemaArrayKeywords = /* @__PURE__ */ new Set([
283
+ "allOf",
284
+ "anyOf",
285
+ "oneOf",
286
+ "prefixItems"
287
+ ]);
288
+ const schemaMapKeywords = /* @__PURE__ */ new Set([
289
+ "$defs",
290
+ "definitions",
291
+ "dependencies",
292
+ "dependentSchemas",
293
+ "patternProperties",
294
+ "properties"
295
+ ]);
296
+ function normalizeAnthropicJsonSchema(schema) {
297
+ if (!isRecord(schema)) return schema;
298
+ let changed = false;
299
+ const normalized = { ...schema };
300
+ for (const [key, value] of Object.entries(schema)) {
301
+ if (schemaValueKeywords.has(key) && !Array.isArray(value)) {
302
+ const next = normalizeAnthropicJsonSchema(value);
303
+ normalized[key] = next;
304
+ changed ||= next !== value;
305
+ continue;
306
+ }
307
+ if (schemaArrayKeywords.has(key) && Array.isArray(value)) {
308
+ const next = value.map(normalizeAnthropicJsonSchema);
309
+ normalized[key] = next;
310
+ changed ||= next.some((entry, index) => entry !== value[index]);
311
+ continue;
312
+ }
313
+ if (schemaMapKeywords.has(key) && isRecord(value)) {
314
+ const next = Object.fromEntries(Object.entries(value).map(([entryKey, entryValue]) => [entryKey, normalizeAnthropicJsonSchema(entryValue)]));
315
+ normalized[key] = next;
316
+ changed ||= Object.entries(value).some(([entryKey, entryValue]) => next[entryKey] !== entryValue);
317
+ }
318
+ }
319
+ if (Array.isArray(schema.items)) {
320
+ normalized.prefixItems = schema.items.map(normalizeAnthropicJsonSchema);
321
+ const additionalItems = schema.additionalItems;
322
+ if (typeof additionalItems === "boolean" || isRecord(additionalItems)) normalized.items = normalizeAnthropicJsonSchema(additionalItems);
323
+ else delete normalized.items;
324
+ delete normalized.additionalItems;
325
+ changed = true;
326
+ }
327
+ return changed ? normalized : schema;
328
+ }
329
+ /** Snapshots direct/custom tool descriptors before Anthropic payload construction. */
330
+ function projectAnthropicTools(tools, toWireName) {
331
+ const projectedTools = [];
332
+ const unavailableOriginalNames = /* @__PURE__ */ new Set();
333
+ for (const tool of tools) {
334
+ let projectedTool;
335
+ let originalName;
336
+ try {
337
+ const name = tool.name;
338
+ originalName = name;
339
+ if (!name) continue;
340
+ const schemaProjection = projectRuntimeToolInputSchema(tool.parameters, `${name}.parameters`);
341
+ if (!isRecord(schemaProjection.schema) || schemaProjection.violations.some((violation) => !isProviderSupportedViolation(violation))) {
342
+ unavailableOriginalNames.add(name);
343
+ continue;
344
+ }
345
+ const anthropicSchema = normalizeAnthropicJsonSchema(schemaProjection.schema);
346
+ if (!isRecord(anthropicSchema)) {
347
+ unavailableOriginalNames.add(name);
348
+ continue;
349
+ }
350
+ const properties = anthropicSchema.properties;
351
+ const required = anthropicSchema.required;
352
+ if (properties !== void 0 && properties !== null && !isRecord(properties) || required !== void 0 && required !== null && (!Array.isArray(required) || required.some((entry) => typeof entry !== "string"))) {
353
+ unavailableOriginalNames.add(name);
354
+ continue;
355
+ }
356
+ let description;
357
+ try {
358
+ description = typeof tool.description === "string" ? tool.description : void 0;
359
+ } catch {}
360
+ projectedTool = {
361
+ originalName: name,
362
+ wireName: toWireName(name),
363
+ ...description ? { description } : {},
364
+ inputSchema: {
365
+ type: "object",
366
+ properties: properties ?? {},
367
+ required: required ?? []
368
+ }
369
+ };
370
+ } catch {
371
+ if (originalName) unavailableOriginalNames.add(originalName);
372
+ continue;
373
+ }
374
+ const conflictingTool = projectedTools.find((entry) => entry.wireName === projectedTool.wireName);
375
+ if (conflictingTool && conflictingTool.originalName !== projectedTool.originalName) throw new Error(`Anthropic tool names "${conflictingTool.originalName}" and "${projectedTool.originalName}" both map to "${projectedTool.wireName}"`);
376
+ projectedTools.push(projectedTool);
377
+ }
378
+ return {
379
+ inputToolCount: tools.length,
380
+ unavailableOriginalNames,
381
+ tools: sortPromptCacheToolsByName(projectedTools)
382
+ };
383
+ }
384
+ /** Keeps forced Anthropic tool choices aligned with the projected wire names. */
385
+ function reconcileAnthropicToolChoice(choice, projection) {
386
+ if (projection.inputToolCount === 0) return choice;
387
+ if (choice.type === "tool") {
388
+ const requestedName = choice.name;
389
+ const originalMatch = projection.tools.find((tool) => tool.originalName === requestedName);
390
+ if (originalMatch) return {
391
+ ...choice,
392
+ name: originalMatch.wireName
393
+ };
394
+ if (projection.unavailableOriginalNames.has(requestedName)) throw new Error(`Anthropic tool_choice requested unavailable tool "${requestedName}" after schema conversion`);
395
+ const matchedTool = projection.tools.find((tool) => tool.wireName === requestedName);
396
+ if (!matchedTool) throw new Error(`Anthropic tool_choice requested unavailable tool "${requestedName}" after schema conversion`);
397
+ return {
398
+ ...choice,
399
+ name: matchedTool.wireName
400
+ };
401
+ }
402
+ if (projection.tools.length === 0) {
403
+ if (choice.type === "auto") return;
404
+ if (choice.type === "any") throw new Error("Anthropic tool_choice requires a tool, but no tools survived schema conversion");
405
+ }
406
+ return choice;
407
+ }
408
+ /** Maps Claude Code wire names without trusting every direct/custom descriptor. */
409
+ function resolveOriginalAnthropicToolName(name, projection) {
410
+ return projection?.tools.find((tool) => tool.wireName === name)?.originalName ?? name;
411
+ }
412
+ //#endregion
413
+ //#region packages/ai/src/providers/anthropic-usage.ts
414
+ function readAnthropicUsageTokenCount(value) {
415
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
416
+ }
417
+ function readAnthropicCacheWriteUsage(usage) {
418
+ if (!usage.cache_creation || typeof usage.cache_creation !== "object") return {};
419
+ const cacheCreation = usage.cache_creation;
420
+ const cacheWrite5m = readAnthropicUsageTokenCount(cacheCreation.ephemeral_5m_input_tokens);
421
+ const cacheWrite1h = readAnthropicUsageTokenCount(cacheCreation.ephemeral_1h_input_tokens);
422
+ return {
423
+ ...cacheWrite5m !== void 0 ? { cacheWrite5m } : {},
424
+ ...cacheWrite1h !== void 0 ? { cacheWrite1h } : {}
425
+ };
426
+ }
427
+ function readAnthropicPromptUsageSnapshot(usage) {
428
+ const input = readAnthropicUsageTokenCount(usage.input_tokens);
429
+ const cacheRead = usage.cache_read_input_tokens == null ? 0 : readAnthropicUsageTokenCount(usage.cache_read_input_tokens);
430
+ const cacheWrite = usage.cache_creation_input_tokens == null ? 0 : readAnthropicUsageTokenCount(usage.cache_creation_input_tokens);
431
+ if (input === void 0 || cacheRead === void 0 || cacheWrite === void 0) return;
432
+ return {
433
+ input,
434
+ cacheRead,
435
+ cacheWrite
436
+ };
437
+ }
438
+ function readLastAnthropicIterationUsage(usage) {
439
+ if (usage.iterations == null) return { state: "absent" };
440
+ if (!Array.isArray(usage.iterations) || usage.iterations.length === 0) return { state: "invalid" };
441
+ const iteration = usage.iterations.at(-1);
442
+ if (!iteration || typeof iteration !== "object" || Array.isArray(iteration)) return { state: "invalid" };
443
+ const record = iteration;
444
+ const input = readAnthropicUsageTokenCount(record.input_tokens);
445
+ const cacheRead = readAnthropicUsageTokenCount(record.cache_read_input_tokens);
446
+ const cacheWrite = readAnthropicUsageTokenCount(record.cache_creation_input_tokens);
447
+ const outputTokens = readAnthropicUsageTokenCount(record.output_tokens);
448
+ if (input === void 0 || cacheRead === void 0 || cacheWrite === void 0 || outputTokens === void 0) return { state: "invalid" };
449
+ const contextPromptTokens = input + cacheRead + cacheWrite;
450
+ return {
451
+ state: "valid",
452
+ usage: {
453
+ contextPromptTokens,
454
+ totalTokens: contextPromptTokens + outputTokens
455
+ }
456
+ };
457
+ }
458
+ //#endregion
459
+ export { canonicalizeBase64 as S, omitFoundryBearerCredentialHeaders as _, projectAnthropicTools as a, normalizeAnthropicInlineContent as b, ANTHROPIC_OMITTED_REASONING_TEXT as c, ANTHROPIC_SERVER_SIDE_FALLBACK_BETA as d, CLAUDE_OPUS_FALLBACK_MODEL_COST as f, applyAnthropicRefusal as g, resolveAnthropicFallbackServingModelCost as h, readLastAnthropicIterationUsage as i, findActiveAnthropicToolTurnAssistantIndex as l, readAnthropicFallbackBoundary as m, readAnthropicPromptUsageSnapshot as n, reconcileAnthropicToolChoice as o, applyAnthropicFallbackBoundary as p, readAnthropicUsageTokenCount as r, resolveOriginalAnthropicToolName as s, readAnthropicCacheWriteUsage as t, ANTHROPIC_SERVER_SIDE_FALLBACKS as u, usesFoundryBearerAuth as v, resolveAnthropicImageMediaType as x, createAnthropicInlineImageBudget as y };
@@ -1,9 +1,10 @@
1
1
  import { n as getEnvApiKey } from "./env-api-keys-DrgeBuva.mjs";
2
2
  import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
3
- import { n as getAiTransportHost } from "./host-XYGZcgO8.mjs";
3
+ import { n as getAiTransportHost } from "./host-Dog2WQiR.mjs";
4
4
  import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
5
- import { A as buildBaseOptions } from "./shared-CdjNZd35.mjs";
6
- import { a as convertResponsesMessages, c as runResponsesStreamLifecycle, i as applyCommonResponsesParams, o as createResponsesAssistantOutput, s as resolveResponsesReasoningEffort, vt as isOpenAICompatibleAzureResponsesBaseUrl, xt as resolveAzureDeploymentNameFromMap } from "./openai-D3PD6PE-.mjs";
5
+ import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
6
+ import { n as buildBaseOptions } from "./simple-options-9lhRrN73.mjs";
7
+ import { a as runResponsesStreamLifecycle, i as resolveResponsesReasoningEffort, n as convertResponsesMessages, r as createResponsesAssistantOutput, t as applyCommonResponsesParams } from "./openai-responses-shared-pXl6Wd8S.mjs";
7
8
  import OpenAI, { AzureOpenAI } from "openai";
8
9
  //#region packages/ai/src/providers/azure-openai-responses.ts
9
10
  const DEFAULT_AZURE_API_VERSION = "v1";
@@ -0,0 +1,62 @@
1
+ //#region packages/ai/src/providers/azure-deployment-map.ts
2
+ /** Parses AZURE_OPENAI_DEPLOYMENT_MAP-style model=deployment entries. */
3
+ function parseAzureDeploymentNameMap(value) {
4
+ const map = /* @__PURE__ */ new Map();
5
+ if (!value) return map;
6
+ for (const entry of value.split(",")) {
7
+ const trimmed = entry.trim();
8
+ if (!trimmed) continue;
9
+ const separator = trimmed.indexOf("=");
10
+ if (separator <= 0) continue;
11
+ const modelId = trimmed.slice(0, separator).trim();
12
+ const deploymentName = trimmed.slice(separator + 1).trim();
13
+ if (!modelId || !deploymentName) continue;
14
+ map.set(modelId, deploymentName);
15
+ }
16
+ return map;
17
+ }
18
+ let cachedDeploymentLookup;
19
+ function getDeploymentLookup(source) {
20
+ const cached = cachedDeploymentLookup;
21
+ if (cached && cached.source === source) return cached;
22
+ const exact = parseAzureDeploymentNameMap(source);
23
+ const folded = /* @__PURE__ */ new Map();
24
+ for (const [modelId, deploymentName] of exact) folded.set(modelId.toLowerCase(), deploymentName);
25
+ cachedDeploymentLookup = {
26
+ source,
27
+ exact,
28
+ folded
29
+ };
30
+ return cachedDeploymentLookup;
31
+ }
32
+ /**
33
+ * Resolves the Azure deployment name for a model id, falling back to the model id.
34
+ *
35
+ * An exact-case match always wins, so configs that intentionally distinguish keys by
36
+ * case keep their exact mappings; a case-insensitive match is only used as a fallback
37
+ * (e.g. `GPT-4o` against a `gpt-4o=...` map) to avoid 404s from casing differences.
38
+ */
39
+ function resolveAzureDeploymentNameFromMap(params) {
40
+ const { exact, folded } = getDeploymentLookup(params.deploymentMap);
41
+ return exact.get(params.modelId) ?? folded.get(params.modelId.toLowerCase()) ?? params.modelId;
42
+ }
43
+ //#endregion
44
+ //#region packages/ai/src/providers/azure-openai-responses-client-compat.ts
45
+ function isTraditionalAzureOpenAIHost(hostname) {
46
+ return hostname.endsWith(".openai.azure.com") || hostname.endsWith(".cognitiveservices.azure.com");
47
+ }
48
+ function isOpenAICompatibleAzureResponsesBaseUrl(baseUrl) {
49
+ let url;
50
+ try {
51
+ url = new URL(baseUrl);
52
+ } catch {
53
+ return false;
54
+ }
55
+ if (isTraditionalAzureOpenAIHost(url.hostname)) return false;
56
+ const hostname = url.hostname.toLowerCase();
57
+ if (!(hostname.endsWith(".services.ai.azure.com") || hostname.endsWith(".api.cognitive.microsoft.com"))) return false;
58
+ const normalizedPath = url.pathname.replace(/\/+$/, "");
59
+ return normalizedPath === "/openai/v1" || normalizedPath.endsWith("/openai/v1");
60
+ }
61
+ //#endregion
62
+ export { resolveAzureDeploymentNameFromMap as i, isTraditionalAzureOpenAIHost as n, parseAzureDeploymentNameMap as r, isOpenAICompatibleAzureResponsesBaseUrl as t };
@@ -0,0 +1,12 @@
1
+ //#region packages/ai/src/providers/cache-retention.ts
2
+ /**
3
+ * Resolve cache retention preference.
4
+ * Defaults to "short" and uses OPENCLAW_CACHE_RETENTION for backward compatibility.
5
+ */
6
+ function resolveCacheRetention(cacheRetention) {
7
+ if (cacheRetention === "short" || cacheRetention === "long" || cacheRetention === "none") return cacheRetention;
8
+ if (typeof process !== "undefined" && process.env.OPENCLAW_CACHE_RETENTION === "long") return "long";
9
+ return "short";
10
+ }
11
+ //#endregion
12
+ export { resolveCacheRetention as t };
@@ -0,0 +1,19 @@
1
+ //#region packages/ai/src/utils/deferred-event-buffer.ts
2
+ function createDeferredEventBuffer(sink, onBufferedEvent) {
3
+ let events = [];
4
+ return {
5
+ push(event) {
6
+ events.push(event);
7
+ onBufferedEvent?.();
8
+ },
9
+ flush() {
10
+ for (const event of events) sink.push(event);
11
+ events = [];
12
+ },
13
+ discard() {
14
+ events = [];
15
+ }
16
+ };
17
+ }
18
+ //#endregion
19
+ export { createDeferredEventBuffer as t };
@@ -0,0 +1,37 @@
1
+ //#region packages/ai/src/providers/cloudflare.ts
2
+ function isCloudflareProvider(provider) {
3
+ return provider === "cloudflare-workers-ai" || provider === "cloudflare-ai-gateway";
4
+ }
5
+ /** Substitute `{VAR}` placeholders in a Cloudflare baseUrl from process.env. */
6
+ function resolveCloudflareBaseUrl(model) {
7
+ const url = model.baseUrl;
8
+ if (!url.includes("{")) return url;
9
+ return url.replace(/\{([A-Z_][A-Z0-9_]*)\}/g, (_match, name) => {
10
+ const value = process.env[name];
11
+ if (!value) throw new Error(`${name} is required for provider ${model.provider} but is not set.`);
12
+ return value;
13
+ });
14
+ }
15
+ //#endregion
16
+ //#region packages/ai/src/providers/github-copilot-headers.ts
17
+ function inferCopilotInitiator(messages) {
18
+ const last = messages[messages.length - 1];
19
+ return last && last.role !== "user" ? "agent" : "user";
20
+ }
21
+ function hasCopilotVisionInput(messages) {
22
+ return messages.some((msg) => {
23
+ if (msg.role === "user" && Array.isArray(msg.content)) return msg.content.some((c) => c.type === "image");
24
+ if (msg.role === "toolResult" && Array.isArray(msg.content)) return msg.content.some((c) => c.type === "image");
25
+ return false;
26
+ });
27
+ }
28
+ function buildCopilotDynamicHeaders(params) {
29
+ const headers = {
30
+ "X-Initiator": inferCopilotInitiator(params.messages),
31
+ "Openai-Intent": "conversation-edits"
32
+ };
33
+ if (params.hasImages) headers["Copilot-Vision-Request"] = "true";
34
+ return headers;
35
+ }
36
+ //#endregion
37
+ export { resolveCloudflareBaseUrl as i, hasCopilotVisionInput as n, isCloudflareProvider as r, buildCopilotDynamicHeaders as t };
@@ -1,8 +1,8 @@
1
1
  import { n as getEnvApiKey } from "./env-api-keys-DrgeBuva.mjs";
2
2
  import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
3
- import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-XYGZcgO8.mjs";
4
- import { A as buildBaseOptions } from "./shared-CdjNZd35.mjs";
5
- import { a as runGoogleGenerateContentLifecycle, i as getDisabledGoogleThinkingConfig, n as buildGoogleSimpleThinking, r as createGoogleAssistantOutput, t as buildGoogleGenerateContentParams } from "./google-shared-J6qvYINH.mjs";
3
+ import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-Dog2WQiR.mjs";
4
+ import { n as buildBaseOptions } from "./simple-options-9lhRrN73.mjs";
5
+ import { a as runGoogleGenerateContentLifecycle, i as getDisabledGoogleThinkingConfig, n as buildGoogleSimpleThinking, r as createGoogleAssistantOutput, t as buildGoogleGenerateContentParams } from "./google-shared-DNBz5rcD.mjs";
6
6
  import { GoogleGenAI } from "@google/genai";
7
7
  //#region packages/ai/src/providers/google.ts
8
8
  let toolCallCounter = 0;
@@ -1,8 +1,10 @@
1
- import { E as isImageWithMediaPayload, S as describeToolResultMediaPlaceholder, o as stripSystemPromptCacheBoundary, u as transformMessages, w as extractToolResultText } from "./shared-CdjNZd35.mjs";
1
+ import { i as transformMessages } from "./host-Dog2WQiR.mjs";
2
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";
3
4
  import { c as calculateCost, l as clampThinkingLevel } from "./number-coercion-DvG7SNMg.mjs";
4
- import { d as transportAbortError } from "./transport-stream-shared-BbMELSI4.mjs";
5
- import { t as formatProviderError } from "./provider-error-apVOZI6G.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";
6
8
  import { FinishReason, FunctionCallingConfigMode, ThinkingLevel } from "@google/genai";
7
9
  //#region packages/ai/src/providers/google-shared.ts
8
10
  /**
@@ -1,7 +1,7 @@
1
1
  import { t as AssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
2
- import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-XYGZcgO8.mjs";
3
- import { A as buildBaseOptions } from "./shared-CdjNZd35.mjs";
4
- import { a as runGoogleGenerateContentLifecycle, n as buildGoogleSimpleThinking, r as createGoogleAssistantOutput, t as buildGoogleGenerateContentParams } from "./google-shared-J6qvYINH.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";
5
5
  import { GoogleGenAI, ResourceScope } from "@google/genai";
6
6
  //#region packages/ai/src/providers/google-vertex.ts
7
7
  const API_VERSION = "v1";