@openclaw/ai 2026.9.2 → 2026.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/anthropic-CZy5U0NY.mjs +376 -0
- package/dist/{anthropic-payload-policy-d46X2pR0.d.mts → anthropic-payload-policy-wuRCb6MH.d.mts} +16 -6
- package/dist/{anthropic-compaction-replay-DB2FGLQc.mjs → anthropic-stream-reducer-B_yo_7pf.mjs} +923 -181
- package/dist/{api-registry-DWtPjzyn.d.mts → api-registry-CB1-1oQ2.d.mts} +2 -2
- package/dist/assistant-output-iqnlJCV2.mjs +16 -0
- package/dist/assistant-text-phase-C20rxWwP.mjs +55 -0
- package/dist/{azure-openai-responses-C5bZRfAP.mjs → azure-openai-responses-Crpa40QR.mjs} +5 -5
- package/dist/{base64-CEFBpSkN.mjs → base64-D-su8YVo.mjs} +1 -27
- package/dist/{diagnostics-DfFyKeX_.mjs → diagnostics-dV98PqIy.mjs} +96 -21
- package/dist/diagnostics.d.mts +3 -1
- package/dist/diagnostics.mjs +3 -3
- package/dist/{event-stream-BhT5T1Ay.d.mts → event-stream-C1Z2piyk.d.mts} +11 -3
- package/dist/{event-stream-BgDvQeum.mjs → event-stream-D8PARQfL.mjs} +45 -1
- package/dist/event-stream-I_GlBsuZ.d.mts +1 -0
- package/dist/event-stream.d.mts +2 -2
- package/dist/event-stream.mjs +1 -1
- package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-B37TB3rB.mjs} +3 -10
- package/dist/github-copilot-request-facts-BTEBMeOv.mjs +16 -0
- package/dist/{google-4qeuE8iX.mjs → google-BDPriaVe.mjs} +10 -10
- package/dist/google-messages-CVn9eFpF.mjs +449 -0
- package/dist/google-shared-BedY23XS.mjs +185 -0
- package/dist/{google-vertex-O9BcnB6X.mjs → google-vertex-DMz8XQCn.mjs} +7 -6
- package/dist/{host-CEvLw30U.mjs → host-CWuF-sS3.mjs} +44 -39
- package/dist/{host-DjzGmdZ2.d.mts → host-DK3wmS3e.d.mts} +3 -3
- package/dist/host-policy-CAopLRKA.mjs +37 -0
- package/dist/{index-FnHM2FcI.d.mts → index-CQ6LTHw8.d.mts} +3 -3
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +4 -4
- package/dist/internal/anthropic.d.mts +7 -7
- package/dist/internal/anthropic.mjs +4 -4
- package/dist/internal/google-model-family.d.mts +5 -0
- package/dist/internal/google-model-family.mjs +15 -0
- package/dist/internal/openai-responses-payload-policy.d.mts +1 -1
- package/dist/internal/openai-responses-payload-policy.mjs +1 -1
- package/dist/internal/openai.d.mts +8 -103
- package/dist/internal/openai.mjs +10 -10
- package/dist/internal/retry-after.d.mts +2 -4
- package/dist/internal/retry-after.mjs +57 -8
- package/dist/internal/runtime.d.mts +7 -6
- package/dist/internal/runtime.mjs +8 -7
- package/dist/internal/shared.d.mts +14 -3
- package/dist/internal/shared.mjs +6 -4
- package/dist/internal/tool-schema.d.mts +63 -0
- package/dist/internal/tool-schema.mjs +3 -0
- package/dist/{json-parse-BuAJEbdW.mjs → json-parse-Dw_hnxsA.mjs} +1 -1
- package/dist/{mistral-Tb6oalqH.mjs → mistral--m-Jm6VZ.mjs} +13 -37
- package/dist/model-transport-url-DKocrEsb.d.mts +28 -0
- package/dist/{openai-chatgpt-responses-yUXjPNfu.mjs → openai-chatgpt-responses-nDZccFW-.mjs} +48 -38
- package/dist/openai-completions-KuoZyx0d.mjs +187 -0
- package/dist/{openai-completions-compat-CpjYUArk.d.mts → openai-completions-compat-CXn3T1we.d.mts} +26 -4
- package/dist/{openai-completions-stream-BsrBe3Gg.mjs → openai-completions-stream-BQk3SkLD.mjs} +622 -452
- package/dist/openai-prompt-cache-BI0rkM-5.mjs +220 -0
- package/dist/openai-prompt-cache-rrutvqxq.d.mts +16 -0
- package/dist/openai-provider-client-ha_WxTyj.mjs +24 -0
- package/dist/openai-reasoning-effort-BK7FbcLT.mjs +167 -0
- package/dist/{openai-responses-CCL41ALM.mjs → openai-responses-D99dOzKI.mjs} +14 -29
- package/dist/{openai-responses-compaction-window-BMVHFOtq.mjs → openai-responses-compaction-window-D5jbzCi3.mjs} +7 -170
- package/dist/{openai-responses-contracts-rF5DDRNS.d.mts → openai-responses-contracts-B55afwRo.d.mts} +3 -3
- package/dist/{openai-responses-prompt-observer-internal-D0bhBfgL.mjs → openai-responses-prompt-observer-internal-tApyTLVu.mjs} +3 -3
- package/dist/{openai-responses-shared-Bmma_3Qc.mjs → openai-responses-shared-ZyQEzS5i.mjs} +44 -115
- package/dist/openai-tool-projection-793cE3QX.d.mts +37 -0
- package/dist/{openai-tool-schema-_pTAJqKF.mjs → openai-tool-schema-CzjyYXun.mjs} +38 -556
- package/dist/openai-tool-schema-ynZBgqW-.d.mts +38 -0
- package/dist/openai-transport-params-DNasp2fU.mjs +674 -0
- package/dist/{provider-error-9TraxGvt.mjs → provider-error-C6TbKiey.mjs} +23 -6
- package/dist/{provider-options-Bcc_p-TU.d.mts → provider-options-BXr9Ec83.d.mts} +4 -39
- package/dist/{provider-transcript-transform-BaMbI1hr.mjs → provider-transcript-transform-pPmUIwKt.mjs} +1 -1
- package/dist/provider-types-CAV0Og3m.d.mts +29 -0
- package/dist/provider-types.d.mts +6 -31
- package/dist/providers.d.mts +2 -2
- package/dist/providers.mjs +11 -11
- package/dist/{reasoning-tag-text-partitioner-DLCNXki6.mjs → reasoning-tag-text-partitioner-BQBi4B9d.mjs} +19 -12
- package/dist/record-coerce-DwRYMj3t.mjs +32 -0
- package/dist/retry-after-CdCURCVg.d.mts +15 -0
- package/dist/{sanitize-unicode-D6xUvZaS.mjs → sanitize-unicode-Bb-v9meu.mjs} +1 -1
- package/dist/session-affinity-CCH7eYdB.mjs +20 -0
- package/dist/{simple-options-BjHCCh4v.mjs → simple-options-tcKOqnpF.mjs} +3 -3
- package/dist/{src-2qBGKg8O.mjs → src-B2Q_6G8V.mjs} +1 -1
- package/dist/{stream-first-event-timeout-DcNjoFQE.mjs → stream-first-event-timeout-2hfrquuz.mjs} +1 -1
- package/dist/string-coerce-fsri9iCu.mjs +34 -0
- package/dist/{string-normalization--fwJ4S2q.mjs → string-normalization-CmLIasuf.mjs} +1 -1
- package/dist/{tool-schema-json-projection-mJhXDcyz.mjs → tool-schema-json-projection-ClptDdAO.mjs} +2 -38
- package/dist/{transport-stream-shared-CZqMhfIw.mjs → transport-stream-shared-Cu3ZPhNW.mjs} +5 -5
- package/dist/{transport-stream-shared-xnaqxmbP.d.mts → transport-stream-shared-DOxpGJ-H.d.mts} +4 -4
- package/dist/transport-utils-CCooe-cr.mjs +121 -0
- package/dist/transports.d.mts +113 -41
- package/dist/transports.mjs +162 -1276
- package/dist/types-BADKjDBI.d.mts +1 -0
- package/dist/{types-CJ1-Ht7A.d.mts → types-Dy1q0CSu.d.mts} +72 -57
- package/dist/types.d.mts +5 -5
- package/dist/types.mjs +3 -3
- package/dist/utf16-slice-CvGodqok.mjs +29 -0
- package/dist/{validation-CJZtym2g.mjs → validation-BDzVDnTs.mjs} +9 -1
- package/dist/{validation-AKZBDGQd.d.mts → validation-CaFUZN9B.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +13 -3
- package/dist/anthropic-BDdqdVLK.mjs +0 -886
- package/dist/event-stream-zctLx0yr.d.mts +0 -1
- package/dist/google-shared-CWeG8RIl.mjs +0 -636
- package/dist/google-thinking-level-C-V3tecN.mjs +0 -9
- package/dist/openai-completions-BIUV3RDT.mjs +0 -403
- package/dist/openai-prompt-cache-CGnVB74a.mjs +0 -21
- package/dist/openai-prompt-cache-CNoIfHYC.d.mts +0 -16
- package/dist/transport-utils-7il795_9.mjs +0 -138
- package/dist/types-3Lnm-QSJ.d.mts +0 -1
- package/dist/utf16-slice-qz3nsy87.mjs +0 -84
package/dist/{anthropic-compaction-replay-DB2FGLQc.mjs → anthropic-stream-reducer-B_yo_7pf.mjs}
RENAMED
|
@@ -1,12 +1,20 @@
|
|
|
1
|
-
import { d as resolveClaudeModelIdentity, m as resolveClaudeOpus5ModelIdentity, u as resolveClaudeFable5ModelIdentity } from "./src-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { _ as supportsClaudeAdaptiveThinking, b as supportsClaudeNativeXhighEffort, d as resolveClaudeModelIdentity, m as resolveClaudeOpus5ModelIdentity, u as resolveClaudeFable5ModelIdentity } from "./src-B2Q_6G8V.mjs";
|
|
2
|
+
import { r as appendAssistantThinking } from "./event-stream-D8PARQfL.mjs";
|
|
3
|
+
import { i as normalizeOptionalLowercaseString, r as normalizeNullableString } from "./string-coerce-fsri9iCu.mjs";
|
|
4
|
+
import { r as calculateCost, t as sanitizeSurrogates } from "./sanitize-unicode-Bb-v9meu.mjs";
|
|
5
|
+
import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, f as ANTHROPIC_CLAUDE_CODE_BILLING_SYSTEM_BLOCK, g as mapAnthropicStopReason, n as getAiTransportHost, s as extractToolResultBlockText, v as requiresClaudeAdaptiveThinking } from "./host-CWuF-sS3.mjs";
|
|
6
|
+
import { a as asRecord, o as isRecord, r as asOptionalObjectRecord, s as readStringField } from "./record-coerce-DwRYMj3t.mjs";
|
|
7
|
+
import { i as asNonNegativeFiniteNumber, n as estimateBase64DecodedBytes } from "./base64-D-su8YVo.mjs";
|
|
8
|
+
import { a as parsePositiveInteger } from "./transport-utils-CCooe-cr.mjs";
|
|
9
|
+
import { a as resolveProviderRequestCapabilities, i as resolveProviderEndpoint } from "./host-policy-CAopLRKA.mjs";
|
|
5
10
|
import { t as resolveCacheRetention } from "./cache-retention-0x979a5V.mjs";
|
|
6
|
-
import { d as stripSystemPromptCacheBoundary, m as sortPromptCacheToolsByName, u as splitSystemPromptCacheBoundary } from "./simple-options-
|
|
7
|
-
import {
|
|
8
|
-
import { s as
|
|
11
|
+
import { d as stripSystemPromptCacheBoundary, m as sortPromptCacheToolsByName, u as splitSystemPromptCacheBoundary } from "./simple-options-tcKOqnpF.mjs";
|
|
12
|
+
import { t as projectRuntimeToolInputSchema } from "./tool-schema-json-projection-ClptDdAO.mjs";
|
|
13
|
+
import { _ as transportAbortError, b as parseJsonObjectPreservingUnsafeIntegers, g as sanitizeTransportPayloadText, h as sanitizeNonEmptyTransportPayloadText, n as coerceTransportToolCallArguments, s as finalizeTerminalToolCallArguments } from "./transport-stream-shared-Cu3ZPhNW.mjs";
|
|
9
14
|
import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-BuSUaAk5.mjs";
|
|
15
|
+
import { i as tagPendingCommentaryText } from "./assistant-text-phase-C20rxWwP.mjs";
|
|
16
|
+
import { r as parseStreamingJson, t as createToolArgumentPreviewSchedule } from "./json-parse-Dw_hnxsA.mjs";
|
|
17
|
+
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
10
18
|
//#region packages/ai/src/providers/anthropic-auth-headers.ts
|
|
11
19
|
/** Inspect resolved credential shape for auth routing without exposing its value. */
|
|
12
20
|
function isAnthropicOAuthApiKey(apiKey) {
|
|
@@ -89,6 +97,48 @@ function resolveAnthropicEphemeralCacheControl(baseUrl, cacheRetention) {
|
|
|
89
97
|
...ttl ? { ttl } : {}
|
|
90
98
|
};
|
|
91
99
|
}
|
|
100
|
+
function resolveAnthropicCacheOptions(model, cacheRetention) {
|
|
101
|
+
const supportsLongCacheRetention = model.compat?.supportsLongCacheRetention ?? model.provider !== "fireworks";
|
|
102
|
+
const cacheControl = resolveAnthropicEphemeralCacheControl(model.baseUrl?.trim() || process.env.ANTHROPIC_BASE_URL?.trim() || "https://api.anthropic.com", cacheRetention);
|
|
103
|
+
return {
|
|
104
|
+
cacheControl: cacheControl && !supportsLongCacheRetention ? { type: "ephemeral" } : cacheControl,
|
|
105
|
+
supportsCacheControlOnTools: model.compat?.supportsCacheControlOnTools ?? model.provider !== "fireworks"
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function buildAnthropicSystemBlocks(systemPrompt, isOAuthToken, cacheControl) {
|
|
109
|
+
const blocks = systemPrompt ? [{
|
|
110
|
+
type: "text",
|
|
111
|
+
text: sanitizeSurrogates(systemPrompt)
|
|
112
|
+
}] : [];
|
|
113
|
+
if (cacheControl) applyAnthropicCacheControlToSystem(blocks, cacheControl);
|
|
114
|
+
else stripAnthropicSystemPromptBoundary(blocks);
|
|
115
|
+
if (systemPrompt && blocks.length === 0) blocks.push({
|
|
116
|
+
type: "text",
|
|
117
|
+
text: ""
|
|
118
|
+
});
|
|
119
|
+
if (isOAuthToken) {
|
|
120
|
+
const identityCacheControl = blocks.some((block) => block.cache_control) ? void 0 : cacheControl;
|
|
121
|
+
blocks.unshift({
|
|
122
|
+
type: "text",
|
|
123
|
+
text: ANTHROPIC_CLAUDE_CODE_BILLING_SYSTEM_BLOCK
|
|
124
|
+
}, {
|
|
125
|
+
type: "text",
|
|
126
|
+
text: "You are Claude Code, Anthropic's official CLI for Claude.",
|
|
127
|
+
...identityCacheControl ? { cache_control: identityCacheControl } : {}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return blocks.length > 0 ? blocks : void 0;
|
|
131
|
+
}
|
|
132
|
+
/** Allocate tool and history checkpoints around the prepared stable system blocks. */
|
|
133
|
+
function applyAnthropicRequestCacheControl(payload, cacheControl, supportsCacheControlOnTools, cacheBreakpointOptOutMessageIndexes = /* @__PURE__ */ new Set()) {
|
|
134
|
+
if (!cacheControl) return;
|
|
135
|
+
if (supportsCacheControlOnTools && Array.isArray(payload.tools)) {
|
|
136
|
+
const lastTool = payload.tools.at(-1);
|
|
137
|
+
if (isRecord(lastTool)) lastTool.cache_control = cacheControl;
|
|
138
|
+
}
|
|
139
|
+
const usedMarkers = countAnthropicCacheControlMarkers(payload.system) + countAnthropicCacheControlMarkers(payload.tools);
|
|
140
|
+
applyAnthropicCacheControlToMessages(payload.messages, cacheControl, ANTHROPIC_CACHE_CONTROL_LIMIT - usedMarkers, cacheBreakpointOptOutMessageIndexes);
|
|
141
|
+
}
|
|
92
142
|
function applyAnthropicCacheControlToSystem(system, cacheControl) {
|
|
93
143
|
if (!Array.isArray(system)) return;
|
|
94
144
|
const normalizedBlocks = [];
|
|
@@ -286,9 +336,7 @@ function applyAnthropicPayloadPolicyToParams(payloadObj, policy, cacheBreakpoint
|
|
|
286
336
|
if (policy.cacheControl) applyAnthropicCacheControlToSystem(payloadObj.system, policy.cacheControl);
|
|
287
337
|
else stripAnthropicSystemPromptBoundary(payloadObj.system);
|
|
288
338
|
applyAnthropicContextManagementEdits(payloadObj, policy);
|
|
289
|
-
|
|
290
|
-
const usedMarkers = countAnthropicCacheControlMarkers(payloadObj.system) + countAnthropicCacheControlMarkers(payloadObj.tools);
|
|
291
|
-
applyAnthropicCacheControlToMessages(payloadObj.messages, policy.cacheControl, ANTHROPIC_CACHE_CONTROL_LIMIT - usedMarkers, cacheBreakpointOptOutMessageIndexes);
|
|
339
|
+
applyAnthropicRequestCacheControl(payloadObj, policy.cacheControl, false, cacheBreakpointOptOutMessageIndexes);
|
|
292
340
|
}
|
|
293
341
|
/** @deprecated Anthropic-family provider payload helper; do not use from third-party plugins. */
|
|
294
342
|
function applyAnthropicEphemeralCacheControlMarkers(payloadObj, cacheControl = { type: "ephemeral" }) {
|
|
@@ -322,70 +370,6 @@ function applyAnthropicEphemeralCacheControlMarkers(payloadObj, cacheControl = {
|
|
|
322
370
|
}
|
|
323
371
|
}
|
|
324
372
|
//#endregion
|
|
325
|
-
//#region packages/ai/src/internal/anthropic-inline-images.ts
|
|
326
|
-
const ANTHROPIC_IMAGE_MEDIA_TYPE_SET = /* @__PURE__ */ new Set([
|
|
327
|
-
"image/jpeg",
|
|
328
|
-
"image/png",
|
|
329
|
-
"image/gif",
|
|
330
|
-
"image/webp"
|
|
331
|
-
]);
|
|
332
|
-
const ANTHROPIC_INLINE_IMAGES_DECODE_SAFETY_BYTES = 67108864;
|
|
333
|
-
function createAnthropicInlineImageBudget() {
|
|
334
|
-
return { totalBytes: 0 };
|
|
335
|
-
}
|
|
336
|
-
function resolveAnthropicImageMediaType(value) {
|
|
337
|
-
if (ANTHROPIC_IMAGE_MEDIA_TYPE_SET.has(value)) return value;
|
|
338
|
-
throw new Error(`Unsupported Anthropic image media type after normalization: ${value}`);
|
|
339
|
-
}
|
|
340
|
-
async function normalizeAnthropicInlineContent(content, budget) {
|
|
341
|
-
if (!content.some((block) => block.type === "image")) return content.filter((block) => block.type === "text");
|
|
342
|
-
const inputBytes = content.reduce((total, block) => block.type === "image" ? total + estimateBase64DecodedBytes(block.data) : total, 0);
|
|
343
|
-
if (budget.totalBytes + inputBytes > ANTHROPIC_INLINE_IMAGES_DECODE_SAFETY_BYTES) throw new Error("Anthropic inline images exceed the 64 MB aggregate decoded safety limit.");
|
|
344
|
-
const normalized = [];
|
|
345
|
-
for (const block of content) {
|
|
346
|
-
if (block.type !== "image") {
|
|
347
|
-
normalized.push(block);
|
|
348
|
-
continue;
|
|
349
|
-
}
|
|
350
|
-
const normalizedBlocks = await getAiTransportHost().normalizeAnthropicInlineContentBlocks([block]);
|
|
351
|
-
const outputBytes = normalizedBlocks.reduce((total, normalizedBlock) => normalizedBlock.type === "image" ? total + estimateBase64DecodedBytes(normalizedBlock.data) : total, 0);
|
|
352
|
-
if (budget.totalBytes + outputBytes > ANTHROPIC_INLINE_IMAGES_DECODE_SAFETY_BYTES) throw new Error("Anthropic inline images exceed the 64 MB aggregate decoded safety limit.");
|
|
353
|
-
budget.totalBytes += outputBytes;
|
|
354
|
-
normalized.push(...normalizedBlocks);
|
|
355
|
-
}
|
|
356
|
-
return normalized;
|
|
357
|
-
}
|
|
358
|
-
//#endregion
|
|
359
|
-
//#region packages/ai/src/providers/anthropic-refusal.ts
|
|
360
|
-
function readAnthropicRefusalDetails(value) {
|
|
361
|
-
if (!value || typeof value !== "object") return {
|
|
362
|
-
category: null,
|
|
363
|
-
explanation: null
|
|
364
|
-
};
|
|
365
|
-
const details = value;
|
|
366
|
-
return {
|
|
367
|
-
category: normalizeNullableString(details.category),
|
|
368
|
-
explanation: normalizeNullableString(details.explanation)
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
function formatAnthropicRefusalMessage(details) {
|
|
372
|
-
return `Anthropic refusal${details.category ? ` (category: ${details.category})` : ""}${details.explanation ? `: ${details.explanation}` : "."}`;
|
|
373
|
-
}
|
|
374
|
-
function applyAnthropicRefusal(output, stopDetails, provider) {
|
|
375
|
-
const details = readAnthropicRefusalDetails(stopDetails);
|
|
376
|
-
output.stopReason = "error";
|
|
377
|
-
output.errorMessage = formatAnthropicRefusalMessage(details);
|
|
378
|
-
output.diagnostics = [...output.diagnostics ?? [], {
|
|
379
|
-
type: "provider_refusal",
|
|
380
|
-
timestamp: Date.now(),
|
|
381
|
-
details: {
|
|
382
|
-
provider,
|
|
383
|
-
category: details.category,
|
|
384
|
-
explanation: details.explanation
|
|
385
|
-
}
|
|
386
|
-
}];
|
|
387
|
-
}
|
|
388
|
-
//#endregion
|
|
389
373
|
//#region packages/ai/src/providers/anthropic-server-fallback.ts
|
|
390
374
|
/** Anthropic beta that re-serves safety refusals on an allowed fallback model. */
|
|
391
375
|
const ANTHROPIC_SERVER_SIDE_FALLBACK_BETA = "server-side-fallback-2026-07-01";
|
|
@@ -594,11 +578,13 @@ function normalizeAnthropicJsonSchema(schema) {
|
|
|
594
578
|
delete normalized.additionalItems;
|
|
595
579
|
changed = true;
|
|
596
580
|
}
|
|
581
|
+
if (changed) delete normalized.$schema;
|
|
597
582
|
return changed ? normalized : schema;
|
|
598
583
|
}
|
|
599
584
|
/** Snapshots direct/custom tool descriptors before Anthropic payload construction. */
|
|
600
585
|
function projectAnthropicTools(tools, toWireName) {
|
|
601
586
|
const projectedTools = [];
|
|
587
|
+
const originalNameByWireName = /* @__PURE__ */ new Map();
|
|
602
588
|
const unavailableOriginalNames = /* @__PURE__ */ new Set();
|
|
603
589
|
for (const tool of tools) {
|
|
604
590
|
let projectedTool;
|
|
@@ -632,6 +618,7 @@ function projectAnthropicTools(tools, toWireName) {
|
|
|
632
618
|
wireName: toWireName(name),
|
|
633
619
|
...description ? { description } : {},
|
|
634
620
|
inputSchema: {
|
|
621
|
+
...anthropicSchema,
|
|
635
622
|
type: "object",
|
|
636
623
|
properties: properties ?? {},
|
|
637
624
|
required: required ?? []
|
|
@@ -641,8 +628,9 @@ function projectAnthropicTools(tools, toWireName) {
|
|
|
641
628
|
if (originalName) unavailableOriginalNames.add(originalName);
|
|
642
629
|
continue;
|
|
643
630
|
}
|
|
644
|
-
const
|
|
645
|
-
if (
|
|
631
|
+
const conflictingName = originalNameByWireName.get(projectedTool.wireName);
|
|
632
|
+
if (conflictingName !== void 0 && conflictingName !== projectedTool.originalName) throw new Error(`Anthropic tool names "${conflictingName}" and "${projectedTool.originalName}" both map to "${projectedTool.wireName}"`);
|
|
633
|
+
originalNameByWireName.set(projectedTool.wireName, projectedTool.originalName);
|
|
646
634
|
projectedTools.push(projectedTool);
|
|
647
635
|
}
|
|
648
636
|
return {
|
|
@@ -680,6 +668,423 @@ function resolveOriginalAnthropicToolName(name, projection) {
|
|
|
680
668
|
return projection?.tools.find((tool) => tool.wireName === name)?.originalName ?? name;
|
|
681
669
|
}
|
|
682
670
|
//#endregion
|
|
671
|
+
//#region packages/ai/src/transports/anthropic-compaction-replay.ts
|
|
672
|
+
const ANTHROPIC_COMPACTION_REPLAY_TYPE = "anthropic-compaction";
|
|
673
|
+
const ANTHROPIC_COMPACTION_SUPPRESSION_TYPE = "anthropic-compaction-suppression";
|
|
674
|
+
const ANTHROPIC_COMPACTION_SUPPRESSION_DATA = "rejected";
|
|
675
|
+
function createCompactionCapture(output, model, options) {
|
|
676
|
+
const pending = /* @__PURE__ */ new Map();
|
|
677
|
+
return {
|
|
678
|
+
begin(index, block, replayIndex) {
|
|
679
|
+
if (block?.type !== "compaction") return false;
|
|
680
|
+
const content = typeof block.content === "string" ? block.content : "";
|
|
681
|
+
pending.set(index, {
|
|
682
|
+
content,
|
|
683
|
+
replayIndex
|
|
684
|
+
});
|
|
685
|
+
return true;
|
|
686
|
+
},
|
|
687
|
+
delta(index, delta) {
|
|
688
|
+
const capture = pending.get(index);
|
|
689
|
+
if (!capture || delta?.type !== "compaction_delta") return false;
|
|
690
|
+
capture.content = typeof delta.content === "string" ? delta.content : capture.content;
|
|
691
|
+
return true;
|
|
692
|
+
},
|
|
693
|
+
complete(index) {
|
|
694
|
+
const capture = pending.get(index);
|
|
695
|
+
if (!capture) return false;
|
|
696
|
+
pending.delete(index);
|
|
697
|
+
captureAnthropicCompaction(output, capture.content, capture.replayIndex, model, options);
|
|
698
|
+
return true;
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
function isAnthropicCompactionState(state) {
|
|
703
|
+
if (state.v !== 1 || typeof state.data !== "string" || typeof state.provider !== "string" || typeof state.api !== "string" || typeof state.model !== "string" || typeof state.baseUrlHash !== "string" || state.sessionHash !== void 0 && typeof state.sessionHash !== "string" || state.authProfileHash !== void 0 && typeof state.authProfileHash !== "string") return false;
|
|
704
|
+
if (state.type === ANTHROPIC_COMPACTION_SUPPRESSION_TYPE) return state.data === ANTHROPIC_COMPACTION_SUPPRESSION_DATA;
|
|
705
|
+
return state.type === ANTHROPIC_COMPACTION_REPLAY_TYPE && state.data.length > 0 && (state.replayIndex === void 0 || typeof state.replayIndex === "number" && Number.isSafeInteger(state.replayIndex) && state.replayIndex >= 0);
|
|
706
|
+
}
|
|
707
|
+
function readAnthropicCompactionState(value) {
|
|
708
|
+
return isRecord(value) && isAnthropicCompactionState(value) ? value : void 0;
|
|
709
|
+
}
|
|
710
|
+
function captureAnthropicCompaction(output, summary, replayIndex, model, options) {
|
|
711
|
+
const context = buildProviderReplayContext(model, options);
|
|
712
|
+
if (!summary || !context.baseUrlHash || !Number.isSafeInteger(replayIndex) || replayIndex < 0) return;
|
|
713
|
+
output.providerReplay = {
|
|
714
|
+
v: 1,
|
|
715
|
+
type: ANTHROPIC_COMPACTION_REPLAY_TYPE,
|
|
716
|
+
data: summary,
|
|
717
|
+
replayIndex,
|
|
718
|
+
...context,
|
|
719
|
+
baseUrlHash: context.baseUrlHash
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
function suppressAnthropicCompaction(output, model, options) {
|
|
723
|
+
const context = buildProviderReplayContext(model, options);
|
|
724
|
+
if (!context.baseUrlHash) return;
|
|
725
|
+
output.providerReplay = {
|
|
726
|
+
v: 1,
|
|
727
|
+
type: ANTHROPIC_COMPACTION_SUPPRESSION_TYPE,
|
|
728
|
+
data: ANTHROPIC_COMPACTION_SUPPRESSION_DATA,
|
|
729
|
+
...context,
|
|
730
|
+
baseUrlHash: context.baseUrlHash
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
function resolveNewestAnthropicCompaction(messages, model, options) {
|
|
734
|
+
const context = buildProviderReplayContext(model, options);
|
|
735
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
736
|
+
const message = messages[index];
|
|
737
|
+
if (message?.role !== "assistant") continue;
|
|
738
|
+
const replayState = readAnthropicCompactionState(message.providerReplay);
|
|
739
|
+
if (replayState?.type === ANTHROPIC_COMPACTION_SUPPRESSION_TYPE) {
|
|
740
|
+
if (providerReplayContextMatches(replayState, context)) return;
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
if (message.providerReplay?.type !== ANTHROPIC_COMPACTION_REPLAY_TYPE) continue;
|
|
744
|
+
if (!replayState) return;
|
|
745
|
+
if (!providerReplayContextMatches(replayState, context)) return;
|
|
746
|
+
return {
|
|
747
|
+
owner: message,
|
|
748
|
+
replayIndex: replayState.replayIndex ?? 0,
|
|
749
|
+
summary: replayState.data
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
function buildAnthropicReplayPlan(messages, model, options) {
|
|
754
|
+
if (options?.enabled !== true) return { messages };
|
|
755
|
+
const checkpoint = resolveNewestAnthropicCompaction(messages, model, options);
|
|
756
|
+
if (!checkpoint) return { messages };
|
|
757
|
+
const ownerIndex = messages.indexOf(checkpoint.owner);
|
|
758
|
+
return {
|
|
759
|
+
messages: [{
|
|
760
|
+
...checkpoint.owner,
|
|
761
|
+
content: checkpoint.owner.content.slice(checkpoint.replayIndex)
|
|
762
|
+
}, ...messages.slice(ownerIndex + 1)],
|
|
763
|
+
compaction: {
|
|
764
|
+
type: "compaction",
|
|
765
|
+
content: checkpoint.summary
|
|
766
|
+
}
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
/** Match Anthropic's 400 response when a replay block is no longer accepted. */
|
|
770
|
+
function isAnthropicReplayRejection(error) {
|
|
771
|
+
if (!error || typeof error !== "object") return false;
|
|
772
|
+
const record = error;
|
|
773
|
+
const nested = record.error && typeof record.error === "object" && !Array.isArray(record.error) ? record.error : void 0;
|
|
774
|
+
const text = [
|
|
775
|
+
record.message,
|
|
776
|
+
record.code,
|
|
777
|
+
nested?.message,
|
|
778
|
+
nested?.code
|
|
779
|
+
].filter((value) => typeof value === "string").join(" ").toLowerCase();
|
|
780
|
+
return (record.status === 400 || text.startsWith("http 400:")) && (text.includes("compaction") || text.includes("context_management"));
|
|
781
|
+
}
|
|
782
|
+
//#endregion
|
|
783
|
+
//#region packages/ai/src/internal/anthropic-inline-images.ts
|
|
784
|
+
const ANTHROPIC_IMAGE_MEDIA_TYPE_SET = /* @__PURE__ */ new Set([
|
|
785
|
+
"image/jpeg",
|
|
786
|
+
"image/png",
|
|
787
|
+
"image/gif",
|
|
788
|
+
"image/webp"
|
|
789
|
+
]);
|
|
790
|
+
const ANTHROPIC_INLINE_IMAGES_DECODE_SAFETY_BYTES = 67108864;
|
|
791
|
+
function createAnthropicInlineImageBudget() {
|
|
792
|
+
return { totalBytes: 0 };
|
|
793
|
+
}
|
|
794
|
+
function resolveAnthropicImageMediaType(value) {
|
|
795
|
+
if (ANTHROPIC_IMAGE_MEDIA_TYPE_SET.has(value)) return value;
|
|
796
|
+
throw new Error(`Unsupported Anthropic image media type after normalization: ${value}`);
|
|
797
|
+
}
|
|
798
|
+
async function normalizeAnthropicInlineContent(content, budget) {
|
|
799
|
+
if (!content.some((block) => block.type === "image")) return content.filter((block) => block.type === "text");
|
|
800
|
+
const inputBytes = content.reduce((total, block) => block.type === "image" ? total + estimateBase64DecodedBytes(block.data) : total, 0);
|
|
801
|
+
if (budget.totalBytes + inputBytes > ANTHROPIC_INLINE_IMAGES_DECODE_SAFETY_BYTES) throw new Error("Anthropic inline images exceed the 64 MB aggregate decoded safety limit.");
|
|
802
|
+
const normalized = [];
|
|
803
|
+
for (const block of content) {
|
|
804
|
+
if (block.type !== "image") {
|
|
805
|
+
normalized.push(block);
|
|
806
|
+
continue;
|
|
807
|
+
}
|
|
808
|
+
const normalizedBlocks = await getAiTransportHost().normalizeAnthropicInlineContentBlocks([block]);
|
|
809
|
+
const outputBytes = normalizedBlocks.reduce((total, normalizedBlock) => normalizedBlock.type === "image" ? total + estimateBase64DecodedBytes(normalizedBlock.data) : total, 0);
|
|
810
|
+
if (budget.totalBytes + outputBytes > ANTHROPIC_INLINE_IMAGES_DECODE_SAFETY_BYTES) throw new Error("Anthropic inline images exceed the 64 MB aggregate decoded safety limit.");
|
|
811
|
+
budget.totalBytes += outputBytes;
|
|
812
|
+
normalized.push(...normalizedBlocks);
|
|
813
|
+
}
|
|
814
|
+
return normalized;
|
|
815
|
+
}
|
|
816
|
+
//#endregion
|
|
817
|
+
//#region packages/ai/src/transports/anthropic-messages.ts
|
|
818
|
+
const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
819
|
+
async function convertContentBlocks(content, model, imageBudget, profile, isError) {
|
|
820
|
+
const mediaPlaceholder = describeToolResultMediaPlaceholder(content);
|
|
821
|
+
if (!((profile === "provider" || model.input.includes("image")) && content.some(isImageWithMediaPayload))) return sanitizeNonEmptyTransportPayloadText(extractToolResultText(content), mediaPlaceholder ?? (profile === "transport" ? "(no output)" : isError ? "[tool error with no output]" : ""));
|
|
822
|
+
const blocks = [];
|
|
823
|
+
let hasTextBlock = false;
|
|
824
|
+
for (const block of content) {
|
|
825
|
+
const record = asOptionalObjectRecord(block);
|
|
826
|
+
if (!record) continue;
|
|
827
|
+
const blockText = extractToolResultBlockText(block);
|
|
828
|
+
if (blockText) {
|
|
829
|
+
blocks.push({
|
|
830
|
+
type: "text",
|
|
831
|
+
text: sanitizeTransportPayloadText(blockText)
|
|
832
|
+
});
|
|
833
|
+
hasTextBlock = true;
|
|
834
|
+
}
|
|
835
|
+
if (!isImageWithMediaPayload(record)) continue;
|
|
836
|
+
const [normalizedImage] = await normalizeAnthropicInlineContent([{
|
|
837
|
+
type: "image",
|
|
838
|
+
data: typeof record.data === "string" ? record.data : "",
|
|
839
|
+
mimeType: typeof record.mimeType === "string" ? record.mimeType : profile === "provider" ? "image/jpeg" : "image/png"
|
|
840
|
+
}], imageBudget);
|
|
841
|
+
if (normalizedImage?.type !== "image") continue;
|
|
842
|
+
blocks.push({
|
|
843
|
+
type: "image",
|
|
844
|
+
source: {
|
|
845
|
+
type: "base64",
|
|
846
|
+
media_type: resolveAnthropicImageMediaType(normalizedImage.mimeType),
|
|
847
|
+
data: normalizedImage.data
|
|
848
|
+
}
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
if (!hasTextBlock) blocks.unshift({
|
|
852
|
+
type: "text",
|
|
853
|
+
text: mediaPlaceholder ?? "(see attached image)"
|
|
854
|
+
});
|
|
855
|
+
return blocks;
|
|
856
|
+
}
|
|
857
|
+
async function convertAnthropicMessages(transformedMessages, model, isOAuthToken, options) {
|
|
858
|
+
const params = [];
|
|
859
|
+
const imageBudget = createAnthropicInlineImageBudget();
|
|
860
|
+
const allowReasoningContentReplay = options.allowReasoningContentReplay === true;
|
|
861
|
+
const replayThinkingEnabled = options.replayThinkingEnabled !== false;
|
|
862
|
+
const managed = options.profile === "transport";
|
|
863
|
+
const activeToolTurnAssistantIndex = replayThinkingEnabled ? -1 : findActiveAnthropicToolTurnAssistantIndex(transformedMessages);
|
|
864
|
+
for (let i = 0; i < transformedMessages.length; i += 1) {
|
|
865
|
+
const msg = transformedMessages[i];
|
|
866
|
+
if (!msg) continue;
|
|
867
|
+
if (msg.role === "user") {
|
|
868
|
+
if (typeof msg.content === "string") {
|
|
869
|
+
if (msg.content.trim().length > 0) {
|
|
870
|
+
const userParam = {
|
|
871
|
+
role: "user",
|
|
872
|
+
content: sanitizeTransportPayloadText(msg.content)
|
|
873
|
+
};
|
|
874
|
+
params.push(userParam);
|
|
875
|
+
}
|
|
876
|
+
continue;
|
|
877
|
+
}
|
|
878
|
+
const blocks = (!managed || model.input.includes("image") ? await normalizeAnthropicInlineContent(msg.content, imageBudget) : msg.content.map((item) => item.type === "image" ? {
|
|
879
|
+
type: "text",
|
|
880
|
+
text: NON_VISION_USER_IMAGE_PLACEHOLDER
|
|
881
|
+
} : item)).map((item) => item.type === "text" ? {
|
|
882
|
+
type: "text",
|
|
883
|
+
text: sanitizeTransportPayloadText(item.text)
|
|
884
|
+
} : {
|
|
885
|
+
type: "image",
|
|
886
|
+
source: {
|
|
887
|
+
type: "base64",
|
|
888
|
+
media_type: resolveAnthropicImageMediaType(item.mimeType),
|
|
889
|
+
data: item.data
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
let filteredBlocks = !managed || model.input.includes("image") ? blocks : blocks.filter((block) => block.type !== "image");
|
|
893
|
+
filteredBlocks = filteredBlocks.filter((block) => block.type !== "text" || block.text.trim().length > 0);
|
|
894
|
+
if (filteredBlocks.length === 0) continue;
|
|
895
|
+
const userParam = {
|
|
896
|
+
role: "user",
|
|
897
|
+
content: filteredBlocks
|
|
898
|
+
};
|
|
899
|
+
params.push(userParam);
|
|
900
|
+
continue;
|
|
901
|
+
}
|
|
902
|
+
if (msg.role === "assistant") {
|
|
903
|
+
const blocks = i === 0 && options.compaction ? [options.compaction] : [];
|
|
904
|
+
const reasoningContent = [];
|
|
905
|
+
let omittedThinking = false;
|
|
906
|
+
for (const block of msg.content) {
|
|
907
|
+
if (block.type === "text") {
|
|
908
|
+
if (block.text.trim().length > 0) blocks.push({
|
|
909
|
+
type: "text",
|
|
910
|
+
text: sanitizeTransportPayloadText(block.text)
|
|
911
|
+
});
|
|
912
|
+
continue;
|
|
913
|
+
}
|
|
914
|
+
if (block.type === "thinking") {
|
|
915
|
+
const thinkingSignature = block.thinkingSignature?.trim();
|
|
916
|
+
const isReasoningContent = thinkingSignature === "reasoning_content";
|
|
917
|
+
if (!replayThinkingEnabled && i !== activeToolTurnAssistantIndex && (!managed || !isReasoningContent)) {
|
|
918
|
+
omittedThinking = true;
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
921
|
+
if (block.redacted) {
|
|
922
|
+
if (!managed && !block.thinkingSignature) throw new Error("redacted thinking block is missing its opaque signature");
|
|
923
|
+
blocks.push({
|
|
924
|
+
type: "redacted_thinking",
|
|
925
|
+
data: block.thinkingSignature
|
|
926
|
+
});
|
|
927
|
+
continue;
|
|
928
|
+
}
|
|
929
|
+
const hasNativeThinkingSignature = Boolean(thinkingSignature) && !isReasoningContent;
|
|
930
|
+
if (block.thinking.trim().length === 0 && !hasNativeThinkingSignature) continue;
|
|
931
|
+
if (!thinkingSignature && !options.allowEmptySignature) blocks.push({
|
|
932
|
+
type: "text",
|
|
933
|
+
text: sanitizeTransportPayloadText(block.thinking)
|
|
934
|
+
});
|
|
935
|
+
else {
|
|
936
|
+
const thinking = thinkingSignature === "reasoning_content" ? sanitizeTransportPayloadText(block.thinking) : block.thinking;
|
|
937
|
+
if (thinkingSignature === "reasoning_content") {
|
|
938
|
+
if (allowReasoningContentReplay) {
|
|
939
|
+
blocks.push({
|
|
940
|
+
type: "thinking",
|
|
941
|
+
thinking,
|
|
942
|
+
signature: thinkingSignature ?? ""
|
|
943
|
+
});
|
|
944
|
+
reasoningContent.push(thinking);
|
|
945
|
+
}
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
blocks.push({
|
|
949
|
+
type: "thinking",
|
|
950
|
+
thinking,
|
|
951
|
+
signature: thinkingSignature ?? ""
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
continue;
|
|
955
|
+
}
|
|
956
|
+
if (block.type === "toolCall") blocks.push({
|
|
957
|
+
type: "tool_use",
|
|
958
|
+
id: block.id,
|
|
959
|
+
name: isOAuthToken ? toClaudeCodeToolName(block.name) : block.name,
|
|
960
|
+
input: managed ? coerceTransportToolCallArguments(block.arguments) : block.arguments ?? {}
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
if (blocks.length === 0 && omittedThinking) blocks.push({
|
|
964
|
+
type: "text",
|
|
965
|
+
text: ANTHROPIC_OMITTED_REASONING_TEXT
|
|
966
|
+
});
|
|
967
|
+
if (blocks.length > 0) {
|
|
968
|
+
const assistantMsg = {
|
|
969
|
+
role: "assistant",
|
|
970
|
+
content: blocks
|
|
971
|
+
};
|
|
972
|
+
if (reasoningContent.length > 0) assistantMsg.reasoning_content = reasoningContent.join("\n");
|
|
973
|
+
else if (allowReasoningContentReplay) blocks.unshift({
|
|
974
|
+
type: "thinking",
|
|
975
|
+
thinking: "",
|
|
976
|
+
signature: "reasoning_content"
|
|
977
|
+
});
|
|
978
|
+
params.push(assistantMsg);
|
|
979
|
+
}
|
|
980
|
+
continue;
|
|
981
|
+
}
|
|
982
|
+
if (msg.role === "toolResult") {
|
|
983
|
+
const toolResults = [];
|
|
984
|
+
let j = i;
|
|
985
|
+
while (j < transformedMessages.length) {
|
|
986
|
+
const nextMsg = transformedMessages.at(j);
|
|
987
|
+
if (nextMsg?.role !== "toolResult") break;
|
|
988
|
+
toolResults.push({
|
|
989
|
+
type: "tool_result",
|
|
990
|
+
tool_use_id: nextMsg.toolCallId,
|
|
991
|
+
content: await convertContentBlocks(nextMsg.content, model, imageBudget, options.profile, nextMsg.isError),
|
|
992
|
+
is_error: nextMsg.isError
|
|
993
|
+
});
|
|
994
|
+
j += 1;
|
|
995
|
+
}
|
|
996
|
+
i = j - 1;
|
|
997
|
+
params.push({
|
|
998
|
+
role: "user",
|
|
999
|
+
content: toolResults
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
return params;
|
|
1004
|
+
}
|
|
1005
|
+
/** Shared generation contract, after each entry point resolves its defaults and tool policy. */
|
|
1006
|
+
function buildAnthropicGenerationParams({ model, options, tools, toolProjection, profile }) {
|
|
1007
|
+
const params = {};
|
|
1008
|
+
const mandatoryAdaptiveThinking = requiresClaudeAdaptiveThinking(model);
|
|
1009
|
+
if (options?.temperature !== void 0 && !options?.thinkingEnabled && !supportsClaudeNativeXhighEffort(model)) params.temperature = options.temperature;
|
|
1010
|
+
if (options?.stop !== void 0 && options.stop.length > 0) params.stop_sequences = options.stop;
|
|
1011
|
+
if (tools && tools.length > 0) params.tools = tools;
|
|
1012
|
+
if (mandatoryAdaptiveThinking || model.reasoning || supportsClaudeAdaptiveThinking(model)) {
|
|
1013
|
+
if (mandatoryAdaptiveThinking || options?.thinkingEnabled) {
|
|
1014
|
+
const display = options?.thinkingDisplay ?? "summarized";
|
|
1015
|
+
if (supportsClaudeAdaptiveThinking(model)) {
|
|
1016
|
+
params.thinking = {
|
|
1017
|
+
type: "adaptive",
|
|
1018
|
+
display
|
|
1019
|
+
};
|
|
1020
|
+
const effort = options?.effort ?? (mandatoryAdaptiveThinking ? "high" : void 0);
|
|
1021
|
+
if (effort) params.output_config = { effort };
|
|
1022
|
+
} else params.thinking = {
|
|
1023
|
+
type: "enabled",
|
|
1024
|
+
budget_tokens: options?.thinkingBudgetTokens ?? 1024,
|
|
1025
|
+
...profile === "provider" ? { display } : {}
|
|
1026
|
+
};
|
|
1027
|
+
} else if (options?.thinkingEnabled === false) params.thinking = { type: "disabled" };
|
|
1028
|
+
}
|
|
1029
|
+
if (options?.metadata) {
|
|
1030
|
+
const userId = options.metadata.user_id;
|
|
1031
|
+
if (typeof userId === "string") params.metadata = { user_id: userId };
|
|
1032
|
+
}
|
|
1033
|
+
if (options?.toolChoice) {
|
|
1034
|
+
const normalizedToolChoice = normalizeAnthropicToolChoice(mandatoryAdaptiveThinking || options?.thinkingEnabled === true, options.toolChoice);
|
|
1035
|
+
const projectedToolChoice = toolProjection ? reconcileAnthropicToolChoice(normalizedToolChoice, toolProjection) : normalizedToolChoice;
|
|
1036
|
+
if (projectedToolChoice) params.tool_choice = projectedToolChoice;
|
|
1037
|
+
}
|
|
1038
|
+
return params;
|
|
1039
|
+
}
|
|
1040
|
+
function convertAnthropicTools(tools, isOAuthTokenLocal, supportsEagerToolInputStreaming = false) {
|
|
1041
|
+
const projection = projectAnthropicTools(tools, (name) => isOAuthTokenLocal ? toClaudeCodeToolName(name) : name);
|
|
1042
|
+
const convertedTools = [];
|
|
1043
|
+
for (const tool of projection.tools) {
|
|
1044
|
+
const convertedTool = {
|
|
1045
|
+
name: tool.wireName,
|
|
1046
|
+
description: tool.description,
|
|
1047
|
+
input_schema: tool.inputSchema
|
|
1048
|
+
};
|
|
1049
|
+
if (supportsEagerToolInputStreaming) convertedTool.eager_input_streaming = true;
|
|
1050
|
+
convertedTools.push(convertedTool);
|
|
1051
|
+
}
|
|
1052
|
+
return {
|
|
1053
|
+
projection,
|
|
1054
|
+
tools: convertedTools
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
//#endregion
|
|
1058
|
+
//#region packages/ai/src/providers/anthropic-refusal.ts
|
|
1059
|
+
function readAnthropicRefusalDetails(value) {
|
|
1060
|
+
if (!value || typeof value !== "object") return {
|
|
1061
|
+
category: null,
|
|
1062
|
+
explanation: null
|
|
1063
|
+
};
|
|
1064
|
+
const details = value;
|
|
1065
|
+
return {
|
|
1066
|
+
category: normalizeNullableString(details.category),
|
|
1067
|
+
explanation: normalizeNullableString(details.explanation)
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
function formatAnthropicRefusalMessage(details) {
|
|
1071
|
+
return `Anthropic refusal${details.category ? ` (category: ${details.category})` : ""}${details.explanation ? `: ${details.explanation}` : "."}`;
|
|
1072
|
+
}
|
|
1073
|
+
function applyAnthropicRefusal(output, stopDetails, provider) {
|
|
1074
|
+
const details = readAnthropicRefusalDetails(stopDetails);
|
|
1075
|
+
output.stopReason = "error";
|
|
1076
|
+
output.errorMessage = formatAnthropicRefusalMessage(details);
|
|
1077
|
+
output.diagnostics = [...output.diagnostics ?? [], {
|
|
1078
|
+
type: "provider_refusal",
|
|
1079
|
+
timestamp: Date.now(),
|
|
1080
|
+
details: {
|
|
1081
|
+
provider,
|
|
1082
|
+
category: details.category,
|
|
1083
|
+
explanation: details.explanation
|
|
1084
|
+
}
|
|
1085
|
+
}];
|
|
1086
|
+
}
|
|
1087
|
+
//#endregion
|
|
683
1088
|
//#region packages/ai/src/providers/anthropic-usage.ts
|
|
684
1089
|
function readAnthropicUsageTokenCount(value) {
|
|
685
1090
|
return asNonNegativeFiniteNumber(value);
|
|
@@ -812,116 +1217,453 @@ function applyAnthropicMessageDeltaUsage(target, usage, messageStartPromptUsage)
|
|
|
812
1217
|
} else target.contextUsage = { state: "unavailable" };
|
|
813
1218
|
}
|
|
814
1219
|
//#endregion
|
|
815
|
-
//#region packages/ai/src/transports/anthropic-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
const
|
|
819
|
-
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
1220
|
+
//#region packages/ai/src/transports/anthropic-stream-reducer.ts
|
|
1221
|
+
/** One Messages protocol reducer; entry points retain their established preview/replay contracts. */
|
|
1222
|
+
async function consumeAnthropicStream(params) {
|
|
1223
|
+
const { model, options, output, stream, refusalBuffer, isOAuthToken, toolProjection } = params;
|
|
1224
|
+
const managed = params.profile === "transport";
|
|
1225
|
+
const eventSink = refusalBuffer ?? stream;
|
|
1226
|
+
let costModel = model;
|
|
1227
|
+
let messageStartPromptUsage;
|
|
1228
|
+
let inputTransformations;
|
|
1229
|
+
const anthropicStream = params.events;
|
|
1230
|
+
try {
|
|
1231
|
+
const blocks = output.content;
|
|
1232
|
+
const blockIndexes = /* @__PURE__ */ new Map();
|
|
1233
|
+
const toolArgumentPreviewSchedules = /* @__PURE__ */ new WeakMap();
|
|
1234
|
+
const seededToolArguments = /* @__PURE__ */ new WeakMap();
|
|
1235
|
+
const sealedToolCalls = [];
|
|
1236
|
+
const compactionCapture = createCompactionCapture(output, model, options);
|
|
1237
|
+
const pendingThinkingSignatures = /* @__PURE__ */ new Map();
|
|
1238
|
+
const allowReasoningContentReplay = managed && resolveProviderEndpoint(model).endpointClass === "xiaomi-native";
|
|
1239
|
+
const reasoningContentThinkingBlocks = /* @__PURE__ */ new Map();
|
|
1240
|
+
const reasoningContentTextBlocks = /* @__PURE__ */ new Map();
|
|
1241
|
+
let sawMessageStop = false;
|
|
1242
|
+
const pendingTextEnds = [];
|
|
1243
|
+
const flushPendingTextEnds = () => {
|
|
1244
|
+
for (const event of pendingTextEnds) eventSink.push(event);
|
|
1245
|
+
pendingTextEnds.length = 0;
|
|
1246
|
+
};
|
|
1247
|
+
const emitTextEnd = (event) => {
|
|
1248
|
+
if (managed) pendingTextEnds.push(event);
|
|
1249
|
+
else eventSink.push(event);
|
|
1250
|
+
};
|
|
1251
|
+
const eventIndexKey = (eventIndex) => typeof eventIndex === "number" ? eventIndex : -1;
|
|
1252
|
+
const appendReasoningContentThinkingDelta = (eventIndex, rawText) => {
|
|
1253
|
+
if (typeof rawText !== "string") return false;
|
|
1254
|
+
const text = sanitizeTransportPayloadText(rawText);
|
|
1255
|
+
if (text.length === 0) return false;
|
|
1256
|
+
const key = eventIndexKey(eventIndex);
|
|
1257
|
+
let contentIndex = reasoningContentThinkingBlocks.get(key);
|
|
1258
|
+
let block = contentIndex === void 0 ? void 0 : blocks[contentIndex];
|
|
1259
|
+
if (!block || block.type !== "thinking") {
|
|
1260
|
+
block = {
|
|
1261
|
+
type: "thinking",
|
|
1262
|
+
thinking: "",
|
|
1263
|
+
thinkingSignature: "reasoning_content"
|
|
1264
|
+
};
|
|
1265
|
+
output.content.push(block);
|
|
1266
|
+
contentIndex = output.content.length - 1;
|
|
1267
|
+
reasoningContentThinkingBlocks.set(key, contentIndex);
|
|
1268
|
+
eventSink.push({
|
|
1269
|
+
type: "thinking_start",
|
|
1270
|
+
contentIndex,
|
|
1271
|
+
partial: output
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
if (contentIndex === void 0) return false;
|
|
1275
|
+
appendAssistantThinking(block, text);
|
|
1276
|
+
block.thinkingSignature = "reasoning_content";
|
|
1277
|
+
eventSink.push({
|
|
1278
|
+
type: "thinking_delta",
|
|
1279
|
+
contentIndex,
|
|
1280
|
+
delta: text,
|
|
1281
|
+
partial: output
|
|
828
1282
|
});
|
|
829
1283
|
return true;
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
1284
|
+
};
|
|
1285
|
+
const appendReasoningContentTextDelta = (eventIndex, rawText) => {
|
|
1286
|
+
if (typeof rawText !== "string") return false;
|
|
1287
|
+
const text = sanitizeTransportPayloadText(rawText);
|
|
1288
|
+
if (text.length === 0) return false;
|
|
1289
|
+
const key = eventIndexKey(eventIndex);
|
|
1290
|
+
let contentIndex = reasoningContentTextBlocks.get(key);
|
|
1291
|
+
let block = contentIndex === void 0 ? void 0 : blocks[contentIndex];
|
|
1292
|
+
if (!block || block.type !== "text") {
|
|
1293
|
+
block = {
|
|
1294
|
+
type: "text",
|
|
1295
|
+
text: ""
|
|
1296
|
+
};
|
|
1297
|
+
output.content.push(block);
|
|
1298
|
+
contentIndex = output.content.length - 1;
|
|
1299
|
+
reasoningContentTextBlocks.set(key, contentIndex);
|
|
1300
|
+
eventSink.push({
|
|
1301
|
+
type: "text_start",
|
|
1302
|
+
contentIndex,
|
|
1303
|
+
partial: output
|
|
1304
|
+
});
|
|
1305
|
+
}
|
|
1306
|
+
if (contentIndex === void 0) return false;
|
|
1307
|
+
block.text += text;
|
|
1308
|
+
eventSink.push({
|
|
1309
|
+
type: "text_delta",
|
|
1310
|
+
contentIndex,
|
|
1311
|
+
delta: text,
|
|
1312
|
+
partial: output
|
|
1313
|
+
});
|
|
842
1314
|
return true;
|
|
1315
|
+
};
|
|
1316
|
+
const finishReasoningContentSidecars = (eventIndex) => {
|
|
1317
|
+
const key = eventIndexKey(eventIndex);
|
|
1318
|
+
const thinkingContentIndex = reasoningContentThinkingBlocks.get(key);
|
|
1319
|
+
if (thinkingContentIndex !== void 0) {
|
|
1320
|
+
reasoningContentThinkingBlocks.delete(key);
|
|
1321
|
+
const block = output.content[thinkingContentIndex];
|
|
1322
|
+
if (block?.type === "thinking") eventSink.push({
|
|
1323
|
+
type: "thinking_end",
|
|
1324
|
+
contentIndex: thinkingContentIndex,
|
|
1325
|
+
content: block.thinking,
|
|
1326
|
+
partial: output
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
const textContentIndex = reasoningContentTextBlocks.get(key);
|
|
1330
|
+
if (textContentIndex === void 0) return;
|
|
1331
|
+
reasoningContentTextBlocks.delete(key);
|
|
1332
|
+
const block = output.content[textContentIndex];
|
|
1333
|
+
if (block?.type === "text") eventSink.push({
|
|
1334
|
+
type: "text_end",
|
|
1335
|
+
contentIndex: textContentIndex,
|
|
1336
|
+
content: block.text,
|
|
1337
|
+
partial: output
|
|
1338
|
+
});
|
|
1339
|
+
};
|
|
1340
|
+
for await (const rawEvent of anthropicStream) {
|
|
1341
|
+
const event = asRecord(rawEvent);
|
|
1342
|
+
inputTransformations = readAnthropicInputTransformations(event) ?? inputTransformations;
|
|
1343
|
+
if (managed) notifyLlmRequestActivity(options.signal);
|
|
1344
|
+
if (event.type === "error") {
|
|
1345
|
+
const error = asOptionalObjectRecord(event.error);
|
|
1346
|
+
throw new Error(readStringField(error, "message") || "Anthropic Messages stream failed");
|
|
1347
|
+
}
|
|
1348
|
+
if (event.type === "message_start") {
|
|
1349
|
+
const message = asOptionalObjectRecord(event.message);
|
|
1350
|
+
const usage = asRecord(message?.usage);
|
|
1351
|
+
output.responseId = typeof message?.id === "string" ? message.id : void 0;
|
|
1352
|
+
output.responseModel = typeof message?.model === "string" ? message.model : void 0;
|
|
1353
|
+
messageStartPromptUsage = applyAnthropicMessageStartUsage(output.usage, usage);
|
|
1354
|
+
calculateCost(costModel, output.usage);
|
|
1355
|
+
eventSink.push({
|
|
1356
|
+
type: "start",
|
|
1357
|
+
partial: output
|
|
1358
|
+
});
|
|
1359
|
+
continue;
|
|
1360
|
+
}
|
|
1361
|
+
if (event.type === "message_stop") {
|
|
1362
|
+
sawMessageStop = true;
|
|
1363
|
+
continue;
|
|
1364
|
+
}
|
|
1365
|
+
if (event.type === "content_block_start") {
|
|
1366
|
+
const contentBlock = asOptionalObjectRecord(event.content_block);
|
|
1367
|
+
const index = typeof event.index === "number" ? event.index : -1;
|
|
1368
|
+
if (options.anthropicServerCompaction === true && compactionCapture.begin(index, contentBlock, output.content.length)) continue;
|
|
1369
|
+
const fallbackBoundary = refusalBuffer ? readAnthropicFallbackBoundary(contentBlock) : null;
|
|
1370
|
+
if (fallbackBoundary) {
|
|
1371
|
+
refusalBuffer?.discard();
|
|
1372
|
+
sealedToolCalls.length = 0;
|
|
1373
|
+
pendingTextEnds.length = 0;
|
|
1374
|
+
blockIndexes.clear();
|
|
1375
|
+
pendingThinkingSignatures.clear();
|
|
1376
|
+
applyAnthropicFallbackBoundary({
|
|
1377
|
+
output,
|
|
1378
|
+
boundary: fallbackBoundary,
|
|
1379
|
+
provider: model.provider
|
|
1380
|
+
});
|
|
1381
|
+
costModel = {
|
|
1382
|
+
...model,
|
|
1383
|
+
cost: resolveAnthropicFallbackServingModelCost({
|
|
1384
|
+
requestedModelId: model.id,
|
|
1385
|
+
servingModelId: fallbackBoundary.toModel,
|
|
1386
|
+
requestedCost: model.cost
|
|
1387
|
+
})
|
|
1388
|
+
};
|
|
1389
|
+
calculateCost(costModel, output.usage);
|
|
1390
|
+
eventSink.push({
|
|
1391
|
+
type: "start",
|
|
1392
|
+
partial: output
|
|
1393
|
+
});
|
|
1394
|
+
for (const [i, block] of blocks.entries()) {
|
|
1395
|
+
if (block.type !== "text") continue;
|
|
1396
|
+
delete block.index;
|
|
1397
|
+
eventSink.push({
|
|
1398
|
+
type: "text_start",
|
|
1399
|
+
contentIndex: i,
|
|
1400
|
+
partial: output
|
|
1401
|
+
});
|
|
1402
|
+
if (block.text) eventSink.push({
|
|
1403
|
+
type: "text_delta",
|
|
1404
|
+
contentIndex: i,
|
|
1405
|
+
delta: block.text,
|
|
1406
|
+
partial: output
|
|
1407
|
+
});
|
|
1408
|
+
emitTextEnd({
|
|
1409
|
+
type: "text_end",
|
|
1410
|
+
contentIndex: i,
|
|
1411
|
+
content: block.text,
|
|
1412
|
+
partial: output
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1415
|
+
continue;
|
|
1416
|
+
}
|
|
1417
|
+
pendingThinkingSignatures.delete(index);
|
|
1418
|
+
if (contentBlock?.type === "text") {
|
|
1419
|
+
const text = typeof contentBlock.text === "string" ? sanitizeTransportPayloadText(contentBlock.text) : "";
|
|
1420
|
+
const block = {
|
|
1421
|
+
type: "text",
|
|
1422
|
+
text,
|
|
1423
|
+
index
|
|
1424
|
+
};
|
|
1425
|
+
output.content.push(block);
|
|
1426
|
+
const contentIndex = output.content.length - 1;
|
|
1427
|
+
blockIndexes.set(index, contentIndex);
|
|
1428
|
+
eventSink.push({
|
|
1429
|
+
type: "text_start",
|
|
1430
|
+
contentIndex,
|
|
1431
|
+
partial: output
|
|
1432
|
+
});
|
|
1433
|
+
if (text.length > 0) eventSink.push({
|
|
1434
|
+
type: "text_delta",
|
|
1435
|
+
contentIndex,
|
|
1436
|
+
delta: text,
|
|
1437
|
+
partial: output
|
|
1438
|
+
});
|
|
1439
|
+
continue;
|
|
1440
|
+
}
|
|
1441
|
+
if (contentBlock?.type === "thinking") {
|
|
1442
|
+
const thinking = typeof contentBlock.thinking === "string" ? contentBlock.thinking : "";
|
|
1443
|
+
const block = {
|
|
1444
|
+
type: "thinking",
|
|
1445
|
+
thinking,
|
|
1446
|
+
thinkingSignature: typeof contentBlock.signature === "string" ? contentBlock.signature : "",
|
|
1447
|
+
index
|
|
1448
|
+
};
|
|
1449
|
+
output.content.push(block);
|
|
1450
|
+
const contentIndex = output.content.length - 1;
|
|
1451
|
+
blockIndexes.set(index, contentIndex);
|
|
1452
|
+
eventSink.push({
|
|
1453
|
+
type: "thinking_start",
|
|
1454
|
+
contentIndex,
|
|
1455
|
+
partial: output
|
|
1456
|
+
});
|
|
1457
|
+
if (thinking.length > 0) eventSink.push({
|
|
1458
|
+
type: "thinking_delta",
|
|
1459
|
+
contentIndex,
|
|
1460
|
+
delta: thinking,
|
|
1461
|
+
partial: output
|
|
1462
|
+
});
|
|
1463
|
+
continue;
|
|
1464
|
+
}
|
|
1465
|
+
if (contentBlock?.type === "redacted_thinking") {
|
|
1466
|
+
const block = {
|
|
1467
|
+
type: "thinking",
|
|
1468
|
+
thinking: "[Reasoning redacted]",
|
|
1469
|
+
thinkingSignature: typeof contentBlock.data === "string" ? contentBlock.data : "",
|
|
1470
|
+
redacted: true,
|
|
1471
|
+
index
|
|
1472
|
+
};
|
|
1473
|
+
output.content.push(block);
|
|
1474
|
+
blockIndexes.set(index, output.content.length - 1);
|
|
1475
|
+
eventSink.push({
|
|
1476
|
+
type: "thinking_start",
|
|
1477
|
+
contentIndex: output.content.length - 1,
|
|
1478
|
+
partial: output
|
|
1479
|
+
});
|
|
1480
|
+
continue;
|
|
1481
|
+
}
|
|
1482
|
+
if (contentBlock?.type === "tool_use") {
|
|
1483
|
+
if (managed) tagPendingCommentaryText(output.content);
|
|
1484
|
+
flushPendingTextEnds();
|
|
1485
|
+
const block = {
|
|
1486
|
+
type: "toolCall",
|
|
1487
|
+
id: typeof contentBlock.id === "string" ? contentBlock.id : "",
|
|
1488
|
+
name: typeof contentBlock.name === "string" ? isOAuthToken ? resolveOriginalAnthropicToolName(contentBlock.name, toolProjection) : contentBlock.name : "",
|
|
1489
|
+
arguments: asRecord(contentBlock.input),
|
|
1490
|
+
partialJson: "",
|
|
1491
|
+
index
|
|
1492
|
+
};
|
|
1493
|
+
output.content.push(block);
|
|
1494
|
+
blockIndexes.set(index, output.content.length - 1);
|
|
1495
|
+
seededToolArguments.set(block, managed ? block.arguments : contentBlock.input ?? {});
|
|
1496
|
+
toolArgumentPreviewSchedules.set(block, createToolArgumentPreviewSchedule());
|
|
1497
|
+
eventSink.push({
|
|
1498
|
+
type: "toolcall_start",
|
|
1499
|
+
contentIndex: output.content.length - 1,
|
|
1500
|
+
partial: output
|
|
1501
|
+
});
|
|
1502
|
+
}
|
|
1503
|
+
continue;
|
|
1504
|
+
}
|
|
1505
|
+
if (event.type === "content_block_delta") {
|
|
1506
|
+
const delta = asOptionalObjectRecord(event.delta);
|
|
1507
|
+
const eventIndex = typeof event.index === "number" ? event.index : void 0;
|
|
1508
|
+
if (eventIndex !== void 0 && compactionCapture.delta(eventIndex, delta)) continue;
|
|
1509
|
+
let index = eventIndex === void 0 ? void 0 : blockIndexes.get(eventIndex);
|
|
1510
|
+
let block = index === void 0 ? void 0 : blocks[index];
|
|
1511
|
+
if (allowReasoningContentReplay) {
|
|
1512
|
+
const appendedThinking = appendReasoningContentThinkingDelta(event.index, delta?.reasoning_content);
|
|
1513
|
+
const hasNativeAnthropicDelta = delta?.type === "text_delta" && typeof delta.text === "string" || delta?.type === "thinking_delta" && typeof delta.thinking === "string" || delta?.type === "input_json_delta" && typeof delta.partial_json === "string" || delta?.type === "signature_delta" && typeof delta.signature === "string";
|
|
1514
|
+
let appendedContent = false;
|
|
1515
|
+
if (!hasNativeAnthropicDelta && typeof delta?.content === "string" && delta.content.length > 0) {
|
|
1516
|
+
const text = sanitizeTransportPayloadText(delta.content);
|
|
1517
|
+
if (text.length > 0) {
|
|
1518
|
+
if (block?.type === "text" && index !== void 0) {
|
|
1519
|
+
block.text += text;
|
|
1520
|
+
eventSink.push({
|
|
1521
|
+
type: "text_delta",
|
|
1522
|
+
contentIndex: index,
|
|
1523
|
+
delta: text,
|
|
1524
|
+
partial: output
|
|
1525
|
+
});
|
|
1526
|
+
appendedContent = true;
|
|
1527
|
+
} else appendedContent = appendReasoningContentTextDelta(event.index, text);
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
if ((appendedThinking || appendedContent) && !hasNativeAnthropicDelta) continue;
|
|
1531
|
+
}
|
|
1532
|
+
if (managed && !block && delta?.type === "text_delta" && typeof delta.text === "string") {
|
|
1533
|
+
block = {
|
|
1534
|
+
type: "text",
|
|
1535
|
+
text: "",
|
|
1536
|
+
index: typeof event.index === "number" ? event.index : blocks.length
|
|
1537
|
+
};
|
|
1538
|
+
output.content.push(block);
|
|
1539
|
+
index = output.content.length - 1;
|
|
1540
|
+
if (typeof event.index === "number") blockIndexes.set(event.index, index);
|
|
1541
|
+
eventSink.push({
|
|
1542
|
+
type: "text_start",
|
|
1543
|
+
contentIndex: index,
|
|
1544
|
+
partial: output
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1547
|
+
if (index === void 0) continue;
|
|
1548
|
+
if (block?.type === "text" && delta?.type === "text_delta" && typeof delta.text === "string") {
|
|
1549
|
+
block.text += delta.text;
|
|
1550
|
+
eventSink.push({
|
|
1551
|
+
type: "text_delta",
|
|
1552
|
+
contentIndex: index,
|
|
1553
|
+
delta: delta.text,
|
|
1554
|
+
partial: output
|
|
1555
|
+
});
|
|
1556
|
+
continue;
|
|
1557
|
+
}
|
|
1558
|
+
if (block?.type === "thinking" && delta?.type === "thinking_delta" && typeof delta.thinking === "string") {
|
|
1559
|
+
appendAssistantThinking(block, delta.thinking);
|
|
1560
|
+
eventSink.push({
|
|
1561
|
+
type: "thinking_delta",
|
|
1562
|
+
contentIndex: index,
|
|
1563
|
+
delta: delta.thinking,
|
|
1564
|
+
partial: output
|
|
1565
|
+
});
|
|
1566
|
+
continue;
|
|
1567
|
+
}
|
|
1568
|
+
if (block?.type === "toolCall" && delta?.type === "input_json_delta" && typeof delta.partial_json === "string") {
|
|
1569
|
+
const partialJson = `${block.partialJson ?? ""}${delta.partial_json}`;
|
|
1570
|
+
block.partialJson = partialJson;
|
|
1571
|
+
if (toolArgumentPreviewSchedules.get(block)?.(partialJson.length)) block.arguments = managed ? coerceTransportToolCallArguments(parseJsonObjectPreservingUnsafeIntegers(partialJson) ?? parseStreamingJson(partialJson)) : parseStreamingJson(partialJson);
|
|
1572
|
+
eventSink.push({
|
|
1573
|
+
type: "toolcall_delta",
|
|
1574
|
+
contentIndex: index,
|
|
1575
|
+
delta: delta.partial_json,
|
|
1576
|
+
partial: output
|
|
1577
|
+
});
|
|
1578
|
+
continue;
|
|
1579
|
+
}
|
|
1580
|
+
if (block?.type === "thinking" && delta?.type === "signature_delta" && typeof delta.signature === "string") {
|
|
1581
|
+
const signatureIndex = eventIndexKey(event.index);
|
|
1582
|
+
const pendingSignature = pendingThinkingSignatures.get(signatureIndex);
|
|
1583
|
+
if (pendingSignature === void 0) {
|
|
1584
|
+
block.thinkingSignature = "";
|
|
1585
|
+
pendingThinkingSignatures.set(signatureIndex, delta.signature);
|
|
1586
|
+
} else pendingThinkingSignatures.set(signatureIndex, pendingSignature + delta.signature);
|
|
1587
|
+
}
|
|
1588
|
+
continue;
|
|
1589
|
+
}
|
|
1590
|
+
if (event.type === "content_block_stop") {
|
|
1591
|
+
const eventIndex = typeof event.index === "number" ? event.index : void 0;
|
|
1592
|
+
if (eventIndex !== void 0 && compactionCapture.complete(eventIndex)) continue;
|
|
1593
|
+
const pendingSignature = eventIndex === void 0 ? void 0 : pendingThinkingSignatures.get(eventIndex);
|
|
1594
|
+
if (eventIndex !== void 0) pendingThinkingSignatures.delete(eventIndex);
|
|
1595
|
+
const index = eventIndex === void 0 ? void 0 : blockIndexes.get(eventIndex);
|
|
1596
|
+
const block = index === void 0 ? void 0 : blocks[index];
|
|
1597
|
+
if (eventIndex === void 0 || index === void 0 || !block) {
|
|
1598
|
+
finishReasoningContentSidecars(event.index);
|
|
1599
|
+
continue;
|
|
1600
|
+
}
|
|
1601
|
+
blockIndexes.delete(eventIndex);
|
|
1602
|
+
delete block.index;
|
|
1603
|
+
if (block.type === "text") {
|
|
1604
|
+
emitTextEnd({
|
|
1605
|
+
type: "text_end",
|
|
1606
|
+
contentIndex: index,
|
|
1607
|
+
content: block.text,
|
|
1608
|
+
partial: output
|
|
1609
|
+
});
|
|
1610
|
+
finishReasoningContentSidecars(event.index);
|
|
1611
|
+
continue;
|
|
1612
|
+
}
|
|
1613
|
+
if (block.type === "thinking") {
|
|
1614
|
+
if (pendingSignature !== void 0) block.thinkingSignature = pendingSignature;
|
|
1615
|
+
eventSink.push({
|
|
1616
|
+
type: "thinking_end",
|
|
1617
|
+
contentIndex: index,
|
|
1618
|
+
content: block.thinking,
|
|
1619
|
+
partial: output
|
|
1620
|
+
});
|
|
1621
|
+
finishReasoningContentSidecars(event.index);
|
|
1622
|
+
continue;
|
|
1623
|
+
}
|
|
1624
|
+
if (block.type === "toolCall") {
|
|
1625
|
+
sealedToolCalls.push({
|
|
1626
|
+
block,
|
|
1627
|
+
contentIndex: index
|
|
1628
|
+
});
|
|
1629
|
+
finishReasoningContentSidecars(event.index);
|
|
1630
|
+
}
|
|
1631
|
+
continue;
|
|
1632
|
+
}
|
|
1633
|
+
if (event.type === "message_delta") {
|
|
1634
|
+
logAnthropicContextEdits(event);
|
|
1635
|
+
const delta = asOptionalObjectRecord(event.delta);
|
|
1636
|
+
const usage = asOptionalObjectRecord(event.usage);
|
|
1637
|
+
if (typeof delta?.stop_reason === "string" && delta.stop_reason) {
|
|
1638
|
+
if (delta.stop_reason === "refusal") applyAnthropicRefusal(output, delta.stop_details, model.provider);
|
|
1639
|
+
else output.stopReason = mapAnthropicStopReason(delta.stop_reason);
|
|
1640
|
+
}
|
|
1641
|
+
applyAnthropicMessageDeltaUsage(output.usage, usage, messageStartPromptUsage);
|
|
1642
|
+
calculateCost(costModel, output.usage);
|
|
1643
|
+
if (managed && (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall"))) tagPendingCommentaryText(output.content);
|
|
1644
|
+
flushPendingTextEnds();
|
|
1645
|
+
}
|
|
843
1646
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
output.providerReplay = {
|
|
858
|
-
v: 1,
|
|
859
|
-
type: ANTHROPIC_COMPACTION_REPLAY_TYPE,
|
|
860
|
-
data: summary,
|
|
861
|
-
replayIndex,
|
|
862
|
-
...context,
|
|
863
|
-
baseUrlHash: context.baseUrlHash
|
|
864
|
-
};
|
|
865
|
-
}
|
|
866
|
-
function suppressAnthropicCompaction(output, model, options) {
|
|
867
|
-
const context = buildProviderReplayContext(model, options);
|
|
868
|
-
if (!context.baseUrlHash) return;
|
|
869
|
-
output.providerReplay = {
|
|
870
|
-
v: 1,
|
|
871
|
-
type: ANTHROPIC_COMPACTION_SUPPRESSION_TYPE,
|
|
872
|
-
data: ANTHROPIC_COMPACTION_SUPPRESSION_DATA,
|
|
873
|
-
...context,
|
|
874
|
-
baseUrlHash: context.baseUrlHash
|
|
875
|
-
};
|
|
876
|
-
}
|
|
877
|
-
function resolveNewestAnthropicCompaction(messages, model, options) {
|
|
878
|
-
const context = buildProviderReplayContext(model, options);
|
|
879
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
880
|
-
const message = messages[index];
|
|
881
|
-
if (message?.role !== "assistant") continue;
|
|
882
|
-
const replayState = readAnthropicCompactionState(message.providerReplay);
|
|
883
|
-
if (replayState?.type === ANTHROPIC_COMPACTION_SUPPRESSION_TYPE) {
|
|
884
|
-
if (providerReplayContextMatches(replayState, context)) return;
|
|
885
|
-
continue;
|
|
1647
|
+
if ((isDirectAnthropicModel(model) || !managed && refusalBuffer) && !sawMessageStop) throw new Error("Anthropic stream ended before message_stop");
|
|
1648
|
+
if (options.signal?.aborted) throw transportAbortError(options.signal);
|
|
1649
|
+
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
|
|
1650
|
+
if ([...blockIndexes.values()].some((index) => blocks[index]?.type === "toolCall")) throw new Error("Provider completed stream with an incomplete tool call");
|
|
1651
|
+
finalizeTerminalToolCallArguments(sealedToolCalls.map(({ block }) => block), (block) => block.partialJson && block.partialJson.length > 0 ? block.partialJson : seededToolArguments.get(block));
|
|
1652
|
+
for (const sealed of sealedToolCalls) {
|
|
1653
|
+
delete sealed.block.partialJson;
|
|
1654
|
+
eventSink.push({
|
|
1655
|
+
type: "toolcall_end",
|
|
1656
|
+
contentIndex: sealed.contentIndex,
|
|
1657
|
+
toolCall: sealed.block,
|
|
1658
|
+
partial: output
|
|
1659
|
+
});
|
|
886
1660
|
}
|
|
887
|
-
|
|
888
|
-
if (
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
replayIndex: replayState.replayIndex ?? 0,
|
|
893
|
-
summary: replayState.data
|
|
894
|
-
};
|
|
1661
|
+
refusalBuffer?.flush();
|
|
1662
|
+
if (managed && (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall"))) tagPendingCommentaryText(output.content);
|
|
1663
|
+
flushPendingTextEnds();
|
|
1664
|
+
} finally {
|
|
1665
|
+
logAnthropicThinkingDrops(inputTransformations);
|
|
895
1666
|
}
|
|
896
1667
|
}
|
|
897
|
-
function buildAnthropicReplayPlan(messages, model, options) {
|
|
898
|
-
if (options?.enabled !== true) return { messages };
|
|
899
|
-
const checkpoint = resolveNewestAnthropicCompaction(messages, model, options);
|
|
900
|
-
if (!checkpoint) return { messages };
|
|
901
|
-
const ownerIndex = messages.indexOf(checkpoint.owner);
|
|
902
|
-
return {
|
|
903
|
-
messages: [{
|
|
904
|
-
...checkpoint.owner,
|
|
905
|
-
content: checkpoint.owner.content.slice(checkpoint.replayIndex)
|
|
906
|
-
}, ...messages.slice(ownerIndex + 1)],
|
|
907
|
-
compaction: {
|
|
908
|
-
type: "compaction",
|
|
909
|
-
content: checkpoint.summary
|
|
910
|
-
}
|
|
911
|
-
};
|
|
912
|
-
}
|
|
913
|
-
/** Match Anthropic's 400 response when a replay block is no longer accepted. */
|
|
914
|
-
function isAnthropicReplayRejection(error) {
|
|
915
|
-
if (!error || typeof error !== "object") return false;
|
|
916
|
-
const record = error;
|
|
917
|
-
const nested = record.error && typeof record.error === "object" && !Array.isArray(record.error) ? record.error : void 0;
|
|
918
|
-
const text = [
|
|
919
|
-
record.message,
|
|
920
|
-
record.code,
|
|
921
|
-
nested?.message,
|
|
922
|
-
nested?.code
|
|
923
|
-
].filter((value) => typeof value === "string").join(" ").toLowerCase();
|
|
924
|
-
return (record.status === 400 || text.startsWith("http 400:")) && (text.includes("compaction") || text.includes("context_management"));
|
|
925
|
-
}
|
|
926
1668
|
//#endregion
|
|
927
|
-
export {
|
|
1669
|
+
export { applyAnthropicFallbackBoundary as A, logAnthropicContextEdits as B, applyAnthropicThinkingBindingControls as C, ANTHROPIC_SERVER_SIDE_FALLBACKS as D, readAnthropicInputTransformations as E, applyAnthropicPayloadPolicyToParams as F, resolveAnthropicServerCompactionPlan as G, resolveAnthropicContextManagementBetaHeader as H, applyAnthropicRequestCacheControl as I, usesFoundryBearerAuth as J, isAnthropicOAuthApiKey as K, buildAnthropicSystemBlocks as L, resolveAnthropicFallbackServingModelCost as M, applyAnthropicContextManagementToRequest as N, ANTHROPIC_SERVER_SIDE_FALLBACK_BETA as O, applyAnthropicEphemeralCacheControlMarkers as P, isAnthropicServerToolClearingEnabled as R, ANTHROPIC_OMITTED_REASONING_TEXT as S, logAnthropicThinkingDrops as T, resolveAnthropicEphemeralCacheControl as U, resolveAnthropicCacheOptions as V, resolveAnthropicPayloadPolicy as W, normalizeAnthropicToolChoice as _, readAnthropicPromptUsageSnapshot as a, resolveOriginalAnthropicToolName as b, applyAnthropicRefusal as c, convertAnthropicTools as d, buildAnthropicReplayPlan as f, normalizeAnthropicToolCallId as g, suppressAnthropicCompaction as h, readAnthropicCacheWriteUsage as i, readAnthropicFallbackBoundary as j, CLAUDE_OPUS_FALLBACK_MODEL_COST as k, buildAnthropicGenerationParams as l, resolveNewestAnthropicCompaction as m, applyAnthropicMessageDeltaUsage as n, readAnthropicUsageTokenCount as o, isAnthropicReplayRejection as p, omitFoundryBearerCredentialHeaders as q, applyAnthropicMessageStartUsage as r, readLastAnthropicIterationUsage as s, consumeAnthropicStream as t, convertAnthropicMessages as u, projectAnthropicTools as v, findActiveAnthropicToolTurnAssistantIndex as w, toClaudeCodeToolName as x, reconcileAnthropicToolChoice as y, isDirectAnthropicModel as z };
|