@openclaw/ai 0.0.0 → 2026.7.1-1

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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -3
  3. package/dist/anthropic-B5gZQM5X.mjs +1383 -0
  4. package/dist/api-registry-BXYnCOIR.d.mts +33 -0
  5. package/dist/azure-openai-responses-DNoSk8Uy.mjs +141 -0
  6. package/dist/azure-openai-responses-client-compat-a_O_GVQV.mjs +41 -0
  7. package/dist/diagnostics-BaTA9eVl.d.mts +25 -0
  8. package/dist/diagnostics-COpOtRwq.mjs +36 -0
  9. package/dist/diagnostics.d.mts +2 -0
  10. package/dist/diagnostics.mjs +2 -0
  11. package/dist/env-api-keys-CtMlqaQ4.mjs +171 -0
  12. package/dist/event-stream-0nZeBKl2.d.mts +26 -0
  13. package/dist/event-stream-ReMmOTzX.mjs +65 -0
  14. package/dist/event-stream.d.mts +2 -0
  15. package/dist/event-stream.mjs +2 -0
  16. package/dist/github-copilot-headers-BsH5cqGj.mjs +48 -0
  17. package/dist/google-D6sIQ1bL.mjs +55 -0
  18. package/dist/google-shared-ZPSl2qTi.mjs +548 -0
  19. package/dist/google-vertex-rDGwkoZK.mjs +111 -0
  20. package/dist/hash-CHgqbJmD.mjs +16 -0
  21. package/dist/headers-B_e4-1J0.mjs +9 -0
  22. package/dist/host-4t713IeR.mjs +37 -0
  23. package/dist/index-BoTnz8cv.d.mts +74 -0
  24. package/dist/index.d.mts +69 -0
  25. package/dist/index.mjs +7 -0
  26. package/dist/internal/anthropic.d.mts +234 -0
  27. package/dist/internal/anthropic.mjs +4 -0
  28. package/dist/internal/openai.d.mts +244 -0
  29. package/dist/internal/openai.mjs +7 -0
  30. package/dist/internal/runtime.d.mts +245 -0
  31. package/dist/internal/runtime.mjs +176 -0
  32. package/dist/internal/shared.d.mts +48 -0
  33. package/dist/internal/shared.mjs +3 -0
  34. package/dist/json-parse-DzNSIQBq.mjs +134 -0
  35. package/dist/llm-request-activity-CehVkZP-.mjs +35 -0
  36. package/dist/mistral-CePVNdws.mjs +563 -0
  37. package/dist/model-utils-DgmOla96.mjs +69 -0
  38. package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +39 -0
  39. package/dist/openai-chatgpt-responses-DVC4Bk_A.mjs +1068 -0
  40. package/dist/openai-completions-B9QLIq2U.mjs +844 -0
  41. package/dist/openai-responses-B6LylGxM.mjs +136 -0
  42. package/dist/openai-responses-shared-sj2YUPYc.mjs +1944 -0
  43. package/dist/openai-tool-projection-BknoV11q.mjs +195 -0
  44. package/dist/providers.d.mts +11 -0
  45. package/dist/providers.mjs +109 -0
  46. package/dist/reasoning-tag-text-partitioner-axhAdUwg.mjs +394 -0
  47. package/dist/sanitize-unicode-BZiVbGwK.d.mts +24 -0
  48. package/dist/sanitize-unicode-DT5o51ur.mjs +26 -0
  49. package/dist/src-CZ503MYJ.mjs +99 -0
  50. package/dist/stream-CREqxHgU.mjs +74 -0
  51. package/dist/stream-first-event-timeout-RjWszj8c.mjs +106 -0
  52. package/dist/streaming-byte-guard-BrbkbwUu.mjs +46 -0
  53. package/dist/tool-schema-json-projection-BXtBc_mD.mjs +74 -0
  54. package/dist/transform-messages-BhGF_fF4.mjs +507 -0
  55. package/dist/types-BVVgDSdq.d.mts +1 -0
  56. package/dist/types-DRgdPqaZ.d.mts +587 -0
  57. package/dist/types.d.mts +6 -0
  58. package/dist/types.mjs +5 -0
  59. package/dist/validation-BDMWOr8d.d.mts +9 -0
  60. package/dist/validation-FrchoOlv.mjs +199 -0
  61. package/dist/validation.d.mts +2 -0
  62. package/dist/validation.mjs +2 -0
  63. package/npm-shrinkwrap.json +645 -0
  64. package/package.json +75 -3
