@openclaw/ai 2026.9.2 → 2026.9.4
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-C4Qu4H0Z.mjs +377 -0
- package/dist/{anthropic-payload-policy-d46X2pR0.d.mts → anthropic-payload-policy-BZ8umAbk.d.mts} +16 -6
- package/dist/{anthropic-compaction-replay-DB2FGLQc.mjs → anthropic-stream-reducer-CILWF7JD.mjs} +931 -184
- package/dist/{api-registry-DWtPjzyn.d.mts → api-registry-ByUwIR0e.d.mts} +2 -2
- package/dist/assistant-output-tLt4H-iQ.mjs +16 -0
- package/dist/assistant-text-phase-C20rxWwP.mjs +55 -0
- package/dist/{azure-openai-responses-C5bZRfAP.mjs → azure-openai-responses-BAlqlKKc.mjs} +5 -5
- package/dist/{base64-CEFBpSkN.mjs → base64-D-su8YVo.mjs} +1 -27
- package/dist/{diagnostics-DfFyKeX_.mjs → diagnostics-QuErwCIl.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-Bt5Y4Pav.d.mts} +11 -3
- package/dist/event-stream-C3WGFsum.d.mts +1 -0
- package/dist/{event-stream-BgDvQeum.mjs → event-stream-D8PARQfL.mjs} +45 -1
- 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-DPBAOaOW.mjs} +10 -10
- package/dist/google-messages-6JkpHrhJ.mjs +448 -0
- package/dist/google-shared-BvBeW9aq.mjs +185 -0
- package/dist/{google-vertex-O9BcnB6X.mjs → google-vertex-k-TMCAYD.mjs} +7 -6
- package/dist/{host-DjzGmdZ2.d.mts → host-4atIX-2V.d.mts} +5 -3
- package/dist/{host-CEvLw30U.mjs → host-B8YfDGd4.mjs} +181 -41
- package/dist/host-policy-Zcg_cNz8.mjs +37 -0
- package/dist/{index-FnHM2FcI.d.mts → index-DdD3qerf.d.mts} +4 -4
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +7 -6
- 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 +3 -3
- package/dist/internal/openai-responses-payload-policy.mjs +3 -2
- package/dist/internal/openai.d.mts +8 -103
- package/dist/internal/openai.mjs +9 -10
- package/dist/internal/retry-after.d.mts +2 -4
- package/dist/internal/retry-after.mjs +57 -8
- package/dist/internal/runtime.d.mts +43 -7
- package/dist/internal/runtime.mjs +6 -7
- package/dist/internal/shared.d.mts +43 -3
- package/dist/internal/shared.mjs +5 -4
- package/dist/internal/tool-schema.d.mts +63 -0
- package/dist/internal/tool-schema.mjs +3 -0
- package/dist/{mistral-Tb6oalqH.mjs → mistral-CxUZ1jUb.mjs} +10 -37
- package/dist/model-transport-url-DKocrEsb.d.mts +28 -0
- package/dist/{openai-chatgpt-responses-yUXjPNfu.mjs → openai-chatgpt-responses-CgO6kZfo.mjs} +50 -41
- package/dist/{openai-completions-compat-CpjYUArk.d.mts → openai-completions-compat-eHgh5UPE.d.mts} +26 -4
- package/dist/{openai-completions-stream-BsrBe3Gg.mjs → openai-completions-stream-Da2vvl-S.mjs} +654 -453
- package/dist/openai-completions-yJuk7eis.mjs +187 -0
- package/dist/openai-prompt-cache-B4eYo2-I.d.mts +16 -0
- package/dist/openai-prompt-cache-Bds-n_9Q.mjs +220 -0
- package/dist/openai-provider-client-S2gCrM2Z.mjs +24 -0
- package/dist/{openai-responses-CCL41ALM.mjs → openai-responses-DaYwH05E.mjs} +14 -29
- package/dist/{openai-responses-compaction-window-BMVHFOtq.mjs → openai-responses-compaction-window-CIhBAkkq.mjs} +6 -246
- package/dist/{openai-responses-contracts-rF5DDRNS.d.mts → openai-responses-contracts-BjBAqAg_.d.mts} +5 -38
- package/dist/openai-responses-contracts-DDOHA62Y.mjs +245 -0
- package/dist/{openai-responses-prompt-observer-internal-D0bhBfgL.mjs → openai-responses-prompt-observer-internal-f8J7wpsk.mjs} +3 -3
- package/dist/{openai-responses-shared-Bmma_3Qc.mjs → openai-responses-shared-B8RdBPCv.mjs} +47 -118
- 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-9aPuV5YY.mjs +675 -0
- package/dist/positive-integer-41zhOdcV.mjs +8 -0
- package/dist/{provider-error-9TraxGvt.mjs → provider-error-BA-v_tKd.mjs} +70 -11
- package/dist/{provider-options-Bcc_p-TU.d.mts → provider-options-Ceqv1OKk.d.mts} +4 -39
- package/dist/{provider-replay-context-BuSUaAk5.mjs → provider-replay-context-CJ_YvcEW.mjs} +1 -1
- package/dist/{provider-transcript-transform-BaMbI1hr.mjs → provider-transcript-transform-V5YzU9zh.mjs} +1 -1
- package/dist/provider-transport-turn-state-D5EXOFL2.mjs +42 -0
- package/dist/provider-types-CVjKjsuq.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-BcR5pztD.mjs} +19 -19
- package/dist/record-coerce-DwRYMj3t.mjs +32 -0
- package/dist/retry-after-CdCURCVg.d.mts +15 -0
- package/dist/session-affinity-Bcunsn4I.mjs +23 -0
- package/dist/{simple-options-BjHCCh4v.mjs → simple-options-BQbb4yQL.mjs} +24 -5
- package/dist/src-DDmEryvj.mjs +2 -0
- 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-xnaqxmbP.d.mts → transport-stream-shared-DNvmoWnv.d.mts} +20 -36
- package/dist/{transport-stream-shared-CZqMhfIw.mjs → transport-stream-shared-zHll9BxO.mjs} +225 -13
- package/dist/transport-utils-zrYjICLZ.mjs +118 -0
- package/dist/transports.d.mts +137 -193
- package/dist/transports.mjs +204 -1334
- package/dist/types-DlfwzH3T.d.mts +1 -0
- package/dist/types-LFWwv0cF.mjs +8 -0
- package/dist/{types-CJ1-Ht7A.d.mts → types-Ntv5z2g2.d.mts} +74 -57
- package/dist/types.d.mts +6 -6
- package/dist/types.mjs +6 -5
- package/dist/{src-2qBGKg8O.mjs → usage-cost-BNWbbXav.mjs} +0 -1
- package/dist/utf16-slice-CvGodqok.mjs +29 -0
- package/dist/{validation-AKZBDGQd.d.mts → validation-B0t_G2H6.d.mts} +1 -1
- package/dist/{validation-CJZtym2g.mjs → validation-BDzVDnTs.mjs} +9 -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/hash-CHgqbJmD.mjs +0 -16
- package/dist/json-parse-BuAJEbdW.mjs +0 -146
- 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/sanitize-unicode-D6xUvZaS.mjs +0 -83
- package/dist/transport-utils-7il795_9.mjs +0 -138
- package/dist/types-3Lnm-QSJ.d.mts +0 -1
- package/dist/types-BDdaOVi2.mjs +0 -6
- package/dist/utf16-slice-qz3nsy87.mjs +0 -84
package/dist/transports.mjs
CHANGED
|
@@ -1,31 +1,34 @@
|
|
|
1
|
-
import { _ as supportsClaudeAdaptiveThinking,
|
|
2
|
-
import {
|
|
3
|
-
import { r as
|
|
4
|
-
import {
|
|
5
|
-
import { i as stableStringify } from "./provider-error-
|
|
6
|
-
import { r as
|
|
7
|
-
import { a as
|
|
8
|
-
import { n as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
1
|
+
import { _ as supportsClaudeAdaptiveThinking, h as resolveClaudeSonnet5ModelIdentity, m as resolveClaudeOpus5ModelIdentity } from "./usage-cost-BNWbbXav.mjs";
|
|
2
|
+
import { n as normalizeLowercaseStringOrEmpty, t as hasNonEmptyString } from "./string-coerce-fsri9iCu.mjs";
|
|
3
|
+
import { E as resolveAnthropicThinkingEffort, O as usesClaudeFable5MessagesContract, S as defaultsClaudeAdaptiveThinking, T as requiresClaudeAdaptiveThinking, b as ANTHROPIC_CLAUDE_CODE_VERSION, k as usesClaudeStreamingRefusalContract, n as getAiTransportHost, r as resolveAiTransportHeaderSentinels, w as prepareClaudeNoPrefillRequestContext, x as applyClaudeRequestContract } from "./host-B8YfDGd4.mjs";
|
|
4
|
+
import { o as isRecord } from "./record-coerce-DwRYMj3t.mjs";
|
|
5
|
+
import { i as stableStringify } from "./provider-error-BA-v_tKd.mjs";
|
|
6
|
+
import { a as isNativeOpenAIEndpoint, c as resolveOpenAIPromptCacheKeySupport, i as detectOpenAICompletionsCompat, l as usesNativeOpenAICodexResponsesBackend, o as isOpenAICodexResponsesModel, r as resolveOpenAIPromptCacheParams, s as resolveOpenAICompletionsCompat } from "./openai-prompt-cache-Bds-n_9Q.mjs";
|
|
7
|
+
import { a as resolveModelSseDebugMode, i as resolveModelPayloadDebugMode, n as formatModelTransportDebugUrl, r as emitModelTransportDebug, t as formatModelTransportDebugBaseUrl, u as toErrorObject } from "./diagnostics-QuErwCIl.mjs";
|
|
8
|
+
import { a as readResponseTextSnippet, i as isCodeModeModelVisibleToolName, n as createAbortError$1, s as resolveModelHeaderSentinels$1, t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE } from "./transport-utils-zrYjICLZ.mjs";
|
|
9
|
+
import { parseRetryAfterHeadersSeconds } from "./internal/retry-after.mjs";
|
|
10
|
+
import { i as resolveProviderEndpoint, r as resolveOpenAIStrictToolSetting, s as transformTransportMessages, t as buildGuardedModelFetch } from "./host-policy-Zcg_cNz8.mjs";
|
|
11
|
+
import { B as logAnthropicContextEdits, C as applyAnthropicThinkingBindingControls, D as ANTHROPIC_SERVER_SIDE_FALLBACKS, F as applyAnthropicPayloadPolicyToParams, G as resolveAnthropicServerCompactionPlan, H as resolveAnthropicContextManagementBetaHeader, I as applyAnthropicRequestCacheControl, J as usesFoundryBearerAuth, K as isAnthropicOAuthApiKey, L as buildAnthropicSystemBlocks, N as applyAnthropicContextManagementToRequest, O as ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, P as applyAnthropicEphemeralCacheControlMarkers, R as isAnthropicServerToolClearingEnabled, U as resolveAnthropicEphemeralCacheControl, V as resolveAnthropicCacheOptions, W as resolveAnthropicPayloadPolicy, d as convertAnthropicTools, f as buildAnthropicReplayPlan, g as normalizeAnthropicToolCallId, h as suppressAnthropicCompaction, l as buildAnthropicGenerationParams, m as resolveNewestAnthropicCompaction, p as isAnthropicReplayRejection, q as omitFoundryBearerCredentialHeaders, t as consumeAnthropicStream, u as convertAnthropicMessages, z as isDirectAnthropicModel } from "./anthropic-stream-reducer-CILWF7JD.mjs";
|
|
11
12
|
import { t as resolveCacheRetention } from "./cache-retention-0x979a5V.mjs";
|
|
12
|
-
import { a as codeModeToolSurfaceObserver,
|
|
13
|
-
import { a as
|
|
14
|
-
import { a as isGoogleGemini3FlashModel, c as parseRetryAfterSeconds, f as resolveModelHeaderSentinels$1, i as isCodeModeModelVisibleToolName, l as readResponseTextSnippet, m as supportsModelTools, n as createAbortError$1, o as isGoogleGemini3ProModel, p as sha256Hex, r as estimateStringChars, t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, u as redactIdentifier } from "./transport-utils-7il795_9.mjs";
|
|
13
|
+
import { a as codeModeToolSurfaceObserver, m as stripSystemPromptCacheBoundary, o as reasoningTagTextPolicy, t as adjustMaxTokensForThinking, v as sortPromptCacheToolsByName } from "./simple-options-BQbb4yQL.mjs";
|
|
14
|
+
import { C as readOpenAICompletionsContentDeltas, D as throwIfModelStreamAborted, E as resolvePromptCacheKey, O as redactIdentifier, S as parseOpenAICompletionsUsage, T as resolveOpenAIClientBaseUrl, _ as createOpenAIProviderAcceptanceHook, a as enforceCodeModeResponsesToolSurface, b as log, c as readCodeModePayloadToolName, d as resolveOpenAIReasoningEffortMap, f as projectOpenAITools, g as createModelStreamCooperativeScheduler, h as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, i as buildOpenAISdkRequestOptions, k as sha256Hex, l as resolveCodeModeResponsesVisibleToolNames, m as reconcileOpenAIResponsesToolChoice, n as buildOpenAIClientHeaders, o as filterCodeModePayloadTools, r as buildOpenAISdkClientOptions, s as getCompat, t as assertCodeModeResponsesToolSurface, u as resolveOpenAIStrictToolFlagWithDiagnostics, v as createOpenAIResponseHook, w as readOpenAICompletionsReasoningBatch, x as measureUtf8AppendBytes, y as isOpenAICompletionsThinkingEnabled } from "./openai-transport-params-9aPuV5YY.mjs";
|
|
15
15
|
import { n as getEnvApiKey } from "./env-api-keys-bktO00EJ.mjs";
|
|
16
|
-
import {
|
|
17
|
-
import { C as createDeepSeekTextFilter, E as tagUnresolvedTextAsCommentary, S as shouldOmitOllamaCompatResponseFormat, T as tagPendingCommentaryText, _ as hasToolCallHistory, a as buildOpenAISdkClientOptions, b as resolveOpenAICompletionsCompat, c as filterCodeModePayloadTools, d as readCodeModePayloadToolName, f as resolveCodeModeResponsesVisibleToolNames, g as convertMessages, h as resolveOpenAIReasoningEffortMap, i as buildOpenAIClientHeaders, l as getCompat, m as usesNativeOpenAICodexResponsesBackend, n as shouldEmitOpenAICompletionsReasoning, o as buildOpenAISdkRequestOptions, p as resolveOpenAIStrictToolFlagWithDiagnostics, r as assertCodeModeResponsesToolSurface, s as enforceCodeModeResponsesToolSurface, t as processCompletionsStream, u as isOpenAICodexResponsesModel, v as finalizeOpenAICompletionsToolCalls, x as resolveOpenAICompletionsResponseFormat, y as detectOpenAICompletionsCompat } from "./openai-completions-stream-BsrBe3Gg.mjs";
|
|
16
|
+
import { C as quoteUnsafeIntegerLiterals, S as parseJsonPreservingUnsafeIntegers, _ as sanitizeTransportPayloadText, a as createEmptyTransportUsage, b as withProviderResponseHook, c as finalizeTerminalToolCallArguments, d as mergeTransportMetadata, f as notifyProviderHttpMetadata, g as sanitizeNonEmptyTransportPayloadText, h as parseTerminalToolCallArguments, i as copyProviderAcceptanceObserver, l as finalizeTransportStream, m as notifyProviderStreamOpened, n as assignTransportErrorDetails, o as createWritableTransportEventStream, p as notifyProviderHttpResponse, r as coerceTransportToolCallArguments, s as failTransportStream, t as IncompleteToolCallError, u as mergeTransportHeaders, v as transportAbortError, x as parseJsonObjectPreservingUnsafeIntegers, y as withProviderAcceptanceObserver } from "./transport-stream-shared-zHll9BxO.mjs";
|
|
18
17
|
import { t as createDeferredEventBuffer } from "./deferred-event-buffer-DAvyP7qA.mjs";
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { t as
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { i as
|
|
25
|
-
import {
|
|
18
|
+
import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-CJ_YvcEW.mjs";
|
|
19
|
+
import { a as tagUnresolvedTextAsCommentary } from "./assistant-text-phase-C20rxWwP.mjs";
|
|
20
|
+
import { t as createAssistantOutput } from "./assistant-output-tLt4H-iQ.mjs";
|
|
21
|
+
import { n as resolveOpencodeSessionHeaders } from "./session-affinity-Bcunsn4I.mjs";
|
|
22
|
+
import { c as flattenCompletionMessagesToStringContent, d as canonicalizeMaxTokensParam, f as resolveMaxTokensParam, l as stripCompletionMessagesToRoleContent, n as shouldEmitOpenAICompletionsReasoning, o as isAzureOpenAICompatibleHost, p as createDeepSeekTextFilter, r as buildOpenAICompletionsParams, s as finalizeOpenAICompletionsToolCalls, t as processCompletionsStream, u as applyCompletionsAnthropicCacheControl } from "./openai-completions-stream-Da2vvl-S.mjs";
|
|
23
|
+
import { a as googleFlashSupportsMinimalThinking, i as consumeGoogleGenerateContentStream, n as projectGoogleMessages, r as requiresGoogleToolCallId, t as convertGoogleTools } from "./google-messages-6JkpHrhJ.mjs";
|
|
24
|
+
import { i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-2hfrquuz.mjs";
|
|
25
|
+
import { C as supportsOpenAITemperature, b as resolveOpenAIReasoningEffortForModel, d as OpenAIResponsesWebSocketSafeRetryError, i as OPENAI_RESPONSES_APIS, l as OpenAIResponsesWebSocketPostDispatchError, p as parseOpenAIResponsesWebSocketServerError, r as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS, t as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, u as OpenAIResponsesWebSocketPreDispatchError, v as normalizeOpenAIReasoningEffort } from "./openai-responses-contracts-DDOHA62Y.mjs";
|
|
26
|
+
import { r as resolveProviderTransportTurnState, t as filterProviderTurnHeadersForExplicitOpencodeSession } from "./provider-transport-turn-state-D5EXOFL2.mjs";
|
|
27
|
+
import { a as applyOpenAIResponsesPayloadPolicy, c as resolveOpenAIResponsesServerCompactionPlan, i as sanitizeResponsesImagePayload, n as isOpenAIResponsesCompactionOutput, o as resolveOpenAIResponsesCompactEndpointPlan, s as resolveOpenAIResponsesPayloadPolicy, t as createBoundedOpenAIResponsesCompactionFetch } from "./openai-responses-compaction-window-CIhBAkkq.mjs";
|
|
28
|
+
import { B as responsesInputFingerprint, F as resolveNextResponsesEncryptedContentAttempt, G as resolveNewestOpenAIResponsesCompactionReplay, H as buildOpenAIResponsesReasoningReplayMetadata, I as buildResponsesInputMessage, K as suppressOpenAIResponsesCompaction, L as convertResponsesMessages, M as createResponsesStreamWithEncryptedContentRetry, N as isInvalidEncryptedContentError, P as resolveAzureOpenAIApiVersion, R as createOpenAIResponsesAssistantOutput, U as captureOpenAIResponsesCompaction, V as CompactionReplayRefreshRequiredError, W as isOpenAIResponsesReplayContext, _ as safeDebugValue, c as convertProjectedResponsesTools, g as logResponsesFailedNoDetails, h as ResponsesStreamFailure, m as observeResponsesStream, n as applyResponsesServiceTierPricing, q as resolveReplayableResponsesMessageId, u as processResponsesStream, v as summarizeOpenAITransportError, y as summarizeResponsesPayload, z as recordResponsesInputReplay } from "./openai-responses-shared-B8RdBPCv.mjs";
|
|
26
29
|
import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
|
|
27
30
|
import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
|
|
28
|
-
import { t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-
|
|
31
|
+
import { t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-f8J7wpsk.mjs";
|
|
29
32
|
import { randomUUID } from "node:crypto";
|
|
30
33
|
import OpenAI, { AzureOpenAI } from "openai";
|
|
31
34
|
import { ResponsesWS } from "openai/resources/responses/ws.js";
|
|
@@ -78,221 +81,12 @@ function buildAnthropicBetaHeader(model, betaFeatures, params) {
|
|
|
78
81
|
if (!isDirectAnthropicModel(model)) return;
|
|
79
82
|
return params.oauth ? `claude-code-20250219,oauth-2025-04-20,${betaFeatures.join(",")}` : betaFeatures.join(",");
|
|
80
83
|
}
|
|
81
|
-
const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
|
|
82
|
-
async function convertContentBlocks(content, model, imageBudget) {
|
|
83
|
-
const text = extractToolResultText(content);
|
|
84
|
-
const mediaPlaceholder = describeToolResultMediaPlaceholder(content);
|
|
85
|
-
if (!(model.input.includes("image") && content.some(isImageWithMediaPayload))) return sanitizeNonEmptyTransportPayloadText(text, mediaPlaceholder ?? "(no output)");
|
|
86
|
-
const blocks = [];
|
|
87
|
-
let hasTextBlock = false;
|
|
88
|
-
for (const block of content) {
|
|
89
|
-
if (!block || typeof block !== "object") continue;
|
|
90
|
-
const record = block;
|
|
91
|
-
const blockText = extractToolResultBlockText(block);
|
|
92
|
-
if (blockText) {
|
|
93
|
-
blocks.push({
|
|
94
|
-
type: "text",
|
|
95
|
-
text: sanitizeTransportPayloadText(blockText)
|
|
96
|
-
});
|
|
97
|
-
hasTextBlock = true;
|
|
98
|
-
}
|
|
99
|
-
if (!isImageWithMediaPayload(record)) continue;
|
|
100
|
-
const [normalizedImage] = await normalizeAnthropicInlineContent([{
|
|
101
|
-
type: "image",
|
|
102
|
-
data: typeof record.data === "string" ? record.data : "",
|
|
103
|
-
mimeType: typeof record.mimeType === "string" ? record.mimeType : "image/png"
|
|
104
|
-
}], imageBudget);
|
|
105
|
-
if (normalizedImage?.type !== "image") continue;
|
|
106
|
-
blocks.push({
|
|
107
|
-
type: "image",
|
|
108
|
-
source: {
|
|
109
|
-
type: "base64",
|
|
110
|
-
media_type: resolveAnthropicImageMediaType(normalizedImage.mimeType),
|
|
111
|
-
data: normalizedImage.data
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
if (!hasTextBlock) blocks.unshift({
|
|
116
|
-
type: "text",
|
|
117
|
-
text: mediaPlaceholder ?? "(see attached image)"
|
|
118
|
-
});
|
|
119
|
-
return blocks;
|
|
120
|
-
}
|
|
121
|
-
async function convertAnthropicMessages(messages, model, isOAuthToken, options) {
|
|
122
|
-
const params = [];
|
|
123
|
-
const imageBudget = createAnthropicInlineImageBudget();
|
|
124
|
-
const allowReasoningContentReplay = options.allowReasoningContentReplay === true;
|
|
125
|
-
const replayThinkingEnabled = options.replayThinkingEnabled !== false;
|
|
126
|
-
const transformedMessages = transformTransportMessages(messages, model, normalizeAnthropicToolCallId);
|
|
127
|
-
const activeToolTurnAssistantIndex = replayThinkingEnabled ? -1 : findActiveAnthropicToolTurnAssistantIndex(transformedMessages);
|
|
128
|
-
for (let i = 0; i < transformedMessages.length; i += 1) {
|
|
129
|
-
const msg = transformedMessages[i];
|
|
130
|
-
if (!msg) continue;
|
|
131
|
-
if (msg.role === "user") {
|
|
132
|
-
if (typeof msg.content === "string") {
|
|
133
|
-
if (msg.content.trim().length > 0) {
|
|
134
|
-
const userParam = {
|
|
135
|
-
role: "user",
|
|
136
|
-
content: sanitizeTransportPayloadText(msg.content)
|
|
137
|
-
};
|
|
138
|
-
params.push(userParam);
|
|
139
|
-
}
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
const blocks = (model.input.includes("image") ? await normalizeAnthropicInlineContent(msg.content, imageBudget) : msg.content.map((item) => item.type === "image" ? {
|
|
143
|
-
type: "text",
|
|
144
|
-
text: NON_VISION_USER_IMAGE_PLACEHOLDER
|
|
145
|
-
} : item)).map((item) => item.type === "text" ? {
|
|
146
|
-
type: "text",
|
|
147
|
-
text: sanitizeTransportPayloadText(item.text)
|
|
148
|
-
} : {
|
|
149
|
-
type: "image",
|
|
150
|
-
source: {
|
|
151
|
-
type: "base64",
|
|
152
|
-
media_type: resolveAnthropicImageMediaType(item.mimeType),
|
|
153
|
-
data: item.data
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
let filteredBlocks = model.input.includes("image") ? blocks : blocks.filter((block) => block.type !== "image");
|
|
157
|
-
filteredBlocks = filteredBlocks.filter((block) => block.type !== "text" || block.text.trim().length > 0);
|
|
158
|
-
if (filteredBlocks.length === 0) continue;
|
|
159
|
-
const userParam = {
|
|
160
|
-
role: "user",
|
|
161
|
-
content: filteredBlocks
|
|
162
|
-
};
|
|
163
|
-
params.push(userParam);
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
if (msg.role === "assistant") {
|
|
167
|
-
const blocks = i === 0 && options.compaction ? [options.compaction] : [];
|
|
168
|
-
const reasoningContent = [];
|
|
169
|
-
let omittedThinking = false;
|
|
170
|
-
for (const block of msg.content) {
|
|
171
|
-
if (block.type === "text") {
|
|
172
|
-
if (block.text.trim().length > 0) blocks.push({
|
|
173
|
-
type: "text",
|
|
174
|
-
text: sanitizeTransportPayloadText(block.text)
|
|
175
|
-
});
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
if (block.type === "thinking") {
|
|
179
|
-
const thinkingSignature = block.thinkingSignature?.trim();
|
|
180
|
-
const isReasoningContent = thinkingSignature === "reasoning_content";
|
|
181
|
-
if (!replayThinkingEnabled && i !== activeToolTurnAssistantIndex && !isReasoningContent) {
|
|
182
|
-
omittedThinking = true;
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
if (block.redacted) {
|
|
186
|
-
blocks.push({
|
|
187
|
-
type: "redacted_thinking",
|
|
188
|
-
data: block.thinkingSignature
|
|
189
|
-
});
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
const hasNativeThinkingSignature = Boolean(thinkingSignature) && !isReasoningContent;
|
|
193
|
-
if (block.thinking.trim().length === 0 && !hasNativeThinkingSignature) continue;
|
|
194
|
-
if (!thinkingSignature) blocks.push({
|
|
195
|
-
type: "text",
|
|
196
|
-
text: sanitizeTransportPayloadText(block.thinking)
|
|
197
|
-
});
|
|
198
|
-
else {
|
|
199
|
-
const thinking = thinkingSignature === "reasoning_content" ? sanitizeTransportPayloadText(block.thinking) : block.thinking;
|
|
200
|
-
if (thinkingSignature === "reasoning_content") {
|
|
201
|
-
if (allowReasoningContentReplay) {
|
|
202
|
-
blocks.push({
|
|
203
|
-
type: "thinking",
|
|
204
|
-
thinking,
|
|
205
|
-
signature: thinkingSignature
|
|
206
|
-
});
|
|
207
|
-
reasoningContent.push(thinking);
|
|
208
|
-
}
|
|
209
|
-
continue;
|
|
210
|
-
}
|
|
211
|
-
blocks.push({
|
|
212
|
-
type: "thinking",
|
|
213
|
-
thinking,
|
|
214
|
-
signature: thinkingSignature
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
if (block.type === "toolCall") blocks.push({
|
|
220
|
-
type: "tool_use",
|
|
221
|
-
id: block.id,
|
|
222
|
-
name: isOAuthToken ? toClaudeCodeToolName(block.name) : block.name,
|
|
223
|
-
input: coerceTransportToolCallArguments(block.arguments)
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
if (blocks.length === 0 && omittedThinking) blocks.push({
|
|
227
|
-
type: "text",
|
|
228
|
-
text: ANTHROPIC_OMITTED_REASONING_TEXT
|
|
229
|
-
});
|
|
230
|
-
if (blocks.length > 0) {
|
|
231
|
-
const assistantMsg = {
|
|
232
|
-
role: "assistant",
|
|
233
|
-
content: blocks
|
|
234
|
-
};
|
|
235
|
-
if (reasoningContent.length > 0) assistantMsg.reasoning_content = reasoningContent.join("\n");
|
|
236
|
-
else if (allowReasoningContentReplay) blocks.unshift({
|
|
237
|
-
type: "thinking",
|
|
238
|
-
thinking: "",
|
|
239
|
-
signature: "reasoning_content"
|
|
240
|
-
});
|
|
241
|
-
params.push(assistantMsg);
|
|
242
|
-
}
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
245
|
-
if (msg.role === "toolResult") {
|
|
246
|
-
const toolResult = msg;
|
|
247
|
-
const toolResults = [{
|
|
248
|
-
type: "tool_result",
|
|
249
|
-
tool_use_id: toolResult.toolCallId,
|
|
250
|
-
content: await convertContentBlocks(toolResult.content, model, imageBudget),
|
|
251
|
-
is_error: toolResult.isError
|
|
252
|
-
}];
|
|
253
|
-
let j = i + 1;
|
|
254
|
-
while (j < transformedMessages.length) {
|
|
255
|
-
const nextMsg = transformedMessages.at(j);
|
|
256
|
-
if (nextMsg?.role !== "toolResult") break;
|
|
257
|
-
toolResults.push({
|
|
258
|
-
type: "tool_result",
|
|
259
|
-
tool_use_id: nextMsg.toolCallId,
|
|
260
|
-
content: await convertContentBlocks(nextMsg.content, model, imageBudget),
|
|
261
|
-
is_error: nextMsg.isError
|
|
262
|
-
});
|
|
263
|
-
j += 1;
|
|
264
|
-
}
|
|
265
|
-
i = j - 1;
|
|
266
|
-
params.push({
|
|
267
|
-
role: "user",
|
|
268
|
-
content: toolResults
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return params;
|
|
273
|
-
}
|
|
274
84
|
function ensureNonEmptyAnthropicMessages(messages) {
|
|
275
85
|
return messages.length > 0 ? messages : [{
|
|
276
86
|
role: "user",
|
|
277
87
|
content: EMPTY_ANTHROPIC_MESSAGES_FALLBACK_TEXT
|
|
278
88
|
}];
|
|
279
89
|
}
|
|
280
|
-
function convertAnthropicTools(tools, isOAuthToken) {
|
|
281
|
-
const projection = projectAnthropicTools(tools ?? [], (name) => isOAuthToken ? toClaudeCodeToolName(name) : name);
|
|
282
|
-
const converted = [];
|
|
283
|
-
for (const tool of projection.tools) converted.push({
|
|
284
|
-
name: tool.wireName,
|
|
285
|
-
description: tool.description,
|
|
286
|
-
input_schema: tool.inputSchema
|
|
287
|
-
});
|
|
288
|
-
return {
|
|
289
|
-
projection,
|
|
290
|
-
tools: converted
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
function parseAnthropicToolCallArguments(inputJson) {
|
|
294
|
-
return coerceTransportToolCallArguments(parseJsonObjectPreservingUnsafeIntegers(inputJson) ?? parseStreamingJson(inputJson));
|
|
295
|
-
}
|
|
296
90
|
const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
|
|
297
91
|
/** Resolve the effective Anthropic API base URL from model or environment. */
|
|
298
92
|
function resolveAnthropicBaseUrl(baseUrl) {
|
|
@@ -323,7 +117,6 @@ function readAnthropicSseChunk(reader, signal) {
|
|
|
323
117
|
if (settled) return;
|
|
324
118
|
settled = true;
|
|
325
119
|
signal.removeEventListener("abort", onAbort);
|
|
326
|
-
reader.cancel(signal.reason).catch(() => void 0);
|
|
327
120
|
reject(createAbortError(signal));
|
|
328
121
|
};
|
|
329
122
|
if (signal.aborted) {
|
|
@@ -388,7 +181,11 @@ async function* parseAnthropicSseBody(body, signal) {
|
|
|
388
181
|
if (data && data !== "[DONE]") yield parseAnthropicSseEventData(data);
|
|
389
182
|
}
|
|
390
183
|
} finally {
|
|
391
|
-
if (!completed)
|
|
184
|
+
if (!completed) {
|
|
185
|
+
const cancellation = reader.cancel(signal?.reason).catch(() => void 0);
|
|
186
|
+
if (signal?.aborted) getAiTransportHost().observePendingProviderWork?.(cancellation);
|
|
187
|
+
else await cancellation;
|
|
188
|
+
}
|
|
392
189
|
reader.releaseLock();
|
|
393
190
|
}
|
|
394
191
|
}
|
|
@@ -415,7 +212,7 @@ function createAnthropicMessagesClient(params) {
|
|
|
415
212
|
} } };
|
|
416
213
|
}
|
|
417
214
|
function formatAnthropicMessagesHttpError(response, detail) {
|
|
418
|
-
const retryAfterSeconds =
|
|
215
|
+
const retryAfterSeconds = parseRetryAfterHeadersSeconds(response.headers);
|
|
419
216
|
const retryAfterSuffix = Number.isFinite(retryAfterSeconds) ? `; Retry-After: ${Math.ceil(retryAfterSeconds ?? 0)} seconds` : "";
|
|
420
217
|
return `HTTP ${response.status}: ${detail || "Anthropic Messages request failed"}${retryAfterSuffix}`;
|
|
421
218
|
}
|
|
@@ -434,6 +231,7 @@ async function readAnthropicMessagesErrorBodySnippet(response) {
|
|
|
434
231
|
}
|
|
435
232
|
function createAnthropicTransportClient(params) {
|
|
436
233
|
const { model, context, apiKey, options } = params;
|
|
234
|
+
const optionHeaders = resolveOpencodeSessionHeaders(model, options);
|
|
437
235
|
const needsInterleavedBeta = (options?.interleavedThinking ?? true) && !supportsClaudeAdaptiveThinking(model);
|
|
438
236
|
const fetch = isKimiAnthropicProvider(model.provider) && options?.thinkingEnabled === true ? buildGuardedModelFetch(model, void 0, { sanitizeSse: false }) : buildGuardedModelFetch(model);
|
|
439
237
|
if (model.provider === "github-copilot") {
|
|
@@ -447,7 +245,7 @@ function createAnthropicTransportClient(params) {
|
|
|
447
245
|
accept: "application/json",
|
|
448
246
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
449
247
|
...betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}
|
|
450
|
-
}, model.headers, getAiTransportHost().buildCopilotDynamicHeaders(context.messages),
|
|
248
|
+
}, model.headers, getAiTransportHost().buildCopilotDynamicHeaders(context.messages), optionHeaders),
|
|
451
249
|
fetch
|
|
452
250
|
}),
|
|
453
251
|
isOAuthToken: false
|
|
@@ -464,7 +262,7 @@ function createAnthropicTransportClient(params) {
|
|
|
464
262
|
accept: "application/json",
|
|
465
263
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
466
264
|
...betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}
|
|
467
|
-
}, omitFoundryBearerCredentialHeaders(model.headers),
|
|
265
|
+
}, omitFoundryBearerCredentialHeaders(model.headers), optionHeaders),
|
|
468
266
|
fetch
|
|
469
267
|
}),
|
|
470
268
|
isOAuthToken: false
|
|
@@ -485,7 +283,7 @@ function createAnthropicTransportClient(params) {
|
|
|
485
283
|
...betaHeader ? { "anthropic-beta": betaHeader } : {},
|
|
486
284
|
"user-agent": `claude-cli/${ANTHROPIC_CLAUDE_CODE_VERSION}`,
|
|
487
285
|
"x-app": "cli"
|
|
488
|
-
}, model.headers,
|
|
286
|
+
}, model.headers, optionHeaders),
|
|
489
287
|
fetch
|
|
490
288
|
}),
|
|
491
289
|
isOAuthToken: true
|
|
@@ -497,7 +295,7 @@ function createAnthropicTransportClient(params) {
|
|
|
497
295
|
accept: "application/json",
|
|
498
296
|
"anthropic-dangerous-direct-browser-access": "true",
|
|
499
297
|
...betaHeader ? { "anthropic-beta": betaHeader } : {}
|
|
500
|
-
}, model.headers,
|
|
298
|
+
}, model.headers, optionHeaders);
|
|
501
299
|
return {
|
|
502
300
|
client: createAnthropicMessagesClient({
|
|
503
301
|
apiKey,
|
|
@@ -510,30 +308,26 @@ function createAnthropicTransportClient(params) {
|
|
|
510
308
|
};
|
|
511
309
|
}
|
|
512
310
|
async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
513
|
-
const
|
|
514
|
-
const replayThinkingEnabled = mandatoryAdaptiveThinking || options?.thinkingEnabled === true;
|
|
311
|
+
const replayThinkingEnabled = requiresClaudeAdaptiveThinking(model) || options?.thinkingEnabled === true;
|
|
515
312
|
const maxTokens = resolveAnthropicMessagesMaxTokens({
|
|
516
313
|
modelContextWindow: model.contextWindow,
|
|
517
314
|
modelMaxTokens: model.maxTokens,
|
|
518
315
|
requestedMaxTokens: options?.maxTokens
|
|
519
316
|
});
|
|
520
317
|
if (maxTokens === void 0) throw new Error(`Anthropic Messages transport requires a positive maxTokens value for ${model.provider}/${model.id}`);
|
|
521
|
-
const
|
|
522
|
-
provider: model.provider,
|
|
523
|
-
api: model.api,
|
|
524
|
-
baseUrl: model.baseUrl,
|
|
525
|
-
cacheRetention: options?.cacheRetention,
|
|
526
|
-
enableCacheControl: true
|
|
527
|
-
}, model);
|
|
318
|
+
const { cacheControl, supportsCacheControlOnTools } = resolveAnthropicCacheOptions(model, options?.cacheRetention);
|
|
528
319
|
const replayPlan = buildAnthropicReplayPlan(context.messages, model, {
|
|
529
320
|
enabled: !isOAuthToken && options?.anthropicServerCompaction === true,
|
|
530
321
|
authProfileId: options?.authProfileId,
|
|
531
322
|
sessionId: options?.sessionId
|
|
532
323
|
});
|
|
533
|
-
const
|
|
324
|
+
const cacheBreakpointOptOutMessageIndexes = /* @__PURE__ */ new Set();
|
|
325
|
+
const messages = await convertAnthropicMessages(transformTransportMessages(replayPlan.messages, model, normalizeAnthropicToolCallId), model, isOAuthToken, {
|
|
326
|
+
profile: "transport",
|
|
534
327
|
allowReasoningContentReplay: supportsReasoningContentReplay(model),
|
|
535
328
|
compaction: replayPlan.compaction,
|
|
536
|
-
replayThinkingEnabled
|
|
329
|
+
replayThinkingEnabled,
|
|
330
|
+
cacheBreakpointOptOutMessageIndexes
|
|
537
331
|
});
|
|
538
332
|
const params = {
|
|
539
333
|
model: resolveAnthropicRequestModelId(model),
|
|
@@ -542,54 +336,18 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
542
336
|
stream: true
|
|
543
337
|
};
|
|
544
338
|
if (!isOAuthToken && useAnthropicServerSideFallback(model)) params.fallbacks = ANTHROPIC_SERVER_SIDE_FALLBACKS;
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
}] : []
|
|
558
|
-
];
|
|
559
|
-
else if (context.systemPrompt) params.system = [{
|
|
560
|
-
type: "text",
|
|
561
|
-
text: sanitizeTransportPayloadText(context.systemPrompt)
|
|
562
|
-
}];
|
|
563
|
-
if (options?.temperature !== void 0 && !options.thinkingEnabled && !supportsClaudeNativeXhighEffort(model)) params.temperature = options.temperature;
|
|
564
|
-
if (options?.stop !== void 0 && options.stop.length > 0) params.stop_sequences = options.stop;
|
|
565
|
-
let toolProjection;
|
|
566
|
-
if (context.tools) {
|
|
567
|
-
const convertedTools = convertAnthropicTools(context.tools, isOAuthToken);
|
|
568
|
-
toolProjection = convertedTools.projection;
|
|
569
|
-
if (convertedTools.tools.length > 0) params.tools = convertedTools.tools;
|
|
570
|
-
}
|
|
571
|
-
if (mandatoryAdaptiveThinking || model.reasoning || supportsClaudeAdaptiveThinking(model)) {
|
|
572
|
-
if (mandatoryAdaptiveThinking || options?.thinkingEnabled) {
|
|
573
|
-
if (supportsClaudeAdaptiveThinking(model)) {
|
|
574
|
-
params.thinking = {
|
|
575
|
-
type: "adaptive",
|
|
576
|
-
display: options?.thinkingDisplay ?? "summarized"
|
|
577
|
-
};
|
|
578
|
-
const effort = options?.effort ?? (mandatoryAdaptiveThinking ? "high" : void 0);
|
|
579
|
-
if (effort) params.output_config = { effort };
|
|
580
|
-
} else params.thinking = {
|
|
581
|
-
type: "enabled",
|
|
582
|
-
budget_tokens: options?.thinkingBudgetTokens ?? 1024
|
|
583
|
-
};
|
|
584
|
-
} else if (options?.thinkingEnabled === false) params.thinking = { type: "disabled" };
|
|
585
|
-
}
|
|
586
|
-
if (options?.metadata && typeof options.metadata.user_id === "string") params.metadata = { user_id: options.metadata.user_id };
|
|
587
|
-
if (options?.toolChoice) {
|
|
588
|
-
const normalizedToolChoice = normalizeAnthropicToolChoice(replayThinkingEnabled, options.toolChoice);
|
|
589
|
-
const projectedToolChoice = toolProjection ? reconcileAnthropicToolChoice(normalizedToolChoice, toolProjection) : normalizedToolChoice;
|
|
590
|
-
if (projectedToolChoice) params.tool_choice = projectedToolChoice;
|
|
591
|
-
}
|
|
592
|
-
applyAnthropicPayloadPolicyToParams(params, payloadPolicy, /* @__PURE__ */ new Set());
|
|
339
|
+
const system = buildAnthropicSystemBlocks(context.systemPrompt, isOAuthToken, cacheControl);
|
|
340
|
+
if (system) params.system = system;
|
|
341
|
+
const convertedTools = context.tools ? convertAnthropicTools(context.tools, isOAuthToken) : void 0;
|
|
342
|
+
const toolProjection = convertedTools?.projection;
|
|
343
|
+
Object.assign(params, buildAnthropicGenerationParams({
|
|
344
|
+
model,
|
|
345
|
+
options,
|
|
346
|
+
tools: convertedTools?.tools,
|
|
347
|
+
toolProjection,
|
|
348
|
+
profile: "transport"
|
|
349
|
+
}));
|
|
350
|
+
applyAnthropicRequestCacheControl(params, cacheControl, supportsCacheControlOnTools, cacheBreakpointOptOutMessageIndexes);
|
|
593
351
|
return {
|
|
594
352
|
params,
|
|
595
353
|
toolProjection,
|
|
@@ -657,22 +415,9 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
657
415
|
const options = rawOptions;
|
|
658
416
|
const { eventStream, stream } = createWritableTransportEventStream();
|
|
659
417
|
(async () => {
|
|
660
|
-
const output =
|
|
661
|
-
role: "assistant",
|
|
662
|
-
content: [],
|
|
663
|
-
api: "anthropic-messages",
|
|
664
|
-
provider: model.provider,
|
|
665
|
-
model: model.id,
|
|
666
|
-
usage: createEmptyTransportUsage(),
|
|
667
|
-
stopReason: "stop",
|
|
668
|
-
timestamp: Date.now()
|
|
669
|
-
};
|
|
418
|
+
const output = createAssistantOutput(model, "anthropic-messages");
|
|
670
419
|
const refusalBuffer = usesClaudeStreamingRefusalContract(model) ? createDeferredEventBuffer(stream) : void 0;
|
|
671
|
-
const eventSink = refusalBuffer ?? stream;
|
|
672
|
-
let costModel = model;
|
|
673
|
-
let messageStartPromptUsage;
|
|
674
420
|
let usedCompactionReplay = false;
|
|
675
|
-
let inputTransformations;
|
|
676
421
|
try {
|
|
677
422
|
const apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? "";
|
|
678
423
|
if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
|
|
@@ -693,7 +438,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
693
438
|
if (nextParams !== void 0) params = nextParams;
|
|
694
439
|
applyClaudeRequestContract(params, model);
|
|
695
440
|
const betaHeader = resolveAnthropicContextManagementBetaHeader(params, directApiKeyBetaHeader);
|
|
696
|
-
const bindingHeaders = applyAnthropicThinkingBindingControls(params, betaHeader) ?? (betaHeader
|
|
441
|
+
const bindingHeaders = applyAnthropicThinkingBindingControls(params, betaHeader) ?? (betaHeader ? { "anthropic-beta": betaHeader } : void 0);
|
|
697
442
|
const { response, stream: anthropicStream } = await client.messages.stream({
|
|
698
443
|
...params,
|
|
699
444
|
stream: true
|
|
@@ -710,432 +455,17 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
710
455
|
const detail = await readAnthropicMessagesErrorBodySnippet(response);
|
|
711
456
|
throw new Error(formatAnthropicMessagesHttpError(response, detail));
|
|
712
457
|
}
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
const flushPendingTextEnds = () => {
|
|
725
|
-
for (const event of pendingTextEnds) eventSink.push(event);
|
|
726
|
-
pendingTextEnds.length = 0;
|
|
727
|
-
};
|
|
728
|
-
const eventIndexKey = (eventIndex) => typeof eventIndex === "number" ? eventIndex : -1;
|
|
729
|
-
const appendReasoningContentThinkingDelta = (eventIndex, rawText) => {
|
|
730
|
-
if (typeof rawText !== "string") return false;
|
|
731
|
-
const text = sanitizeTransportPayloadText(rawText);
|
|
732
|
-
if (text.length === 0) return false;
|
|
733
|
-
const key = eventIndexKey(eventIndex);
|
|
734
|
-
let contentIndex = reasoningContentThinkingBlocks.get(key);
|
|
735
|
-
let block = contentIndex === void 0 ? void 0 : output.content[contentIndex];
|
|
736
|
-
if (!block || block.type !== "thinking") {
|
|
737
|
-
block = {
|
|
738
|
-
type: "thinking",
|
|
739
|
-
thinking: "",
|
|
740
|
-
thinkingSignature: "reasoning_content"
|
|
741
|
-
};
|
|
742
|
-
output.content.push(block);
|
|
743
|
-
contentIndex = output.content.length - 1;
|
|
744
|
-
reasoningContentThinkingBlocks.set(key, contentIndex);
|
|
745
|
-
eventSink.push({
|
|
746
|
-
type: "thinking_start",
|
|
747
|
-
contentIndex,
|
|
748
|
-
partial: output
|
|
749
|
-
});
|
|
750
|
-
}
|
|
751
|
-
if (contentIndex === void 0) return false;
|
|
752
|
-
block.thinking += text;
|
|
753
|
-
block.thinkingSignature = "reasoning_content";
|
|
754
|
-
eventSink.push({
|
|
755
|
-
type: "thinking_delta",
|
|
756
|
-
contentIndex,
|
|
757
|
-
delta: text,
|
|
758
|
-
partial: output
|
|
759
|
-
});
|
|
760
|
-
return true;
|
|
761
|
-
};
|
|
762
|
-
const appendReasoningContentTextDelta = (eventIndex, rawText) => {
|
|
763
|
-
if (typeof rawText !== "string") return false;
|
|
764
|
-
const text = sanitizeTransportPayloadText(rawText);
|
|
765
|
-
if (text.length === 0) return false;
|
|
766
|
-
const key = eventIndexKey(eventIndex);
|
|
767
|
-
let contentIndex = reasoningContentTextBlocks.get(key);
|
|
768
|
-
let block = contentIndex === void 0 ? void 0 : output.content[contentIndex];
|
|
769
|
-
if (!block || block.type !== "text") {
|
|
770
|
-
block = {
|
|
771
|
-
type: "text",
|
|
772
|
-
text: ""
|
|
773
|
-
};
|
|
774
|
-
output.content.push(block);
|
|
775
|
-
contentIndex = output.content.length - 1;
|
|
776
|
-
reasoningContentTextBlocks.set(key, contentIndex);
|
|
777
|
-
eventSink.push({
|
|
778
|
-
type: "text_start",
|
|
779
|
-
contentIndex,
|
|
780
|
-
partial: output
|
|
781
|
-
});
|
|
782
|
-
}
|
|
783
|
-
if (contentIndex === void 0) return false;
|
|
784
|
-
block.text += text;
|
|
785
|
-
eventSink.push({
|
|
786
|
-
type: "text_delta",
|
|
787
|
-
contentIndex,
|
|
788
|
-
delta: text,
|
|
789
|
-
partial: output
|
|
790
|
-
});
|
|
791
|
-
return true;
|
|
792
|
-
};
|
|
793
|
-
const finishReasoningContentSidecars = (eventIndex) => {
|
|
794
|
-
const key = eventIndexKey(eventIndex);
|
|
795
|
-
const thinkingContentIndex = reasoningContentThinkingBlocks.get(key);
|
|
796
|
-
if (thinkingContentIndex !== void 0) {
|
|
797
|
-
reasoningContentThinkingBlocks.delete(key);
|
|
798
|
-
const block = output.content[thinkingContentIndex];
|
|
799
|
-
if (block?.type === "thinking") eventSink.push({
|
|
800
|
-
type: "thinking_end",
|
|
801
|
-
contentIndex: thinkingContentIndex,
|
|
802
|
-
content: block.thinking,
|
|
803
|
-
partial: output
|
|
804
|
-
});
|
|
805
|
-
}
|
|
806
|
-
const textContentIndex = reasoningContentTextBlocks.get(key);
|
|
807
|
-
if (textContentIndex === void 0) return;
|
|
808
|
-
reasoningContentTextBlocks.delete(key);
|
|
809
|
-
const block = output.content[textContentIndex];
|
|
810
|
-
if (block?.type === "text") eventSink.push({
|
|
811
|
-
type: "text_end",
|
|
812
|
-
contentIndex: textContentIndex,
|
|
813
|
-
content: block.text,
|
|
814
|
-
partial: output
|
|
815
|
-
});
|
|
816
|
-
};
|
|
817
|
-
for await (const event of anthropicStream) {
|
|
818
|
-
inputTransformations = readAnthropicInputTransformations(event) ?? inputTransformations;
|
|
819
|
-
notifyLlmRequestActivity(transportOptions.signal);
|
|
820
|
-
if (event.type === "error") {
|
|
821
|
-
const error = event.error;
|
|
822
|
-
throw new Error(error?.message || "Anthropic Messages stream failed");
|
|
823
|
-
}
|
|
824
|
-
if (event.type === "message_start") {
|
|
825
|
-
const message = event.message;
|
|
826
|
-
const usage = message?.usage ?? {};
|
|
827
|
-
output.responseId = typeof message?.id === "string" ? message.id : void 0;
|
|
828
|
-
output.responseModel = typeof message?.model === "string" ? message.model : void 0;
|
|
829
|
-
messageStartPromptUsage = applyAnthropicMessageStartUsage(output.usage, usage);
|
|
830
|
-
calculateCost(costModel, output.usage);
|
|
831
|
-
eventSink.push({
|
|
832
|
-
type: "start",
|
|
833
|
-
partial: output
|
|
834
|
-
});
|
|
835
|
-
continue;
|
|
836
|
-
}
|
|
837
|
-
if (event.type === "message_stop") {
|
|
838
|
-
sawMessageStop = true;
|
|
839
|
-
continue;
|
|
840
|
-
}
|
|
841
|
-
if (event.type === "content_block_start") {
|
|
842
|
-
const contentBlock = event.content_block;
|
|
843
|
-
const index = typeof event.index === "number" ? event.index : -1;
|
|
844
|
-
if (transportOptions.anthropicServerCompaction === true && compactionCapture.begin(index, contentBlock, output.content.length)) continue;
|
|
845
|
-
const fallbackBoundary = refusalBuffer ? readAnthropicFallbackBoundary(contentBlock) : null;
|
|
846
|
-
if (fallbackBoundary) {
|
|
847
|
-
refusalBuffer?.discard();
|
|
848
|
-
sealedToolCalls.length = 0;
|
|
849
|
-
pendingTextEnds.length = 0;
|
|
850
|
-
blockIndexes.clear();
|
|
851
|
-
pendingThinkingSignatures.clear();
|
|
852
|
-
applyAnthropicFallbackBoundary({
|
|
853
|
-
output,
|
|
854
|
-
boundary: fallbackBoundary,
|
|
855
|
-
provider: model.provider
|
|
856
|
-
});
|
|
857
|
-
costModel = {
|
|
858
|
-
...model,
|
|
859
|
-
cost: resolveAnthropicFallbackServingModelCost({
|
|
860
|
-
requestedModelId: model.id,
|
|
861
|
-
servingModelId: fallbackBoundary.toModel,
|
|
862
|
-
requestedCost: model.cost
|
|
863
|
-
})
|
|
864
|
-
};
|
|
865
|
-
calculateCost(costModel, output.usage);
|
|
866
|
-
eventSink.push({
|
|
867
|
-
type: "start",
|
|
868
|
-
partial: output
|
|
869
|
-
});
|
|
870
|
-
for (const [i, block] of output.content.entries()) {
|
|
871
|
-
if (block.type !== "text") continue;
|
|
872
|
-
delete block.index;
|
|
873
|
-
eventSink.push({
|
|
874
|
-
type: "text_start",
|
|
875
|
-
contentIndex: i,
|
|
876
|
-
partial: output
|
|
877
|
-
});
|
|
878
|
-
if (block.text) eventSink.push({
|
|
879
|
-
type: "text_delta",
|
|
880
|
-
contentIndex: i,
|
|
881
|
-
delta: block.text,
|
|
882
|
-
partial: output
|
|
883
|
-
});
|
|
884
|
-
pendingTextEnds.push({
|
|
885
|
-
type: "text_end",
|
|
886
|
-
contentIndex: i,
|
|
887
|
-
content: block.text,
|
|
888
|
-
partial: output
|
|
889
|
-
});
|
|
890
|
-
}
|
|
891
|
-
continue;
|
|
892
|
-
}
|
|
893
|
-
pendingThinkingSignatures.delete(index);
|
|
894
|
-
if (contentBlock?.type === "text") {
|
|
895
|
-
const text = typeof contentBlock.text === "string" ? sanitizeTransportPayloadText(contentBlock.text) : "";
|
|
896
|
-
const block = {
|
|
897
|
-
type: "text",
|
|
898
|
-
text,
|
|
899
|
-
index
|
|
900
|
-
};
|
|
901
|
-
output.content.push(block);
|
|
902
|
-
const contentIndex = output.content.length - 1;
|
|
903
|
-
blockIndexes.set(index, contentIndex);
|
|
904
|
-
eventSink.push({
|
|
905
|
-
type: "text_start",
|
|
906
|
-
contentIndex,
|
|
907
|
-
partial: output
|
|
908
|
-
});
|
|
909
|
-
if (text.length > 0) eventSink.push({
|
|
910
|
-
type: "text_delta",
|
|
911
|
-
contentIndex,
|
|
912
|
-
delta: text,
|
|
913
|
-
partial: output
|
|
914
|
-
});
|
|
915
|
-
continue;
|
|
916
|
-
}
|
|
917
|
-
if (contentBlock?.type === "thinking") {
|
|
918
|
-
const thinking = typeof contentBlock.thinking === "string" ? contentBlock.thinking : "";
|
|
919
|
-
const block = {
|
|
920
|
-
type: "thinking",
|
|
921
|
-
thinking,
|
|
922
|
-
thinkingSignature: typeof contentBlock.signature === "string" ? contentBlock.signature : "",
|
|
923
|
-
index
|
|
924
|
-
};
|
|
925
|
-
output.content.push(block);
|
|
926
|
-
const contentIndex = output.content.length - 1;
|
|
927
|
-
blockIndexes.set(index, contentIndex);
|
|
928
|
-
eventSink.push({
|
|
929
|
-
type: "thinking_start",
|
|
930
|
-
contentIndex,
|
|
931
|
-
partial: output
|
|
932
|
-
});
|
|
933
|
-
if (thinking.length > 0) eventSink.push({
|
|
934
|
-
type: "thinking_delta",
|
|
935
|
-
contentIndex,
|
|
936
|
-
delta: thinking,
|
|
937
|
-
partial: output
|
|
938
|
-
});
|
|
939
|
-
continue;
|
|
940
|
-
}
|
|
941
|
-
if (contentBlock?.type === "redacted_thinking") {
|
|
942
|
-
const block = {
|
|
943
|
-
type: "thinking",
|
|
944
|
-
thinking: "[Reasoning redacted]",
|
|
945
|
-
thinkingSignature: typeof contentBlock.data === "string" ? contentBlock.data : "",
|
|
946
|
-
redacted: true,
|
|
947
|
-
index
|
|
948
|
-
};
|
|
949
|
-
output.content.push(block);
|
|
950
|
-
blockIndexes.set(index, output.content.length - 1);
|
|
951
|
-
eventSink.push({
|
|
952
|
-
type: "thinking_start",
|
|
953
|
-
contentIndex: output.content.length - 1,
|
|
954
|
-
partial: output
|
|
955
|
-
});
|
|
956
|
-
continue;
|
|
957
|
-
}
|
|
958
|
-
if (contentBlock?.type === "tool_use") {
|
|
959
|
-
tagPendingCommentaryText(output.content);
|
|
960
|
-
flushPendingTextEnds();
|
|
961
|
-
const block = {
|
|
962
|
-
type: "toolCall",
|
|
963
|
-
id: typeof contentBlock.id === "string" ? contentBlock.id : "",
|
|
964
|
-
name: typeof contentBlock.name === "string" ? isOAuthToken ? resolveOriginalAnthropicToolName(contentBlock.name, toolProjection) : contentBlock.name : "",
|
|
965
|
-
arguments: contentBlock.input && typeof contentBlock.input === "object" ? contentBlock.input : {},
|
|
966
|
-
partialJson: "",
|
|
967
|
-
index
|
|
968
|
-
};
|
|
969
|
-
output.content.push(block);
|
|
970
|
-
blockIndexes.set(index, output.content.length - 1);
|
|
971
|
-
toolArgumentPreviewSchedules.set(block, createToolArgumentPreviewSchedule());
|
|
972
|
-
eventSink.push({
|
|
973
|
-
type: "toolcall_start",
|
|
974
|
-
contentIndex: output.content.length - 1,
|
|
975
|
-
partial: output
|
|
976
|
-
});
|
|
977
|
-
}
|
|
978
|
-
continue;
|
|
979
|
-
}
|
|
980
|
-
if (event.type === "content_block_delta") {
|
|
981
|
-
const delta = event.delta;
|
|
982
|
-
const eventIndex = typeof event.index === "number" ? event.index : void 0;
|
|
983
|
-
if (eventIndex !== void 0 && compactionCapture.delta(eventIndex, delta)) continue;
|
|
984
|
-
let index = eventIndex === void 0 ? void 0 : blockIndexes.get(eventIndex);
|
|
985
|
-
let block = index === void 0 ? void 0 : blocks[index];
|
|
986
|
-
if (allowReasoningContentReplay) {
|
|
987
|
-
const appendedThinking = appendReasoningContentThinkingDelta(event.index, delta?.reasoning_content);
|
|
988
|
-
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";
|
|
989
|
-
let appendedContent = false;
|
|
990
|
-
if (!hasNativeAnthropicDelta && typeof delta?.content === "string" && delta.content.length > 0) {
|
|
991
|
-
const text = sanitizeTransportPayloadText(delta.content);
|
|
992
|
-
if (text.length > 0) {
|
|
993
|
-
if (block?.type === "text" && index !== void 0) {
|
|
994
|
-
block.text += text;
|
|
995
|
-
eventSink.push({
|
|
996
|
-
type: "text_delta",
|
|
997
|
-
contentIndex: index,
|
|
998
|
-
delta: text,
|
|
999
|
-
partial: output
|
|
1000
|
-
});
|
|
1001
|
-
appendedContent = true;
|
|
1002
|
-
} else appendedContent = appendReasoningContentTextDelta(event.index, text);
|
|
1003
|
-
}
|
|
1004
|
-
}
|
|
1005
|
-
if ((appendedThinking || appendedContent) && !hasNativeAnthropicDelta) continue;
|
|
1006
|
-
}
|
|
1007
|
-
if (!block && delta?.type === "text_delta" && typeof delta.text === "string") {
|
|
1008
|
-
block = {
|
|
1009
|
-
type: "text",
|
|
1010
|
-
text: "",
|
|
1011
|
-
index: typeof event.index === "number" ? event.index : blocks.length
|
|
1012
|
-
};
|
|
1013
|
-
output.content.push(block);
|
|
1014
|
-
index = output.content.length - 1;
|
|
1015
|
-
if (typeof event.index === "number") blockIndexes.set(event.index, index);
|
|
1016
|
-
eventSink.push({
|
|
1017
|
-
type: "text_start",
|
|
1018
|
-
contentIndex: index,
|
|
1019
|
-
partial: output
|
|
1020
|
-
});
|
|
1021
|
-
}
|
|
1022
|
-
if (index === void 0) continue;
|
|
1023
|
-
if (block?.type === "text" && delta?.type === "text_delta" && typeof delta.text === "string") {
|
|
1024
|
-
block.text += delta.text;
|
|
1025
|
-
eventSink.push({
|
|
1026
|
-
type: "text_delta",
|
|
1027
|
-
contentIndex: index,
|
|
1028
|
-
delta: delta.text,
|
|
1029
|
-
partial: output
|
|
1030
|
-
});
|
|
1031
|
-
continue;
|
|
1032
|
-
}
|
|
1033
|
-
if (block?.type === "thinking" && delta?.type === "thinking_delta" && typeof delta.thinking === "string") {
|
|
1034
|
-
block.thinking += delta.thinking;
|
|
1035
|
-
eventSink.push({
|
|
1036
|
-
type: "thinking_delta",
|
|
1037
|
-
contentIndex: index,
|
|
1038
|
-
delta: delta.thinking,
|
|
1039
|
-
partial: output
|
|
1040
|
-
});
|
|
1041
|
-
continue;
|
|
1042
|
-
}
|
|
1043
|
-
if (block?.type === "toolCall" && delta?.type === "input_json_delta" && typeof delta.partial_json === "string") {
|
|
1044
|
-
const partialJson = `${block.partialJson ?? ""}${delta.partial_json}`;
|
|
1045
|
-
block.partialJson = partialJson;
|
|
1046
|
-
if (toolArgumentPreviewSchedules.get(block)?.(partialJson.length)) block.arguments = parseAnthropicToolCallArguments(partialJson);
|
|
1047
|
-
eventSink.push({
|
|
1048
|
-
type: "toolcall_delta",
|
|
1049
|
-
contentIndex: index,
|
|
1050
|
-
delta: delta.partial_json,
|
|
1051
|
-
partial: output
|
|
1052
|
-
});
|
|
1053
|
-
continue;
|
|
1054
|
-
}
|
|
1055
|
-
if (block?.type === "thinking" && delta?.type === "signature_delta" && typeof delta.signature === "string") {
|
|
1056
|
-
const signatureIndex = eventIndexKey(event.index);
|
|
1057
|
-
const pendingSignature = pendingThinkingSignatures.get(signatureIndex);
|
|
1058
|
-
if (pendingSignature === void 0) {
|
|
1059
|
-
block.thinkingSignature = "";
|
|
1060
|
-
pendingThinkingSignatures.set(signatureIndex, delta.signature);
|
|
1061
|
-
} else pendingThinkingSignatures.set(signatureIndex, pendingSignature + delta.signature);
|
|
1062
|
-
}
|
|
1063
|
-
continue;
|
|
1064
|
-
}
|
|
1065
|
-
if (event.type === "content_block_stop") {
|
|
1066
|
-
const eventIndex = typeof event.index === "number" ? event.index : void 0;
|
|
1067
|
-
if (eventIndex !== void 0 && compactionCapture.complete(eventIndex)) continue;
|
|
1068
|
-
const pendingSignature = eventIndex === void 0 ? void 0 : pendingThinkingSignatures.get(eventIndex);
|
|
1069
|
-
if (eventIndex !== void 0) pendingThinkingSignatures.delete(eventIndex);
|
|
1070
|
-
const index = eventIndex === void 0 ? void 0 : blockIndexes.get(eventIndex);
|
|
1071
|
-
const block = index === void 0 ? void 0 : blocks[index];
|
|
1072
|
-
if (eventIndex === void 0 || index === void 0 || !block) {
|
|
1073
|
-
finishReasoningContentSidecars(event.index);
|
|
1074
|
-
continue;
|
|
1075
|
-
}
|
|
1076
|
-
blockIndexes.delete(eventIndex);
|
|
1077
|
-
delete block.index;
|
|
1078
|
-
if (block.type === "text") {
|
|
1079
|
-
pendingTextEnds.push({
|
|
1080
|
-
type: "text_end",
|
|
1081
|
-
contentIndex: index,
|
|
1082
|
-
content: block.text,
|
|
1083
|
-
partial: output
|
|
1084
|
-
});
|
|
1085
|
-
finishReasoningContentSidecars(event.index);
|
|
1086
|
-
continue;
|
|
1087
|
-
}
|
|
1088
|
-
if (block.type === "thinking") {
|
|
1089
|
-
if (pendingSignature !== void 0) block.thinkingSignature = pendingSignature;
|
|
1090
|
-
eventSink.push({
|
|
1091
|
-
type: "thinking_end",
|
|
1092
|
-
contentIndex: index,
|
|
1093
|
-
content: block.thinking,
|
|
1094
|
-
partial: output
|
|
1095
|
-
});
|
|
1096
|
-
finishReasoningContentSidecars(event.index);
|
|
1097
|
-
continue;
|
|
1098
|
-
}
|
|
1099
|
-
if (block.type === "toolCall") {
|
|
1100
|
-
sealedToolCalls.push({
|
|
1101
|
-
block,
|
|
1102
|
-
contentIndex: index
|
|
1103
|
-
});
|
|
1104
|
-
finishReasoningContentSidecars(event.index);
|
|
1105
|
-
}
|
|
1106
|
-
continue;
|
|
1107
|
-
}
|
|
1108
|
-
if (event.type === "message_delta") {
|
|
1109
|
-
logAnthropicContextEdits(event);
|
|
1110
|
-
const delta = event.delta;
|
|
1111
|
-
const usage = event.usage;
|
|
1112
|
-
if (delta?.stop_reason) {
|
|
1113
|
-
if (delta.stop_reason === "refusal") applyAnthropicRefusal(output, delta.stop_details, model.provider);
|
|
1114
|
-
else output.stopReason = mapAnthropicStopReason(delta.stop_reason);
|
|
1115
|
-
}
|
|
1116
|
-
applyAnthropicMessageDeltaUsage(output.usage, usage, messageStartPromptUsage);
|
|
1117
|
-
calculateCost(costModel, output.usage);
|
|
1118
|
-
if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
|
|
1119
|
-
flushPendingTextEnds();
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
if (isDirectAnthropicModel(model) && !sawMessageStop) throw new Error("Anthropic stream ended before message_stop");
|
|
1123
|
-
if (transportOptions.signal?.aborted) throw transportAbortError(transportOptions.signal);
|
|
1124
|
-
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
|
|
1125
|
-
if ([...blockIndexes.values()].some((index) => blocks[index]?.type === "toolCall")) throw new Error("Provider completed stream with an incomplete tool call");
|
|
1126
|
-
finalizeTerminalToolCallArguments(sealedToolCalls.map(({ block }) => block), (block) => block.partialJson && block.partialJson.length > 0 ? block.partialJson : block.arguments);
|
|
1127
|
-
for (const sealed of sealedToolCalls) {
|
|
1128
|
-
delete sealed.block.partialJson;
|
|
1129
|
-
eventSink.push({
|
|
1130
|
-
type: "toolcall_end",
|
|
1131
|
-
contentIndex: sealed.contentIndex,
|
|
1132
|
-
toolCall: sealed.block,
|
|
1133
|
-
partial: output
|
|
1134
|
-
});
|
|
1135
|
-
}
|
|
1136
|
-
refusalBuffer?.flush();
|
|
1137
|
-
if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
|
|
1138
|
-
flushPendingTextEnds();
|
|
458
|
+
await consumeAnthropicStream({
|
|
459
|
+
events: anthropicStream,
|
|
460
|
+
model,
|
|
461
|
+
options: transportOptions,
|
|
462
|
+
output,
|
|
463
|
+
stream,
|
|
464
|
+
refusalBuffer,
|
|
465
|
+
isOAuthToken,
|
|
466
|
+
toolProjection,
|
|
467
|
+
profile: "transport"
|
|
468
|
+
});
|
|
1139
469
|
finalizeTransportStream({
|
|
1140
470
|
stream,
|
|
1141
471
|
output
|
|
@@ -1155,71 +485,12 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1155
485
|
for (const block of output.content) delete block.index;
|
|
1156
486
|
}
|
|
1157
487
|
});
|
|
1158
|
-
} finally {
|
|
1159
|
-
logAnthropicThinkingDrops(inputTransformations);
|
|
1160
488
|
}
|
|
1161
489
|
})();
|
|
1162
490
|
return eventStream;
|
|
1163
491
|
};
|
|
1164
492
|
}
|
|
1165
493
|
//#endregion
|
|
1166
|
-
//#region packages/ai/src/transports/model-max-tokens-params.ts
|
|
1167
|
-
/**
|
|
1168
|
-
* Max-token parameter normalization across provider/native naming variants.
|
|
1169
|
-
* Callers canonicalize aliases before dispatch so payloads cannot carry
|
|
1170
|
-
* conflicting limits.
|
|
1171
|
-
*/
|
|
1172
|
-
const MAX_TOKENS_PARAM_KEYS = [
|
|
1173
|
-
"maxTokens",
|
|
1174
|
-
"max_completion_tokens",
|
|
1175
|
-
"max_tokens"
|
|
1176
|
-
];
|
|
1177
|
-
/** Resolve the first supported max-token parameter present in a params object. */
|
|
1178
|
-
function resolveMaxTokensParam(params) {
|
|
1179
|
-
if (!params) return;
|
|
1180
|
-
for (const key of MAX_TOKENS_PARAM_KEYS) {
|
|
1181
|
-
const resolved = asNonNegativeFiniteNumber(params[key]);
|
|
1182
|
-
if (resolved !== void 0) return resolved;
|
|
1183
|
-
}
|
|
1184
|
-
}
|
|
1185
|
-
/**
|
|
1186
|
-
* Canonicalize merged params to `maxTokens`, preserving source precedence from
|
|
1187
|
-
* left to right across the provided source objects.
|
|
1188
|
-
*/
|
|
1189
|
-
function canonicalizeMaxTokensParam(params) {
|
|
1190
|
-
let resolved;
|
|
1191
|
-
for (const source of params.sources) {
|
|
1192
|
-
const sourceValue = resolveMaxTokensParam(source);
|
|
1193
|
-
if (sourceValue !== void 0) resolved = sourceValue;
|
|
1194
|
-
}
|
|
1195
|
-
if (resolved === void 0) return;
|
|
1196
|
-
for (const key of MAX_TOKENS_PARAM_KEYS) delete params.merged[key];
|
|
1197
|
-
params.merged.maxTokens = resolved;
|
|
1198
|
-
}
|
|
1199
|
-
//#endregion
|
|
1200
|
-
//#region packages/ai/src/transports/model-transport-url.ts
|
|
1201
|
-
/**
|
|
1202
|
-
* Debug formatting helpers for model transport endpoints.
|
|
1203
|
-
* Keeps logs useful without exposing credentials, request params, or fragments.
|
|
1204
|
-
*/
|
|
1205
|
-
/** Return a sanitized URL suitable for logs and diagnostics. */
|
|
1206
|
-
function formatModelTransportDebugUrl(rawUrl) {
|
|
1207
|
-
try {
|
|
1208
|
-
const parsed = new URL(rawUrl);
|
|
1209
|
-
parsed.username = "";
|
|
1210
|
-
parsed.password = "";
|
|
1211
|
-
parsed.search = "";
|
|
1212
|
-
parsed.hash = "";
|
|
1213
|
-
return parsed.toString();
|
|
1214
|
-
} catch {
|
|
1215
|
-
return "<invalid-url>";
|
|
1216
|
-
}
|
|
1217
|
-
}
|
|
1218
|
-
/** Format a configured base URL for debug output, or the implicit default. */
|
|
1219
|
-
function formatModelTransportDebugBaseUrl(rawUrl) {
|
|
1220
|
-
return rawUrl ? formatModelTransportDebugUrl(rawUrl) : "default";
|
|
1221
|
-
}
|
|
1222
|
-
//#endregion
|
|
1223
494
|
//#region packages/ai/src/transports/openai-compatible-conversation-turn.ts
|
|
1224
495
|
/**
|
|
1225
496
|
* OpenAI-compatible conversation turn detector.
|
|
@@ -1256,450 +527,6 @@ function hasOpenAICompatibleConversationTurn(messages) {
|
|
|
1256
527
|
});
|
|
1257
528
|
}
|
|
1258
529
|
//#endregion
|
|
1259
|
-
//#region packages/ai/src/transports/openai-completions-string-content.ts
|
|
1260
|
-
/**
|
|
1261
|
-
* OpenAI Chat Completions compatibility helpers. Some providers only accept
|
|
1262
|
-
* role/content messages with plain string content instead of text block arrays.
|
|
1263
|
-
*/
|
|
1264
|
-
function flattenStringOnlyCompletionContent(content) {
|
|
1265
|
-
if (!Array.isArray(content)) return content;
|
|
1266
|
-
const textParts = [];
|
|
1267
|
-
for (const item of content) {
|
|
1268
|
-
if (!item || typeof item !== "object" || item.type !== "text" || typeof item.text !== "string") return content;
|
|
1269
|
-
textParts.push(item.text);
|
|
1270
|
-
}
|
|
1271
|
-
return textParts.join("\n");
|
|
1272
|
-
}
|
|
1273
|
-
/** Flatten string-only text block content arrays into newline-joined strings. */
|
|
1274
|
-
function flattenCompletionMessagesToStringContent(messages) {
|
|
1275
|
-
return messages.map((message) => {
|
|
1276
|
-
if (!message || typeof message !== "object") return message;
|
|
1277
|
-
const content = message.content;
|
|
1278
|
-
const flattenedContent = flattenStringOnlyCompletionContent(content);
|
|
1279
|
-
if (flattenedContent === content) return message;
|
|
1280
|
-
return {
|
|
1281
|
-
...message,
|
|
1282
|
-
content: flattenedContent
|
|
1283
|
-
};
|
|
1284
|
-
});
|
|
1285
|
-
}
|
|
1286
|
-
/** Strip completion messages to role/content fields for strict providers. */
|
|
1287
|
-
function stripCompletionMessagesToRoleContent(messages) {
|
|
1288
|
-
return messages.map((message) => {
|
|
1289
|
-
if (!message || typeof message !== "object" || Array.isArray(message)) return message;
|
|
1290
|
-
const record = message;
|
|
1291
|
-
const stripped = {};
|
|
1292
|
-
if (Object.hasOwn(record, "role")) stripped.role = record.role;
|
|
1293
|
-
if (Object.hasOwn(record, "content")) stripped.content = record.content;
|
|
1294
|
-
return stripped;
|
|
1295
|
-
});
|
|
1296
|
-
}
|
|
1297
|
-
//#endregion
|
|
1298
|
-
//#region packages/ai/src/transports/openai-completions-host.ts
|
|
1299
|
-
/**
|
|
1300
|
-
* Chat Completions accepts Azure AI Foundry hosts in addition to traditional
|
|
1301
|
-
* Azure OpenAI hosts. Do not replace this with isTraditionalAzureOpenAIHost,
|
|
1302
|
-
* which intentionally excludes the .services.ai.azure.com Foundry suffix.
|
|
1303
|
-
*/
|
|
1304
|
-
function isAzureOpenAICompatibleHost(hostname) {
|
|
1305
|
-
return hostname.endsWith(".openai.azure.com") || hostname.endsWith(".services.ai.azure.com") || hostname.endsWith(".cognitiveservices.azure.com");
|
|
1306
|
-
}
|
|
1307
|
-
//#endregion
|
|
1308
|
-
//#region packages/ai/src/transports/openai-completions-replay.ts
|
|
1309
|
-
function isGoogleOpenAICompatModel(model) {
|
|
1310
|
-
const endpointClass = detectOpenAICompletionsCompat(model).capabilities.endpointClass;
|
|
1311
|
-
return model.provider === "google" || endpointClass === "google-generative-ai" || endpointClass === "google-vertex";
|
|
1312
|
-
}
|
|
1313
|
-
function requiresGoogleCompatToolCallThoughtSignature(model) {
|
|
1314
|
-
return isGoogleGemini3ProModel(model.id) || isGoogleGemini3FlashModel(model.id);
|
|
1315
|
-
}
|
|
1316
|
-
const GOOGLE_COMPAT_THOUGHT_SIGNATURE_ELLIPSIS_RE = /[\u2026]|\.\.\./;
|
|
1317
|
-
const GOOGLE_COMPAT_THOUGHT_SIGNATURE_BASE64_RE = /^[A-Za-z0-9+/=]+$/;
|
|
1318
|
-
function hasGoogleCompatThoughtSignatureTruncationFootprint(value) {
|
|
1319
|
-
return GOOGLE_COMPAT_THOUGHT_SIGNATURE_ELLIPSIS_RE.test(value) || GOOGLE_COMPAT_THOUGHT_SIGNATURE_BASE64_RE.test(value) && value.length % 4 !== 0;
|
|
1320
|
-
}
|
|
1321
|
-
function injectToolCallThoughtSignatures(outgoingMessages, context, model) {
|
|
1322
|
-
if (!isGoogleOpenAICompatModel(model)) return;
|
|
1323
|
-
const sigById = /* @__PURE__ */ new Map();
|
|
1324
|
-
const fallbackSig = requiresGoogleCompatToolCallThoughtSignature(model) ? GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP : void 0;
|
|
1325
|
-
for (const msg of context.messages ?? []) {
|
|
1326
|
-
if (msg.role !== "assistant") continue;
|
|
1327
|
-
const source = msg;
|
|
1328
|
-
if (!Array.isArray(source.content)) continue;
|
|
1329
|
-
for (const block of source.content) {
|
|
1330
|
-
if (block.type !== "toolCall") continue;
|
|
1331
|
-
const id = block.id;
|
|
1332
|
-
const sig = block.thoughtSignature;
|
|
1333
|
-
if (typeof id === "string" && typeof sig === "string" && sig.length > 0) {
|
|
1334
|
-
const isSameRoute = source.api === model.api && source.provider === model.provider && source.model === model.id;
|
|
1335
|
-
if (!isSameRoute && !fallbackSig) continue;
|
|
1336
|
-
sigById.set(id, isSameRoute ? sig : fallbackSig ?? sig);
|
|
1337
|
-
}
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
if (sigById.size === 0 && !fallbackSig) return;
|
|
1341
|
-
for (const message of outgoingMessages) {
|
|
1342
|
-
const toolCalls = message.tool_calls;
|
|
1343
|
-
if (!Array.isArray(toolCalls)) continue;
|
|
1344
|
-
for (const toolCall of toolCalls) {
|
|
1345
|
-
const id = toolCall.id;
|
|
1346
|
-
if (typeof id !== "string") continue;
|
|
1347
|
-
let sig = sigById.get(id) ?? fallbackSig;
|
|
1348
|
-
if (typeof sig === "string" && sig.length > 0) {
|
|
1349
|
-
if (hasGoogleCompatThoughtSignatureTruncationFootprint(sig.trim())) sig = fallbackSig;
|
|
1350
|
-
}
|
|
1351
|
-
if (typeof sig !== "string" || sig.length === 0) continue;
|
|
1352
|
-
const extra = toolCall.extra_content && typeof toolCall.extra_content === "object" ? toolCall.extra_content : {};
|
|
1353
|
-
toolCall.extra_content = extra;
|
|
1354
|
-
const google = extra.google && typeof extra.google === "object" ? extra.google : {};
|
|
1355
|
-
extra.google = google;
|
|
1356
|
-
google.thought_signature = sig;
|
|
1357
|
-
}
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
const COMPLETIONS_REASONING_REPLAY_FIELDS = [
|
|
1361
|
-
"reasoning_details",
|
|
1362
|
-
"reasoning_content",
|
|
1363
|
-
"reasoning",
|
|
1364
|
-
"reasoning_text"
|
|
1365
|
-
];
|
|
1366
|
-
function stripCompletionsReasoningReplayFields(record) {
|
|
1367
|
-
for (const field of COMPLETIONS_REASONING_REPLAY_FIELDS) if (field in record) delete record[field];
|
|
1368
|
-
}
|
|
1369
|
-
function sanitizeOpenRouterReasoningReplayFields(record) {
|
|
1370
|
-
const reasoningDetails = record.reasoning_details;
|
|
1371
|
-
if (typeof reasoningDetails === "string") {
|
|
1372
|
-
if (reasoningDetails.length > 0 && typeof record.reasoning !== "string") record.reasoning = reasoningDetails;
|
|
1373
|
-
delete record.reasoning_details;
|
|
1374
|
-
} else if (reasoningDetails !== void 0 && !Array.isArray(reasoningDetails)) delete record.reasoning_details;
|
|
1375
|
-
if ("reasoning" in record && (typeof record.reasoning !== "string" || record.reasoning === "")) delete record.reasoning;
|
|
1376
|
-
if ("reasoning_content" in record && (typeof record.reasoning_content !== "string" || record.reasoning_content === "")) delete record.reasoning_content;
|
|
1377
|
-
const reasoningText = record.reasoning_text;
|
|
1378
|
-
if (typeof reasoningText === "string" && reasoningText.length > 0 && typeof record.reasoning !== "string" && typeof record.reasoning_content !== "string") record.reasoning = reasoningText;
|
|
1379
|
-
if ("reasoning_text" in record) delete record.reasoning_text;
|
|
1380
|
-
}
|
|
1381
|
-
function sanitizeReasoningContentReplayFields(record) {
|
|
1382
|
-
if ("reasoning_content" in record && typeof record.reasoning_content !== "string") delete record.reasoning_content;
|
|
1383
|
-
delete record.reasoning_details;
|
|
1384
|
-
delete record.reasoning;
|
|
1385
|
-
delete record.reasoning_text;
|
|
1386
|
-
}
|
|
1387
|
-
const REASONING_CONTENT_REPLAY_MODEL_IDS = /* @__PURE__ */ new Set([
|
|
1388
|
-
"deepseek-v4-flash",
|
|
1389
|
-
"deepseek-v4-pro",
|
|
1390
|
-
"kimi-for-coding",
|
|
1391
|
-
"kimi-k2.5",
|
|
1392
|
-
"kimi-k2.6",
|
|
1393
|
-
"kimi-k2.7-code",
|
|
1394
|
-
"kimi-k2.7-code-highspeed",
|
|
1395
|
-
"kimi-k3",
|
|
1396
|
-
"kimi-k2-thinking",
|
|
1397
|
-
"kimi-k2-thinking-turbo",
|
|
1398
|
-
"mimo-v2-pro",
|
|
1399
|
-
"mimo-v2-omni",
|
|
1400
|
-
"mimo-v2.5",
|
|
1401
|
-
"mimo-v2.5-pro",
|
|
1402
|
-
"mimo-v2.6-pro"
|
|
1403
|
-
]);
|
|
1404
|
-
const REASONING_CONTENT_REPLAY_TIER_SUFFIXES = [
|
|
1405
|
-
"-free",
|
|
1406
|
-
"-paid",
|
|
1407
|
-
"-trial"
|
|
1408
|
-
];
|
|
1409
|
-
function stripReasoningContentReplayTierSuffix(modelId) {
|
|
1410
|
-
for (const suffix of REASONING_CONTENT_REPLAY_TIER_SUFFIXES) if (modelId.length > suffix.length && modelId.endsWith(suffix)) return modelId.slice(0, -suffix.length);
|
|
1411
|
-
return modelId;
|
|
1412
|
-
}
|
|
1413
|
-
function getReasoningContentReplayModelIdCandidates(modelId) {
|
|
1414
|
-
if (typeof modelId !== "string") return [];
|
|
1415
|
-
const normalized = modelId.trim().toLowerCase();
|
|
1416
|
-
if (!normalized) return [];
|
|
1417
|
-
const parts = normalized.split("/").filter(Boolean);
|
|
1418
|
-
const finalPart = parts[parts.length - 1] ?? normalized;
|
|
1419
|
-
const candidates = [finalPart];
|
|
1420
|
-
const colonParts = finalPart.split(":").filter(Boolean);
|
|
1421
|
-
if (colonParts.length > 1) candidates.push(colonParts[0] ?? "", colonParts[colonParts.length - 1] ?? "");
|
|
1422
|
-
const baseCount = candidates.length;
|
|
1423
|
-
for (let index = 0; index < baseCount; index += 1) {
|
|
1424
|
-
const candidate = candidates[index];
|
|
1425
|
-
if (typeof candidate !== "string") continue;
|
|
1426
|
-
const stripped = stripReasoningContentReplayTierSuffix(candidate);
|
|
1427
|
-
if (stripped !== candidate) candidates.push(stripped);
|
|
1428
|
-
}
|
|
1429
|
-
return uniqueStrings(candidates.filter(Boolean));
|
|
1430
|
-
}
|
|
1431
|
-
function shouldPreserveReasoningContentReplay(model, compat) {
|
|
1432
|
-
if (compat.requiresReasoningContentOnAssistantMessages || compat.thinkingFormat === "deepseek" || compat.thinkingFormat === "zai" || shouldTrustReasoningContentReplayMetadata(model)) return true;
|
|
1433
|
-
return getReasoningContentReplayModelIdCandidates(model.id).some((modelId) => REASONING_CONTENT_REPLAY_MODEL_IDS.has(modelId));
|
|
1434
|
-
}
|
|
1435
|
-
function shouldPreserveOpenRouterReasoningReplay(model) {
|
|
1436
|
-
if (model.provider !== "openrouter") return true;
|
|
1437
|
-
const normalizedModelId = model.id.trim().toLowerCase();
|
|
1438
|
-
return !(normalizedModelId.startsWith("anthropic/") || normalizedModelId.startsWith("x-ai/"));
|
|
1439
|
-
}
|
|
1440
|
-
function shouldTrustReasoningContentReplayMetadata(model) {
|
|
1441
|
-
if (!model.reasoning) return false;
|
|
1442
|
-
if (model.provider.trim().toLowerCase() === "openai") return false;
|
|
1443
|
-
return shouldPreserveOpenRouterReasoningReplay(model);
|
|
1444
|
-
}
|
|
1445
|
-
function sanitizeCompletionsReasoningReplayFields(messages, options) {
|
|
1446
|
-
if (!Array.isArray(messages)) return;
|
|
1447
|
-
for (const msg of messages) {
|
|
1448
|
-
if (!msg || typeof msg !== "object") continue;
|
|
1449
|
-
const record = msg;
|
|
1450
|
-
if (record.role !== "assistant") continue;
|
|
1451
|
-
if (options.preserveOpenRouterReasoning) sanitizeOpenRouterReasoningReplayFields(record);
|
|
1452
|
-
else if (options.preserveReasoningContent) sanitizeReasoningContentReplayFields(record);
|
|
1453
|
-
else stripCompletionsReasoningReplayFields(record);
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
function applyCompletionsReplay(outgoingMessages, context, model, compat) {
|
|
1457
|
-
injectToolCallThoughtSignatures(outgoingMessages, context, model);
|
|
1458
|
-
sanitizeCompletionsReasoningReplayFields(outgoingMessages, {
|
|
1459
|
-
preserveOpenRouterReasoning: compat.thinkingFormat === "openrouter" && shouldPreserveOpenRouterReasoningReplay(model),
|
|
1460
|
-
preserveReasoningContent: shouldPreserveReasoningContentReplay(model, compat)
|
|
1461
|
-
});
|
|
1462
|
-
}
|
|
1463
|
-
//#endregion
|
|
1464
|
-
//#region packages/ai/src/transports/openai-completions-params.ts
|
|
1465
|
-
function isKnownOpenAICompletionsEndpoint(model) {
|
|
1466
|
-
if (!model.baseUrl.trim()) return true;
|
|
1467
|
-
const endpointClass = resolveProviderEndpoint(model).endpointClass;
|
|
1468
|
-
if (endpointClass === "openai-public" || endpointClass === "azure-openai") return true;
|
|
1469
|
-
try {
|
|
1470
|
-
return isAzureOpenAICompatibleHost(new URL(model.baseUrl).hostname.toLowerCase());
|
|
1471
|
-
} catch {
|
|
1472
|
-
return false;
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
|
-
function resolveOpenAICompletionsReasoningEffort(options) {
|
|
1476
|
-
return options?.reasoningEffort ?? options?.reasoning ?? "high";
|
|
1477
|
-
}
|
|
1478
|
-
function resolveOpenAICompletionsMaxTokens(model, options) {
|
|
1479
|
-
if (options?.maxTokens) return {
|
|
1480
|
-
maxTokens: options.maxTokens,
|
|
1481
|
-
clampToModelMaxTokens: true
|
|
1482
|
-
};
|
|
1483
|
-
const paramsMaxTokens = resolveMaxTokensParam(model.params);
|
|
1484
|
-
if (paramsMaxTokens) return {
|
|
1485
|
-
maxTokens: paramsMaxTokens,
|
|
1486
|
-
clampToModelMaxTokens: false
|
|
1487
|
-
};
|
|
1488
|
-
return {
|
|
1489
|
-
maxTokens: model.maxTokens,
|
|
1490
|
-
clampToModelMaxTokens: false
|
|
1491
|
-
};
|
|
1492
|
-
}
|
|
1493
|
-
function resolveOpenAICompletionsModelMaxTokens(model) {
|
|
1494
|
-
return typeof model.maxTokens === "number" && Number.isFinite(model.maxTokens) && model.maxTokens > 0 ? Math.floor(model.maxTokens) : void 0;
|
|
1495
|
-
}
|
|
1496
|
-
const OPENAI_COMPLETIONS_INPUT_TOKEN_SAFETY_MARGIN = 1.25;
|
|
1497
|
-
const OPENAI_COMPLETIONS_IMAGE_CHAR_ESTIMATE = 8e3;
|
|
1498
|
-
function estimateOpenAICompletionsInputTokens(payload) {
|
|
1499
|
-
let adjustedChars = 0;
|
|
1500
|
-
adjustedChars += estimateOpenAICompletionsMessagesChars(payload.messages);
|
|
1501
|
-
if (Array.isArray(payload.tools) && payload.tools.length > 0) try {
|
|
1502
|
-
adjustedChars += estimateStringChars(JSON.stringify(payload.tools));
|
|
1503
|
-
} catch {
|
|
1504
|
-
adjustedChars += 1024;
|
|
1505
|
-
}
|
|
1506
|
-
if (payload.response_format !== void 0) try {
|
|
1507
|
-
adjustedChars += estimateStringChars(JSON.stringify(payload.response_format));
|
|
1508
|
-
} catch {
|
|
1509
|
-
adjustedChars += 256;
|
|
1510
|
-
}
|
|
1511
|
-
return Math.ceil(adjustedChars / 4 * OPENAI_COMPLETIONS_INPUT_TOKEN_SAFETY_MARGIN);
|
|
1512
|
-
}
|
|
1513
|
-
function estimateOpenAICompletionsMessagesChars(messages) {
|
|
1514
|
-
if (!Array.isArray(messages)) return 0;
|
|
1515
|
-
let adjustedChars = 0;
|
|
1516
|
-
for (const message of messages) {
|
|
1517
|
-
if (!message || typeof message !== "object") continue;
|
|
1518
|
-
const record = message;
|
|
1519
|
-
adjustedChars += estimateOpenAICompletionsContentChars(record.content);
|
|
1520
|
-
for (const field of COMPLETIONS_REASONING_REPLAY_FIELDS) adjustedChars += estimateOpenAICompletionsContentChars(record[field]);
|
|
1521
|
-
if (record.tool_calls !== void 0) try {
|
|
1522
|
-
adjustedChars += estimateStringChars(JSON.stringify(record.tool_calls));
|
|
1523
|
-
} catch {
|
|
1524
|
-
adjustedChars += 256;
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
return adjustedChars;
|
|
1528
|
-
}
|
|
1529
|
-
function estimateOpenAICompletionsContentChars(value) {
|
|
1530
|
-
if (typeof value === "string") return estimateStringChars(value);
|
|
1531
|
-
if (!Array.isArray(value)) return 0;
|
|
1532
|
-
let adjustedChars = 0;
|
|
1533
|
-
for (const block of value) {
|
|
1534
|
-
if (!block || typeof block !== "object") continue;
|
|
1535
|
-
const record = block;
|
|
1536
|
-
if (record.type === "image_url" || record.type === "input_image") {
|
|
1537
|
-
adjustedChars += OPENAI_COMPLETIONS_IMAGE_CHAR_ESTIMATE;
|
|
1538
|
-
continue;
|
|
1539
|
-
}
|
|
1540
|
-
const text = record.text;
|
|
1541
|
-
if (typeof text === "string") {
|
|
1542
|
-
adjustedChars += estimateStringChars(text);
|
|
1543
|
-
continue;
|
|
1544
|
-
}
|
|
1545
|
-
try {
|
|
1546
|
-
adjustedChars += estimateStringChars(JSON.stringify(block));
|
|
1547
|
-
} catch {
|
|
1548
|
-
adjustedChars += 256;
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
return adjustedChars;
|
|
1552
|
-
}
|
|
1553
|
-
function resolveOpenAICompletionsEffectiveContextTokens(model) {
|
|
1554
|
-
const contextTokens = model.contextTokens;
|
|
1555
|
-
if (typeof contextTokens === "number" && Number.isFinite(contextTokens) && contextTokens > 0) return contextTokens;
|
|
1556
|
-
return typeof model.contextWindow === "number" && Number.isFinite(model.contextWindow) && model.contextWindow > 0 ? model.contextWindow : void 0;
|
|
1557
|
-
}
|
|
1558
|
-
function isQwenOpenAICompletionsThinkingFormat(format) {
|
|
1559
|
-
return format === "qwen" || format === "qwen-chat-template";
|
|
1560
|
-
}
|
|
1561
|
-
function setQwenChatTemplateThinking(params, enabled) {
|
|
1562
|
-
const existing = params.chat_template_kwargs;
|
|
1563
|
-
params.chat_template_kwargs = existing && typeof existing === "object" && !Array.isArray(existing) ? {
|
|
1564
|
-
...existing,
|
|
1565
|
-
enable_thinking: enabled
|
|
1566
|
-
} : { enable_thinking: enabled };
|
|
1567
|
-
}
|
|
1568
|
-
function applyQwenOpenAICompletionsThinkingParams(params) {
|
|
1569
|
-
if (!params.modelReasoning || !isQwenOpenAICompletionsThinkingFormat(params.compatThinkingFormat)) return false;
|
|
1570
|
-
const enabled = isOpenAICompletionsThinkingEnabled(params.requestedEffort);
|
|
1571
|
-
if (params.compatThinkingFormat === "qwen-chat-template") setQwenChatTemplateThinking(params.payload, enabled);
|
|
1572
|
-
else params.payload.enable_thinking = enabled;
|
|
1573
|
-
return true;
|
|
1574
|
-
}
|
|
1575
|
-
function applyTogetherOpenAICompletionsThinkingParams(params) {
|
|
1576
|
-
if (!params.modelReasoning || params.compatThinkingFormat !== "together") return;
|
|
1577
|
-
params.payload.reasoning = { enabled: isOpenAICompletionsThinkingEnabled(params.requestedEffort) };
|
|
1578
|
-
}
|
|
1579
|
-
function convertTools(tools, compat, model) {
|
|
1580
|
-
const projection = projectOpenAITools(tools);
|
|
1581
|
-
const strict = resolveOpenAIStrictToolFlagWithDiagnostics(projection, resolveOpenAIStrictToolSetting(model, {
|
|
1582
|
-
transport: "stream",
|
|
1583
|
-
supportsStrictMode: compat?.supportsStrictMode
|
|
1584
|
-
}), {
|
|
1585
|
-
transport: "completions",
|
|
1586
|
-
model
|
|
1587
|
-
});
|
|
1588
|
-
return {
|
|
1589
|
-
projection,
|
|
1590
|
-
tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
|
|
1591
|
-
const functionTool = {
|
|
1592
|
-
name: tool.name,
|
|
1593
|
-
description: tool.description,
|
|
1594
|
-
parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model.compat)
|
|
1595
|
-
};
|
|
1596
|
-
if (strict !== void 0) functionTool.strict = strict;
|
|
1597
|
-
return {
|
|
1598
|
-
type: "function",
|
|
1599
|
-
function: functionTool
|
|
1600
|
-
};
|
|
1601
|
-
})
|
|
1602
|
-
};
|
|
1603
|
-
}
|
|
1604
|
-
function buildOpenAICompletionsParams(model, context, options) {
|
|
1605
|
-
const compat = getCompat(model);
|
|
1606
|
-
const compatDetection = detectOpenAICompletionsCompat(model);
|
|
1607
|
-
const completionsContext = context.systemPrompt ? {
|
|
1608
|
-
...context,
|
|
1609
|
-
systemPrompt: stripSystemPromptCacheBoundary(context.systemPrompt)
|
|
1610
|
-
} : context;
|
|
1611
|
-
let messages = convertMessages(model, completionsContext, compat);
|
|
1612
|
-
applyCompletionsReplay(messages, context, model, compat);
|
|
1613
|
-
if (compat.strictMessageKeys) messages = stripCompletionMessagesToRoleContent(messages);
|
|
1614
|
-
const cacheRetention = resolveCacheRetention(options?.cacheRetention);
|
|
1615
|
-
const promptCacheKey = resolvePromptCacheKey(options, cacheRetention);
|
|
1616
|
-
const params = {
|
|
1617
|
-
model: model.id,
|
|
1618
|
-
messages: compat.requiresStringContent ? flattenCompletionMessagesToStringContent(messages) : messages,
|
|
1619
|
-
stream: true
|
|
1620
|
-
};
|
|
1621
|
-
if (compat.supportsUsageInStreaming) params.stream_options = { include_usage: true };
|
|
1622
|
-
if (compat.supportsStore) params.store = false;
|
|
1623
|
-
if (compat.supportsPromptCacheKey && promptCacheKey) {
|
|
1624
|
-
params.prompt_cache_key = promptCacheKey;
|
|
1625
|
-
if (cacheRetention === "long" && compat.supportsLongCacheRetention) params.prompt_cache_retention = "24h";
|
|
1626
|
-
}
|
|
1627
|
-
if (options?.temperature !== void 0) params.temperature = options.temperature;
|
|
1628
|
-
if (options?.topP !== void 0) params.top_p = options.topP;
|
|
1629
|
-
const responseFormat = resolveOpenAICompletionsResponseFormat(shouldOmitOllamaCompatResponseFormat({
|
|
1630
|
-
provider: model.provider,
|
|
1631
|
-
baseUrl: model.baseUrl,
|
|
1632
|
-
hasTools: () => Boolean(context.tools?.length)
|
|
1633
|
-
}) ? void 0 : options?.responseFormat, compat.supportsJsonSchemaResponseFormat);
|
|
1634
|
-
if (responseFormat !== void 0) params.response_format = responseFormat;
|
|
1635
|
-
if (options?.frequencyPenalty !== void 0) params.frequency_penalty = options.frequencyPenalty;
|
|
1636
|
-
if (options?.presencePenalty !== void 0) params.presence_penalty = options.presencePenalty;
|
|
1637
|
-
if (options?.seed !== void 0) params.seed = options.seed;
|
|
1638
|
-
if (options?.stop !== void 0 && options.stop.length > 0) params.stop = options.stop;
|
|
1639
|
-
if (supportsModelTools(model)) {
|
|
1640
|
-
if (context.tools) {
|
|
1641
|
-
const converted = convertTools(context.tools, compat, model);
|
|
1642
|
-
if (converted.tools.length > 0 || converted.projection.inputToolCount === 0 && converted.projection.diagnostics.length === 0) params.tools = converted.tools;
|
|
1643
|
-
else if (hasToolCallHistory(context.messages)) params.tools = [];
|
|
1644
|
-
if (options?.toolChoice) {
|
|
1645
|
-
const toolChoice = reconcileOpenAICompletionsToolChoice(options.toolChoice, converted.projection);
|
|
1646
|
-
if (toolChoice !== void 0) params.tool_choice = toolChoice;
|
|
1647
|
-
} else if (compatDetection.capabilities.usesExplicitProxyLikeEndpoint && Array.isArray(params.tools) && params.tools.length > 0) params.tool_choice = "auto";
|
|
1648
|
-
} else if (hasToolCallHistory(context.messages)) params.tools = [];
|
|
1649
|
-
if (compatDetection.capabilities.usesExplicitProxyLikeEndpoint && Array.isArray(params.tools) && params.tools.length === 0) {
|
|
1650
|
-
delete params.tools;
|
|
1651
|
-
delete params.tool_choice;
|
|
1652
|
-
}
|
|
1653
|
-
}
|
|
1654
|
-
{
|
|
1655
|
-
const maxTokenBudget = resolveOpenAICompletionsMaxTokens(model, options);
|
|
1656
|
-
const effectiveMaxTokens = maxTokenBudget.maxTokens;
|
|
1657
|
-
const effectiveContextTokens = resolveOpenAICompletionsEffectiveContextTokens(model);
|
|
1658
|
-
let clampedMaxTokens = effectiveMaxTokens;
|
|
1659
|
-
const modelMaxTokens = resolveOpenAICompletionsModelMaxTokens(model);
|
|
1660
|
-
if (maxTokenBudget.clampToModelMaxTokens && clampedMaxTokens !== void 0 && modelMaxTokens !== void 0 && clampedMaxTokens > modelMaxTokens) {
|
|
1661
|
-
clampedMaxTokens = modelMaxTokens;
|
|
1662
|
-
emitModelTransportDebug(log, `[completions] clamp_max_tokens provider=${model.provider} api=${model.api} model=${model.id} requested=${effectiveMaxTokens} output=${clampedMaxTokens} modelMaxTokens=${modelMaxTokens}`);
|
|
1663
|
-
}
|
|
1664
|
-
if (compatDetection.capabilities.usesExplicitProxyLikeEndpoint && clampedMaxTokens !== void 0 && effectiveContextTokens !== void 0) {
|
|
1665
|
-
const estimatedInputTokens = estimateOpenAICompletionsInputTokens(params);
|
|
1666
|
-
const remainingBudget = Math.max(1, effectiveContextTokens - estimatedInputTokens - 1);
|
|
1667
|
-
if (clampedMaxTokens > remainingBudget) {
|
|
1668
|
-
clampedMaxTokens = remainingBudget;
|
|
1669
|
-
emitModelTransportDebug(log, `[completions] clamp_max_tokens provider=${model.provider} api=${model.api} model=${model.id} requested=${effectiveMaxTokens} output=${clampedMaxTokens} effectiveContext=${effectiveContextTokens} estimatedInput=${estimatedInputTokens}`);
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
if (clampedMaxTokens) {
|
|
1673
|
-
if (compat.maxTokensField === "max_tokens") params.max_tokens = clampedMaxTokens;
|
|
1674
|
-
else params.max_completion_tokens = clampedMaxTokens;
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
const completionsReasoningEffort = resolveOpenAICompletionsReasoningEffort(options);
|
|
1678
|
-
const resolvedCompletionsReasoningEffort = completionsReasoningEffort ? resolveOpenAIReasoningEffortForModel({
|
|
1679
|
-
model,
|
|
1680
|
-
effort: completionsReasoningEffort,
|
|
1681
|
-
fallbackMap: compat.reasoningEffortMap
|
|
1682
|
-
}) : void 0;
|
|
1683
|
-
const omitChatCompletionsToolReasoningEffort = Array.isArray(params.tools) && params.tools.length > 0 && (isOpenAIGpt54MiniModel(model) || isOpenAIGpt55Model(model) && isKnownOpenAICompletionsEndpoint(model));
|
|
1684
|
-
const disableChatCompletionsToolReasoning = Array.isArray(params.tools) && params.tools.length > 0 && isOpenAIGpt56Model(model) && isKnownOpenAICompletionsEndpoint(model);
|
|
1685
|
-
const handledQwenThinkingFormat = applyQwenOpenAICompletionsThinkingParams({
|
|
1686
|
-
compatThinkingFormat: compat.thinkingFormat,
|
|
1687
|
-
modelReasoning: model.reasoning,
|
|
1688
|
-
payload: params,
|
|
1689
|
-
requestedEffort: completionsReasoningEffort
|
|
1690
|
-
});
|
|
1691
|
-
applyTogetherOpenAICompletionsThinkingParams({
|
|
1692
|
-
compatThinkingFormat: compat.thinkingFormat,
|
|
1693
|
-
modelReasoning: model.reasoning,
|
|
1694
|
-
payload: params,
|
|
1695
|
-
requestedEffort: completionsReasoningEffort
|
|
1696
|
-
});
|
|
1697
|
-
if (disableChatCompletionsToolReasoning) params.reasoning_effort = "none";
|
|
1698
|
-
else if (compat.thinkingFormat === "openrouter" && model.reasoning && resolvedCompletionsReasoningEffort) params.reasoning = { effort: resolvedCompletionsReasoningEffort };
|
|
1699
|
-
else if (resolvedCompletionsReasoningEffort && model.reasoning && compat.supportsReasoningEffort && !handledQwenThinkingFormat && !omitChatCompletionsToolReasoningEffort) params.reasoning_effort = resolvedCompletionsReasoningEffort;
|
|
1700
|
-
return params;
|
|
1701
|
-
}
|
|
1702
|
-
//#endregion
|
|
1703
530
|
//#region packages/ai/src/transports/openai-completions-transport.ts
|
|
1704
531
|
function assertOpenAICompletionsPayloadHasConversationTurn(params, model) {
|
|
1705
532
|
const messages = params.messages;
|
|
@@ -1810,6 +637,14 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
1810
637
|
let firstEventAbort;
|
|
1811
638
|
try {
|
|
1812
639
|
const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
|
|
640
|
+
const turnState = resolveProviderTransportTurnState(model, {
|
|
641
|
+
sessionId: options?.sessionId,
|
|
642
|
+
turnId: randomUUID(),
|
|
643
|
+
attempt: 1,
|
|
644
|
+
transport: "stream"
|
|
645
|
+
});
|
|
646
|
+
const optionHeaders = resolveOpencodeSessionHeaders(model, options);
|
|
647
|
+
const turnHeaders = filterProviderTurnHeadersForExplicitOpencodeSession(model, options, turnState?.headers);
|
|
1813
648
|
const doneDetector = createSseDoneDetector();
|
|
1814
649
|
const baseFetch = buildGuardedModelFetch(model);
|
|
1815
650
|
const doneDetectingFetch = async (url, init) => {
|
|
@@ -1831,7 +666,10 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
1831
666
|
statusText: response.statusText
|
|
1832
667
|
});
|
|
1833
668
|
};
|
|
1834
|
-
const client = createOpenAICompletionsClient(model, context, apiKey,
|
|
669
|
+
const client = createOpenAICompletionsClient(model, context, apiKey, {
|
|
670
|
+
...turnHeaders,
|
|
671
|
+
...optionHeaders
|
|
672
|
+
}, { fetch: doneDetectingFetch });
|
|
1835
673
|
let params = buildOpenAICompletionsParams(model, context, options);
|
|
1836
674
|
const nextParams = await options?.onPayload?.(params, model);
|
|
1837
675
|
if (nextParams !== void 0) params = nextParams;
|
|
@@ -1895,26 +733,6 @@ const OPENAI_RESPONSES_TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set([
|
|
|
1895
733
|
"azure-openai-responses",
|
|
1896
734
|
"github-copilot"
|
|
1897
735
|
]);
|
|
1898
|
-
function convertResponsesTools(tools, model, options) {
|
|
1899
|
-
const projection = projectOpenAITools(tools);
|
|
1900
|
-
const strict = resolveOpenAIStrictToolFlagWithDiagnostics(projection, options?.strict, {
|
|
1901
|
-
transport: "responses",
|
|
1902
|
-
model
|
|
1903
|
-
});
|
|
1904
|
-
return {
|
|
1905
|
-
projection,
|
|
1906
|
-
tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
|
|
1907
|
-
const result = {
|
|
1908
|
-
type: "function",
|
|
1909
|
-
name: tool.name,
|
|
1910
|
-
description: tool.description,
|
|
1911
|
-
parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model.compat)
|
|
1912
|
-
};
|
|
1913
|
-
if (strict !== void 0) result.strict = strict;
|
|
1914
|
-
return result;
|
|
1915
|
-
})
|
|
1916
|
-
};
|
|
1917
|
-
}
|
|
1918
736
|
function resolveOpenAIReasoningEffort(options) {
|
|
1919
737
|
return normalizeOpenAIReasoningEffort(options?.reasoningEffort ?? options?.reasoning ?? "high");
|
|
1920
738
|
}
|
|
@@ -1947,6 +765,7 @@ const OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS = [
|
|
|
1947
765
|
"max_output_tokens",
|
|
1948
766
|
"metadata",
|
|
1949
767
|
"prompt_cache_retention",
|
|
768
|
+
"prompt_cache_options",
|
|
1950
769
|
"service_tier",
|
|
1951
770
|
"temperature",
|
|
1952
771
|
"top_p"
|
|
@@ -1962,6 +781,7 @@ function stripOpenAICodexResponsesUnsupportedTextFields(params) {
|
|
|
1962
781
|
function sanitizeOpenAICodexResponsesParams(model, params) {
|
|
1963
782
|
if (!usesNativeOpenAICodexResponsesBackend(model)) return params;
|
|
1964
783
|
for (const key of OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS) delete params[key];
|
|
784
|
+
Object.assign(params, { store: false });
|
|
1965
785
|
stripOpenAICodexResponsesUnsupportedTextFields(params);
|
|
1966
786
|
return params;
|
|
1967
787
|
}
|
|
@@ -2018,14 +838,15 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
|
|
|
2018
838
|
const messages = convertOpenAIResponsesMessagesForRequest(model, context, options, replayMode);
|
|
2019
839
|
ensureOpenAIResponsesNonEmptyInput(messages, context);
|
|
2020
840
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention);
|
|
2021
|
-
const
|
|
841
|
+
const compat = getCompat(model);
|
|
842
|
+
const promptCacheKey = compat.supportsPromptCacheKey ? resolvePromptCacheKey(options, cacheRetention) : void 0;
|
|
2022
843
|
const instructions = resolveOpenAIResponsesInstructions(model, context, payloadPolicy.usesInstructionsField);
|
|
2023
844
|
const params = {
|
|
2024
845
|
model: model.id,
|
|
2025
846
|
input: messages,
|
|
2026
847
|
stream: true,
|
|
2027
848
|
prompt_cache_key: promptCacheKey,
|
|
2028
|
-
...
|
|
849
|
+
...resolveOpenAIPromptCacheParams(model, cacheRetention, compat),
|
|
2029
850
|
...instructions ? { instructions } : {},
|
|
2030
851
|
...metadata ? { metadata } : {}
|
|
2031
852
|
};
|
|
@@ -2039,10 +860,13 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
|
|
|
2039
860
|
};
|
|
2040
861
|
if (options?.serviceTier !== void 0 && payloadPolicy.allowsServiceTier) params.service_tier = options.serviceTier;
|
|
2041
862
|
if (context.tools) {
|
|
2042
|
-
const
|
|
2043
|
-
|
|
863
|
+
const tools = context.tools;
|
|
864
|
+
const strict = resolveOpenAIStrictToolSetting(model, { transport: "stream" });
|
|
865
|
+
const projection = projectOpenAITools(tools);
|
|
866
|
+
const converted = convertProjectedResponsesTools(projection, strict, model);
|
|
867
|
+
if (converted.length > 0 || projection.inputToolCount === 0 && projection.diagnostics.length === 0) params.tools = converted;
|
|
2044
868
|
if (options?.toolChoice) {
|
|
2045
|
-
const toolChoice = reconcileOpenAIResponsesToolChoice(options.toolChoice,
|
|
869
|
+
const toolChoice = reconcileOpenAIResponsesToolChoice(options.toolChoice, projection);
|
|
2046
870
|
if (toolChoice !== void 0) params.tool_choice = toolChoice;
|
|
2047
871
|
}
|
|
2048
872
|
}
|
|
@@ -2165,6 +989,14 @@ function normalizeAssistantReplayInput(input, fromResponse = false) {
|
|
|
2165
989
|
return stableItem;
|
|
2166
990
|
});
|
|
2167
991
|
}
|
|
992
|
+
function responsesContinuationRequestFingerprint(request) {
|
|
993
|
+
const serialized = JSON.stringify(requestWithoutInput(request));
|
|
994
|
+
return sha256Hex(stableStringify(JSON.parse(serialized)));
|
|
995
|
+
}
|
|
996
|
+
function responsesContinuationPrefixFingerprint(input, output = []) {
|
|
997
|
+
const serialized = JSON.stringify([...normalizeAssistantReplayInput(input), ...normalizeAssistantReplayInput(output, true)]);
|
|
998
|
+
return sha256Hex(stableStringify(JSON.parse(serialized)));
|
|
999
|
+
}
|
|
2168
1000
|
function resolveResponsesContinuationRequest(continuation, request, steering) {
|
|
2169
1001
|
if (!continuation) return {
|
|
2170
1002
|
request,
|
|
@@ -2227,8 +1059,9 @@ function claimOpenAIResponsesHttpContinuation(params) {
|
|
|
2227
1059
|
};
|
|
2228
1060
|
httpContinuationEntries.set(key, claimed);
|
|
2229
1061
|
try {
|
|
2230
|
-
const
|
|
2231
|
-
const
|
|
1062
|
+
const request = previous?.kind === "ready" ? params.request : params.restoreRequest?.() ?? params.request;
|
|
1063
|
+
const resolved = resolveResponsesContinuationRequest(previous?.kind === "ready" ? previous.state : void 0, request);
|
|
1064
|
+
const fullRequest = resolved.fullRequest ?? request;
|
|
2232
1065
|
return {
|
|
2233
1066
|
request: params.request.store === false ? fullRequest : resolved.request,
|
|
2234
1067
|
fullRequest,
|
|
@@ -2532,7 +1365,7 @@ function readServerEvent(message) {
|
|
|
2532
1365
|
}
|
|
2533
1366
|
function createOpenAIResponsesWebSocketStream(params) {
|
|
2534
1367
|
const connection = prepareWebSocketConnection(params.client, params.headers);
|
|
2535
|
-
|
|
1368
|
+
let fullRequest = sanitizeWebSocketRequest(params.request);
|
|
2536
1369
|
const requestModel = typeof fullRequest.model === "string" ? fullRequest.model : "";
|
|
2537
1370
|
const degradationKey = `${params.sessionId ?? ""}\0${connection.identity}\0${requestModel}`;
|
|
2538
1371
|
const degraded = degradedWebSocketConnections.get(degradationKey);
|
|
@@ -2561,10 +1394,13 @@ function createOpenAIResponsesWebSocketStream(params) {
|
|
|
2561
1394
|
if (continuation && lease.entry) {
|
|
2562
1395
|
lease.entry.continuation = void 0;
|
|
2563
1396
|
prepared = resolveResponsesContinuationRequest(continuation, fullRequest, steeringMode);
|
|
2564
|
-
} else
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
1397
|
+
} else {
|
|
1398
|
+
fullRequest = params.restoreRequest?.(fullRequest) ?? fullRequest;
|
|
1399
|
+
prepared = {
|
|
1400
|
+
request: fullRequest,
|
|
1401
|
+
continuationStatus: lease.entry ? "no_previous_response" : "socket_not_cached"
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
2568
1404
|
} catch (error) {
|
|
2569
1405
|
lease.iterator.return?.().catch(() => void 0);
|
|
2570
1406
|
lease.release({ keep: false });
|
|
@@ -2731,6 +1567,7 @@ function createOpenAIResponsesWebSocketStream(params) {
|
|
|
2731
1567
|
}
|
|
2732
1568
|
} },
|
|
2733
1569
|
request: prepared.request,
|
|
1570
|
+
fullRequest: prepared.fullRequest ?? fullRequest,
|
|
2734
1571
|
reusedConnection: lease.reusedConnection,
|
|
2735
1572
|
continuationStatus: prepared.continuationStatus,
|
|
2736
1573
|
inputReplay,
|
|
@@ -2810,6 +1647,59 @@ async function requestPreparedOpenAIResponsesCompaction(streamFn, model, context
|
|
|
2810
1647
|
}
|
|
2811
1648
|
}
|
|
2812
1649
|
//#endregion
|
|
1650
|
+
//#region packages/ai/src/transports/openai-responses-reasoning-state.ts
|
|
1651
|
+
function inputReplay(message) {
|
|
1652
|
+
const value = "openclawResponsesInputReplay" in message ? message.openclawResponsesInputReplay : void 0;
|
|
1653
|
+
return isRecord(value) ? value : void 0;
|
|
1654
|
+
}
|
|
1655
|
+
/** Save only admitted settings and hashes, never another copy of the conversation. */
|
|
1656
|
+
function recordResponsesReasoningState(message, model, identity, request, output) {
|
|
1657
|
+
if (!supportsResponsesReasoningUpdate(request) || !isRecord(request.reasoning) || !request.input || request.previous_response_id || message.providerReplay || output.some((item) => isRecord(item) && item.type === "compaction")) return;
|
|
1658
|
+
const reasoning = {
|
|
1659
|
+
...buildProviderReplayContext(model, identity),
|
|
1660
|
+
effort: request.reasoning.effort,
|
|
1661
|
+
controls: request.input.flatMap((item, index) => isConfigurationUpdate(item) ? [{
|
|
1662
|
+
index,
|
|
1663
|
+
item
|
|
1664
|
+
}] : []),
|
|
1665
|
+
inputLength: request.input.length,
|
|
1666
|
+
outputLength: output.length,
|
|
1667
|
+
prefixHash: responsesContinuationPrefixFingerprint(request.input, output),
|
|
1668
|
+
requestHash: responsesContinuationRequestFingerprint(request)
|
|
1669
|
+
};
|
|
1670
|
+
Object.assign(message, { openclawResponsesInputReplay: {
|
|
1671
|
+
...inputReplay(message),
|
|
1672
|
+
reasoning
|
|
1673
|
+
} });
|
|
1674
|
+
}
|
|
1675
|
+
/** A cold transport can replay controls, but cannot resurrect a server response handle. */
|
|
1676
|
+
function restoreResponsesReasoningState(context, model, identity, request) {
|
|
1677
|
+
const latest = context.messages.findLast((message) => message.role === "assistant");
|
|
1678
|
+
const state = latest ? inputReplay(latest)?.reasoning : void 0;
|
|
1679
|
+
if (!isRecord(state)) return request;
|
|
1680
|
+
const { effort, inputLength, outputLength, controls, prefixHash, requestHash } = state;
|
|
1681
|
+
if (!isOpenAIResponsesReplayContext(state) || !providerReplayContextMatches(state, buildProviderReplayContext(model, identity)) || latest?.providerReplay || !supportsResponsesReasoningUpdate(request) || !isRecord(request.reasoning) || !request.input || request.previous_response_id || request.input.some(isConfigurationUpdate) || typeof effort !== "string" || typeof inputLength !== "number" || !Number.isSafeInteger(inputLength) || inputLength < 0 || typeof outputLength !== "number" || !Number.isSafeInteger(outputLength) || outputLength < 0 || !Array.isArray(controls) || controls.length > inputLength || inputLength + outputLength > request.input.length + controls.length) return request;
|
|
1682
|
+
const previousInput = request.input.slice(0, inputLength - controls.length);
|
|
1683
|
+
let lastIndex = -1;
|
|
1684
|
+
for (const control of controls) {
|
|
1685
|
+
if (!isRecord(control) || typeof control.index !== "number" || !Number.isSafeInteger(control.index) || control.index <= lastIndex || control.index > previousInput.length || !isConfigurationUpdate(control.item)) return request;
|
|
1686
|
+
previousInput.splice(control.index, 0, control.item);
|
|
1687
|
+
lastIndex = control.index;
|
|
1688
|
+
}
|
|
1689
|
+
const previous = {
|
|
1690
|
+
...request,
|
|
1691
|
+
reasoning: {
|
|
1692
|
+
...request.reasoning,
|
|
1693
|
+
effort
|
|
1694
|
+
},
|
|
1695
|
+
input: previousInput
|
|
1696
|
+
};
|
|
1697
|
+
if (responsesContinuationRequestFingerprint(previous) !== requestHash) return request;
|
|
1698
|
+
const prepared = replayResponsesReasoningUpdates(previous, request, outputLength);
|
|
1699
|
+
if (responsesContinuationPrefixFingerprint((prepared.input ?? []).slice(0, inputLength + outputLength)) !== prefixHash) return request;
|
|
1700
|
+
return prepared;
|
|
1701
|
+
}
|
|
1702
|
+
//#endregion
|
|
2813
1703
|
//#region packages/ai/src/transports/openai-responses-client.ts
|
|
2814
1704
|
function resolveNativeOpenAIResponsesWebSocketMode(model, transport) {
|
|
2815
1705
|
if (transport !== "websocket" && transport !== "websocket-cached" && transport !== "auto") return;
|
|
@@ -2825,30 +1715,12 @@ function combineWebSocketTimeoutSignal(signal, model, timeoutMs) {
|
|
|
2825
1715
|
if (resolvedTimeoutMs === void 0 || !Number.isFinite(resolvedTimeoutMs)) return signal;
|
|
2826
1716
|
return AbortSignal.any([signal, AbortSignal.timeout(Math.max(1, resolvedTimeoutMs))]);
|
|
2827
1717
|
}
|
|
2828
|
-
function
|
|
2829
|
-
const normalizedProvider = model.provider.trim().toLowerCase();
|
|
2830
|
-
const allowRuntimePluginLoad = normalizedProvider === "openai" || normalizedProvider === "azure-openai" || normalizedProvider === "azure-openai-responses";
|
|
2831
|
-
return getAiTransportHost().plugin.resolveTransportTurnState({
|
|
2832
|
-
provider: model.provider,
|
|
2833
|
-
modelId: model.id,
|
|
2834
|
-
allowRuntimePluginLoad,
|
|
2835
|
-
context: {
|
|
2836
|
-
provider: model.provider,
|
|
2837
|
-
modelId: model.id,
|
|
2838
|
-
model,
|
|
2839
|
-
sessionId: params.sessionId,
|
|
2840
|
-
turnId: params.turnId,
|
|
2841
|
-
attempt: params.attempt,
|
|
2842
|
-
transport: params.transport
|
|
2843
|
-
}
|
|
2844
|
-
});
|
|
2845
|
-
}
|
|
2846
|
-
function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId, fetchOverride) {
|
|
1718
|
+
function createOpenAIResponsesClient(model, apiKey, defaultHeaders, fetchOverride) {
|
|
2847
1719
|
return new OpenAI({
|
|
2848
1720
|
apiKey,
|
|
2849
1721
|
baseURL: resolveOpenAIClientBaseUrl(model),
|
|
2850
1722
|
dangerouslyAllowBrowser: true,
|
|
2851
|
-
defaultHeaders
|
|
1723
|
+
defaultHeaders,
|
|
2852
1724
|
fetch: fetchOverride ?? buildGuardedModelFetch(model),
|
|
2853
1725
|
...buildOpenAISdkClientOptions(model)
|
|
2854
1726
|
});
|
|
@@ -2872,8 +1744,11 @@ function createResponsesTransportExecutor(config) {
|
|
|
2872
1744
|
transport: websocketMode ? "websocket" : "stream"
|
|
2873
1745
|
});
|
|
2874
1746
|
const websocketSessionPolicy = websocketMode ? turnState?.websocket : void 0;
|
|
2875
|
-
const
|
|
2876
|
-
const
|
|
1747
|
+
const httpTurnHeaders = filterProviderTurnHeadersForExplicitOpencodeSession(model, options, turnState?.headers);
|
|
1748
|
+
const websocketTurnHeaders = filterProviderTurnHeadersForExplicitOpencodeSession(model, options, websocketSessionPolicy?.headers);
|
|
1749
|
+
const websocketHeaders = websocketMode ? buildOpenAIClientHeaders(model, context, options?.headers, websocketTurnHeaders, options?.sessionId, options?.cacheRetention) : void 0;
|
|
1750
|
+
const httpHeaders = buildOpenAIClientHeaders(model, context, options?.headers, httpTurnHeaders, options?.sessionId, options?.cacheRetention);
|
|
1751
|
+
const client = config.createClient(model, apiKey, httpHeaders, compactRequest ? createBoundedOpenAIResponsesCompactionFetch(buildGuardedModelFetch(model)) : void 0);
|
|
2877
1752
|
const nativeAstra = model.id === "gpt-6-astra" && supportsNativeOpenAIResponsesEndpoint(model);
|
|
2878
1753
|
const asyncToolExecutionEligible = nativeAstra && options?.asyncToolExecution === true && !responsesOptions?.openclawCodeModeToolSurface;
|
|
2879
1754
|
const prepareRequest = async (request) => {
|
|
@@ -2926,8 +1801,9 @@ function createResponsesTransportExecutor(config) {
|
|
|
2926
1801
|
sessionId,
|
|
2927
1802
|
apiKey,
|
|
2928
1803
|
baseUrl: model.baseUrl,
|
|
2929
|
-
headers:
|
|
2930
|
-
request: params
|
|
1804
|
+
headers: httpHeaders,
|
|
1805
|
+
request: params,
|
|
1806
|
+
restoreRequest: () => restoreResponsesReasoningState(context, model, responsesOptions, params)
|
|
2931
1807
|
});
|
|
2932
1808
|
if (continuationClaim) params = continuationClaim.fullRequest;
|
|
2933
1809
|
}
|
|
@@ -2965,7 +1841,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
2965
1841
|
onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, responsesOptions, checkpoint),
|
|
2966
1842
|
canRetryStream: () => output.content.length === 0,
|
|
2967
1843
|
wrapStream: ({ stream: rawResponseStream, response, attempt }) => {
|
|
2968
|
-
|
|
1844
|
+
continuationBaseline = attempt.request.previous_response_id ? params : attempt.request;
|
|
2969
1845
|
return withProviderResponseHook({
|
|
2970
1846
|
stream: observeResponsesStream(rawResponseStream, model, requestStartedAt),
|
|
2971
1847
|
signal: firstEvent.signal,
|
|
@@ -2981,6 +1857,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
2981
1857
|
return responseStream;
|
|
2982
1858
|
};
|
|
2983
1859
|
let responseStream;
|
|
1860
|
+
let websocketBaseline;
|
|
2984
1861
|
let finishWebSocket;
|
|
2985
1862
|
let transport = "sse";
|
|
2986
1863
|
const logWebSocketFallback = (reason) => emitModelTransportDebug(log, `[responses] websocket_fallback provider=${model.provider} api=${model.api} model=${model.id} reason=${reason}`);
|
|
@@ -2994,6 +1871,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
2994
1871
|
const websocket = createOpenAIResponsesWebSocketStream({
|
|
2995
1872
|
client,
|
|
2996
1873
|
request: params,
|
|
1874
|
+
restoreRequest: (request) => restoreResponsesReasoningState(context, model, responsesOptions, request),
|
|
2997
1875
|
mode: websocketMode,
|
|
2998
1876
|
sessionId: options?.sessionId,
|
|
2999
1877
|
headers: websocketHeaders,
|
|
@@ -3007,6 +1885,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
3007
1885
|
}))
|
|
3008
1886
|
});
|
|
3009
1887
|
finishWebSocket = websocket.finish;
|
|
1888
|
+
websocketBaseline = websocket.fullRequest;
|
|
3010
1889
|
recordResponsesInputReplay(output, websocket.inputReplay);
|
|
3011
1890
|
observePrompt?.(websocket.request, {
|
|
3012
1891
|
egress: "responses-websocket",
|
|
@@ -3071,6 +1950,8 @@ function createResponsesTransportExecutor(config) {
|
|
|
3071
1950
|
finishWebSocket?.();
|
|
3072
1951
|
if (options?.signal?.aborted) throw transportAbortError(options.signal);
|
|
3073
1952
|
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
|
|
1953
|
+
const admitted = transport === "websocket" ? websocketBaseline : continuationBaseline;
|
|
1954
|
+
if (terminal && admitted && supportsNativeOpenAIResponsesEndpoint(model)) recordResponsesReasoningState(output, model, responsesOptions, admitted, terminal.output);
|
|
3074
1955
|
if (continuationClaim && continuationBaseline && terminal) continuationClaim.commit(continuationBaseline, terminal);
|
|
3075
1956
|
} catch (error) {
|
|
3076
1957
|
finishWebSocket?.({ keep: false });
|
|
@@ -3135,12 +2016,12 @@ function resolveAzureDeploymentName(model) {
|
|
|
3135
2016
|
deploymentMap: process.env.AZURE_OPENAI_DEPLOYMENT_NAME_MAP
|
|
3136
2017
|
});
|
|
3137
2018
|
}
|
|
3138
|
-
function createAzureOpenAIClient(model,
|
|
2019
|
+
function createAzureOpenAIClient(model, apiKey, defaultHeaders, fetchOverride) {
|
|
3139
2020
|
const baseURL = model.baseUrl.replace(/\/+$/, "");
|
|
3140
2021
|
const clientOptions = {
|
|
3141
2022
|
apiKey,
|
|
3142
2023
|
dangerouslyAllowBrowser: true,
|
|
3143
|
-
defaultHeaders
|
|
2024
|
+
defaultHeaders,
|
|
3144
2025
|
baseURL,
|
|
3145
2026
|
fetch: fetchOverride ?? buildGuardedModelFetch(model),
|
|
3146
2027
|
...buildOpenAISdkClientOptions(model)
|
|
@@ -3158,35 +2039,6 @@ function buildAzureOpenAIResponsesParams(model, context, options, deploymentName
|
|
|
3158
2039
|
return params;
|
|
3159
2040
|
}
|
|
3160
2041
|
//#endregion
|
|
3161
|
-
//#region packages/ai/src/transports/openai-responses-transport.ts
|
|
3162
|
-
/** OpenAI Responses transport facade. */
|
|
3163
|
-
const responsesTesting = {
|
|
3164
|
-
getCompat,
|
|
3165
|
-
assertCodeModeResponsesToolSurface,
|
|
3166
|
-
buildOpenAIResponsesParams,
|
|
3167
|
-
buildOpenAIClientHeaders,
|
|
3168
|
-
buildOpenAISdkClientOptions,
|
|
3169
|
-
buildOpenAISdkRequestOptions,
|
|
3170
|
-
createAzureOpenAIClient,
|
|
3171
|
-
createOpenAIResponsesClient,
|
|
3172
|
-
enforceCodeModeResponsesToolSurface,
|
|
3173
|
-
sanitizeOpenAICodexResponsesParams,
|
|
3174
|
-
processResponsesStream,
|
|
3175
|
-
formatModelTransportDebugBaseUrl,
|
|
3176
|
-
buildResponsesFailedNoDetailsObservation,
|
|
3177
|
-
buildOpenAIResponsesReasoningReplayMetadata,
|
|
3178
|
-
isInvalidEncryptedContentError,
|
|
3179
|
-
normalizeResponsesFailedEvent,
|
|
3180
|
-
createResponsesStreamWithEncryptedContentRetry,
|
|
3181
|
-
resolveAzureOpenAIApiVersion,
|
|
3182
|
-
summarizeResponsesFailedNoDetailsObservation,
|
|
3183
|
-
summarizeResponsesPayload,
|
|
3184
|
-
summarizeResponsesTools,
|
|
3185
|
-
stringifyRedactedEvent,
|
|
3186
|
-
stringifyRedactedPayload
|
|
3187
|
-
};
|
|
3188
|
-
if (process.env.VITEST || false) globalThis.openclawOpenAIResponsesTransportTestApi = responsesTesting;
|
|
3189
|
-
//#endregion
|
|
3190
2042
|
//#region packages/ai/src/transports/provider-compaction-replay.ts
|
|
3191
2043
|
function isAssistantReplayMessage(message) {
|
|
3192
2044
|
return message.role === "assistant";
|
|
@@ -3353,7 +2205,7 @@ const SIMPLE_TRANSPORT_API_ALIAS = {
|
|
|
3353
2205
|
"google-generative-ai": "openclaw-google-generative-ai-transport"
|
|
3354
2206
|
};
|
|
3355
2207
|
function createProviderOwnedGoogleTransportStreamFn(model, ctx) {
|
|
3356
|
-
|
|
2208
|
+
const streamFn = getAiTransportHost().plugin.resolveProviderStream({
|
|
3357
2209
|
provider: model.provider,
|
|
3358
2210
|
config: ctx?.cfg,
|
|
3359
2211
|
workspaceDir: ctx?.workspaceDir,
|
|
@@ -3380,6 +2232,10 @@ function createProviderOwnedGoogleTransportStreamFn(model, ctx) {
|
|
|
3380
2232
|
model
|
|
3381
2233
|
}
|
|
3382
2234
|
}) ?? void 0;
|
|
2235
|
+
return streamFn ? (requestModel, context, options) => streamFn(requestModel, context, {
|
|
2236
|
+
...options,
|
|
2237
|
+
headers: resolveOpencodeSessionHeaders(requestModel, options)
|
|
2238
|
+
}) : void 0;
|
|
3383
2239
|
}
|
|
3384
2240
|
function createSupportedTransportStreamFn(model, ctx) {
|
|
3385
2241
|
switch (model.api) {
|
|
@@ -3438,6 +2294,18 @@ function buildTransportAwareSimpleStreamFn(model, ctx) {
|
|
|
3438
2294
|
}
|
|
3439
2295
|
//#endregion
|
|
3440
2296
|
//#region packages/ai/src/transports/simple-completion-transport.ts
|
|
2297
|
+
/**
|
|
2298
|
+
* Simple completion transport preparation.
|
|
2299
|
+
*
|
|
2300
|
+
* Registers provider-specific stream functions and rewrites models that need OpenClaw-managed transport semantics.
|
|
2301
|
+
*/
|
|
2302
|
+
/** Standalone completions have no durable session, but may require routing identity. */
|
|
2303
|
+
function prepareHeadersForSimpleCompletion(model, options) {
|
|
2304
|
+
return resolveOpencodeSessionHeaders(model, {
|
|
2305
|
+
...options,
|
|
2306
|
+
sessionId: options?.sessionId || randomUUID()
|
|
2307
|
+
});
|
|
2308
|
+
}
|
|
3441
2309
|
const PROVIDER_SIMPLE_COMPLETION_API_PREFIX = "openclaw-provider-simple:";
|
|
3442
2310
|
const PROVIDER_STREAM_API_PREFIX = "openclaw-provider-stream:";
|
|
3443
2311
|
const INVALID_CODEX_BASE_URL_MESSAGE = "OpenAI Codex Responses baseUrl must not include query parameters or fragments";
|
|
@@ -3564,7 +2432,9 @@ function prepareProviderStreamModel(params) {
|
|
|
3564
2432
|
const streamFn = providerStreamFn ? wrapPluginProviderStream(providerStreamFn) : transportFallback && params.model.api === "google-generative-ai" ? wrapPluginProviderStream(transportFallback) : transportFallback;
|
|
3565
2433
|
if (!streamFn) return;
|
|
3566
2434
|
const api = params.apiRegistry.getApiProvider(params.model.api) ? resolveProviderStreamApi(params.model) : params.model.api;
|
|
3567
|
-
|
|
2435
|
+
const sourceApi = params.model.api;
|
|
2436
|
+
const sourceStreamFn = (runtimeModel, context, options) => streamFn(projectModel(runtimeModel, { api: sourceApi }), context, options);
|
|
2437
|
+
if (!registerCustomApi(params.apiRegistry, api, sourceStreamFn)) return;
|
|
3568
2438
|
return api === params.model.api ? params.model : projectModel(params.model, { api });
|
|
3569
2439
|
}
|
|
3570
2440
|
function prepareModelForSimpleCompletion(params) {
|
|
@@ -3589,4 +2459,4 @@ function prepareModelForSimpleCompletion(params) {
|
|
|
3589
2459
|
return applyProviderSimpleCompletionWrapper(apiRegistry, model, cfg);
|
|
3590
2460
|
}
|
|
3591
2461
|
//#endregion
|
|
3592
|
-
export { CompactionReplayRefreshRequiredError, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP,
|
|
2462
|
+
export { CompactionReplayRefreshRequiredError, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, IncompleteToolCallError, MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, applyAnthropicContextManagementToRequest, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyAnthropicRequestCacheControl, applyCompletionsAnthropicCacheControl, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildAnthropicSystemBlocks, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, captureOpenAIResponsesCompaction, coerceTransportToolCallArguments, consumeGoogleGenerateContentStream, convertGoogleTools, copyProviderAcceptanceObserver, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIProviderAcceptanceHook, createOpenAIResponseHook, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, filterCodeModePayloadTools, finalizeTerminalToolCallArguments, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, googleFlashSupportsMinimalThinking, hasOpenAICompatibleConversationTurn, isAnthropicServerToolClearingEnabled, isCodeModeModelVisibleToolName, isCompactionReplayCheckpoint, isDirectAnthropicModel, isNativeOpenAIEndpoint, isOpenAICodexResponsesModel, isOpenAICompletionsThinkingEnabled, log, logAnthropicContextEdits, measureUtf8AppendBytes, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, notifyProviderHttpMetadata, notifyProviderHttpResponse, notifyProviderStreamOpened, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, parseOpenAICompletionsUsage, parseTerminalToolCallArguments, prepareHeadersForSimpleCompletion, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, preserveCompactionReplayWindow, projectGoogleMessages, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, readOpenAICompletionsReasoningBatch, replaceCompactionReplayOwnerContent, requestPreparedOpenAIResponsesCompaction, requiresCompactionReplayRefresh, requiresGoogleToolCallId, resolveAnthropicCacheOptions, resolveAnthropicContextManagementBetaHeader, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveAnthropicServerCompactionPlan, resolveCodeModeResponsesVisibleToolNames, resolveCompactionReplayEligibility, resolveCompactionReplayPressure, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAIClientBaseUrl, resolveOpenAICompletionsCompat, resolveOpenAIPromptCacheKeySupport, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesCompactEndpointPlan, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIResponsesServerCompactionPlan, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompactionReplayCheckpoint, stripCompactionReplayCheckpointInPlace, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend, withProviderAcceptanceObserver, withProviderResponseHook };
|