@openclaw/ai 2026.7.2-beta.7 → 2026.8.1-beta.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.
- package/dist/{anthropic-CH4UUnZr.mjs → anthropic-CE-7SkF6.mjs} +28 -191
- package/dist/{anthropic-usage-DWU-x8MI.mjs → anthropic-usage-Ma4iX6uG.mjs} +262 -4
- package/dist/{api-registry-DlMgPR39.d.mts → api-registry-EpJoVwM1.d.mts} +1 -1
- package/dist/{azure-openai-responses-CImcwB83.mjs → azure-openai-responses-Cc_kasye.mjs} +4 -4
- package/dist/{event-stream-D8n2uFee.mjs → event-stream-CEV9t6da.mjs} +10 -2
- package/dist/{event-stream-YjaPW20U.d.mts → event-stream-DRmDMRHH.d.mts} +2 -1
- package/dist/event-stream.d.mts +1 -1
- package/dist/event-stream.mjs +1 -1
- package/dist/{google-CtSg0iTS.mjs → google-CGQu21aw.mjs} +5 -5
- package/dist/{google-shared-DNBz5rcD.mjs → google-shared-Cq2UKx1l.mjs} +151 -85
- package/dist/{google-vertex-31f1uS9L.mjs → google-vertex-CusxWzvE.mjs} +10 -7
- package/dist/{host-Dog2WQiR.mjs → host-Bl7Kgddo.mjs} +40 -2
- package/dist/{host-B9GUmcra.d.mts → host-Dn4_SZI2.d.mts} +2 -2
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +2 -2
- package/dist/internal/anthropic.d.mts +19 -3
- package/dist/internal/anthropic.mjs +4 -4
- package/dist/internal/openai.d.mts +4 -4
- package/dist/internal/openai.mjs +7 -7
- package/dist/internal/runtime.d.mts +2 -2
- package/dist/internal/runtime.mjs +3 -3
- package/dist/internal/shared.d.mts +1 -1
- package/dist/internal/shared.mjs +3 -4
- package/dist/{mistral-CWmpvWYh.mjs → mistral-Dx6VzNjf.mjs} +25 -9
- package/dist/model-utils-Dau5dlgm.mjs +64 -0
- package/dist/number-coercion-1Miyb5MO.mjs +66 -0
- package/dist/{openai-chatgpt-responses-B84Ibtrd.mjs → openai-chatgpt-responses-SC9m0FSf.mjs} +94 -131
- package/dist/{openai-completions-DsOxhOD1.mjs → openai-completions-BaIpl93j.mjs} +47 -66
- package/dist/{openai-reasoning-compat-YgeLncHw.mjs → openai-reasoning-compat-DKebnIBL.mjs} +147 -6
- package/dist/{openai-responses-BT7A3sLu.mjs → openai-responses-Bdx3V_Yu.mjs} +6 -22
- package/dist/openai-responses-contracts-BBKBfAqR.d.mts +116 -0
- package/dist/openai-responses-prompt-observer-internal-DDZPxRfr.mjs +46 -0
- package/dist/{openai-responses-shared-pXl6Wd8S.mjs → openai-responses-shared-CCyMvg7M.mjs} +21 -10
- package/dist/{openai-responses-stream-internal-Cw5txaGW.mjs → openai-responses-stream-internal-Bl8YyVtF.mjs} +244 -81
- package/dist/{openai-tool-projection-OhX64DoP.mjs → openai-transport-shared-Cipt7egQ.mjs} +129 -29
- package/dist/{provider-error-CAEvRjry.mjs → provider-error-DI0Ts28U.mjs} +1 -1
- package/dist/{provider-options-D8bB3z9b.d.mts → provider-options-C5kYML7i.d.mts} +1 -1
- package/dist/providers.d.mts +1 -1
- package/dist/providers.mjs +9 -9
- package/dist/{stream-first-event-timeout-BBys9hSb.mjs → stream-first-event-timeout-BIBomOGq.mjs} +1 -1
- package/dist/{tool-result-text-CTpIRbYd.mjs → tool-result-text-Dvkp2Dus.mjs} +51 -2
- package/dist/{tool-schema-json-projection-BwNu3nDi.mjs → tool-schema-json-projection-B1b-XCn5.mjs} +28 -1
- package/dist/transform-messages-DfjpNXNQ.mjs +2 -0
- package/dist/{transport-stream-shared-D81p90xq.mjs → transport-stream-shared-CPNv7A3r.mjs} +4 -4
- package/dist/transports.d.mts +41 -73
- package/dist/transports.mjs +317 -601
- package/dist/{types-bzp5k29J.d.mts → types-CH7ReIcU.d.mts} +4 -0
- package/dist/types.d.mts +3 -3
- package/dist/types.mjs +1 -1
- package/dist/{validation-B-j7cOYp.d.mts → validation-CcPcuEbR.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/package.json +1 -1
- package/dist/error-coercion-DgxlWC0n.mjs +0 -15
- package/dist/number-coercion-DvG7SNMg.mjs +0 -129
- package/dist/openai-completions-compat-DBWjXoMZ.d.mts +0 -43
- package/dist/simple-options-9lhRrN73.mjs +0 -50
- package/dist/transform-messages-C8mBqZxF.mjs +0 -2
package/dist/transports.mjs
CHANGED
|
@@ -1,364 +1,45 @@
|
|
|
1
1
|
import { n as getEnvApiKey } from "./env-api-keys-DrgeBuva.mjs";
|
|
2
|
-
import { d as resolveClaudeSonnet5ModelIdentity, g as supportsClaudeNativeXhighEffort,
|
|
3
|
-
import { r as createAssistantMessageEventStream } from "./event-stream-
|
|
4
|
-
import { a as
|
|
2
|
+
import { d as resolveClaudeSonnet5ModelIdentity, g as supportsClaudeNativeXhighEffort, p as supportsClaudeAdaptiveThinking, u as resolveClaudeOpus5ModelIdentity } from "./src-QkygScBs.mjs";
|
|
3
|
+
import { r as createAssistantMessageEventStream } from "./event-stream-CEV9t6da.mjs";
|
|
4
|
+
import { _ as normalizeLowercaseStringOrEmpty, a as ANTHROPIC_CLAUDE_CODE_BILLING_SYSTEM_BLOCK, b as isRecord, c as defaultsClaudeAdaptiveThinking, d as requiresClaudeAdaptiveThinking, f as resolveAnthropicThinkingEffort, g as hasNonEmptyString, h as usesClaudeStreamingRefusalContract, l as mapAnthropicStopReason, m as usesClaudeFable5MessagesContract, n as getAiTransportHost, o as ANTHROPIC_CLAUDE_CODE_VERSION, r as resolveAiTransportHeaderSentinels, s as applyClaudeRequestContract, u as prepareClaudeNoPrefillRequestContext, y as readStringValue } from "./host-Bl7Kgddo.mjs";
|
|
5
|
+
import { n as calculateCost } from "./model-utils-Dau5dlgm.mjs";
|
|
5
6
|
import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
|
|
6
7
|
import { t as resolveCacheRetention } from "./cache-retention-0x979a5V.mjs";
|
|
7
|
-
import { a as isImageWithMediaPayload,
|
|
8
|
-
import { a as
|
|
9
|
-
import { t as
|
|
10
|
-
import {
|
|
11
|
-
import { a as
|
|
12
|
-
import { a as resolveOpenAICompletionsCompat, c as clearPendingCommentaryText, i as detectOpenAICompletionsCompat, l as rememberPendingCommentaryTags, n as mapOpenAIStopReason, o as resolveOpenAICompletionsResponseFormat, r as convertMessages, s as shouldOmitOllamaCompatResponseFormat, t as resolveOpenAIReasoningEffortMap, u as tagPendingCommentaryText } from "./openai-reasoning-compat-YgeLncHw.mjs";
|
|
8
|
+
import { a as isImageWithMediaPayload, h as stripSystemPromptCacheBoundary, n as extractToolResultBlockText, r as extractToolResultText, s as adjustMaxTokensForThinking, t as describeToolResultMediaPlaceholder, v as sortPromptCacheToolsByName } from "./tool-result-text-Dvkp2Dus.mjs";
|
|
9
|
+
import { a as resolveProviderEndpoint, c as transformTransportMessages, i as resolveOpenAIStrictToolSetting, n as buildGuardedModelFetch, r as resolveModelRequestTimeoutMs, s as resolveProviderRequestPolicyConfig } from "./tool-schema-json-projection-B1b-XCn5.mjs";
|
|
10
|
+
import { A as applyAnthropicPayloadPolicyToParams, C as usesFoundryBearerAuth, D as canonicalizeBase64, E as resolveAnthropicImageMediaType, M as resolveAnthropicPayloadPolicy, O as applyAnthropicCacheControlToMessages, S as omitFoundryBearerCredentialHeaders, T as normalizeAnthropicInlineContent, b as resolveAnthropicFallbackServingModelCost, c as normalizeAnthropicToolChoice, d as resolveOriginalAnthropicToolName, f as toClaudeCodeToolName, g as ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, h as ANTHROPIC_SERVER_SIDE_FALLBACKS, j as resolveAnthropicEphemeralCacheControl, k as applyAnthropicEphemeralCacheControlMarkers, l as projectAnthropicTools, m as findActiveAnthropicToolTurnAssistantIndex, n as applyAnthropicMessageStartUsage, p as ANTHROPIC_OMITTED_REASONING_TEXT, s as normalizeAnthropicToolCallId, t as applyAnthropicMessageDeltaUsage, u as reconcileAnthropicToolChoice, v as applyAnthropicFallbackBoundary, w as createAnthropicInlineImageBudget, x as applyAnthropicRefusal, y as readAnthropicFallbackBoundary } from "./anthropic-usage-Ma4iX6uG.mjs";
|
|
11
|
+
import { n as toErrorObject, t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-DDZPxRfr.mjs";
|
|
12
|
+
import { a as convertMessages, c as resolveOpenAICompletionsResponseFormat, d as rememberPendingCommentaryTags, f as tagPendingCommentaryText, i as finalizeOpenAICompletionsToolCalls, l as shouldOmitOllamaCompatResponseFormat, n as mapOpenAIStopReason, o as detectOpenAICompletionsCompat, r as createOpenAICompletionsToolCallDeltaNormalizer, s as resolveOpenAICompletionsCompat, t as resolveOpenAIReasoningEffortMap, u as clearPendingCommentaryText } from "./openai-reasoning-compat-DKebnIBL.mjs";
|
|
13
13
|
import { t as createDeferredEventBuffer } from "./deferred-event-buffer-DAvyP7qA.mjs";
|
|
14
14
|
import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
|
|
15
15
|
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
16
|
-
import { C as
|
|
17
|
-
import {
|
|
16
|
+
import { A as normalizeResponsesFailedEvent, C as prepareOpenAIResponsesReasoningItemForReplay, D as applyServiceTierPricing, E as tagOpenAIResponsesReasoningReplayItem, F as summarizeResponsesFailedNoDetailsObservation, G as normalizeOpenAIStrictToolParameters, I as summarizeResponsesPayload, L as summarizeResponsesTools, M as stringifyRedactedEvent, N as stringifyRedactedPayload, O as buildResponsesFailedNoDetailsObservation, P as summarizeOpenAITransportError, R as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, S as isInvalidEncryptedContentError, T as stripResponsesRequestEncryptedContent, U as findOpenAIStrictToolProjectionDiagnostics, V as resolveReplayableResponsesMessageId, _t as resolveModelSseDebugMode, b as convertResponsesMessages, bt as quoteUnsafeIntegerLiterals, ct as isOpenAIGpt56Model, ft as supportsOpenAIReasoningEffort, gt as resolveModelPayloadDebugMode, ht as emitModelTransportDebug, j as safeDebugValue, k as logResponsesFailedNoDetails, lt as normalizeOpenAIReasoningEffort, mt as uniqueStrings, n as processResponsesStream, o as observeResponsesStream, ot as isOpenAIGpt54MiniModel, q as resolveOpenAIProjectedToolsStrictToolFlag, st as isOpenAIGpt55Model, t as ResponsesStreamFailure, ut as resolveOpenAIReasoningEffortForModel, v as buildOpenAIResponsesReasoningReplayMetadata, vt as parseJsonObjectPreservingUnsafeIntegers, w as resolveAzureOpenAIApiVersion, x as createResponsesStreamWithEncryptedContentRetry, y as buildResponsesInputMessage, yt as parseJsonPreservingUnsafeIntegers, z as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS } from "./openai-responses-stream-internal-Bl8YyVtF.mjs";
|
|
17
|
+
import { a as parseStrictPositiveInteger } from "./number-coercion-1Miyb5MO.mjs";
|
|
18
|
+
import { C as resolveSecretSentinel, S as resolveModelHeaderSentinels$1, T as supportsModelTools, _ as isGoogleGemini3ProModel, a as failTransportStream, c as mergeTransportMetadata, d as transportAbortError, f as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, g as isGoogleGemini3FlashModel, h as isCodeModeModelVisibleToolName, i as createWritableTransportEventStream, l as sanitizeNonEmptyTransportPayloadText, m as estimateStringChars, n as coerceTransportToolCallArguments, o as finalizeTransportStream, p as createAbortError$1, r as createEmptyTransportUsage, s as mergeTransportHeaders, t as assignTransportErrorDetails, u as sanitizeTransportPayloadText, v as parseRetryAfterSeconds, w as sha256Hex, y as readResponseTextSnippet } from "./transport-stream-shared-CPNv7A3r.mjs";
|
|
19
|
+
import { a as parseOpenAICompletionsUsage, c as throwIfModelStreamAborted, d as reconcileOpenAIResponsesToolChoice, i as log, l as projectOpenAITools, n as createModelStreamCooperativeScheduler, o as readOpenAICompletionsContentDeltas, r as isOpenAICompletionsThinkingEnabled, s as resolvePromptCacheKey, t as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, u as reconcileOpenAICompletionsToolChoice } from "./openai-transport-shared-Cipt7egQ.mjs";
|
|
18
20
|
import { t as createReasoningTagTextPartitioner } from "./reasoning-tag-text-partitioner-CGDyLWUR.mjs";
|
|
19
|
-
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-
|
|
21
|
+
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-BIBomOGq.mjs";
|
|
20
22
|
import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
|
|
23
|
+
import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
|
|
21
24
|
import { randomUUID } from "node:crypto";
|
|
22
25
|
import OpenAI, { AzureOpenAI } from "openai";
|
|
23
|
-
//#region packages/ai/src/transports/anthropic-payload-policy.ts
|
|
24
|
-
/**
|
|
25
|
-
* Anthropic-family request payload policy helpers.
|
|
26
|
-
* Applies service-tier and cache-control markers only when provider endpoint
|
|
27
|
-
* capabilities allow them.
|
|
28
|
-
*/
|
|
29
|
-
const ANTHROPIC_CACHE_CONTROL_LIMIT = 4;
|
|
30
|
-
function resolveBaseUrlHostname(baseUrl) {
|
|
31
|
-
try {
|
|
32
|
-
return new URL(baseUrl).hostname;
|
|
33
|
-
} catch {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function isLongTtlEligibleEndpoint(baseUrl) {
|
|
38
|
-
if (typeof baseUrl !== "string") return false;
|
|
39
|
-
const hostname = resolveBaseUrlHostname(baseUrl);
|
|
40
|
-
if (!hostname) return false;
|
|
41
|
-
return hostname === "api.anthropic.com" || hostname === "aiplatform.googleapis.com" || hostname.endsWith("-aiplatform.googleapis.com");
|
|
42
|
-
}
|
|
43
|
-
/** Resolve Anthropic cache-control marker retention for a request endpoint. */
|
|
44
|
-
function resolveAnthropicEphemeralCacheControl(baseUrl, cacheRetention) {
|
|
45
|
-
const retention = resolveCacheRetention(cacheRetention);
|
|
46
|
-
if (retention === "none") return;
|
|
47
|
-
const ttl = retention === "long" && (cacheRetention === "long" || isLongTtlEligibleEndpoint(baseUrl)) ? "1h" : void 0;
|
|
48
|
-
return {
|
|
49
|
-
type: "ephemeral",
|
|
50
|
-
...ttl ? { ttl } : {}
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function applyAnthropicCacheControlToSystem(system, cacheControl) {
|
|
54
|
-
if (!Array.isArray(system)) return;
|
|
55
|
-
const normalizedBlocks = [];
|
|
56
|
-
for (const block of system) {
|
|
57
|
-
if (!block || typeof block !== "object") {
|
|
58
|
-
normalizedBlocks.push(block);
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
const record = block;
|
|
62
|
-
if (record.type !== "text" || typeof record.text !== "string") {
|
|
63
|
-
normalizedBlocks.push(block);
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
const split = splitSystemPromptCacheBoundary(record.text);
|
|
67
|
-
if (!split) {
|
|
68
|
-
if (record.cache_control === void 0) record.cache_control = cacheControl;
|
|
69
|
-
normalizedBlocks.push(record);
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
const { cache_control: existingCacheControl, ...rest } = record;
|
|
73
|
-
if (split.stablePrefix) normalizedBlocks.push({
|
|
74
|
-
...rest,
|
|
75
|
-
text: split.stablePrefix,
|
|
76
|
-
cache_control: existingCacheControl ?? cacheControl
|
|
77
|
-
});
|
|
78
|
-
if (split.dynamicSuffix) normalizedBlocks.push({
|
|
79
|
-
...rest,
|
|
80
|
-
text: split.dynamicSuffix
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
system.splice(0, system.length, ...normalizedBlocks);
|
|
84
|
-
}
|
|
85
|
-
function stripAnthropicSystemPromptBoundary(system) {
|
|
86
|
-
if (!Array.isArray(system)) return;
|
|
87
|
-
for (const block of system) {
|
|
88
|
-
if (!block || typeof block !== "object") continue;
|
|
89
|
-
const record = block;
|
|
90
|
-
if (record.type === "text" && typeof record.text === "string") record.text = stripSystemPromptCacheBoundary(record.text);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
function applyAnthropicCacheControlToMessages(messages, cacheControl, markerLimit, cacheBreakpointOptOutMessageIndexes) {
|
|
94
|
-
if (!Array.isArray(messages) || messages.length === 0 || markerLimit <= 0) return;
|
|
95
|
-
let fallbackToolResult;
|
|
96
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
97
|
-
const message = messages[i];
|
|
98
|
-
if (!message || typeof message !== "object") continue;
|
|
99
|
-
const record = message;
|
|
100
|
-
if (record.role !== "user" || cacheBreakpointOptOutMessageIndexes.has(i)) continue;
|
|
101
|
-
const content = record.content;
|
|
102
|
-
if (typeof content === "string") {
|
|
103
|
-
if (fallbackToolResult && markerLimit === 1) {
|
|
104
|
-
fallbackToolResult.cache_control = cacheControl;
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
record.content = [{
|
|
108
|
-
type: "text",
|
|
109
|
-
text: content,
|
|
110
|
-
cache_control: cacheControl
|
|
111
|
-
}];
|
|
112
|
-
if (fallbackToolResult && markerLimit > 1) fallbackToolResult.cache_control = cacheControl;
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
if (!Array.isArray(content)) continue;
|
|
116
|
-
for (let j = content.length - 1; j >= 0; j--) {
|
|
117
|
-
const block = content[j];
|
|
118
|
-
if (!block || typeof block !== "object") continue;
|
|
119
|
-
const blockRecord = block;
|
|
120
|
-
if (blockRecord.type === "text" || blockRecord.type === "image") {
|
|
121
|
-
if (fallbackToolResult && markerLimit === 1) {
|
|
122
|
-
fallbackToolResult.cache_control = cacheControl;
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
blockRecord.cache_control = cacheControl;
|
|
126
|
-
if (fallbackToolResult && markerLimit > 1) fallbackToolResult.cache_control = cacheControl;
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
if (blockRecord.type === "tool_result" && fallbackToolResult === void 0) fallbackToolResult = blockRecord;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (fallbackToolResult) fallbackToolResult.cache_control = cacheControl;
|
|
133
|
-
}
|
|
134
|
-
function countAnthropicCacheControlMarkers(blocks) {
|
|
135
|
-
if (!Array.isArray(blocks)) return 0;
|
|
136
|
-
let count = 0;
|
|
137
|
-
for (const block of blocks) if (block && typeof block === "object" && "cache_control" in block) count += 1;
|
|
138
|
-
return count;
|
|
139
|
-
}
|
|
140
|
-
/** @deprecated Anthropic-family provider payload helper; do not use from third-party plugins. */
|
|
141
|
-
function resolveAnthropicPayloadPolicy(input) {
|
|
142
|
-
return {
|
|
143
|
-
allowsServiceTier: resolveProviderRequestCapabilities({
|
|
144
|
-
provider: input.provider,
|
|
145
|
-
api: input.api,
|
|
146
|
-
baseUrl: input.baseUrl,
|
|
147
|
-
capability: "llm",
|
|
148
|
-
transport: "stream"
|
|
149
|
-
}).allowsAnthropicServiceTier,
|
|
150
|
-
cacheControl: input.enableCacheControl === true ? resolveAnthropicEphemeralCacheControl(input.baseUrl, input.cacheRetention) : void 0,
|
|
151
|
-
serviceTier: input.serviceTier
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
/** @deprecated Anthropic-family provider payload helper; do not use from third-party plugins. */
|
|
155
|
-
function applyAnthropicPayloadPolicyToParams(payloadObj, policy, cacheBreakpointOptOutMessageIndexes) {
|
|
156
|
-
if (policy.allowsServiceTier && policy.serviceTier !== void 0 && payloadObj.service_tier === void 0) payloadObj.service_tier = policy.serviceTier;
|
|
157
|
-
if (policy.cacheControl) applyAnthropicCacheControlToSystem(payloadObj.system, policy.cacheControl);
|
|
158
|
-
else stripAnthropicSystemPromptBoundary(payloadObj.system);
|
|
159
|
-
if (!policy.cacheControl) return;
|
|
160
|
-
const usedMarkers = countAnthropicCacheControlMarkers(payloadObj.system) + countAnthropicCacheControlMarkers(payloadObj.tools);
|
|
161
|
-
applyAnthropicCacheControlToMessages(payloadObj.messages, policy.cacheControl, ANTHROPIC_CACHE_CONTROL_LIMIT - usedMarkers, cacheBreakpointOptOutMessageIndexes);
|
|
162
|
-
}
|
|
163
|
-
/** @deprecated Anthropic-family provider payload helper; do not use from third-party plugins. */
|
|
164
|
-
function applyAnthropicEphemeralCacheControlMarkers(payloadObj, cacheControl = { type: "ephemeral" }) {
|
|
165
|
-
const messages = payloadObj.messages;
|
|
166
|
-
if (!Array.isArray(messages)) return;
|
|
167
|
-
for (const message of messages) {
|
|
168
|
-
if (message.role === "system" || message.role === "developer") {
|
|
169
|
-
if (!cacheControl) continue;
|
|
170
|
-
if (typeof message.content === "string") {
|
|
171
|
-
message.content = [{
|
|
172
|
-
type: "text",
|
|
173
|
-
text: message.content,
|
|
174
|
-
cache_control: cacheControl
|
|
175
|
-
}];
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
if (Array.isArray(message.content) && message.content.length > 0) {
|
|
179
|
-
const last = message.content[message.content.length - 1];
|
|
180
|
-
if (last && typeof last === "object") {
|
|
181
|
-
const record = last;
|
|
182
|
-
if (record.type !== "thinking" && record.type !== "redacted_thinking") record.cache_control = cacheControl;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
if (message.role === "assistant" && Array.isArray(message.content)) for (const block of message.content) {
|
|
188
|
-
if (!block || typeof block !== "object") continue;
|
|
189
|
-
const record = block;
|
|
190
|
-
if (record.type === "thinking" || record.type === "redacted_thinking") delete record.cache_control;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
//#endregion
|
|
195
|
-
//#region packages/ai/src/transports/json-unsafe-integers.ts
|
|
196
|
-
/**
|
|
197
|
-
* JSON parsing helpers that preserve integer literals larger than
|
|
198
|
-
* Number.MAX_SAFE_INTEGER as strings before JSON.parse can round them.
|
|
199
|
-
*/
|
|
200
|
-
const MAX_SAFE_INTEGER_ABS_STR = String(Number.MAX_SAFE_INTEGER);
|
|
201
|
-
function isAsciiDigit(ch) {
|
|
202
|
-
return ch !== void 0 && ch >= "0" && ch <= "9";
|
|
203
|
-
}
|
|
204
|
-
function parseJsonNumberToken(input, start) {
|
|
205
|
-
let idx = start;
|
|
206
|
-
if (input[idx] === "-") idx += 1;
|
|
207
|
-
if (idx >= input.length) return null;
|
|
208
|
-
if (input[idx] === "0") idx += 1;
|
|
209
|
-
else if (isAsciiDigit(input[idx]) && input[idx] !== "0") while (isAsciiDigit(input[idx])) idx += 1;
|
|
210
|
-
else return null;
|
|
211
|
-
let isInteger = true;
|
|
212
|
-
if (input[idx] === ".") {
|
|
213
|
-
isInteger = false;
|
|
214
|
-
idx += 1;
|
|
215
|
-
if (!isAsciiDigit(input[idx])) return null;
|
|
216
|
-
while (isAsciiDigit(input[idx])) idx += 1;
|
|
217
|
-
}
|
|
218
|
-
if (input[idx] === "e" || input[idx] === "E") {
|
|
219
|
-
isInteger = false;
|
|
220
|
-
idx += 1;
|
|
221
|
-
if (input[idx] === "+" || input[idx] === "-") idx += 1;
|
|
222
|
-
if (!isAsciiDigit(input[idx])) return null;
|
|
223
|
-
while (isAsciiDigit(input[idx])) idx += 1;
|
|
224
|
-
}
|
|
225
|
-
return {
|
|
226
|
-
token: input.slice(start, idx),
|
|
227
|
-
end: idx,
|
|
228
|
-
isInteger
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
function isUnsafeIntegerLiteral(token) {
|
|
232
|
-
const digits = token[0] === "-" ? token.slice(1) : token;
|
|
233
|
-
if (digits.length < MAX_SAFE_INTEGER_ABS_STR.length) return false;
|
|
234
|
-
if (digits.length > MAX_SAFE_INTEGER_ABS_STR.length) return true;
|
|
235
|
-
return digits > MAX_SAFE_INTEGER_ABS_STR;
|
|
236
|
-
}
|
|
237
|
-
/** Quotes integer literals above Number.MAX_SAFE_INTEGER before JSON.parse. */
|
|
238
|
-
function quoteUnsafeIntegerLiterals(input) {
|
|
239
|
-
let out = "";
|
|
240
|
-
let inString = false;
|
|
241
|
-
let escaped = false;
|
|
242
|
-
let idx = 0;
|
|
243
|
-
while (idx < input.length) {
|
|
244
|
-
const ch = input[idx] ?? "";
|
|
245
|
-
if (inString) {
|
|
246
|
-
out += ch;
|
|
247
|
-
if (escaped) escaped = false;
|
|
248
|
-
else if (ch === "\\") escaped = true;
|
|
249
|
-
else if (ch === "\"") inString = false;
|
|
250
|
-
idx += 1;
|
|
251
|
-
continue;
|
|
252
|
-
}
|
|
253
|
-
if (ch === "\"") {
|
|
254
|
-
inString = true;
|
|
255
|
-
out += ch;
|
|
256
|
-
idx += 1;
|
|
257
|
-
continue;
|
|
258
|
-
}
|
|
259
|
-
if (ch === "-" || isAsciiDigit(ch)) {
|
|
260
|
-
const parsed = parseJsonNumberToken(input, idx);
|
|
261
|
-
if (parsed) {
|
|
262
|
-
if (parsed.isInteger && isUnsafeIntegerLiteral(parsed.token)) out += `"${parsed.token}"`;
|
|
263
|
-
else out += parsed.token;
|
|
264
|
-
idx = parsed.end;
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
out += ch;
|
|
269
|
-
idx += 1;
|
|
270
|
-
}
|
|
271
|
-
return out;
|
|
272
|
-
}
|
|
273
|
-
/** Parses JSON while preserving unsafe integer literals as strings. */
|
|
274
|
-
function parseJsonPreservingUnsafeIntegers(input) {
|
|
275
|
-
return JSON.parse(quoteUnsafeIntegerLiterals(input));
|
|
276
|
-
}
|
|
277
|
-
/** Parses or accepts an object while preserving unsafe integer literals in string input. */
|
|
278
|
-
function parseJsonObjectPreservingUnsafeIntegers(value) {
|
|
279
|
-
if (typeof value === "string") {
|
|
280
|
-
try {
|
|
281
|
-
const parsed = parseJsonPreservingUnsafeIntegers(value);
|
|
282
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
|
|
283
|
-
} catch {
|
|
284
|
-
return null;
|
|
285
|
-
}
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
if (value && typeof value === "object" && !Array.isArray(value)) return value;
|
|
289
|
-
return null;
|
|
290
|
-
}
|
|
291
|
-
//#endregion
|
|
292
26
|
//#region packages/ai/src/transports/anthropic-transport-stream.ts
|
|
293
27
|
/**
|
|
294
28
|
* Native Anthropic Messages streaming transport.
|
|
295
29
|
* Converts OpenClaw contexts/tools into Anthropic payloads, streams SSE events
|
|
296
30
|
* back into runtime output blocks, and applies provider request policy.
|
|
297
31
|
*/
|
|
298
|
-
const CLAUDE_CODE_VERSION = "2.1.75";
|
|
299
|
-
const CLAUDE_CODE_BILLING_SYSTEM_BLOCK = `x-anthropic-billing-header: cc_version=${CLAUDE_CODE_VERSION}; cc_entrypoint=sdk-cli;`;
|
|
300
32
|
const ANTHROPIC_MESSAGES_ERROR_BODY_MAX_BYTES = 8 * 1024;
|
|
301
33
|
const ANTHROPIC_MESSAGES_ERROR_BODY_MAX_CHARS = 400;
|
|
302
34
|
const ANTHROPIC_MESSAGES_ERROR_BODY_READ_IDLE_TIMEOUT_MS = 1e4;
|
|
303
35
|
const ANTHROPIC_MESSAGES_DEFAULT_MAX_TOKENS = 4096;
|
|
304
36
|
const ANTHROPIC_MESSAGES_FALLBACK_CONTEXT_DIVISOR = 4;
|
|
305
37
|
const ANTHROPIC_MESSAGES_SSE_PENDING_BUFFER_MAX_CHARS = 16 * 1024 * 1024;
|
|
306
|
-
const CLAUDE_CODE_TOOL_LOOKUP = new Map([
|
|
307
|
-
"Read",
|
|
308
|
-
"Write",
|
|
309
|
-
"Edit",
|
|
310
|
-
"Bash",
|
|
311
|
-
"Grep",
|
|
312
|
-
"Glob",
|
|
313
|
-
"AskUserQuestion",
|
|
314
|
-
"EnterPlanMode",
|
|
315
|
-
"ExitPlanMode",
|
|
316
|
-
"KillShell",
|
|
317
|
-
"NotebookEdit",
|
|
318
|
-
"Skill",
|
|
319
|
-
"Task",
|
|
320
|
-
"TaskOutput",
|
|
321
|
-
"TodoWrite",
|
|
322
|
-
"WebFetch",
|
|
323
|
-
"WebSearch"
|
|
324
|
-
].map((tool) => [normalizeLowercaseStringOrEmpty(tool), tool]));
|
|
325
38
|
function resolveAnthropicRequestModelId(model) {
|
|
326
39
|
if (isDirectAnthropicModel(model) && /^anthropic\//i.test(model.id)) return model.id.replace(/^anthropic\//i, "");
|
|
327
40
|
return model.id;
|
|
328
41
|
}
|
|
329
42
|
const EMPTY_ANTHROPIC_MESSAGES_FALLBACK_TEXT = ".";
|
|
330
|
-
function normalizeAnthropicToolChoice(thinkingEnabled, toolChoice) {
|
|
331
|
-
if (thinkingEnabled && (toolChoice === "any" || typeof toolChoice === "object" && toolChoice.type === "tool")) return { type: "auto" };
|
|
332
|
-
return typeof toolChoice === "string" ? { type: toolChoice } : toolChoice;
|
|
333
|
-
}
|
|
334
|
-
function supportsNativeXhighEffort(model) {
|
|
335
|
-
return supportsClaudeNativeXhighEffort(model);
|
|
336
|
-
}
|
|
337
|
-
function supportsAdaptiveThinking(model) {
|
|
338
|
-
return supportsClaudeAdaptiveThinking(model);
|
|
339
|
-
}
|
|
340
|
-
function mapThinkingLevelToEffort(level, model) {
|
|
341
|
-
const thinkingLevelMap = resolveClaudeNativeThinkingLevelMap(model);
|
|
342
|
-
const resolvedLevel = clampThinkingLevel({
|
|
343
|
-
...model,
|
|
344
|
-
...typeof model.params?.canonicalModelId === "string" ? { reasoning: true } : {},
|
|
345
|
-
...thinkingLevelMap ? { thinkingLevelMap } : {}
|
|
346
|
-
}, level);
|
|
347
|
-
const mapped = thinkingLevelMap?.[resolvedLevel];
|
|
348
|
-
if (typeof mapped === "string") return mapped;
|
|
349
|
-
switch (resolvedLevel) {
|
|
350
|
-
case "off":
|
|
351
|
-
case "minimal":
|
|
352
|
-
case "low": return "low";
|
|
353
|
-
case "medium": return "medium";
|
|
354
|
-
case "xhigh": return supportsNativeXhighEffort(model) ? "xhigh" : "high";
|
|
355
|
-
case "max": return supportsClaudeNativeMaxEffort(model) ? "max" : "high";
|
|
356
|
-
default: return "high";
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
function clampReasoningLevel(level) {
|
|
360
|
-
return level === "xhigh" || level === "max" ? "high" : level;
|
|
361
|
-
}
|
|
362
43
|
function resolvePositiveAnthropicTokenLimit(value) {
|
|
363
44
|
if (typeof value !== "number" || !Number.isFinite(value)) return;
|
|
364
45
|
const floored = Math.floor(value);
|
|
@@ -373,23 +54,6 @@ function resolveAnthropicMessagesMaxTokens(params) {
|
|
|
373
54
|
const contextWindow = resolvePositiveAnthropicTokenLimit(params.modelContextWindow);
|
|
374
55
|
return contextWindow === void 0 ? ANTHROPIC_MESSAGES_DEFAULT_MAX_TOKENS : Math.max(1, Math.min(ANTHROPIC_MESSAGES_DEFAULT_MAX_TOKENS, Math.floor(contextWindow / ANTHROPIC_MESSAGES_FALLBACK_CONTEXT_DIVISOR)));
|
|
375
56
|
}
|
|
376
|
-
function adjustMaxTokensForThinking(params) {
|
|
377
|
-
const budgets = {
|
|
378
|
-
minimal: 1024,
|
|
379
|
-
low: 2048,
|
|
380
|
-
medium: 8192,
|
|
381
|
-
high: 16384,
|
|
382
|
-
...params.customBudgets
|
|
383
|
-
};
|
|
384
|
-
const minOutputTokens = 1024;
|
|
385
|
-
let thinkingBudget = budgets[clampReasoningLevel(params.reasoningLevel)];
|
|
386
|
-
const maxTokens = Math.min(params.baseMaxTokens + thinkingBudget, params.modelMaxTokens);
|
|
387
|
-
if (maxTokens <= thinkingBudget) thinkingBudget = Math.max(0, maxTokens - minOutputTokens);
|
|
388
|
-
return {
|
|
389
|
-
maxTokens,
|
|
390
|
-
thinkingBudget
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
57
|
function isAnthropicOAuthToken(apiKey) {
|
|
394
58
|
return (resolveSecretSentinel(apiKey) ?? apiKey).includes("sk-ant-oat");
|
|
395
59
|
}
|
|
@@ -416,9 +80,6 @@ function buildAnthropicBetaHeader(model, betaFeatures, params) {
|
|
|
416
80
|
if (!isDirectAnthropicModel(model)) return;
|
|
417
81
|
return params.oauth ? `claude-code-20250219,oauth-2025-04-20,${betaFeatures.join(",")}` : betaFeatures.join(",");
|
|
418
82
|
}
|
|
419
|
-
function toClaudeCodeName(name) {
|
|
420
|
-
return CLAUDE_CODE_TOOL_LOOKUP.get(normalizeLowercaseStringOrEmpty(name)) ?? name;
|
|
421
|
-
}
|
|
422
83
|
const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
423
84
|
async function convertContentBlocks(content, model, imageBudget) {
|
|
424
85
|
const text = extractToolResultText(content);
|
|
@@ -459,15 +120,12 @@ async function convertContentBlocks(content, model, imageBudget) {
|
|
|
459
120
|
});
|
|
460
121
|
return blocks;
|
|
461
122
|
}
|
|
462
|
-
function normalizeToolCallId(id) {
|
|
463
|
-
return id.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 64);
|
|
464
|
-
}
|
|
465
123
|
async function convertAnthropicMessages(messages, model, isOAuthToken, options) {
|
|
466
124
|
const params = [];
|
|
467
125
|
const imageBudget = createAnthropicInlineImageBudget();
|
|
468
126
|
const allowReasoningContentReplay = options.allowReasoningContentReplay === true;
|
|
469
127
|
const replayThinkingEnabled = options.replayThinkingEnabled !== false;
|
|
470
|
-
const transformedMessages = transformTransportMessages(messages, model,
|
|
128
|
+
const transformedMessages = transformTransportMessages(messages, model, normalizeAnthropicToolCallId);
|
|
471
129
|
const activeToolTurnAssistantIndex = replayThinkingEnabled ? -1 : findActiveAnthropicToolTurnAssistantIndex(transformedMessages);
|
|
472
130
|
for (let i = 0; i < transformedMessages.length; i += 1) {
|
|
473
131
|
const msg = transformedMessages[i];
|
|
@@ -566,7 +224,7 @@ async function convertAnthropicMessages(messages, model, isOAuthToken, options)
|
|
|
566
224
|
if (block.type === "toolCall") blocks.push({
|
|
567
225
|
type: "tool_use",
|
|
568
226
|
id: block.id,
|
|
569
|
-
name: isOAuthToken ?
|
|
227
|
+
name: isOAuthToken ? toClaudeCodeToolName(block.name) : block.name,
|
|
570
228
|
input: coerceTransportToolCallArguments(block.arguments)
|
|
571
229
|
});
|
|
572
230
|
}
|
|
@@ -625,7 +283,7 @@ function ensureNonEmptyAnthropicMessages(messages) {
|
|
|
625
283
|
}];
|
|
626
284
|
}
|
|
627
285
|
function convertAnthropicTools(tools, isOAuthToken) {
|
|
628
|
-
const projection = projectAnthropicTools(tools ?? [], (name) => isOAuthToken ?
|
|
286
|
+
const projection = projectAnthropicTools(tools ?? [], (name) => isOAuthToken ? toClaudeCodeToolName(name) : name);
|
|
629
287
|
const converted = [];
|
|
630
288
|
for (const tool of projection.tools) converted.push({
|
|
631
289
|
name: tool.wireName,
|
|
@@ -640,18 +298,6 @@ function convertAnthropicTools(tools, isOAuthToken) {
|
|
|
640
298
|
function parseAnthropicToolCallArguments(inputJson) {
|
|
641
299
|
return parseJsonObjectPreservingUnsafeIntegers(inputJson) ?? parseStreamingJson(inputJson);
|
|
642
300
|
}
|
|
643
|
-
function mapStopReason(reason) {
|
|
644
|
-
switch (reason) {
|
|
645
|
-
case "end_turn": return "stop";
|
|
646
|
-
case "max_tokens": return "length";
|
|
647
|
-
case "tool_use": return "toolUse";
|
|
648
|
-
case "pause_turn": return "stop";
|
|
649
|
-
case "refusal":
|
|
650
|
-
case "sensitive": return "error";
|
|
651
|
-
case "stop_sequence": return "stop";
|
|
652
|
-
default: throw new Error(`Unhandled stop reason: ${String(reason)}`);
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
301
|
const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
|
|
656
302
|
/** Resolve the effective Anthropic API base URL from model or environment. */
|
|
657
303
|
function resolveAnthropicBaseUrl(baseUrl) {
|
|
@@ -794,7 +440,7 @@ async function readAnthropicMessagesErrorBodySnippet(response) {
|
|
|
794
440
|
}
|
|
795
441
|
function createAnthropicTransportClient(params) {
|
|
796
442
|
const { model, context, apiKey, options } = params;
|
|
797
|
-
const needsInterleavedBeta = (options?.interleavedThinking ?? true) && !
|
|
443
|
+
const needsInterleavedBeta = (options?.interleavedThinking ?? true) && !supportsClaudeAdaptiveThinking(model);
|
|
798
444
|
const fetch = isKimiAnthropicProvider(model.provider) && options?.thinkingEnabled === true ? buildGuardedModelFetch(model, void 0, { sanitizeSse: false }) : buildGuardedModelFetch(model);
|
|
799
445
|
if (model.provider === "github-copilot") {
|
|
800
446
|
const betaFeatures = needsInterleavedBeta ? ["interleaved-thinking-2025-05-14"] : [];
|
|
@@ -843,7 +489,7 @@ function createAnthropicTransportClient(params) {
|
|
|
843
489
|
accept: "application/json",
|
|
844
490
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
845
491
|
...betaHeader ? { "anthropic-beta": betaHeader } : {},
|
|
846
|
-
"user-agent": `claude-cli/${
|
|
492
|
+
"user-agent": `claude-cli/${ANTHROPIC_CLAUDE_CODE_VERSION}`,
|
|
847
493
|
"x-app": "cli"
|
|
848
494
|
}, model.headers, options?.headers),
|
|
849
495
|
fetch
|
|
@@ -899,7 +545,7 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
899
545
|
if (isOAuthToken) params.system = [
|
|
900
546
|
{
|
|
901
547
|
type: "text",
|
|
902
|
-
text:
|
|
548
|
+
text: ANTHROPIC_CLAUDE_CODE_BILLING_SYSTEM_BLOCK
|
|
903
549
|
},
|
|
904
550
|
{
|
|
905
551
|
type: "text",
|
|
@@ -914,7 +560,7 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
914
560
|
type: "text",
|
|
915
561
|
text: sanitizeTransportPayloadText(context.systemPrompt)
|
|
916
562
|
}];
|
|
917
|
-
if (options?.temperature !== void 0 && !options.thinkingEnabled && !
|
|
563
|
+
if (options?.temperature !== void 0 && !options.thinkingEnabled && !supportsClaudeNativeXhighEffort(model)) params.temperature = options.temperature;
|
|
918
564
|
if (options?.stop !== void 0 && options.stop.length > 0) params.stop_sequences = options.stop;
|
|
919
565
|
let toolProjection;
|
|
920
566
|
if (context.tools) {
|
|
@@ -922,8 +568,8 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
922
568
|
toolProjection = convertedTools.projection;
|
|
923
569
|
if (convertedTools.tools.length > 0) params.tools = convertedTools.tools;
|
|
924
570
|
}
|
|
925
|
-
if (mandatoryAdaptiveThinking || model.reasoning ||
|
|
926
|
-
if (mandatoryAdaptiveThinking || options?.thinkingEnabled) if (
|
|
571
|
+
if (mandatoryAdaptiveThinking || model.reasoning || supportsClaudeAdaptiveThinking(model)) {
|
|
572
|
+
if (mandatoryAdaptiveThinking || options?.thinkingEnabled) if (supportsClaudeAdaptiveThinking(model)) {
|
|
927
573
|
params.thinking = {
|
|
928
574
|
type: "adaptive",
|
|
929
575
|
display: options?.thinkingDisplay ?? "summarized"
|
|
@@ -985,17 +631,12 @@ function resolveAnthropicTransportOptions(model, options, apiKey) {
|
|
|
985
631
|
if (resolved.thinkingEnabled) resolved.effort = "high";
|
|
986
632
|
return resolved;
|
|
987
633
|
}
|
|
988
|
-
if (
|
|
634
|
+
if (supportsClaudeAdaptiveThinking(model)) {
|
|
989
635
|
resolved.thinkingEnabled = true;
|
|
990
|
-
resolved.effort =
|
|
636
|
+
resolved.effort = resolveAnthropicThinkingEffort(model, reasoning);
|
|
991
637
|
return resolved;
|
|
992
638
|
}
|
|
993
|
-
const adjusted = adjustMaxTokensForThinking(
|
|
994
|
-
baseMaxTokens,
|
|
995
|
-
modelMaxTokens: reasoningModelMaxTokens,
|
|
996
|
-
reasoningLevel: reasoning,
|
|
997
|
-
customBudgets: options?.thinkingBudgets
|
|
998
|
-
});
|
|
639
|
+
const adjusted = adjustMaxTokensForThinking(baseMaxTokens, reasoningModelMaxTokens, reasoning === "max" ? "high" : reasoning, options?.thinkingBudgets);
|
|
999
640
|
const thinkingEnabled = adjusted.thinkingBudget >= 1024;
|
|
1000
641
|
resolved.maxTokens = adjusted.maxTokens;
|
|
1001
642
|
resolved.thinkingEnabled = thinkingEnabled;
|
|
@@ -1153,23 +794,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1153
794
|
const usage = message?.usage ?? {};
|
|
1154
795
|
output.responseId = typeof message?.id === "string" ? message.id : void 0;
|
|
1155
796
|
output.responseModel = typeof message?.model === "string" ? message.model : void 0;
|
|
1156
|
-
|
|
1157
|
-
const messageStartPromptTokens = promptUsage ? promptUsage.input + promptUsage.cacheRead + promptUsage.cacheWrite : 0;
|
|
1158
|
-
messageStartPromptUsage = messageStartPromptTokens > 0 ? promptUsage : void 0;
|
|
1159
|
-
const inputTokens = readAnthropicUsageTokenCount(usage.input_tokens);
|
|
1160
|
-
if (inputTokens !== void 0) output.usage.input = inputTokens;
|
|
1161
|
-
const outputTokens = readAnthropicUsageTokenCount(usage.output_tokens);
|
|
1162
|
-
if (outputTokens !== void 0) output.usage.output = outputTokens;
|
|
1163
|
-
const cacheReadTokens = usage.cache_read_input_tokens == null ? 0 : readAnthropicUsageTokenCount(usage.cache_read_input_tokens);
|
|
1164
|
-
if (cacheReadTokens !== void 0) output.usage.cacheRead = cacheReadTokens;
|
|
1165
|
-
const cacheWriteTokens = usage.cache_creation_input_tokens == null ? 0 : readAnthropicUsageTokenCount(usage.cache_creation_input_tokens);
|
|
1166
|
-
if (cacheWriteTokens !== void 0) output.usage.cacheWrite = cacheWriteTokens;
|
|
1167
|
-
output.usage.totalTokens = output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
|
|
1168
|
-
if (messageStartPromptUsage && outputTokens !== void 0) output.usage.contextUsage = {
|
|
1169
|
-
state: "available",
|
|
1170
|
-
promptTokens: messageStartPromptTokens,
|
|
1171
|
-
totalTokens: messageStartPromptTokens + output.usage.output
|
|
1172
|
-
};
|
|
797
|
+
messageStartPromptUsage = applyAnthropicMessageStartUsage(output.usage, usage);
|
|
1173
798
|
calculateCost(costModel, output.usage);
|
|
1174
799
|
eventSink.push({
|
|
1175
800
|
type: "start",
|
|
@@ -1447,31 +1072,8 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1447
1072
|
const delta = event.delta;
|
|
1448
1073
|
const usage = event.usage;
|
|
1449
1074
|
if (delta?.stop_reason) if (delta.stop_reason === "refusal") applyAnthropicRefusal(output, delta.stop_details, model.provider);
|
|
1450
|
-
else output.stopReason =
|
|
1451
|
-
|
|
1452
|
-
if (inputTokens !== void 0) output.usage.input = inputTokens;
|
|
1453
|
-
const outputTokens = readAnthropicUsageTokenCount(usage?.output_tokens);
|
|
1454
|
-
if (outputTokens !== void 0) output.usage.output = outputTokens;
|
|
1455
|
-
const cacheReadTokens = readAnthropicUsageTokenCount(usage?.cache_read_input_tokens);
|
|
1456
|
-
if (cacheReadTokens !== void 0) output.usage.cacheRead = cacheReadTokens;
|
|
1457
|
-
const cacheWriteTokens = readAnthropicUsageTokenCount(usage?.cache_creation_input_tokens);
|
|
1458
|
-
if (cacheWriteTokens !== void 0) output.usage.cacheWrite = cacheWriteTokens;
|
|
1459
|
-
output.usage.totalTokens = output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
|
|
1460
|
-
const iterationUsage = readLastAnthropicIterationUsage(usage ?? {});
|
|
1461
|
-
if (iterationUsage.state === "valid") output.usage.contextUsage = {
|
|
1462
|
-
state: "available",
|
|
1463
|
-
promptTokens: iterationUsage.usage.contextPromptTokens,
|
|
1464
|
-
totalTokens: iterationUsage.usage.totalTokens
|
|
1465
|
-
};
|
|
1466
|
-
else if (iterationUsage.state === "invalid") output.usage.contextUsage = { state: "unavailable" };
|
|
1467
|
-
else if (outputTokens !== void 0 && (messageStartPromptUsage !== void 0 || inputTokens !== void 0 && cacheReadTokens !== void 0 && cacheWriteTokens !== void 0)) {
|
|
1468
|
-
const promptTokens = output.usage.input + output.usage.cacheRead + output.usage.cacheWrite;
|
|
1469
|
-
output.usage.contextUsage = {
|
|
1470
|
-
state: "available",
|
|
1471
|
-
promptTokens,
|
|
1472
|
-
totalTokens: promptTokens + output.usage.output
|
|
1473
|
-
};
|
|
1474
|
-
} else output.usage.contextUsage = { state: "unavailable" };
|
|
1075
|
+
else output.stopReason = mapAnthropicStopReason(delta.stop_reason);
|
|
1076
|
+
applyAnthropicMessageDeltaUsage(output.usage, usage, messageStartPromptUsage);
|
|
1475
1077
|
calculateCost(costModel, output.usage);
|
|
1476
1078
|
if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
|
|
1477
1079
|
flushPendingTextEnds();
|
|
@@ -2098,7 +1700,11 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
2098
1700
|
stream,
|
|
2099
1701
|
output,
|
|
2100
1702
|
signal: options?.signal,
|
|
2101
|
-
error
|
|
1703
|
+
error,
|
|
1704
|
+
cleanup: () => {
|
|
1705
|
+
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
1706
|
+
finalizeOpenAICompletionsToolCalls(output, { allowSilentToolCallPromotion: false });
|
|
1707
|
+
}
|
|
2102
1708
|
});
|
|
2103
1709
|
} finally {
|
|
2104
1710
|
firstEventAbort?.dispose();
|
|
@@ -2124,6 +1730,7 @@ async function processOpenAICompletionsStream(responseStream, output, model, str
|
|
|
2124
1730
|
const provisionalCommentaryTags = /* @__PURE__ */ new Map();
|
|
2125
1731
|
const toolCallBlockBytes = /* @__PURE__ */ new WeakMap();
|
|
2126
1732
|
const toolCallBlockIndices = /* @__PURE__ */ new WeakMap();
|
|
1733
|
+
const normalizeToolCallDeltas = createOpenAICompletionsToolCallDeltaNormalizer();
|
|
2127
1734
|
let sawStopFinishReason = false;
|
|
2128
1735
|
let sawNativeToolCallDelta = false;
|
|
2129
1736
|
const blockIndex = () => output.content.length - 1;
|
|
@@ -2296,10 +1903,7 @@ async function processOpenAICompletionsStream(responseStream, output, model, str
|
|
|
2296
1903
|
const latestBlock = output.content[output.content.length - 1];
|
|
2297
1904
|
if (currentBlock?.type === "text" || currentBlock?.type === "toolCall") return;
|
|
2298
1905
|
if (latestBlock?.type === "text" || latestBlock?.type === "toolCall") return;
|
|
2299
|
-
appendThinkingDelta({
|
|
2300
|
-
signature: "",
|
|
2301
|
-
text: ""
|
|
2302
|
-
});
|
|
1906
|
+
appendThinkingDelta({ text: "" });
|
|
2303
1907
|
};
|
|
2304
1908
|
const flushReasoningTagTextPartitionerAtEnd = () => {
|
|
2305
1909
|
for (const delta of reasoningTagTextPartitioner.flush()) appendPartitionedVisibleDelta(delta);
|
|
@@ -2327,7 +1931,7 @@ async function processOpenAICompletionsStream(responseStream, output, model, str
|
|
|
2327
1931
|
output.responseId ||= chunk.id;
|
|
2328
1932
|
let hasReasoningUsageActivity = false;
|
|
2329
1933
|
if (chunk.usage) {
|
|
2330
|
-
output.usage =
|
|
1934
|
+
output.usage = parseOpenAICompletionsUsage(chunk.usage, model);
|
|
2331
1935
|
hasReasoningUsageActivity = hasOpenAICompletionsReasoningUsageActivity(chunk.usage);
|
|
2332
1936
|
}
|
|
2333
1937
|
const choice = Array.isArray(chunk.choices) ? chunk.choices[0] : void 0;
|
|
@@ -2338,7 +1942,7 @@ async function processOpenAICompletionsStream(responseStream, output, model, str
|
|
|
2338
1942
|
}
|
|
2339
1943
|
const choiceUsage = choice.usage;
|
|
2340
1944
|
if (!chunk.usage && choiceUsage) {
|
|
2341
|
-
output.usage =
|
|
1945
|
+
output.usage = parseOpenAICompletionsUsage(choiceUsage, model);
|
|
2342
1946
|
hasReasoningUsageActivity = hasOpenAICompletionsReasoningUsageActivity(choiceUsage);
|
|
2343
1947
|
}
|
|
2344
1948
|
if (choice.finish_reason) {
|
|
@@ -2347,91 +1951,92 @@ async function processOpenAICompletionsStream(responseStream, output, model, str
|
|
|
2347
1951
|
if (finishReasonResult.stopReason === "stop") sawStopFinishReason = true;
|
|
2348
1952
|
if (finishReasonResult.errorMessage) output.errorMessage = finishReasonResult.errorMessage;
|
|
2349
1953
|
}
|
|
2350
|
-
const
|
|
2351
|
-
if (!
|
|
1954
|
+
const rawChoiceDelta = choice.delta ?? choice.message;
|
|
1955
|
+
if (!rawChoiceDelta) {
|
|
2352
1956
|
emitReasoningUsageActivity(hasReasoningUsageActivity);
|
|
2353
1957
|
await cooperativeScheduler.afterEvent();
|
|
2354
1958
|
continue;
|
|
2355
1959
|
}
|
|
2356
|
-
const
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
1960
|
+
for (const normalizedDelta of normalizeToolCallDeltas(rawChoiceDelta, choice.finish_reason)) {
|
|
1961
|
+
const choiceDelta = normalizedDelta.delta;
|
|
1962
|
+
const reasoningDeltas = getCompletionsReasoningDeltas(choiceDelta, compat.visibleReasoningDetailTypes);
|
|
1963
|
+
const hasMirroredReasoning = reasoningDeltas.some((delta) => delta.kind === "thinking");
|
|
1964
|
+
if (hasMirroredReasoning) reasoningTagTextPartitioner.markStrict();
|
|
1965
|
+
const contentDeltas = readOpenAICompletionsContentDeltas(choiceDelta.content, choiceDelta.refusal, reasoningDeltas.filter((reasoningDelta) => reasoningDelta.kind === "thinking").map((reasoningDelta) => reasoningDelta.text));
|
|
1966
|
+
const appendReasoningDeltas = () => {
|
|
1967
|
+
for (const reasoningDelta of reasoningDeltas) {
|
|
1968
|
+
if (reasoningDelta.kind === "thinking" && !emitReasoning) continue;
|
|
1969
|
+
if (currentBlock?.type === "toolCall") {
|
|
1970
|
+
queuePostToolCallDelta({ ...reasoningDelta });
|
|
1971
|
+
continue;
|
|
1972
|
+
}
|
|
1973
|
+
if (reasoningDelta.kind === "text") appendTextDelta(reasoningDelta.text);
|
|
1974
|
+
else if (emitReasoning) appendThinkingDelta(reasoningDelta);
|
|
1975
|
+
}
|
|
1976
|
+
};
|
|
1977
|
+
if (hasMirroredReasoning) appendReasoningDeltas();
|
|
2361
1978
|
for (const contentDelta of contentDeltas) if (contentDelta.kind === "text") {
|
|
2362
1979
|
const routedDeltas = hasMirroredReasoning ? reasoningTagTextPartitioner.push(contentDelta.text) : reasoningTagTextPartitioner.pushVisible(contentDelta.text);
|
|
2363
1980
|
for (const routedDelta of routedDeltas) appendPartitionedVisibleDelta(routedDelta);
|
|
2364
1981
|
} else {
|
|
2365
|
-
reasoningTagTextPartitioner.markStrict();
|
|
1982
|
+
if (reasoningTagTextPartitioner.hasPending()) reasoningTagTextPartitioner.markStrict();
|
|
2366
1983
|
appendRoutedContentDelta(contentDelta);
|
|
2367
1984
|
}
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
1985
|
+
if (!hasMirroredReasoning) appendReasoningDeltas();
|
|
1986
|
+
const toolCallDeltas = normalizedDelta.toolCalls;
|
|
1987
|
+
if (toolCallDeltas.length > 0) {
|
|
1988
|
+
sawNativeToolCallDelta = true;
|
|
1989
|
+
flushReasoningTagTextPartitionerAtEnd();
|
|
1990
|
+
rememberPendingCommentaryTags(provisionalCommentaryTags, tagPendingCommentaryText(output.content));
|
|
1991
|
+
for (const toolCall of toolCallDeltas) {
|
|
1992
|
+
const streamIndex = typeof toolCall.index === "number" ? toolCall.index : void 0;
|
|
1993
|
+
let block = streamIndex !== void 0 ? toolCallBlocksByIndex.get(streamIndex) : void 0;
|
|
1994
|
+
if (!block && toolCall.id) block = toolCallBlocksById.get(toolCall.id);
|
|
1995
|
+
if (!block) {
|
|
1996
|
+
if (currentBlock?.type === "toolCall") {
|
|
1997
|
+
currentBlock = null;
|
|
1998
|
+
flushPendingPostToolCallDeltas();
|
|
1999
|
+
}
|
|
2000
|
+
const initialSig = extractGoogleThoughtSignature(toolCall);
|
|
2001
|
+
block = {
|
|
2002
|
+
type: "toolCall",
|
|
2003
|
+
id: toolCall.id || "",
|
|
2004
|
+
name: toolCall.function?.name || "",
|
|
2005
|
+
arguments: {},
|
|
2006
|
+
partialArgs: "",
|
|
2007
|
+
...initialSig ? { thoughtSignature: initialSig } : {}
|
|
2008
|
+
};
|
|
2009
|
+
output.content.push(block);
|
|
2010
|
+
toolCallBlockIndices.set(block, output.content.length - 1);
|
|
2011
|
+
pushStreamEvent({
|
|
2012
|
+
type: "toolcall_start",
|
|
2013
|
+
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2014
|
+
partial: output
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
if (streamIndex !== void 0 && !toolCallBlocksByIndex.has(streamIndex)) toolCallBlocksByIndex.set(streamIndex, block);
|
|
2018
|
+
if (toolCall.id) {
|
|
2019
|
+
block.id = toolCall.id;
|
|
2020
|
+
toolCallBlocksById.set(toolCall.id, block);
|
|
2021
|
+
}
|
|
2022
|
+
currentBlock = block;
|
|
2023
|
+
if (toolCall.function?.name) block.name = toolCall.function.name;
|
|
2024
|
+
const deltaSig = extractGoogleThoughtSignature(toolCall);
|
|
2025
|
+
if (deltaSig) block.thoughtSignature = deltaSig;
|
|
2026
|
+
if (toolCall.function?.arguments) {
|
|
2027
|
+
const nextArgumentBytes = measureUtf8Bytes(toolCall.function.arguments);
|
|
2028
|
+
const currentBlockArgBytes = toolCallBlockBytes.get(block) ?? 0;
|
|
2029
|
+
if (currentBlockArgBytes + nextArgumentBytes > MAX_TOOL_CALL_ARGUMENT_BUFFER_BYTES) throw new Error("Exceeded tool-call argument buffer limit");
|
|
2030
|
+
toolCallBlockBytes.set(block, currentBlockArgBytes + nextArgumentBytes);
|
|
2031
|
+
block.partialArgs += toolCall.function.arguments;
|
|
2032
|
+
block.arguments = parseStreamingJson(block.partialArgs);
|
|
2033
|
+
pushStreamEvent({
|
|
2034
|
+
type: "toolcall_delta",
|
|
2035
|
+
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2036
|
+
delta: toolCall.function.arguments,
|
|
2037
|
+
partial: output
|
|
2038
|
+
});
|
|
2395
2039
|
}
|
|
2396
|
-
const initialSig = extractGoogleThoughtSignature(toolCall);
|
|
2397
|
-
block = {
|
|
2398
|
-
type: "toolCall",
|
|
2399
|
-
id: toolCall.id || "",
|
|
2400
|
-
name: toolCall.function?.name || "",
|
|
2401
|
-
arguments: {},
|
|
2402
|
-
partialArgs: "",
|
|
2403
|
-
...initialSig ? { thoughtSignature: initialSig } : {}
|
|
2404
|
-
};
|
|
2405
|
-
output.content.push(block);
|
|
2406
|
-
toolCallBlockIndices.set(block, output.content.length - 1);
|
|
2407
|
-
pushStreamEvent({
|
|
2408
|
-
type: "toolcall_start",
|
|
2409
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2410
|
-
partial: output
|
|
2411
|
-
});
|
|
2412
|
-
}
|
|
2413
|
-
if (streamIndex !== void 0 && !toolCallBlocksByIndex.has(streamIndex)) toolCallBlocksByIndex.set(streamIndex, block);
|
|
2414
|
-
if (toolCall.id) {
|
|
2415
|
-
block.id = toolCall.id;
|
|
2416
|
-
toolCallBlocksById.set(toolCall.id, block);
|
|
2417
|
-
}
|
|
2418
|
-
currentBlock = block;
|
|
2419
|
-
if (toolCall.function?.name) block.name = toolCall.function.name;
|
|
2420
|
-
const deltaSig = extractGoogleThoughtSignature(toolCall);
|
|
2421
|
-
if (deltaSig) block.thoughtSignature = deltaSig;
|
|
2422
|
-
if (toolCall.function?.arguments) {
|
|
2423
|
-
const nextArgumentBytes = measureUtf8Bytes(toolCall.function.arguments);
|
|
2424
|
-
const currentBlockArgBytes = toolCallBlockBytes.get(block) ?? 0;
|
|
2425
|
-
if (currentBlockArgBytes + nextArgumentBytes > MAX_TOOL_CALL_ARGUMENT_BUFFER_BYTES) throw new Error("Exceeded tool-call argument buffer limit");
|
|
2426
|
-
toolCallBlockBytes.set(block, currentBlockArgBytes + nextArgumentBytes);
|
|
2427
|
-
block.partialArgs += toolCall.function.arguments;
|
|
2428
|
-
block.arguments = parseStreamingJson(block.partialArgs);
|
|
2429
|
-
pushStreamEvent({
|
|
2430
|
-
type: "toolcall_delta",
|
|
2431
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2432
|
-
delta: toolCall.function.arguments,
|
|
2433
|
-
partial: output
|
|
2434
|
-
});
|
|
2435
2040
|
}
|
|
2436
2041
|
}
|
|
2437
2042
|
}
|
|
@@ -2444,11 +2049,17 @@ async function processOpenAICompletionsStream(responseStream, output, model, str
|
|
|
2444
2049
|
flushDeepSeekTextFilterAtEnd();
|
|
2445
2050
|
currentBlock = null;
|
|
2446
2051
|
flushPendingPostToolCallDeltas();
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2052
|
+
finalizeOpenAICompletionsToolCalls(output, {
|
|
2053
|
+
allowSilentToolCallPromotion: sawStopFinishReason || sawNativeToolCallDelta && (options?.sawStreamDONE?.() ?? false),
|
|
2054
|
+
onConfirmedToolCall(block, contentIndex) {
|
|
2055
|
+
pushStreamEvent({
|
|
2056
|
+
type: "toolcall_end",
|
|
2057
|
+
contentIndex,
|
|
2058
|
+
toolCall: block,
|
|
2059
|
+
partial: output
|
|
2060
|
+
});
|
|
2061
|
+
}
|
|
2062
|
+
});
|
|
2452
2063
|
if (output.stopReason !== "toolUse") clearPendingCommentaryText(provisionalCommentaryTags);
|
|
2453
2064
|
if (output.stopReason === "toolUse") tagPendingCommentaryText(output.content);
|
|
2454
2065
|
}
|
|
@@ -2463,42 +2074,80 @@ const DEEPSEEK_DSML_TOOL_KINDS = [
|
|
|
2463
2074
|
];
|
|
2464
2075
|
const DEEPSEEK_DSML_TOOL_OPEN_TOKENS = DEEPSEEK_DSML_BARS.flatMap((bar) => DEEPSEEK_DSML_TOOL_KINDS.map((kind) => `<${bar}DSML${bar}${kind}>`));
|
|
2465
2076
|
const DEEPSEEK_DSML_TOOL_CLOSE_TOKENS = DEEPSEEK_DSML_BARS.flatMap((bar) => DEEPSEEK_DSML_TOOL_KINDS.map((kind) => `</${bar}DSML${bar}${kind}>`));
|
|
2077
|
+
const DEEPSEEK_DSML_INVOKE_OPEN_PREFIXES = DEEPSEEK_DSML_BARS.map((bar) => `<${bar}DSML${bar}invoke`);
|
|
2078
|
+
const DEEPSEEK_DSML_INVOKE_CLOSE_TOKENS = DEEPSEEK_DSML_BARS.map((bar) => `</${bar}DSML${bar}invoke>`);
|
|
2466
2079
|
const DEEPSEEK_DSML_TOOL_MAX_OPEN_TOKEN_LEN = Math.max(...DEEPSEEK_DSML_TOOL_OPEN_TOKENS.map((token) => token.length));
|
|
2080
|
+
const DEEPSEEK_DSML_RECOVERY_MAX_BOUNDARY_LEN = Math.max(...DEEPSEEK_DSML_TOOL_OPEN_TOKENS.map((token) => token.length), ...DEEPSEEK_DSML_TOOL_CLOSE_TOKENS.map((token) => token.length), ...DEEPSEEK_DSML_INVOKE_OPEN_PREFIXES.map((token) => token.length), ...DEEPSEEK_DSML_INVOKE_CLOSE_TOKENS.map((token) => token.length));
|
|
2081
|
+
const MAX_DSML_RECOVERY_BUFFER_BYTES = 256e3;
|
|
2082
|
+
const DEEPSEEK_DSML_SCAN_BATCH_CHARS = 64 * 1024;
|
|
2467
2083
|
function createDeepSeekDsmlToolCallRecoverer() {
|
|
2468
2084
|
let buffer = "";
|
|
2085
|
+
let bufferBytes = 0;
|
|
2086
|
+
let bufferEndsWithHighSurrogate = false;
|
|
2087
|
+
let pendingScanChars = 0;
|
|
2088
|
+
let activeOpenToken = null;
|
|
2089
|
+
let blockScanState = {
|
|
2090
|
+
offset: 0,
|
|
2091
|
+
mode: "outer",
|
|
2092
|
+
invokeOpenStart: -1
|
|
2093
|
+
};
|
|
2094
|
+
const resetBlockScan = () => {
|
|
2095
|
+
activeOpenToken = null;
|
|
2096
|
+
pendingScanChars = 0;
|
|
2097
|
+
blockScanState = {
|
|
2098
|
+
offset: 0,
|
|
2099
|
+
mode: "outer",
|
|
2100
|
+
invokeOpenStart: -1
|
|
2101
|
+
};
|
|
2102
|
+
};
|
|
2469
2103
|
const consume = (final) => {
|
|
2470
2104
|
const output = [];
|
|
2471
2105
|
while (buffer) {
|
|
2472
|
-
const open =
|
|
2106
|
+
const open = activeOpenToken ? {
|
|
2107
|
+
index: 0,
|
|
2108
|
+
token: activeOpenToken
|
|
2109
|
+
} : findEarliestStringToken(buffer, DEEPSEEK_DSML_TOOL_OPEN_TOKENS);
|
|
2473
2110
|
if (!open) {
|
|
2111
|
+
resetBlockScan();
|
|
2474
2112
|
if (final) {
|
|
2475
2113
|
output.push({
|
|
2476
2114
|
kind: "text",
|
|
2477
2115
|
text: buffer
|
|
2478
2116
|
});
|
|
2479
2117
|
buffer = "";
|
|
2118
|
+
bufferBytes = 0;
|
|
2119
|
+
bufferEndsWithHighSurrogate = false;
|
|
2480
2120
|
return output;
|
|
2481
2121
|
}
|
|
2482
2122
|
const keep = longestDeepSeekDsmlToolOpenPrefixSuffixLength(buffer);
|
|
2483
2123
|
const emitLength = buffer.length - keep;
|
|
2484
2124
|
if (emitLength > 0) {
|
|
2125
|
+
const emitted = buffer.slice(0, emitLength);
|
|
2485
2126
|
output.push({
|
|
2486
2127
|
kind: "text",
|
|
2487
|
-
text:
|
|
2128
|
+
text: emitted
|
|
2488
2129
|
});
|
|
2489
|
-
|
|
2130
|
+
bufferBytes -= Buffer.byteLength(emitted, "utf8");
|
|
2131
|
+
buffer = buffer.slice(emitted.length);
|
|
2132
|
+
if (!buffer) bufferEndsWithHighSurrogate = false;
|
|
2490
2133
|
}
|
|
2491
2134
|
return output;
|
|
2492
2135
|
}
|
|
2493
2136
|
if (open.index > 0) {
|
|
2137
|
+
const prefix = buffer.slice(0, open.index);
|
|
2494
2138
|
output.push({
|
|
2495
2139
|
kind: "text",
|
|
2496
|
-
text:
|
|
2140
|
+
text: prefix
|
|
2497
2141
|
});
|
|
2498
|
-
|
|
2142
|
+
bufferBytes -= Buffer.byteLength(prefix, "utf8");
|
|
2143
|
+
buffer = buffer.slice(prefix.length);
|
|
2144
|
+
resetBlockScan();
|
|
2499
2145
|
}
|
|
2500
|
-
|
|
2501
|
-
|
|
2146
|
+
activeOpenToken = open.token;
|
|
2147
|
+
if (blockScanState.offset === 0) blockScanState.offset = open.token.length;
|
|
2148
|
+
const blockScan = scanDeepSeekDsmlToolBlock(buffer, open.token.replace("<", "</"), open.token.length, blockScanState);
|
|
2149
|
+
if (blockScan.kind === "nested-open") throw new Error("Nested DeepSeek DSML recovery wrappers are not supported");
|
|
2150
|
+
const close = blockScan.kind === "close" ? blockScan : null;
|
|
2502
2151
|
if (!close) {
|
|
2503
2152
|
if (final) {
|
|
2504
2153
|
output.push({
|
|
@@ -2506,24 +2155,38 @@ function createDeepSeekDsmlToolCallRecoverer() {
|
|
|
2506
2155
|
text: buffer
|
|
2507
2156
|
});
|
|
2508
2157
|
buffer = "";
|
|
2158
|
+
bufferBytes = 0;
|
|
2159
|
+
bufferEndsWithHighSurrogate = false;
|
|
2160
|
+
return output;
|
|
2509
2161
|
}
|
|
2162
|
+
if (bufferBytes > MAX_DSML_RECOVERY_BUFFER_BYTES) throw new Error("Exceeded DeepSeek DSML recovery buffer limit");
|
|
2510
2163
|
return output;
|
|
2511
2164
|
}
|
|
2512
|
-
|
|
2513
|
-
const
|
|
2165
|
+
resetBlockScan();
|
|
2166
|
+
const body = buffer.slice(open.token.length, close.index);
|
|
2167
|
+
const blockText = buffer.slice(0, close.index + close.token.length);
|
|
2168
|
+
if (Buffer.byteLength(blockText, "utf8") > MAX_DSML_RECOVERY_BUFFER_BYTES) throw new Error("Exceeded DeepSeek DSML recovery buffer limit");
|
|
2514
2169
|
const recoveredToolCalls = parseDeepSeekDsmlToolCallBlock(body);
|
|
2515
2170
|
if (recoveredToolCalls.length > 0) output.push(...recoveredToolCalls);
|
|
2516
2171
|
else output.push({
|
|
2517
2172
|
kind: "text",
|
|
2518
|
-
text:
|
|
2173
|
+
text: blockText
|
|
2519
2174
|
});
|
|
2520
|
-
|
|
2175
|
+
bufferBytes -= Buffer.byteLength(blockText, "utf8");
|
|
2176
|
+
buffer = buffer.slice(blockText.length);
|
|
2177
|
+
if (!buffer) bufferEndsWithHighSurrogate = false;
|
|
2521
2178
|
}
|
|
2522
2179
|
return output;
|
|
2523
2180
|
};
|
|
2524
2181
|
return {
|
|
2525
2182
|
push(chunk) {
|
|
2183
|
+
const append = utf8ByteLengthForAppend(bufferEndsWithHighSurrogate, chunk);
|
|
2184
|
+
bufferBytes += append.bytes;
|
|
2185
|
+
bufferEndsWithHighSurrogate = append.endsWithHighSurrogate;
|
|
2526
2186
|
buffer += chunk;
|
|
2187
|
+
pendingScanChars += chunk.length;
|
|
2188
|
+
if (activeOpenToken && pendingScanChars < DEEPSEEK_DSML_SCAN_BATCH_CHARS && !chunk.includes("<") && !chunk.includes(">") && bufferBytes <= MAX_DSML_RECOVERY_BUFFER_BYTES) return [];
|
|
2189
|
+
pendingScanChars = 0;
|
|
2527
2190
|
return consume(false);
|
|
2528
2191
|
},
|
|
2529
2192
|
flush() {
|
|
@@ -2533,16 +2196,16 @@ function createDeepSeekDsmlToolCallRecoverer() {
|
|
|
2533
2196
|
}
|
|
2534
2197
|
function parseDeepSeekDsmlToolCallBlock(body) {
|
|
2535
2198
|
const toolCalls = [];
|
|
2536
|
-
const invokeOpenRegex = /<[||]DSML[||]invoke\b([
|
|
2199
|
+
const invokeOpenRegex = /<[||]DSML[||]invoke\b([^<>]*)>/g;
|
|
2537
2200
|
let openMatch;
|
|
2538
2201
|
while ((openMatch = invokeOpenRegex.exec(body)) !== null) {
|
|
2539
|
-
const invokeName = parseXmlAttribute(openMatch[1] ?? "", "name");
|
|
2540
|
-
if (!invokeName) continue;
|
|
2541
2202
|
const invokeBodyStart = openMatch.index + openMatch[0].length;
|
|
2542
2203
|
const invokeClose = findEarliestStringToken(body.slice(invokeBodyStart), ["</|DSML|invoke>", "</|DSML|invoke>"]);
|
|
2543
|
-
if (!invokeClose)
|
|
2204
|
+
if (!invokeClose) break;
|
|
2544
2205
|
const invokeBody = body.slice(invokeBodyStart, invokeBodyStart + invokeClose.index);
|
|
2545
2206
|
invokeOpenRegex.lastIndex = invokeBodyStart + invokeClose.index + invokeClose.token.length;
|
|
2207
|
+
const invokeName = parseXmlAttribute(openMatch[1] ?? "", "name");
|
|
2208
|
+
if (!invokeName) continue;
|
|
2546
2209
|
const parsedArguments = parseDeepSeekDsmlInvokeArguments(invokeBody);
|
|
2547
2210
|
if (!parsedArguments) continue;
|
|
2548
2211
|
toolCalls.push({
|
|
@@ -2593,10 +2256,10 @@ function parseXmlAttribute(attributes, name) {
|
|
|
2593
2256
|
function decodeDeepSeekDsmlText(value) {
|
|
2594
2257
|
return value.replaceAll(""", "\"").replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">").replaceAll("&", "&");
|
|
2595
2258
|
}
|
|
2596
|
-
function findEarliestStringToken(text, tokens) {
|
|
2259
|
+
function findEarliestStringToken(text, tokens, fromIndex = 0) {
|
|
2597
2260
|
let best = null;
|
|
2598
2261
|
for (const token of tokens) {
|
|
2599
|
-
const index = text.indexOf(token);
|
|
2262
|
+
const index = text.indexOf(token, fromIndex);
|
|
2600
2263
|
if (index !== -1 && (!best || index < best.index)) best = {
|
|
2601
2264
|
index,
|
|
2602
2265
|
token
|
|
@@ -2604,6 +2267,89 @@ function findEarliestStringToken(text, tokens) {
|
|
|
2604
2267
|
}
|
|
2605
2268
|
return best;
|
|
2606
2269
|
}
|
|
2270
|
+
function scanDeepSeekDsmlToolBlock(text, closeToken, contentStartIndex, state) {
|
|
2271
|
+
while (state.offset < text.length) {
|
|
2272
|
+
if (state.mode === "invoke-open") {
|
|
2273
|
+
const nextOpen = text.indexOf("<", state.offset);
|
|
2274
|
+
const nextClose = text.indexOf(">", state.offset);
|
|
2275
|
+
if (nextClose === -1 && nextOpen === -1) {
|
|
2276
|
+
state.offset = text.length;
|
|
2277
|
+
return { kind: "incomplete" };
|
|
2278
|
+
}
|
|
2279
|
+
if (nextOpen !== -1 && (nextClose === -1 || nextOpen < nextClose)) {
|
|
2280
|
+
state.mode = "outer";
|
|
2281
|
+
state.offset = nextOpen;
|
|
2282
|
+
state.invokeOpenStart = -1;
|
|
2283
|
+
continue;
|
|
2284
|
+
}
|
|
2285
|
+
const invokeOpenTag = text.slice(state.invokeOpenStart, nextClose + 1);
|
|
2286
|
+
if (!/^<[||]DSML[||]invoke\b[^<>]*>$/.test(invokeOpenTag)) {
|
|
2287
|
+
state.mode = "outer";
|
|
2288
|
+
state.offset = state.invokeOpenStart + 1;
|
|
2289
|
+
state.invokeOpenStart = -1;
|
|
2290
|
+
continue;
|
|
2291
|
+
}
|
|
2292
|
+
state.mode = "invoke-body";
|
|
2293
|
+
state.offset = nextClose + 1;
|
|
2294
|
+
state.invokeOpenStart = -1;
|
|
2295
|
+
continue;
|
|
2296
|
+
}
|
|
2297
|
+
if (state.mode === "invoke-body") {
|
|
2298
|
+
const invokeClose = findEarliestStringToken(text, DEEPSEEK_DSML_INVOKE_CLOSE_TOKENS, state.offset);
|
|
2299
|
+
if (!invokeClose) {
|
|
2300
|
+
state.offset = Math.max(0, text.length - DEEPSEEK_DSML_RECOVERY_MAX_BOUNDARY_LEN + 1);
|
|
2301
|
+
return { kind: "incomplete" };
|
|
2302
|
+
}
|
|
2303
|
+
state.mode = "outer";
|
|
2304
|
+
state.offset = invokeClose.index + invokeClose.token.length;
|
|
2305
|
+
continue;
|
|
2306
|
+
}
|
|
2307
|
+
const toolOpen = findEarliestStringToken(text, DEEPSEEK_DSML_TOOL_OPEN_TOKENS, state.offset);
|
|
2308
|
+
const toolCloseIndex = text.indexOf(closeToken, state.offset);
|
|
2309
|
+
const invokeOpen = findEarliestStringToken(text, DEEPSEEK_DSML_INVOKE_OPEN_PREFIXES, state.offset);
|
|
2310
|
+
const next = [
|
|
2311
|
+
toolOpen ? {
|
|
2312
|
+
kind: "nested-open",
|
|
2313
|
+
...toolOpen
|
|
2314
|
+
} : null,
|
|
2315
|
+
toolCloseIndex === -1 ? null : {
|
|
2316
|
+
kind: "close",
|
|
2317
|
+
index: toolCloseIndex,
|
|
2318
|
+
token: closeToken
|
|
2319
|
+
},
|
|
2320
|
+
invokeOpen ? {
|
|
2321
|
+
kind: "invoke-open",
|
|
2322
|
+
...invokeOpen
|
|
2323
|
+
} : null
|
|
2324
|
+
].filter((candidate) => candidate !== null).toSorted((left, right) => left.index - right.index)[0];
|
|
2325
|
+
if (!next) {
|
|
2326
|
+
state.offset = Math.max(contentStartIndex, text.length - DEEPSEEK_DSML_RECOVERY_MAX_BOUNDARY_LEN + 1);
|
|
2327
|
+
return { kind: "incomplete" };
|
|
2328
|
+
}
|
|
2329
|
+
if (next.kind === "invoke-open") {
|
|
2330
|
+
state.mode = "invoke-open";
|
|
2331
|
+
state.invokeOpenStart = next.index;
|
|
2332
|
+
state.offset = next.index + next.token.length;
|
|
2333
|
+
continue;
|
|
2334
|
+
}
|
|
2335
|
+
return next;
|
|
2336
|
+
}
|
|
2337
|
+
return { kind: "incomplete" };
|
|
2338
|
+
}
|
|
2339
|
+
function utf8ByteLengthForAppend(bufferEndsWithHighSurrogate, chunk) {
|
|
2340
|
+
let bytes = Buffer.byteLength(chunk, "utf8");
|
|
2341
|
+
if (!chunk) return {
|
|
2342
|
+
bytes,
|
|
2343
|
+
endsWithHighSurrogate: bufferEndsWithHighSurrogate
|
|
2344
|
+
};
|
|
2345
|
+
const nextCodeUnit = chunk.charCodeAt(0);
|
|
2346
|
+
if (bufferEndsWithHighSurrogate && nextCodeUnit >= 56320 && nextCodeUnit <= 57343) bytes -= 2;
|
|
2347
|
+
const finalCodeUnit = chunk.charCodeAt(chunk.length - 1);
|
|
2348
|
+
return {
|
|
2349
|
+
bytes,
|
|
2350
|
+
endsWithHighSurrogate: finalCodeUnit >= 55296 && finalCodeUnit <= 56319
|
|
2351
|
+
};
|
|
2352
|
+
}
|
|
2607
2353
|
function longestDeepSeekDsmlToolOpenPrefixSuffixLength(text) {
|
|
2608
2354
|
const maxLength = Math.min(text.length, DEEPSEEK_DSML_TOOL_MAX_OPEN_TOKEN_LEN - 1);
|
|
2609
2355
|
for (let length = maxLength; length > 0; length -= 1) {
|
|
@@ -2612,37 +2358,6 @@ function longestDeepSeekDsmlToolOpenPrefixSuffixLength(text) {
|
|
|
2612
2358
|
}
|
|
2613
2359
|
return 0;
|
|
2614
2360
|
}
|
|
2615
|
-
function getCompletionsContentDeltas(content) {
|
|
2616
|
-
if (typeof content === "string") return content ? [{
|
|
2617
|
-
kind: "text",
|
|
2618
|
-
text: content
|
|
2619
|
-
}] : [];
|
|
2620
|
-
if (Array.isArray(content)) return content.flatMap((item) => getCompletionsContentDeltas(item));
|
|
2621
|
-
if (!content || typeof content !== "object") return [];
|
|
2622
|
-
const record = content;
|
|
2623
|
-
const type = typeof record.type === "string" ? record.type.toLowerCase() : "";
|
|
2624
|
-
const extractText = (value) => {
|
|
2625
|
-
if (typeof value === "string") return value;
|
|
2626
|
-
if (Array.isArray(value)) return value.map((item) => extractText(item)).join("");
|
|
2627
|
-
if (value && typeof value === "object") {
|
|
2628
|
-
const nested = value;
|
|
2629
|
-
return extractText(nested.text ?? nested.content ?? nested.thinking);
|
|
2630
|
-
}
|
|
2631
|
-
return "";
|
|
2632
|
-
};
|
|
2633
|
-
const text = extractText(record.text ?? record.content ?? record.thinking);
|
|
2634
|
-
if (!text) return [];
|
|
2635
|
-
if (type.includes("thinking") || type.includes("reasoning")) return [{
|
|
2636
|
-
kind: "thinking",
|
|
2637
|
-
signature: "content",
|
|
2638
|
-
text
|
|
2639
|
-
}];
|
|
2640
|
-
if (type === "text" || type === "output_text" || type.endsWith(".output_text")) return [{
|
|
2641
|
-
kind: "text",
|
|
2642
|
-
text
|
|
2643
|
-
}];
|
|
2644
|
-
return [];
|
|
2645
|
-
}
|
|
2646
2361
|
function getCompletionsReasoningDeltas(delta, visibleReasoningDetailTypes) {
|
|
2647
2362
|
const output = [];
|
|
2648
2363
|
const pushDelta = (next) => {
|
|
@@ -2795,10 +2510,6 @@ function resolveOpenAICompletionsEffectiveContextTokens(model) {
|
|
|
2795
2510
|
function isQwenOpenAICompletionsThinkingFormat(format) {
|
|
2796
2511
|
return format === "qwen" || format === "qwen-chat-template";
|
|
2797
2512
|
}
|
|
2798
|
-
function isOpenAICompletionsThinkingEnabled(effort) {
|
|
2799
|
-
const normalized = effort.trim().toLowerCase();
|
|
2800
|
-
return normalized !== "off" && normalized !== "none";
|
|
2801
|
-
}
|
|
2802
2513
|
function setQwenChatTemplateThinking(params, enabled) {
|
|
2803
2514
|
const existing = params.chat_template_kwargs;
|
|
2804
2515
|
params.chat_template_kwargs = existing && typeof existing === "object" && !Array.isArray(existing) ? {
|
|
@@ -3097,32 +2808,6 @@ function buildOpenAICompletionsParams(model, context, options) {
|
|
|
3097
2808
|
else if (resolvedCompletionsReasoningEffort && model.reasoning && compat.supportsReasoningEffort && !handledQwenThinkingFormat && !omitChatCompletionsToolReasoningEffort) params.reasoning_effort = resolvedCompletionsReasoningEffort;
|
|
3098
2809
|
return params;
|
|
3099
2810
|
}
|
|
3100
|
-
function parseTransportChunkUsage(rawUsage, model) {
|
|
3101
|
-
const cacheWriteTokens = rawUsage.prompt_tokens_details?.cache_write_tokens || 0;
|
|
3102
|
-
const cachedTokens = rawUsage.prompt_tokens_details?.cached_tokens || 0;
|
|
3103
|
-
const promptTokens = rawUsage.prompt_tokens || 0;
|
|
3104
|
-
const input = Math.max(0, promptTokens - cachedTokens - cacheWriteTokens);
|
|
3105
|
-
const outputTokens = rawUsage.completion_tokens || 0;
|
|
3106
|
-
const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens;
|
|
3107
|
-
const usage = {
|
|
3108
|
-
input,
|
|
3109
|
-
output: outputTokens,
|
|
3110
|
-
cacheRead: cachedTokens,
|
|
3111
|
-
cacheWrite: cacheWriteTokens,
|
|
3112
|
-
...typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) ? { reasoningTokens } : {},
|
|
3113
|
-
totalTokens: input + outputTokens + cachedTokens + cacheWriteTokens,
|
|
3114
|
-
cost: {
|
|
3115
|
-
input: 0,
|
|
3116
|
-
output: 0,
|
|
3117
|
-
cacheRead: 0,
|
|
3118
|
-
cacheWrite: 0,
|
|
3119
|
-
total: 0
|
|
3120
|
-
}
|
|
3121
|
-
};
|
|
3122
|
-
calculateCost(model, usage);
|
|
3123
|
-
applyProviderReportedUsageCost(usage, rawUsage.cost);
|
|
3124
|
-
return usage;
|
|
3125
|
-
}
|
|
3126
2811
|
function hasOpenAICompletionsReasoningUsageActivity(rawUsage) {
|
|
3127
2812
|
const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens;
|
|
3128
2813
|
return typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) && reasoningTokens > 0;
|
|
@@ -3132,7 +2817,7 @@ const completionsTesting = {
|
|
|
3132
2817
|
createSseDoneDetector,
|
|
3133
2818
|
createOpenAICompletionsClient,
|
|
3134
2819
|
buildOpenAICompletionsClientConfig,
|
|
3135
|
-
parseTransportChunkUsage,
|
|
2820
|
+
parseTransportChunkUsage: parseOpenAICompletionsUsage,
|
|
3136
2821
|
processOpenAICompletionsStream,
|
|
3137
2822
|
shouldEmitOpenAICompletionsReasoningForModel
|
|
3138
2823
|
};
|
|
@@ -3731,6 +3416,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
3731
3416
|
enforceCodeModeResponsesToolSurface(params, visibleToolNames);
|
|
3732
3417
|
assertCodeModeResponsesToolSurface(params, visibleToolNames);
|
|
3733
3418
|
}
|
|
3419
|
+
const observePrompt = createResponsesPromptEgressObserver(responsesOptions, context.systemPrompt);
|
|
3734
3420
|
const requestStartedAt = Date.now();
|
|
3735
3421
|
firstEventAbort = createFirstStreamEventAbortController(options?.signal);
|
|
3736
3422
|
const requestOptions = buildOpenAISdkRequestOptions(model, firstEventAbort.signal, {
|
|
@@ -3739,12 +3425,17 @@ function createResponsesTransportExecutor(config) {
|
|
|
3739
3425
|
maxRetries: options?.maxRetries
|
|
3740
3426
|
});
|
|
3741
3427
|
emitModelTransportDebug(log, `[responses] start provider=${model.provider} api=${model.api} model=${model.id} baseUrl=${formatModelTransportDebugBaseUrl(model.baseUrl)} timeoutMs=${safeDebugValue(requestOptions?.timeout)} apiKey=${apiKey ? "present" : "missing"} ${summarizeResponsesPayload(params)}`);
|
|
3742
|
-
const responseStream = await config.createResponseStream({
|
|
3428
|
+
const { stream: responseStream, response } = await config.createResponseStream({
|
|
3743
3429
|
client,
|
|
3744
3430
|
request: params,
|
|
3745
3431
|
requestOptions,
|
|
3746
|
-
model
|
|
3432
|
+
model,
|
|
3433
|
+
observePrompt
|
|
3747
3434
|
});
|
|
3435
|
+
await options?.onResponse?.({
|
|
3436
|
+
status: response.status,
|
|
3437
|
+
headers: headersToRecord(response.headers)
|
|
3438
|
+
}, model);
|
|
3748
3439
|
emitModelTransportDebug(log, `[responses] headers provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - requestStartedAt}`);
|
|
3749
3440
|
stream.push({
|
|
3750
3441
|
type: "start",
|
|
@@ -3804,7 +3495,17 @@ function createAzureOpenAIResponsesTransportStreamFn() {
|
|
|
3804
3495
|
firstEventTimeoutMs: AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS,
|
|
3805
3496
|
createClient: createAzureOpenAIClient,
|
|
3806
3497
|
buildRequest: (model, context, options, metadata) => buildAzureOpenAIResponsesParams(model, context, options, resolveAzureDeploymentName(model), metadata),
|
|
3807
|
-
createResponseStream: async ({ client, request, requestOptions }) =>
|
|
3498
|
+
createResponseStream: async ({ client, request, requestOptions, observePrompt }) => {
|
|
3499
|
+
observePrompt?.(request, {
|
|
3500
|
+
egress: "responses-sdk",
|
|
3501
|
+
payloadVariant: "initial"
|
|
3502
|
+
});
|
|
3503
|
+
const { data, response } = await client.responses.create(request, requestOptions).withResponse();
|
|
3504
|
+
return {
|
|
3505
|
+
stream: data,
|
|
3506
|
+
response
|
|
3507
|
+
};
|
|
3508
|
+
}
|
|
3808
3509
|
});
|
|
3809
3510
|
}
|
|
3810
3511
|
function normalizeAzureBaseUrl(baseUrl) {
|
|
@@ -3971,6 +3672,7 @@ function buildTransportAwareSimpleStreamFn(model, ctx) {
|
|
|
3971
3672
|
//#endregion
|
|
3972
3673
|
//#region packages/ai/src/transports/simple-completion-transport.ts
|
|
3973
3674
|
const PROVIDER_SIMPLE_COMPLETION_API_PREFIX = "openclaw-provider-simple:";
|
|
3675
|
+
const PROVIDER_STREAM_API_PREFIX = "openclaw-provider-stream:";
|
|
3974
3676
|
const INVALID_CODEX_BASE_URL_MESSAGE = "OpenAI Codex Responses baseUrl must not include query parameters or fragments";
|
|
3975
3677
|
function registerCustomApi(registry, api, streamFn) {
|
|
3976
3678
|
getAiTransportHost().registerCustomApi(registry, api, streamFn);
|
|
@@ -4023,6 +3725,15 @@ function resolveProviderSimpleCompletionApi(model) {
|
|
|
4023
3725
|
];
|
|
4024
3726
|
return `${PROVIDER_SIMPLE_COMPLETION_API_PREFIX}${parts.map((part) => encodeURIComponent(part)).join(":")}`;
|
|
4025
3727
|
}
|
|
3728
|
+
function resolveProviderStreamApi(model) {
|
|
3729
|
+
const parts = [
|
|
3730
|
+
model.provider,
|
|
3731
|
+
model.id,
|
|
3732
|
+
model.api,
|
|
3733
|
+
model.baseUrl || "default"
|
|
3734
|
+
];
|
|
3735
|
+
return `${PROVIDER_STREAM_API_PREFIX}${parts.map((part) => encodeURIComponent(part)).join(":")}`;
|
|
3736
|
+
}
|
|
4026
3737
|
function applyProviderSimpleCompletionWrapper(registry, model, cfg) {
|
|
4027
3738
|
if (model.api.startsWith(PROVIDER_SIMPLE_COMPLETION_API_PREFIX)) return model;
|
|
4028
3739
|
const sourceProvider = registry.getApiProvider(model.api);
|
|
@@ -4069,7 +3780,8 @@ function wrapPluginProviderStream(streamFn) {
|
|
|
4069
3780
|
});
|
|
4070
3781
|
};
|
|
4071
3782
|
}
|
|
4072
|
-
function
|
|
3783
|
+
function prepareProviderStreamModel(params) {
|
|
3784
|
+
if (params.model.api === "google-generative-ai") return;
|
|
4073
3785
|
const pluginModel = resolveModelHeaderSentinels(params.model);
|
|
4074
3786
|
const providerStreamFn = getAiTransportHost().plugin.resolveProviderStream({
|
|
4075
3787
|
provider: params.model.provider,
|
|
@@ -4083,15 +3795,19 @@ function registerProviderStreamForModel(params) {
|
|
|
4083
3795
|
});
|
|
4084
3796
|
const transportFallback = providerStreamFn ? void 0 : createTransportAwareStreamFnForModel(params.model.api === "google-generative-ai" ? pluginModel : params.model, { cfg: params.cfg });
|
|
4085
3797
|
const streamFn = providerStreamFn ? wrapPluginProviderStream(providerStreamFn) : transportFallback && params.model.api === "google-generative-ai" ? wrapPluginProviderStream(transportFallback) : transportFallback;
|
|
4086
|
-
|
|
3798
|
+
if (!streamFn) return;
|
|
3799
|
+
const api = params.apiRegistry.getApiProvider(params.model.api) ? resolveProviderStreamApi(params.model) : params.model.api;
|
|
3800
|
+
if (!registerCustomApi(params.apiRegistry, api, streamFn)) return;
|
|
3801
|
+
return api === params.model.api ? params.model : projectModel(params.model, { api });
|
|
4087
3802
|
}
|
|
4088
3803
|
function prepareModelForSimpleCompletion(params) {
|
|
4089
3804
|
const { apiRegistry, model, cfg } = params;
|
|
4090
|
-
|
|
3805
|
+
const providerStreamModel = prepareProviderStreamModel({
|
|
4091
3806
|
model,
|
|
4092
3807
|
cfg,
|
|
4093
3808
|
apiRegistry
|
|
4094
|
-
})
|
|
3809
|
+
});
|
|
3810
|
+
if (providerStreamModel) return applyProviderSimpleCompletionWrapper(apiRegistry, providerStreamModel, cfg);
|
|
4095
3811
|
const codexTransportModel = prepareCodexSimpleTransportModel(apiRegistry, model, cfg);
|
|
4096
3812
|
if (codexTransportModel) return applyProviderSimpleCompletionWrapper(apiRegistry, codexTransportModel, cfg);
|
|
4097
3813
|
const transportAwareModel = prepareTransportAwareSimpleModel(model, { cfg });
|
|
@@ -4107,4 +3823,4 @@ function prepareModelForSimpleCompletion(params) {
|
|
|
4107
3823
|
return applyProviderSimpleCompletionWrapper(apiRegistry, model, cfg);
|
|
4108
3824
|
}
|
|
4109
3825
|
//#endregion
|
|
4110
|
-
export { GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, coerceTransportToolCallArguments, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, filterCodeModePayloadTools, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, hasOpenAICompatibleConversationTurn, isCodeModeModelVisibleToolName, isOpenAICodexResponsesModel, log, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveCodeModeResponsesVisibleToolNames, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAICompletionsCompat, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend };
|
|
3826
|
+
export { GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, applyAnthropicCacheControlToMessages, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, coerceTransportToolCallArguments, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, filterCodeModePayloadTools, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, hasOpenAICompatibleConversationTurn, isCodeModeModelVisibleToolName, isOpenAICodexResponsesModel, isOpenAICompletionsThinkingEnabled, log, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, parseOpenAICompletionsUsage, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveCodeModeResponsesVisibleToolNames, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAICompletionsCompat, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend };
|