@@ -0,0 +1,1383 @@
1
+ import { n as getEnvApiKey, r as __exportAll } from "./env-api-keys-CtMlqaQ4.mjs";
2
+ import { c as resolveClaudeNativeThinkingLevelMap, d as supportsClaudeNativeMaxEffort, f as supportsClaudeNativeXhighEffort, l as resolveClaudeSonnet5ModelIdentity, u as supportsClaudeAdaptiveThinking } from "./src-CZ503MYJ.mjs";
3
+ import { t as AssistantMessageEventStream } from "./event-stream-ReMmOTzX.mjs";
4
+ import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-4t713IeR.mjs";
5
+ import { n as calculateCost, r as clampThinkingLevel } from "./model-utils-DgmOla96.mjs";
6
+ import { r as createDeferredEventBuffer, t as notifyLlmRequestActivity } from "./llm-request-activity-CehVkZP-.mjs";
7
+ import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
8
+ import { n as parseStreamingJson, t as parseJsonWithRepair } from "./json-parse-DzNSIQBq.mjs";
9
+ import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
10
+ import { a as adjustMaxTokensForThinking, b as stripSystemPromptCacheBoundary, c as isRecord, d as prepareClaudeSonnet5RequestContext, f as requiresClaudeAdaptiveThinking, h as usesClaudeStreamingRefusalContract, i as extractToolResultText, l as applyClaudeRequestContract, m as usesClaudeFable5MessagesContract, n as describeToolResultMediaPlaceholder, o as buildBaseOptions, r as extractToolResultBlockText, t as transformMessages, y as splitSystemPromptCacheBoundary } from "./transform-messages-BhGF_fF4.mjs";
11
+ import { t as projectRuntimeToolInputSchema } from "./tool-schema-json-projection-BXtBc_mD.mjs";
12
+ import { a as resolveCacheRetention, i as resolveCloudflareBaseUrl, n as hasCopilotVisionInput, t as buildCopilotDynamicHeaders } from "./github-copilot-headers-BsH5cqGj.mjs";
13
+ import Anthropic from "@anthropic-ai/sdk";
14
+ //#region packages/ai/src/providers/anthropic-auth-headers.ts
15
+ function usesFoundryBearerAuth(model) {
16
+ return model.provider === "microsoft-foundry" && (model.authHeader === true || hasBearerAuthorizationHeader(model.headers));
17
+ }
18
+ function hasBearerAuthorizationHeader(headers) {
19
+ if (!headers) return false;
20
+ return Object.entries(headers).some(([key, value]) => key.toLowerCase() === "authorization" && /^bearer\s+\S+/i.test(value.trim()));
21
+ }
22
+ function omitFoundryBearerCredentialHeaders(headers) {
23
+ if (!headers) return;
24
+ const next = {};
25
+ for (const [key, value] of Object.entries(headers)) {
26
+ const lower = key.toLowerCase();
27
+ if (lower === "authorization" || lower === "x-api-key" || lower === "api-key") continue;
28
+ next[key] = value;
29
+ }
30
+ return Object.keys(next).length > 0 ? next : void 0;
31
+ }
32
+ //#endregion
33
+ //#region packages/ai/src/providers/anthropic-refusal.ts
34
+ function readNullableString(value) {
35
+ return typeof value === "string" && value.trim() ? value.trim() : null;
36
+ }
37
+ function readAnthropicRefusalDetails(value) {
38
+ if (!value || typeof value !== "object") return {
39
+ category: null,
40
+ explanation: null
41
+ };
42
+ const details = value;
43
+ return {
44
+ category: readNullableString(details.category),
45
+ explanation: readNullableString(details.explanation)
46
+ };
47
+ }
48
+ function formatAnthropicRefusalMessage(details) {
49
+ return `Anthropic refusal${details.category ? ` (category: ${details.category})` : ""}${details.explanation ? `: ${details.explanation}` : "."}`;
50
+ }
51
+ function applyAnthropicRefusal(output, stopDetails, provider) {
52
+ const details = readAnthropicRefusalDetails(stopDetails);
53
+ output.stopReason = "error";
54
+ output.errorMessage = formatAnthropicRefusalMessage(details);
55
+ output.diagnostics = [...output.diagnostics ?? [], {
56
+ type: "provider_refusal",
57
+ timestamp: Date.now(),
58
+ details: {
59
+ provider,
60
+ category: details.category,
61
+ explanation: details.explanation
62
+ }
63
+ }];
64
+ }
65
+ //#endregion
66
+ //#region packages/ai/src/providers/anthropic-server-fallback.ts
67
+ /** Anthropic beta that re-serves safety refusals on an allowed fallback model. */
68
+ const ANTHROPIC_SERVER_SIDE_FALLBACK_BETA = "server-side-fallback-2026-06-01";
69
+ const CLAUDE_FABLE_5_FALLBACK_MODEL = "claude-opus-4-8";
70
+ const CLAUDE_FABLE_5_FALLBACK_MODEL_COST = {
71
+ input: 5,
72
+ output: 25,
73
+ cacheRead: .5,
74
+ cacheWrite: 6.25
75
+ };
76
+ function buildAnthropicServerSideFallbacks() {
77
+ return [{ model: CLAUDE_FABLE_5_FALLBACK_MODEL }];
78
+ }
79
+ function readBoundaryModel(value) {
80
+ if (!value || typeof value !== "object") return null;
81
+ const model = value.model;
82
+ return typeof model === "string" && model.trim() ? model : null;
83
+ }
84
+ /** Reads a `fallback` content block marking where one model's output gives way to the next. */
85
+ function readAnthropicFallbackBoundary(block) {
86
+ if (!block || typeof block !== "object") return null;
87
+ const record = block;
88
+ if (record.type !== "fallback") return null;
89
+ return {
90
+ fromModel: readBoundaryModel(record.from),
91
+ toModel: readBoundaryModel(record.to)
92
+ };
93
+ }
94
+ /**
95
+ * Drops pre-fallback thinking/tool calls while preserving the text prefix that
96
+ * the serving model continued. Dropped tool calls must never execute or replay.
97
+ */
98
+ function applyAnthropicFallbackBoundary(params) {
99
+ const { output, boundary } = params;
100
+ const survivors = output.content.filter((block) => block.type === "text");
101
+ for (const survivor of survivors) delete survivor.textSignature;
102
+ output.content.splice(0, output.content.length, ...survivors);
103
+ if (boundary.toModel) output.responseModel = boundary.toModel;
104
+ output.diagnostics = [...output.diagnostics ?? [], {
105
+ type: "provider_fallback",
106
+ timestamp: Date.now(),
107
+ details: {
108
+ provider: params.provider,
109
+ fromModel: boundary.fromModel,
110
+ toModel: boundary.toModel
111
+ }
112
+ }];
113
+ }
114
+ //#endregion
115
+ //#region packages/ai/src/providers/anthropic-thinking-replay.ts
116
+ const ANTHROPIC_OMITTED_REASONING_TEXT = "[assistant reasoning omitted]";
117
+ function asReplayMessage(value) {
118
+ return value && typeof value === "object" ? value : void 0;
119
+ }
120
+ /**
121
+ * Anthropic tool results continue the preceding assistant turn. Preserve that
122
+ * turn's signed thinking even when the next request disables new thinking.
123
+ */
124
+ function findActiveAnthropicToolTurnAssistantIndex(messages) {
125
+ const toolResultIds = /* @__PURE__ */ new Set();
126
+ let index = messages.length - 1;
127
+ while (index >= 0) {
128
+ const message = asReplayMessage(messages[index]);
129
+ if (message?.role !== "toolResult") break;
130
+ if (typeof message.toolCallId === "string") toolResultIds.add(message.toolCallId);
131
+ index -= 1;
132
+ }
133
+ if (toolResultIds.size === 0) return -1;
134
+ const assistant = asReplayMessage(messages[index]);
135
+ if (assistant?.role !== "assistant" || !Array.isArray(assistant.content)) return -1;
136
+ const toolCallIds = /* @__PURE__ */ new Set();
137
+ for (const block of assistant.content) {
138
+ if (!block || typeof block !== "object") continue;
139
+ const record = block;
140
+ if ((record.type === "toolCall" || record.type === "tool_use" || record.type === "function_call") && typeof record.id === "string") toolCallIds.add(record.id);
141
+ }
142
+ return [...toolResultIds].every((toolCallId) => toolCallIds.has(toolCallId)) ? index : -1;
143
+ }
144
+ //#endregion
145
+ //#region packages/ai/src/providers/anthropic-tool-projection.ts
146
+ function isProviderSupportedViolation(violation) {
147
+ return violation.endsWith(".$dynamicRef") || violation.endsWith(".$dynamicAnchor");
148
+ }
149
+ const schemaValueKeywords = /* @__PURE__ */ new Set([
150
+ "additionalProperties",
151
+ "contains",
152
+ "contentSchema",
153
+ "else",
154
+ "if",
155
+ "items",
156
+ "not",
157
+ "propertyNames",
158
+ "then",
159
+ "unevaluatedItems",
160
+ "unevaluatedProperties"
161
+ ]);
162
+ const schemaArrayKeywords = /* @__PURE__ */ new Set([
163
+ "allOf",
164
+ "anyOf",
165
+ "oneOf",
166
+ "prefixItems"
167
+ ]);
168
+ const schemaMapKeywords = /* @__PURE__ */ new Set([
169
+ "$defs",
170
+ "definitions",
171
+ "dependencies",
172
+ "dependentSchemas",
173
+ "patternProperties",
174
+ "properties"
175
+ ]);
176
+ function normalizeAnthropicJsonSchema(schema) {
177
+ if (!isRecord(schema)) return schema;
178
+ let changed = false;
179
+ const normalized = { ...schema };
180
+ for (const [key, value] of Object.entries(schema)) {
181
+ if (schemaValueKeywords.has(key) && !Array.isArray(value)) {
182
+ const next = normalizeAnthropicJsonSchema(value);
183
+ normalized[key] = next;
184
+ changed ||= next !== value;
185
+ continue;
186
+ }
187
+ if (schemaArrayKeywords.has(key) && Array.isArray(value)) {
188
+ const next = value.map(normalizeAnthropicJsonSchema);
189
+ normalized[key] = next;
190
+ changed ||= next.some((entry, index) => entry !== value[index]);
191
+ continue;
192
+ }
193
+ if (schemaMapKeywords.has(key) && isRecord(value)) {
194
+ const next = Object.fromEntries(Object.entries(value).map(([entryKey, entryValue]) => [entryKey, normalizeAnthropicJsonSchema(entryValue)]));
195
+ normalized[key] = next;
196
+ changed ||= Object.entries(value).some(([entryKey, entryValue]) => next[entryKey] !== entryValue);
197
+ }
198
+ }
199
+ if (Array.isArray(schema.items)) {
200
+ normalized.prefixItems = schema.items.map(normalizeAnthropicJsonSchema);
201
+ const additionalItems = schema.additionalItems;
202
+ if (typeof additionalItems === "boolean" || isRecord(additionalItems)) normalized.items = normalizeAnthropicJsonSchema(additionalItems);
203
+ else delete normalized.items;
204
+ delete normalized.additionalItems;
205
+ changed = true;
206
+ }
207
+ return changed ? normalized : schema;
208
+ }
209
+ /** Snapshots direct/custom tool descriptors before Anthropic payload construction. */
210
+ function projectAnthropicTools(tools, toWireName) {
211
+ const projectedTools = [];
212
+ const unavailableOriginalNames = /* @__PURE__ */ new Set();
213
+ for (const tool of tools) {
214
+ let projectedTool;
215
+ let originalName;
216
+ try {
217
+ const name = tool.name;
218
+ originalName = name;
219
+ if (!name) continue;
220
+ const schemaProjection = projectRuntimeToolInputSchema(tool.parameters, `${name}.parameters`);
221
+ if (!isRecord(schemaProjection.schema) || schemaProjection.violations.some((violation) => !isProviderSupportedViolation(violation))) {
222
+ unavailableOriginalNames.add(name);
223
+ continue;
224
+ }
225
+ const anthropicSchema = normalizeAnthropicJsonSchema(schemaProjection.schema);
226
+ if (!isRecord(anthropicSchema)) {
227
+ unavailableOriginalNames.add(name);
228
+ continue;
229
+ }
230
+ const properties = anthropicSchema.properties;
231
+ const required = anthropicSchema.required;
232
+ if (properties !== void 0 && properties !== null && !isRecord(properties) || required !== void 0 && required !== null && (!Array.isArray(required) || required.some((entry) => typeof entry !== "string"))) {
233
+ unavailableOriginalNames.add(name);
234
+ continue;
235
+ }
236
+ let description;
237
+ try {
238
+ description = typeof tool.description === "string" ? tool.description : void 0;
239
+ } catch {}
240
+ projectedTool = {
241
+ originalName: name,
242
+ wireName: toWireName(name),
243
+ ...description ? { description } : {},
244
+ inputSchema: {
245
+ type: "object",
246
+ properties: properties ?? {},
247
+ required: required ?? []
248
+ }
249
+ };
250
+ } catch {
251
+ if (originalName) unavailableOriginalNames.add(originalName);
252
+ continue;
253
+ }
254
+ const conflictingTool = projectedTools.find((entry) => entry.wireName === projectedTool.wireName);
255
+ if (conflictingTool && conflictingTool.originalName !== projectedTool.originalName) throw new Error(`Anthropic tool names "${conflictingTool.originalName}" and "${projectedTool.originalName}" both map to "${projectedTool.wireName}"`);
256
+ projectedTools.push(projectedTool);
257
+ }
258
+ return {
259
+ inputToolCount: tools.length,
260
+ unavailableOriginalNames,
261
+ tools: projectedTools
262
+ };
263
+ }
264
+ /** Keeps forced Anthropic tool choices aligned with the projected wire names. */
265
+ function reconcileAnthropicToolChoice(choice, projection) {
266
+ if (projection.inputToolCount === 0) return choice;
267
+ if (choice.type === "tool") {
268
+ const requestedName = choice.name;
269
+ const originalMatch = projection.tools.find((tool) => tool.originalName === requestedName);
270
+ if (originalMatch) return {
271
+ ...choice,
272
+ name: originalMatch.wireName
273
+ };
274
+ if (projection.unavailableOriginalNames.has(requestedName)) throw new Error(`Anthropic tool_choice requested unavailable tool "${requestedName}" after schema conversion`);
275
+ const matchedTool = projection.tools.find((tool) => tool.wireName === requestedName);
276
+ if (!matchedTool) throw new Error(`Anthropic tool_choice requested unavailable tool "${requestedName}" after schema conversion`);
277
+ return {
278
+ ...choice,
279
+ name: matchedTool.wireName
280
+ };
281
+ }
282
+ if (projection.tools.length === 0) {
283
+ if (choice.type === "auto") return;
284
+ if (choice.type === "any") throw new Error("Anthropic tool_choice requires a tool, but no tools survived schema conversion");
285
+ }
286
+ return choice;
287
+ }
288
+ /** Maps Claude Code wire names without trusting every direct/custom descriptor. */
289
+ function resolveOriginalAnthropicToolName(name, projection) {
290
+ return projection?.tools.find((tool) => tool.wireName === name)?.originalName ?? name;
291
+ }
292
+ //#endregion
293
+ //#region packages/ai/src/providers/anthropic-usage.ts
294
+ function readAnthropicUsageTokenCount(value) {
295
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
296
+ }
297
+ function readAnthropicPromptUsageSnapshot(usage) {
298
+ const input = readAnthropicUsageTokenCount(usage.input_tokens);
299
+ const cacheRead = usage.cache_read_input_tokens == null ? 0 : readAnthropicUsageTokenCount(usage.cache_read_input_tokens);
300
+ const cacheWrite = usage.cache_creation_input_tokens == null ? 0 : readAnthropicUsageTokenCount(usage.cache_creation_input_tokens);
301
+ if (input === void 0 || cacheRead === void 0 || cacheWrite === void 0) return;
302
+ return {
303
+ input,
304
+ cacheRead,
305
+ cacheWrite
306
+ };
307
+ }
308
+ function readLastAnthropicIterationUsage(usage) {
309
+ if (usage.iterations == null) return { state: "absent" };
310
+ if (!Array.isArray(usage.iterations) || usage.iterations.length === 0) return { state: "invalid" };
311
+ const iteration = usage.iterations.at(-1);
312
+ if (!iteration || typeof iteration !== "object" || Array.isArray(iteration)) return { state: "invalid" };
313
+ const record = iteration;
314
+ const input = readAnthropicUsageTokenCount(record.input_tokens);
315
+ const cacheRead = readAnthropicUsageTokenCount(record.cache_read_input_tokens);
316
+ const cacheWrite = readAnthropicUsageTokenCount(record.cache_creation_input_tokens);
317
+ const outputTokens = readAnthropicUsageTokenCount(record.output_tokens);
318
+ if (input === void 0 || cacheRead === void 0 || cacheWrite === void 0 || outputTokens === void 0) return { state: "invalid" };
319
+ const contextPromptTokens = input + cacheRead + cacheWrite;
320
+ return {
321
+ state: "valid",
322
+ usage: {
323
+ contextPromptTokens,
324
+ totalTokens: contextPromptTokens + outputTokens
325
+ }
326
+ };
327
+ }
328
+ //#endregion
329
+ //#region packages/ai/src/providers/anthropic.ts
330
+ var anthropic_exports = /* @__PURE__ */ __exportAll({
331
+ streamAnthropic: () => streamAnthropic,
332
+ streamSimpleAnthropic: () => streamSimpleAnthropic
333
+ });
334
+ const ANTHROPIC_CACHE_CONTROL_LIMIT = 4;
335
+ const EMPTY_ERROR_TOOL_RESULT_TEXT = "[tool error with no output]";
336
+ function getCacheControl(model, cacheRetention) {
337
+ const retention = resolveCacheRetention(cacheRetention);
338
+ if (retention === "none") return { retention };
339
+ const ttl = retention === "long" && getAnthropicCompat(model).supportsLongCacheRetention ? "1h" : void 0;
340
+ return {
341
+ retention,
342
+ cacheControl: {
343
+ type: "ephemeral",
344
+ ...ttl && { ttl }
345
+ }
346
+ };
347
+ }
348
+ const claudeCodeVersion = "2.1.75";
349
+ const claudeCodeBillingSystemBlock = `x-anthropic-billing-header: cc_version=${claudeCodeVersion}; cc_entrypoint=sdk-cli;`;
350
+ const ccToolLookup = new Map([
351
+ "Read",
352
+ "Write",
353
+ "Edit",
354
+ "Bash",
355
+ "Grep",
356
+ "Glob",
357
+ "AskUserQuestion",
358
+ "EnterPlanMode",
359
+ "ExitPlanMode",
360
+ "KillShell",
361
+ "NotebookEdit",
362
+ "Skill",
363
+ "Task",
364
+ "TaskOutput",
365
+ "TodoWrite",
366
+ "WebFetch",
367
+ "WebSearch"
368
+ ].map((t) => [t.toLowerCase(), t]));
369
+ const toClaudeCodeName = (name) => ccToolLookup.get(name.toLowerCase()) ?? name;
370
+ /**
371
+ * Convert content blocks to Anthropic API format
372
+ */
373
+ function convertContentBlocks(content, isError) {
374
+ const text = extractToolResultText(content);
375
+ const mediaPlaceholder = describeToolResultMediaPlaceholder(content);
376
+ if (!(Array.isArray(content) && content.some((item) => item && typeof item === "object" && item.type === "image"))) {
377
+ const sanitized = sanitizeSurrogates(text);
378
+ return sanitized.trim().length > 0 ? sanitized : mediaPlaceholder ?? (isError ? EMPTY_ERROR_TOOL_RESULT_TEXT : "");
379
+ }
380
+ const blocks = [];
381
+ let hasTextBlock = false;
382
+ for (const block of Array.isArray(content) ? content : []) {
383
+ if (!block || typeof block !== "object") continue;
384
+ const record = block;
385
+ const blockText = extractToolResultBlockText(block);
386
+ if (blockText) {
387
+ blocks.push({
388
+ type: "text",
389
+ text: sanitizeSurrogates(blockText)
390
+ });
391
+ hasTextBlock = true;
392
+ }
393
+ if (record.type !== "image") continue;
394
+ blocks.push({
395
+ type: "image",
396
+ source: {
397
+ type: "base64",
398
+ media_type: typeof record.mimeType === "string" ? record.mimeType : "image/jpeg",
399
+ data: typeof record.data === "string" ? record.data : ""
400
+ }
401
+ });
402
+ }
403
+ if (!hasTextBlock) blocks.unshift({
404
+ type: "text",
405
+ text: mediaPlaceholder ?? "(see attached image)"
406
+ });
407
+ return blocks;
408
+ }
409
+ const FINE_GRAINED_TOOL_STREAMING_BETA = "fine-grained-tool-streaming-2025-05-14";
410
+ const INTERLEAVED_THINKING_BETA = "interleaved-thinking-2025-05-14";
411
+ const ANTHROPIC_MIN_THINKING_BUDGET_TOKENS = 1024;
412
+ function getAnthropicCompat(model) {
413
+ const isFireworks = model.provider === "fireworks";
414
+ const isCloudflareAiGatewayAnthropic = model.provider === "cloudflare-ai-gateway" && model.baseUrl.includes("anthropic");
415
+ return {
416
+ supportsEagerToolInputStreaming: model.compat?.supportsEagerToolInputStreaming ?? !isFireworks,
417
+ supportsLongCacheRetention: model.compat?.supportsLongCacheRetention ?? !isFireworks,
418
+ sendSessionAffinityHeaders: model.compat?.sendSessionAffinityHeaders ?? (isFireworks || isCloudflareAiGatewayAnthropic),
419
+ supportsCacheControlOnTools: model.compat?.supportsCacheControlOnTools ?? !isFireworks
420
+ };
421
+ }
422
+ function mergeHeaders(...headerSources) {
423
+ const merged = {};
424
+ for (const headers of headerSources) if (headers) Object.assign(merged, headers);
425
+ return merged;
426
+ }
427
+ const ANTHROPIC_MESSAGE_EVENTS = /* @__PURE__ */ new Set([
428
+ "message_start",
429
+ "message_delta",
430
+ "message_stop",
431
+ "content_block_start",
432
+ "content_block_delta",
433
+ "content_block_stop"
434
+ ]);
435
+ function flushSseEvent(state) {
436
+ if (!state.event && state.data.length === 0) return null;
437
+ const event = {
438
+ event: state.event,
439
+ data: state.data.join("\n"),
440
+ raw: [...state.raw]
441
+ };
442
+ state.event = null;
443
+ state.data = [];
444
+ state.raw = [];
445
+ return event;
446
+ }
447
+ function decodeSseLine(line, state) {
448
+ if (line === "") return flushSseEvent(state);
449
+ state.raw.push(line);
450
+ if (line.startsWith(":")) return null;
451
+ const delimiterIndex = line.indexOf(":");
452
+ const fieldName = delimiterIndex === -1 ? line : line.slice(0, delimiterIndex);
453
+ let value = delimiterIndex === -1 ? "" : line.slice(delimiterIndex + 1);
454
+ if (value.startsWith(" ")) value = value.slice(1);
455
+ if (fieldName === "event") state.event = value;
456
+ else if (fieldName === "data") state.data.push(value);
457
+ return null;
458
+ }
459
+ function nextLineBreakIndex(text) {
460
+ const carriageReturnIndex = text.indexOf("\r");
461
+ const newlineIndex = text.indexOf("\n");
462
+ if (carriageReturnIndex === -1) return newlineIndex;
463
+ if (newlineIndex === -1) return carriageReturnIndex;
464
+ return Math.min(carriageReturnIndex, newlineIndex);
465
+ }
466
+ function consumeLine(text) {
467
+ const lineBreakIndex = nextLineBreakIndex(text);
468
+ if (lineBreakIndex === -1) return null;
469
+ let nextIndex = lineBreakIndex + 1;
470
+ if (text[lineBreakIndex] === "\r" && text[nextIndex] === "\n") nextIndex += 1;
471
+ return {
472
+ line: text.slice(0, lineBreakIndex),
473
+ rest: text.slice(nextIndex)
474
+ };
475
+ }
476
+ async function* iterateSseMessages(body, signal) {
477
+ const reader = body.getReader();
478
+ const decoder = new TextDecoder();
479
+ const state = {
480
+ event: null,
481
+ data: [],
482
+ raw: []
483
+ };
484
+ let buffer = "";
485
+ try {
486
+ while (true) {
487
+ if (signal?.aborted) throw new Error("Request was aborted");
488
+ const { value, done } = await reader.read();
489
+ if (done) break;
490
+ buffer += decoder.decode(value, { stream: true });
491
+ let consumed = consumeLine(buffer);
492
+ while (consumed) {
493
+ buffer = consumed.rest;
494
+ const event = decodeSseLine(consumed.line, state);
495
+ if (event) yield event;
496
+ consumed = consumeLine(buffer);
497
+ }
498
+ }
499
+ buffer += decoder.decode();
500
+ let consumed = consumeLine(buffer);
501
+ while (consumed) {
502
+ buffer = consumed.rest;
503
+ const event = decodeSseLine(consumed.line, state);
504
+ if (event) yield event;
505
+ consumed = consumeLine(buffer);
506
+ }
507
+ if (buffer.length > 0) {
508
+ const event = decodeSseLine(buffer, state);
509
+ if (event) yield event;
510
+ }
511
+ const trailingEvent = flushSseEvent(state);
512
+ if (trailingEvent) yield trailingEvent;
513
+ } finally {
514
+ reader.releaseLock();
515
+ }
516
+ }
517
+ async function* iterateAnthropicEvents(response, signal, requireMessageStop = false) {
518
+ if (!response.body) throw new Error("Attempted to iterate over an Anthropic response with no body");
519
+ let sawMessageStart = false;
520
+ let sawMessageEnd = false;
521
+ for await (const sse of iterateSseMessages(response.body, signal)) {
522
+ if (sse.event === "error") throw new Error(sse.data);
523
+ if (!ANTHROPIC_MESSAGE_EVENTS.has(sse.event ?? "")) continue;
524
+ try {
525
+ const event = parseJsonWithRepair(sse.data);
526
+ if (event.type === "message_start") sawMessageStart = true;
527
+ else if (event.type === "message_stop") sawMessageEnd = true;
528
+ yield event;
529
+ } catch (error) {
530
+ const message = error instanceof Error ? error.message : String(error);
531
+ throw new Error(`Could not parse Anthropic SSE event ${sse.event}: ${message}; data=${sse.data}; raw=${sse.raw.join("\\n")}`, { cause: error });
532
+ }
533
+ }
534
+ if ((sawMessageStart || requireMessageStop) && !sawMessageEnd) throw new Error("Anthropic stream ended before message_stop");
535
+ }
536
+ const streamAnthropic = (model, context, options) => {
537
+ const stream = new AssistantMessageEventStream();
538
+ const requestContext = prepareClaudeSonnet5RequestContext(model, context);
539
+ const requestOptions = normalizeAnthropicThinkingOptions(model, options);
540
+ (async () => {
541
+ const output = {
542
+ role: "assistant",
543
+ content: [],
544
+ api: model.api,
545
+ provider: model.provider,
546
+ model: model.id,
547
+ usage: {
548
+ input: 0,
549
+ output: 0,
550
+ cacheRead: 0,
551
+ cacheWrite: 0,
552
+ totalTokens: 0,
553
+ cost: {
554
+ input: 0,
555
+ output: 0,
556
+ cacheRead: 0,
557
+ cacheWrite: 0,
558
+ total: 0
559
+ }
560
+ },
561
+ stopReason: "stop",
562
+ timestamp: Date.now()
563
+ };
564
+ const refusalBuffer = usesClaudeStreamingRefusalContract(model) ? createDeferredEventBuffer(stream, () => notifyLlmRequestActivity(requestOptions?.signal)) : void 0;
565
+ const eventSink = refusalBuffer ?? stream;
566
+ let costModel = model;
567
+ let messageStartPromptUsage;
568
+ try {
569
+ let client;
570
+ let isOAuth;
571
+ let serverSideFallback = false;
572
+ if (requestOptions?.client) {
573
+ client = requestOptions.client;
574
+ isOAuth = false;
575
+ } else {
576
+ const apiKey = requestOptions?.apiKey ?? getEnvApiKey(model.provider) ?? "";
577
+ let copilotDynamicHeaders;
578
+ if (model.provider === "github-copilot") {
579
+ const hasImages = hasCopilotVisionInput(requestContext.messages);
580
+ copilotDynamicHeaders = buildCopilotDynamicHeaders({
581
+ messages: requestContext.messages,
582
+ hasImages
583
+ });
584
+ }
585
+ const cacheSessionId = (requestOptions?.cacheRetention ?? resolveCacheRetention()) === "none" ? void 0 : requestOptions?.sessionId;
586
+ const created = createClient(model, apiKey, requestOptions?.thinkingEnabled === true, requestOptions?.interleavedThinking ?? true, shouldUseFineGrainedToolStreamingBeta(model, requestContext), requestOptions?.headers, copilotDynamicHeaders, cacheSessionId);
587
+ client = created.client;
588
+ isOAuth = created.isOAuthToken;
589
+ serverSideFallback = created.serverSideFallback;
590
+ }
591
+ const builtParams = buildParams(model, requestContext, isOAuth, requestOptions, serverSideFallback);
592
+ let params = builtParams.params;
593
+ const toolProjection = builtParams.toolProjection;
594
+ const nextParams = await requestOptions?.onPayload?.(params, model);
595
+ if (nextParams !== void 0) params = nextParams;
596
+ applyClaudeRequestContract(params, model);
597
+ const sdkRequestOptions = {
598
+ ...requestOptions?.signal ? { signal: requestOptions.signal } : {},
599
+ ...requestOptions?.timeoutMs !== void 0 ? { timeout: requestOptions.timeoutMs } : {},
600
+ ...requestOptions?.maxRetries !== void 0 ? { maxRetries: requestOptions.maxRetries } : {}
601
+ };
602
+ const response = await client.messages.create({
603
+ ...params,
604
+ stream: true
605
+ }, sdkRequestOptions).asResponse();
606
+ await requestOptions?.onResponse?.({
607
+ status: response.status,
608
+ headers: headersToRecord(response.headers)
609
+ }, model);
610
+ const blocks = output.content;
611
+ const blockIndexes = /* @__PURE__ */ new Map();
612
+ for await (const event of iterateAnthropicEvents(response, requestOptions?.signal, refusalBuffer !== void 0)) if (event.type === "message_start") {
613
+ output.responseId = event.message.id;
614
+ output.responseModel = event.message.model;
615
+ const promptUsage = readAnthropicPromptUsageSnapshot(event.message.usage);
616
+ const messageStartPromptTokens = promptUsage ? promptUsage.input + promptUsage.cacheRead + promptUsage.cacheWrite : 0;
617
+ messageStartPromptUsage = messageStartPromptTokens > 0 ? promptUsage : void 0;
618
+ const inputTokens = readAnthropicUsageTokenCount(event.message.usage.input_tokens);
619
+ if (inputTokens !== void 0) output.usage.input = inputTokens;
620
+ const outputTokens = readAnthropicUsageTokenCount(event.message.usage.output_tokens);
621
+ if (outputTokens !== void 0) output.usage.output = outputTokens;
622
+ const cacheReadTokens = event.message.usage.cache_read_input_tokens == null ? 0 : readAnthropicUsageTokenCount(event.message.usage.cache_read_input_tokens);
623
+ if (cacheReadTokens !== void 0) output.usage.cacheRead = cacheReadTokens;
624
+ const cacheWriteTokens = event.message.usage.cache_creation_input_tokens == null ? 0 : readAnthropicUsageTokenCount(event.message.usage.cache_creation_input_tokens);
625
+ if (cacheWriteTokens !== void 0) output.usage.cacheWrite = cacheWriteTokens;
626
+ output.usage.totalTokens = output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
627
+ if (messageStartPromptUsage && outputTokens !== void 0) output.usage.contextUsage = {
628
+ state: "available",
629
+ promptTokens: messageStartPromptTokens,
630
+ totalTokens: messageStartPromptTokens + output.usage.output
631
+ };
632
+ calculateCost(costModel, output.usage);
633
+ eventSink.push({
634
+ type: "start",
635
+ partial: output
636
+ });
637
+ } else if (event.type === "content_block_start") {
638
+ const fallbackBoundary = refusalBuffer ? readAnthropicFallbackBoundary(event.content_block) : null;
639
+ if (fallbackBoundary) {
640
+ refusalBuffer?.discard();
641
+ blockIndexes.clear();
642
+ applyAnthropicFallbackBoundary({
643
+ output,
644
+ boundary: fallbackBoundary,
645
+ provider: model.provider
646
+ });
647
+ costModel = {
648
+ ...model,
649
+ cost: CLAUDE_FABLE_5_FALLBACK_MODEL_COST
650
+ };
651
+ calculateCost(costModel, output.usage);
652
+ eventSink.push({
653
+ type: "start",
654
+ partial: output
655
+ });
656
+ for (let i = 0; i < blocks.length; i += 1) {
657
+ const block = blocks[i];
658
+ if (block.type !== "text") continue;
659
+ delete block.index;
660
+ eventSink.push({
661
+ type: "text_start",
662
+ contentIndex: i,
663
+ partial: output
664
+ });
665
+ if (block.text) eventSink.push({
666
+ type: "text_delta",
667
+ contentIndex: i,
668
+ delta: block.text,
669
+ partial: output
670
+ });
671
+ eventSink.push({
672
+ type: "text_end",
673
+ contentIndex: i,
674
+ content: block.text,
675
+ partial: output
676
+ });
677
+ }
678
+ } else if (event.content_block.type === "text") {
679
+ const block = {
680
+ type: "text",
681
+ text: "",
682
+ index: event.index
683
+ };
684
+ output.content.push(block);
685
+ blockIndexes.set(event.index, output.content.length - 1);
686
+ eventSink.push({
687
+ type: "text_start",
688
+ contentIndex: output.content.length - 1,
689
+ partial: output
690
+ });
691
+ } else if (event.content_block.type === "thinking") {
692
+ const block = {
693
+ type: "thinking",
694
+ thinking: "",
695
+ thinkingSignature: "",
696
+ index: event.index
697
+ };
698
+ output.content.push(block);
699
+ blockIndexes.set(event.index, output.content.length - 1);
700
+ eventSink.push({
701
+ type: "thinking_start",
702
+ contentIndex: output.content.length - 1,
703
+ partial: output
704
+ });
705
+ } else if (event.content_block.type === "redacted_thinking") {
706
+ const block = {
707
+ type: "thinking",
708
+ thinking: "[Reasoning redacted]",
709
+ thinkingSignature: event.content_block.data,
710
+ redacted: true,
711
+ index: event.index
712
+ };
713
+ output.content.push(block);
714
+ blockIndexes.set(event.index, output.content.length - 1);
715
+ eventSink.push({
716
+ type: "thinking_start",
717
+ contentIndex: output.content.length - 1,
718
+ partial: output
719
+ });
720
+ } else if (event.content_block.type === "tool_use") {
721
+ const block = {
722
+ type: "toolCall",
723
+ id: event.content_block.id,
724
+ name: isOAuth ? resolveOriginalAnthropicToolName(event.content_block.name, toolProjection) : event.content_block.name,
725
+ arguments: event.content_block.input ?? {},
726
+ partialJson: "",
727
+ index: event.index
728
+ };
729
+ output.content.push(block);
730
+ blockIndexes.set(event.index, output.content.length - 1);
731
+ eventSink.push({
732
+ type: "toolcall_start",
733
+ contentIndex: output.content.length - 1,
734
+ partial: output
735
+ });
736
+ }
737
+ } else if (event.type === "content_block_delta") {
738
+ if (event.delta.type === "text_delta") {
739
+ const index = blockIndexes.get(event.index);
740
+ const block = index === void 0 ? void 0 : blocks[index];
741
+ if (index !== void 0 && block?.type === "text") {
742
+ block.text += event.delta.text;
743
+ eventSink.push({
744
+ type: "text_delta",
745
+ contentIndex: index,
746
+ delta: event.delta.text,
747
+ partial: output
748
+ });
749
+ }
750
+ } else if (event.delta.type === "thinking_delta") {
751
+ const index = blockIndexes.get(event.index);
752
+ const block = index === void 0 ? void 0 : blocks[index];
753
+ if (index !== void 0 && block?.type === "thinking") {
754
+ block.thinking += event.delta.thinking;
755
+ eventSink.push({
756
+ type: "thinking_delta",
757
+ contentIndex: index,
758
+ delta: event.delta.thinking,
759
+ partial: output
760
+ });
761
+ }
762
+ } else if (event.delta.type === "input_json_delta") {
763
+ const index = blockIndexes.get(event.index);
764
+ const block = index === void 0 ? void 0 : blocks[index];
765
+ if (index !== void 0 && block?.type === "toolCall") {
766
+ block.partialJson += event.delta.partial_json;
767
+ block.arguments = parseStreamingJson(block.partialJson);
768
+ eventSink.push({
769
+ type: "toolcall_delta",
770
+ contentIndex: index,
771
+ delta: event.delta.partial_json,
772
+ partial: output
773
+ });
774
+ }
775
+ } else if (event.delta.type === "signature_delta") {
776
+ const index = blockIndexes.get(event.index);
777
+ const block = index === void 0 ? void 0 : blocks[index];
778
+ if (index !== void 0 && block?.type === "thinking") {
779
+ block.thinkingSignature = block.thinkingSignature || "";
780
+ block.thinkingSignature += event.delta.signature;
781
+ }
782
+ }
783
+ } else if (event.type === "content_block_stop") {
784
+ const index = blockIndexes.get(event.index);
785
+ const block = index === void 0 ? void 0 : blocks[index];
786
+ if (index !== void 0 && block) {
787
+ blockIndexes.delete(event.index);
788
+ delete block.index;
789
+ if (block.type === "text") eventSink.push({
790
+ type: "text_end",
791
+ contentIndex: index,
792
+ content: block.text,
793
+ partial: output
794
+ });
795
+ else if (block.type === "thinking") eventSink.push({
796
+ type: "thinking_end",
797
+ contentIndex: index,
798
+ content: block.thinking,
799
+ partial: output
800
+ });
801
+ else if (block.type === "toolCall") {
802
+ block.arguments = parseStreamingJson(block.partialJson);
803
+ delete block.partialJson;
804
+ eventSink.push({
805
+ type: "toolcall_end",
806
+ contentIndex: index,
807
+ toolCall: block,
808
+ partial: output
809
+ });
810
+ }
811
+ }
812
+ } else if (event.type === "message_delta") {
813
+ if (event.delta.stop_reason) if (event.delta.stop_reason === "refusal") applyAnthropicRefusal(output, event.delta.stop_details, model.provider);
814
+ else output.stopReason = mapStopReason(event.delta.stop_reason);
815
+ const inputTokens = readAnthropicUsageTokenCount(event.usage.input_tokens);
816
+ if (inputTokens !== void 0) output.usage.input = inputTokens;
817
+ const outputTokens = readAnthropicUsageTokenCount(event.usage.output_tokens);
818
+ if (outputTokens !== void 0) output.usage.output = outputTokens;
819
+ const cacheReadTokens = readAnthropicUsageTokenCount(event.usage.cache_read_input_tokens);
820
+ if (cacheReadTokens !== void 0) output.usage.cacheRead = cacheReadTokens;
821
+ const cacheWriteTokens = readAnthropicUsageTokenCount(event.usage.cache_creation_input_tokens);
822
+ if (cacheWriteTokens !== void 0) output.usage.cacheWrite = cacheWriteTokens;
823
+ output.usage.totalTokens = output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
824
+ const iterationUsage = readLastAnthropicIterationUsage(event.usage);
825
+ if (iterationUsage.state === "valid") output.usage.contextUsage = {
826
+ state: "available",
827
+ promptTokens: iterationUsage.usage.contextPromptTokens,
828
+ totalTokens: iterationUsage.usage.totalTokens
829
+ };
830
+ else if (iterationUsage.state === "invalid") output.usage.contextUsage = { state: "unavailable" };
831
+ else if (outputTokens !== void 0 && (messageStartPromptUsage !== void 0 || inputTokens !== void 0 && cacheReadTokens !== void 0 && cacheWriteTokens !== void 0)) {
832
+ const promptTokens = output.usage.input + output.usage.cacheRead + output.usage.cacheWrite;
833
+ output.usage.contextUsage = {
834
+ state: "available",
835
+ promptTokens,
836
+ totalTokens: promptTokens + output.usage.output
837
+ };
838
+ } else output.usage.contextUsage = { state: "unavailable" };
839
+ calculateCost(costModel, output.usage);
840
+ }
841
+ if (requestOptions?.signal?.aborted) throw new Error("Request was aborted");
842
+ if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
843
+ refusalBuffer?.flush();
844
+ stream.push({
845
+ type: "done",
846
+ reason: output.stopReason,
847
+ message: output
848
+ });
849
+ stream.end();
850
+ } catch (error) {
851
+ for (const block of output.content) {
852
+ delete block.index;
853
+ delete block.partialJson;
854
+ }
855
+ if (refusalBuffer) {
856
+ refusalBuffer.discard();
857
+ output.content = [];
858
+ }
859
+ output.stopReason = requestOptions?.signal?.aborted ? "aborted" : "error";
860
+ output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
861
+ stream.push({
862
+ type: "error",
863
+ reason: output.stopReason,
864
+ error: output
865
+ });
866
+ stream.end();
867
+ }
868
+ })();
869
+ return stream;
870
+ };
871
+ function normalizeAnthropicToolChoice(thinkingEnabled, toolChoice) {
872
+ if (thinkingEnabled && (toolChoice === "any" || typeof toolChoice === "object" && toolChoice.type === "tool")) return { type: "auto" };
873
+ return typeof toolChoice === "string" ? { type: toolChoice } : toolChoice;
874
+ }
875
+ /**
876
+ * Check if a model supports adaptive thinking (Fable 5, Opus 4.6+, Sonnet 4.6).
877
+ */
878
+ function supportsAdaptiveThinking(model) {
879
+ return supportsClaudeAdaptiveThinking(model);
880
+ }
881
+ function normalizeAnthropicThinkingOptions(model, options) {
882
+ if (options?.thinkingEnabled !== true || supportsAdaptiveThinking(model)) return options;
883
+ const budgetTokens = options.thinkingBudgetTokens ?? ANTHROPIC_MIN_THINKING_BUDGET_TOKENS;
884
+ const maxTokens = options.maxTokens ?? model.maxTokens;
885
+ if (budgetTokens >= ANTHROPIC_MIN_THINKING_BUDGET_TOKENS && budgetTokens < maxTokens) return options;
886
+ return {
887
+ ...options,
888
+ thinkingEnabled: false,
889
+ thinkingBudgetTokens: void 0
890
+ };
891
+ }
892
+ function supportsNativeXhighEffort(model) {
893
+ return supportsClaudeNativeXhighEffort(model);
894
+ }
895
+ /**
896
+ * Map ThinkingLevel to Anthropic effort levels for adaptive thinking.
897
+ * Model metadata owns the provider-specific extended effort mapping.
898
+ */
899
+ function mapThinkingLevelToEffort(model, level) {
900
+ const requestedLevel = level;
901
+ const hasCanonicalAlias = typeof model.params?.canonicalModelId === "string";
902
+ const thinkingLevelMap = resolveClaudeNativeThinkingLevelMap(model);
903
+ const clampModel = {
904
+ ...model,
905
+ ...hasCanonicalAlias ? { reasoning: true } : {},
906
+ ...thinkingLevelMap ? { thinkingLevelMap } : {}
907
+ };
908
+ const clampedLevel = requestedLevel ? clampThinkingLevel(clampModel, requestedLevel) : requestedLevel;
909
+ const mapped = clampedLevel ? thinkingLevelMap?.[clampedLevel] : void 0;
910
+ if (typeof mapped === "string") return mapped;
911
+ switch (clampedLevel) {
912
+ case "off":
913
+ case "minimal":
914
+ case "low": return "low";
915
+ case "medium": return "medium";
916
+ case "high": return "high";
917
+ case "xhigh": return supportsNativeXhighEffort(model) ? "xhigh" : "high";
918
+ case "max": return supportsClaudeNativeMaxEffort(model) ? "max" : "high";
919
+ default: return "high";
920
+ }
921
+ }
922
+ const streamSimpleAnthropic = (model, context, options) => {
923
+ const apiKey = options?.apiKey || getEnvApiKey(model.provider);
924
+ if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
925
+ const base = {
926
+ ...buildBaseOptions(model, options, apiKey),
927
+ toolChoice: options?.toolChoice
928
+ };
929
+ const mandatoryAdaptiveThinking = requiresClaudeAdaptiveThinking(model);
930
+ if (options?.reasoning === "off" && !mandatoryAdaptiveThinking) return streamAnthropic(model, context, {
931
+ ...base,
932
+ thinkingEnabled: false
933
+ });
934
+ const reasoning = options?.reasoning === "off" ? mandatoryAdaptiveThinking ? "low" : "high" : options?.reasoning;
935
+ if (resolveClaudeSonnet5ModelIdentity(model)) return streamAnthropic(model, context, {
936
+ ...base,
937
+ thinkingEnabled: true,
938
+ effort: mapThinkingLevelToEffort(model, reasoning ?? "high")
939
+ });
940
+ if (!reasoning) return streamAnthropic(model, context, {
941
+ ...base,
942
+ thinkingEnabled: mandatoryAdaptiveThinking,
943
+ ...mandatoryAdaptiveThinking ? { effort: "high" } : {}
944
+ });
945
+ if (supportsAdaptiveThinking(model)) {
946
+ const effort = mapThinkingLevelToEffort(model, reasoning);
947
+ return streamAnthropic(model, context, {
948
+ ...base,
949
+ thinkingEnabled: true,
950
+ effort
951
+ });
952
+ }
953
+ const adjusted = adjustMaxTokensForThinking(base.maxTokens, model.maxTokens, reasoning, options?.thinkingBudgets);
954
+ const thinkingEnabled = adjusted.thinkingBudget >= 1024;
955
+ return streamAnthropic(model, context, {
956
+ ...base,
957
+ maxTokens: adjusted.maxTokens,
958
+ thinkingEnabled,
959
+ thinkingBudgetTokens: thinkingEnabled ? adjusted.thinkingBudget : void 0
960
+ });
961
+ };
962
+ function isOAuthToken(apiKey) {
963
+ return getAiTransportHost().resolveSecretSentinel(apiKey).includes("sk-ant-oat");
964
+ }
965
+ function isAnthropicPublicEndpoint(baseUrl) {
966
+ if (!baseUrl) return true;
967
+ try {
968
+ return new URL(baseUrl).hostname.toLowerCase() === "api.anthropic.com";
969
+ } catch {
970
+ return false;
971
+ }
972
+ }
973
+ /**
974
+ * Server-side refusal fallback is a first-party Claude API beta: proxies and
975
+ * Bedrock/Vertex/Foundry reject the `fallbacks` param, and OAuth (Claude Code
976
+ * identity) requests are excluded until the beta is verified there.
977
+ */
978
+ function supportsAnthropicServerSideFallback(model) {
979
+ if (!usesClaudeFable5MessagesContract(model) || model.provider !== "anthropic") return false;
980
+ return isAnthropicPublicEndpoint(model.baseUrl);
981
+ }
982
+ function createClient(model, apiKey, thinkingEnabled, interleavedThinking, useFineGrainedToolStreamingBeta, optionsHeaders, dynamicHeaders, sessionId) {
983
+ const needsInterleavedBeta = interleavedThinking && !supportsAdaptiveThinking(model);
984
+ const betaFeatures = [];
985
+ if (useFineGrainedToolStreamingBeta) betaFeatures.push(FINE_GRAINED_TOOL_STREAMING_BETA);
986
+ if (needsInterleavedBeta) betaFeatures.push(INTERLEAVED_THINKING_BETA);
987
+ const fetchOptions = /^kimi(?:-|$)/.test(model.provider) && thinkingEnabled ? { sanitizeSse: false } : void 0;
988
+ const fetch = getAiTransportHost().buildModelFetch(model, void 0, fetchOptions);
989
+ if (model.provider === "cloudflare-ai-gateway") return {
990
+ client: new Anthropic({
991
+ apiKey,
992
+ authToken: null,
993
+ baseURL: resolveCloudflareBaseUrl(model),
994
+ dangerouslyAllowBrowser: true,
995
+ defaultHeaders: mergeHeaders({
996
+ accept: "application/json",
997
+ "anthropic-dangerous-direct-browser-access": "true",
998
+ Authorization: null,
999
+ ...betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}
1000
+ }, model.headers, optionsHeaders),
1001
+ fetch
1002
+ }),
1003
+ isOAuthToken: false,
1004
+ serverSideFallback: false
1005
+ };
1006
+ if (model.provider === "github-copilot") return {
1007
+ client: new Anthropic({
1008
+ apiKey: null,
1009
+ authToken: apiKey,
1010
+ baseURL: model.baseUrl,
1011
+ dangerouslyAllowBrowser: true,
1012
+ defaultHeaders: mergeHeaders({
1013
+ accept: "application/json",
1014
+ "anthropic-dangerous-direct-browser-access": "true",
1015
+ ...betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}
1016
+ }, model.headers, dynamicHeaders, optionsHeaders),
1017
+ fetch
1018
+ }),
1019
+ isOAuthToken: false,
1020
+ serverSideFallback: false
1021
+ };
1022
+ if (usesFoundryBearerAuth({
1023
+ ...model,
1024
+ headers: resolveAiTransportHeaderSentinels(model.headers)
1025
+ })) return {
1026
+ client: new Anthropic({
1027
+ apiKey: null,
1028
+ authToken: apiKey,
1029
+ baseURL: model.baseUrl,
1030
+ dangerouslyAllowBrowser: true,
1031
+ defaultHeaders: mergeHeaders({
1032
+ accept: "application/json",
1033
+ "anthropic-dangerous-direct-browser-access": "true",
1034
+ ...betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}
1035
+ }, omitFoundryBearerCredentialHeaders(model.headers), dynamicHeaders, optionsHeaders),
1036
+ fetch
1037
+ }),
1038
+ isOAuthToken: false,
1039
+ serverSideFallback: false
1040
+ };
1041
+ if (isOAuthToken(apiKey)) return {
1042
+ client: new Anthropic({
1043
+ apiKey: null,
1044
+ authToken: apiKey,
1045
+ baseURL: model.baseUrl,
1046
+ dangerouslyAllowBrowser: true,
1047
+ defaultHeaders: mergeHeaders({
1048
+ accept: "application/json",
1049
+ "anthropic-dangerous-direct-browser-access": "true",
1050
+ "anthropic-beta": [
1051
+ "claude-code-20250219",
1052
+ "oauth-2025-04-20",
1053
+ ...betaFeatures
1054
+ ].join(","),
1055
+ "user-agent": `claude-cli/${claudeCodeVersion}`,
1056
+ "x-app": "cli"
1057
+ }, model.headers, optionsHeaders),
1058
+ fetch
1059
+ }),
1060
+ isOAuthToken: true,
1061
+ serverSideFallback: false
1062
+ };
1063
+ const serverSideFallback = supportsAnthropicServerSideFallback(model);
1064
+ if (serverSideFallback) betaFeatures.push(ANTHROPIC_SERVER_SIDE_FALLBACK_BETA);
1065
+ const sessionAffinityHeaders = sessionId && getAnthropicCompat(model).sendSessionAffinityHeaders ? { "x-session-affinity": sessionId } : {};
1066
+ return {
1067
+ client: new Anthropic({
1068
+ apiKey,
1069
+ authToken: null,
1070
+ baseURL: model.baseUrl,
1071
+ dangerouslyAllowBrowser: true,
1072
+ defaultHeaders: mergeHeaders({
1073
+ accept: "application/json",
1074
+ "anthropic-dangerous-direct-browser-access": "true",
1075
+ ...betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}
1076
+ }, sessionAffinityHeaders, model.headers, optionsHeaders),
1077
+ fetch
1078
+ }),
1079
+ isOAuthToken: false,
1080
+ serverSideFallback
1081
+ };
1082
+ }
1083
+ function buildParams(model, context, isOAuthTokenResult, options, serverSideFallback = false) {
1084
+ const mandatoryAdaptiveThinking = requiresClaudeAdaptiveThinking(model);
1085
+ const replayThinkingEnabled = mandatoryAdaptiveThinking || options?.thinkingEnabled === true;
1086
+ const { cacheControl } = getCacheControl(model, options?.cacheRetention);
1087
+ const system = buildAnthropicSystemBlocks(context.systemPrompt, isOAuthTokenResult, cacheControl);
1088
+ const compat = context.tools ? getAnthropicCompat(model) : void 0;
1089
+ const convertedTools = context.tools && compat ? convertTools(context.tools, isOAuthTokenResult, compat.supportsEagerToolInputStreaming, compat.supportsCacheControlOnTools ? cacheControl : void 0) : void 0;
1090
+ const tools = convertedTools?.tools;
1091
+ const toolProjection = convertedTools?.projection;
1092
+ const systemCacheControlCount = countNativeCacheControlMarkers(system);
1093
+ const toolCacheControlCount = countNativeCacheControlMarkers(tools);
1094
+ const messageCacheControlLimit = Math.max(0, ANTHROPIC_CACHE_CONTROL_LIMIT - systemCacheControlCount - toolCacheControlCount);
1095
+ const params = {
1096
+ model: model.id,
1097
+ messages: convertMessages(context.messages, model, isOAuthTokenResult, cacheControl, messageCacheControlLimit, replayThinkingEnabled),
1098
+ max_tokens: options?.maxTokens ?? model.maxTokens,
1099
+ stream: true
1100
+ };
1101
+ if (system) params.system = system;
1102
+ if (serverSideFallback) params.fallbacks = buildAnthropicServerSideFallbacks();
1103
+ if (options?.temperature !== void 0 && !options?.thinkingEnabled && !supportsNativeXhighEffort(model)) params.temperature = options.temperature;
1104
+ if (options?.stop !== void 0 && options.stop.length > 0) params.stop_sequences = options.stop;
1105
+ if (tools && tools.length > 0) params.tools = tools;
1106
+ if (mandatoryAdaptiveThinking || model.reasoning || supportsAdaptiveThinking(model)) {
1107
+ if (mandatoryAdaptiveThinking || options?.thinkingEnabled) {
1108
+ const display = options?.thinkingDisplay ?? "summarized";
1109
+ if (supportsAdaptiveThinking(model)) {
1110
+ params.thinking = {
1111
+ type: "adaptive",
1112
+ display
1113
+ };
1114
+ const effort = options?.effort ?? (mandatoryAdaptiveThinking ? "high" : void 0);
1115
+ if (effort) params.output_config = effort === "xhigh" ? { effort } : { effort };
1116
+ } else params.thinking = {
1117
+ type: "enabled",
1118
+ budget_tokens: options?.thinkingBudgetTokens ?? ANTHROPIC_MIN_THINKING_BUDGET_TOKENS,
1119
+ display
1120
+ };
1121
+ } else if (options?.thinkingEnabled === false) params.thinking = { type: "disabled" };
1122
+ }
1123
+ if (options?.metadata) {
1124
+ const userId = options.metadata.user_id;
1125
+ if (typeof userId === "string") params.metadata = { user_id: userId };
1126
+ }
1127
+ if (options?.toolChoice) {
1128
+ const normalizedToolChoice = normalizeAnthropicToolChoice(replayThinkingEnabled, options.toolChoice);
1129
+ const projectedToolChoice = toolProjection ? reconcileAnthropicToolChoice(normalizedToolChoice, toolProjection) : normalizedToolChoice;
1130
+ if (projectedToolChoice) params.tool_choice = projectedToolChoice;
1131
+ }
1132
+ return {
1133
+ params,
1134
+ toolProjection
1135
+ };
1136
+ }
1137
+ function normalizeToolCallId(id) {
1138
+ return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
1139
+ }
1140
+ function convertMessages(messages, model, isOAuthTokenValue, cacheControl, messageCacheControlLimit = 4, replayThinkingEnabled = true) {
1141
+ const params = [];
1142
+ const cacheBreakpointOptOutParamIndexes = /* @__PURE__ */ new Set();
1143
+ const transformedMessages = transformMessages(messages, model, normalizeToolCallId);
1144
+ const activeToolTurnAssistantIndex = replayThinkingEnabled ? -1 : findActiveAnthropicToolTurnAssistantIndex(transformedMessages);
1145
+ for (let i = 0; i < transformedMessages.length; i++) {
1146
+ const msg = transformedMessages[i];
1147
+ if (msg.role === "user") {
1148
+ const isRuntimeContextCarrier = msg.runtimeContextCarrier === true;
1149
+ if (typeof msg.content === "string") {
1150
+ if (msg.content.trim().length > 0) {
1151
+ if (isRuntimeContextCarrier) cacheBreakpointOptOutParamIndexes.add(params.length);
1152
+ params.push({
1153
+ role: "user",
1154
+ content: sanitizeSurrogates(msg.content)
1155
+ });
1156
+ }
1157
+ } else {
1158
+ const filteredBlocks = msg.content.map((item) => {
1159
+ if (item.type === "text") return {
1160
+ type: "text",
1161
+ text: sanitizeSurrogates(item.text)
1162
+ };
1163
+ return {
1164
+ type: "image",
1165
+ source: {
1166
+ type: "base64",
1167
+ media_type: item.mimeType,
1168
+ data: item.data
1169
+ }
1170
+ };
1171
+ }).filter((b) => {
1172
+ if (b.type === "text") return b.text.trim().length > 0;
1173
+ return true;
1174
+ });
1175
+ if (filteredBlocks.length === 0) continue;
1176
+ if (isRuntimeContextCarrier) cacheBreakpointOptOutParamIndexes.add(params.length);
1177
+ params.push({
1178
+ role: "user",
1179
+ content: filteredBlocks
1180
+ });
1181
+ }
1182
+ } else if (msg.role === "assistant") {
1183
+ const blocks = [];
1184
+ let omittedThinking = false;
1185
+ for (const block of msg.content) if (block.type === "text") {
1186
+ if (block.text.trim().length === 0) continue;
1187
+ blocks.push({
1188
+ type: "text",
1189
+ text: sanitizeSurrogates(block.text)
1190
+ });
1191
+ } else if (block.type === "thinking") {
1192
+ if (!replayThinkingEnabled && i !== activeToolTurnAssistantIndex) {
1193
+ omittedThinking = true;
1194
+ continue;
1195
+ }
1196
+ if (block.redacted) {
1197
+ blocks.push({
1198
+ type: "redacted_thinking",
1199
+ data: block.thinkingSignature
1200
+ });
1201
+ continue;
1202
+ }
1203
+ const thinkingSignature = block.thinkingSignature?.trim();
1204
+ const hasNativeThinkingSignature = Boolean(thinkingSignature) && thinkingSignature !== "reasoning_content";
1205
+ if (block.thinking.trim().length === 0 && !hasNativeThinkingSignature) continue;
1206
+ if (!thinkingSignature) blocks.push({
1207
+ type: "text",
1208
+ text: sanitizeSurrogates(block.thinking)
1209
+ });
1210
+ else {
1211
+ if (thinkingSignature === "reasoning_content") continue;
1212
+ blocks.push({
1213
+ type: "thinking",
1214
+ thinking: block.thinking,
1215
+ signature: thinkingSignature
1216
+ });
1217
+ }
1218
+ } else if (block.type === "toolCall") blocks.push({
1219
+ type: "tool_use",
1220
+ id: block.id,
1221
+ name: isOAuthTokenValue ? toClaudeCodeName(block.name) : block.name,
1222
+ input: block.arguments ?? {}
1223
+ });
1224
+ if (blocks.length === 0 && omittedThinking) blocks.push({
1225
+ type: "text",
1226
+ text: ANTHROPIC_OMITTED_REASONING_TEXT
1227
+ });
1228
+ if (blocks.length === 0) continue;
1229
+ params.push({
1230
+ role: "assistant",
1231
+ content: blocks
1232
+ });
1233
+ } else if (msg.role === "toolResult") {
1234
+ const toolResults = [];
1235
+ toolResults.push({
1236
+ type: "tool_result",
1237
+ tool_use_id: msg.toolCallId,
1238
+ content: convertContentBlocks(msg.content, msg.isError),
1239
+ is_error: msg.isError
1240
+ });
1241
+ let j = i + 1;
1242
+ while (j < transformedMessages.length && transformedMessages[j].role === "toolResult") {
1243
+ const nextMsg = transformedMessages[j];
1244
+ toolResults.push({
1245
+ type: "tool_result",
1246
+ tool_use_id: nextMsg.toolCallId,
1247
+ content: convertContentBlocks(nextMsg.content, nextMsg.isError),
1248
+ is_error: nextMsg.isError
1249
+ });
1250
+ j++;
1251
+ }
1252
+ i = j - 1;
1253
+ params.push({
1254
+ role: "user",
1255
+ content: toolResults
1256
+ });
1257
+ }
1258
+ }
1259
+ if (cacheControl && params.length > 0 && messageCacheControlLimit > 0) {
1260
+ let fallbackToolResult;
1261
+ for (let i = params.length - 1; i >= 0; i--) {
1262
+ const message = params[i];
1263
+ if (message.role !== "user" || cacheBreakpointOptOutParamIndexes.has(i)) continue;
1264
+ if (Array.isArray(message.content)) {
1265
+ for (let j = message.content.length - 1; j >= 0; j--) {
1266
+ const block = message.content[j];
1267
+ if (block.type === "text" || block.type === "image") {
1268
+ if (fallbackToolResult && messageCacheControlLimit === 1) {
1269
+ applyContentBlockCacheControl(fallbackToolResult, cacheControl);
1270
+ return params;
1271
+ }
1272
+ applyContentBlockCacheControl(block, cacheControl);
1273
+ if (fallbackToolResult && messageCacheControlLimit > 1) applyContentBlockCacheControl(fallbackToolResult, cacheControl);
1274
+ return params;
1275
+ }
1276
+ if (block.type === "tool_result" && fallbackToolResult === void 0) fallbackToolResult = block;
1277
+ }
1278
+ continue;
1279
+ }
1280
+ if (typeof message.content === "string") {
1281
+ if (fallbackToolResult && messageCacheControlLimit === 1) {
1282
+ applyContentBlockCacheControl(fallbackToolResult, cacheControl);
1283
+ return params;
1284
+ }
1285
+ message.content = [{
1286
+ type: "text",
1287
+ text: message.content,
1288
+ cache_control: cacheControl
1289
+ }];
1290
+ if (fallbackToolResult && messageCacheControlLimit > 1) applyContentBlockCacheControl(fallbackToolResult, cacheControl);
1291
+ return params;
1292
+ }
1293
+ }
1294
+ if (fallbackToolResult) applyContentBlockCacheControl(fallbackToolResult, cacheControl);
1295
+ }
1296
+ return params;
1297
+ }
1298
+ function applyContentBlockCacheControl(block, cacheControl) {
1299
+ block.cache_control = cacheControl;
1300
+ }
1301
+ function buildAnthropicSystemBlocks(systemPrompt, isOAuthTokenResult, cacheControl) {
1302
+ const blocks = [];
1303
+ if (isOAuthTokenResult) {
1304
+ blocks.push({
1305
+ type: "text",
1306
+ text: claudeCodeBillingSystemBlock
1307
+ });
1308
+ blocks.push({
1309
+ type: "text",
1310
+ text: "You are Claude Code, Anthropic's official CLI for Claude.",
1311
+ ...cacheControl ? { cache_control: cacheControl } : {}
1312
+ });
1313
+ }
1314
+ if (systemPrompt) blocks.push(...buildSystemPromptBlocks(systemPrompt, cacheControl));
1315
+ return blocks.length > 0 ? blocks : void 0;
1316
+ }
1317
+ function buildSystemPromptBlocks(systemPrompt, cacheControl) {
1318
+ if (!cacheControl) return [{
1319
+ type: "text",
1320
+ text: sanitizeSurrogates(stripSystemPromptCacheBoundary(systemPrompt))
1321
+ }];
1322
+ const split = splitSystemPromptCacheBoundary(systemPrompt);
1323
+ if (!split) return [{
1324
+ type: "text",
1325
+ text: sanitizeSurrogates(systemPrompt),
1326
+ cache_control: cacheControl
1327
+ }];
1328
+ const blocks = [];
1329
+ if (split.stablePrefix) blocks.push({
1330
+ type: "text",
1331
+ text: sanitizeSurrogates(split.stablePrefix),
1332
+ cache_control: cacheControl
1333
+ });
1334
+ if (split.dynamicSuffix) blocks.push({
1335
+ type: "text",
1336
+ text: sanitizeSurrogates(split.dynamicSuffix)
1337
+ });
1338
+ return blocks.length > 0 ? blocks : [{
1339
+ type: "text",
1340
+ text: ""
1341
+ }];
1342
+ }
1343
+ function countNativeCacheControlMarkers(blocks) {
1344
+ if (!Array.isArray(blocks)) return 0;
1345
+ let count = 0;
1346
+ for (const block of blocks) if (block && typeof block === "object" && "cache_control" in block) count += 1;
1347
+ return count;
1348
+ }
1349
+ function shouldUseFineGrainedToolStreamingBeta(model, context) {
1350
+ return Boolean(context.tools?.length) && !getAnthropicCompat(model).supportsEagerToolInputStreaming;
1351
+ }
1352
+ function convertTools(tools, isOAuthTokenLocal, supportsEagerToolInputStreaming, cacheControl) {
1353
+ const projection = projectAnthropicTools(tools, (name) => isOAuthTokenLocal ? toClaudeCodeName(name) : name);
1354
+ const convertedTools = [];
1355
+ for (const [index, tool] of projection.tools.entries()) {
1356
+ const convertedTool = {
1357
+ name: tool.wireName,
1358
+ description: tool.description,
1359
+ input_schema: tool.inputSchema
1360
+ };
1361
+ if (supportsEagerToolInputStreaming) convertedTool.eager_input_streaming = true;
1362
+ if (cacheControl && index === projection.tools.length - 1) convertedTool.cache_control = cacheControl;
1363
+ convertedTools.push(convertedTool);
1364
+ }
1365
+ return {
1366
+ projection,
1367
+ tools: convertedTools
1368
+ };
1369
+ }
1370
+ function mapStopReason(reason) {
1371
+ switch (reason) {
1372
+ case "end_turn": return "stop";
1373
+ case "max_tokens": return "length";
1374
+ case "tool_use": return "toolUse";
1375
+ case "refusal": return "error";
1376
+ case "pause_turn": return "stop";
1377
+ case "stop_sequence": return "stop";
1378
+ case "sensitive": return "error";
1379
+ default: throw new Error(`Unhandled stop reason: ${reason}`);
1380
+ }
1381
+ }
1382
+ //#endregion
1383
+ export { readAnthropicFallbackBoundary as _, readAnthropicUsageTokenCount as a, usesFoundryBearerAuth as b, reconcileAnthropicToolChoice as c, findActiveAnthropicToolTurnAssistantIndex as d, ANTHROPIC_SERVER_SIDE_FALLBACK_BETA as f, buildAnthropicServerSideFallbacks as g, applyAnthropicFallbackBoundary as h, readAnthropicPromptUsageSnapshot as i, resolveOriginalAnthropicToolName as l, CLAUDE_FABLE_5_FALLBACK_MODEL_COST as m, streamAnthropic as n, readLastAnthropicIterationUsage as o, CLAUDE_FABLE_5_FALLBACK_MODEL as p, streamSimpleAnthropic as r, projectAnthropicTools as s, anthropic_exports as t, ANTHROPIC_OMITTED_REASONING_TEXT as u, applyAnthropicRefusal as v, omitFoundryBearerCredentialHeaders as y };