@openclaw/ai 2026.8.1-beta.2 → 2026.9.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{anthropic-SrGtwsJu.d.mts → anthropic-BECQCNdF.d.mts} +0 -2
- package/dist/{anthropic-B6dLpq5L.mjs → anthropic-DI4PZKKB.mjs} +46 -34
- package/dist/{anthropic-compaction-replay-8lJNKXOE.mjs → anthropic-compaction-replay-nhKaCXu6.mjs} +17 -22
- package/dist/{anthropic-payload-policy-CiEuQS72.d.mts → anthropic-payload-policy-B_0n0enE.d.mts} +3 -1
- package/dist/{api-registry-k3zTz0cV.d.mts → api-registry-CTd8NzcD.d.mts} +2 -1
- package/dist/{azure-openai-responses-mxIOtUnn.mjs → azure-openai-responses-D8dI0ekg.mjs} +3 -3
- package/dist/diagnostics.d.mts +0 -1
- package/dist/diagnostics.mjs +1 -1
- package/dist/event-stream-BKp4fOt_.d.mts +1 -0
- package/dist/{event-stream-BP6AWT8j.d.mts → event-stream-LiXePESD.d.mts} +1 -2
- package/dist/event-stream.d.mts +2 -1
- package/dist/{google-C7h2QzDX.mjs → google-Od-LLdVK.mjs} +3 -3
- package/dist/{google-shared-B0Qr9OR7.mjs → google-shared-Bgr9lFPw.mjs} +22 -8
- package/dist/{google-vertex-Bhc3TjDl.mjs → google-vertex-aerRSXc4.mjs} +4 -4
- package/dist/{host-DTqNc7ad.mjs → host-D51fmkH6.mjs} +40 -33
- package/dist/{host-vWgMMhiJ.d.mts → host-DsbPMFU6.d.mts} +7 -7
- package/dist/index-Qbej8io0.d.mts +3 -0
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +2 -3
- package/dist/internal/anthropic.d.mts +13 -6
- package/dist/internal/anthropic.mjs +4 -4
- package/dist/internal/openai-responses-payload-policy.d.mts +2 -2
- package/dist/internal/openai-responses-payload-policy.mjs +2 -2
- package/dist/internal/openai.d.mts +6 -6
- package/dist/internal/openai.mjs +10 -8
- package/dist/internal/runtime.d.mts +18 -5
- package/dist/internal/runtime.mjs +8 -7
- package/dist/internal/shared.d.mts +18 -4
- package/dist/internal/shared.mjs +4 -4
- package/dist/{json-parse-CDnesDM_.mjs → json-parse-BuAJEbdW.mjs} +18 -2
- package/dist/{headers-DdOQtGuU.mjs → llm-request-activity-BjtkplhG.mjs} +1 -9
- package/dist/{mistral-CEWoQI_g.mjs → mistral-EiHdymeb.mjs} +59 -49
- package/dist/{openai-chatgpt-responses-CrPmqERt.mjs → openai-chatgpt-responses-DHpF9o1e.mjs} +42 -17
- package/dist/{openai-completions-BPnt4Sml.mjs → openai-completions-EFPiUGfS.mjs} +60 -257
- package/dist/{openai-completions-compat-Dt3dcawL.d.mts → openai-completions-compat-BefmHT26.d.mts} +3 -3
- package/dist/openai-completions-stream-DUlGwRMz.mjs +1621 -0
- package/dist/{openai-responses-DhIKtOup.mjs → openai-responses-BogP8OjX.mjs} +6 -5
- package/dist/{openai-responses-contracts-XpZJxrRG.d.mts → openai-responses-contracts-Dvj_UtPy.d.mts} +3 -3
- package/dist/{openai-responses-contracts-CyfIkQi5.mjs → openai-responses-contracts-QUY12X0B.mjs} +6 -26
- package/dist/{openai-responses-payload-policy-BSs371VM.d.mts → openai-responses-payload-policy-CNGFT9zr.d.mts} +1 -0
- package/dist/{openai-responses-payload-policy-BDxV-W0c.mjs → openai-responses-payload-policy-D8EdimYe.mjs} +6 -8
- package/dist/{openai-responses-prompt-observer-internal-DgNTYnRY.mjs → openai-responses-prompt-observer-internal-Cd4hJG-S.mjs} +3 -3
- package/dist/{openai-responses-shared-DXIt3iY5.mjs → openai-responses-shared-DJThc6jW.mjs} +205 -1472
- package/dist/openai-stop-reason-Drnn_6Qj.mjs +28 -0
- package/dist/openai-tool-schema-ho-hIkQf.mjs +1695 -0
- package/dist/{provider-error-BUwEnjXq.mjs → provider-error-DDOs_Bz0.mjs} +20 -27
- package/dist/provider-options-AvldWZt8.mjs +21 -0
- package/dist/{provider-options-B96RdNpH.d.mts → provider-options-MdMBLzlU.d.mts} +15 -4
- package/dist/provider-transcript-transform-C01bQ5a3.mjs +32 -0
- package/dist/provider-types.d.mts +7 -5
- package/dist/providers.d.mts +1 -2
- package/dist/providers.mjs +9 -9
- package/dist/{reasoning-tag-text-partitioner-rnPwX2pg.mjs → reasoning-tag-text-partitioner-5ygO2rZc.mjs} +3 -0
- package/dist/{sanitize-unicode-BYqrYtC_.mjs → sanitize-unicode-DCkltN94.mjs} +1 -2
- package/dist/{simple-options-D58D5Kvw.mjs → simple-options-CFj7x3J4.mjs} +5 -4
- package/dist/{anthropic-JsNA5KCu.mjs → src-Bu3FiFAG.mjs} +1 -1
- package/dist/{streaming-byte-guard-BrbkbwUu.mjs → streaming-byte-guard-CC-HMn_u.mjs} +5 -6
- package/dist/string-normalization--fwJ4S2q.mjs +16 -0
- package/dist/{tool-schema-json-projection-q5d7QX5c.mjs → tool-schema-json-projection-qvTEs5Am.mjs} +17 -8
- package/dist/transport-stream-shared-ljShVIZB.mjs +342 -0
- package/dist/transport-stream-shared-rvaCyFYt.d.mts +138 -0
- package/dist/{transport-utils-DJqkxbhC.mjs → transport-utils-LJ1_rbi-.mjs} +8 -5
- package/dist/transports.d.mts +45 -106
- package/dist/transports.mjs +134 -1089
- package/dist/{types-BHNrPS1l.d.mts → types-DhLoJbFm.d.mts} +49 -17
- package/dist/types-GiAjXatj.d.mts +1 -0
- package/dist/types.d.mts +6 -5
- package/dist/types.mjs +1 -2
- package/dist/utf16-slice-qz3nsy87.mjs +84 -0
- package/dist/{validation-DT9SrFn3.d.mts → validation-Dk7q7NMN.d.mts} +1 -2
- package/dist/validation.d.mts +1 -1
- package/package.json +5 -5
- package/dist/index-BVVgDSdq.d.mts +0 -1
- package/dist/openai-stop-reason-BkFkqqK0.mjs +0 -563
- package/dist/openai-tool-projection-CY04OcvQ.mjs +0 -338
- package/dist/provider-transcript-transform-ePx-Bbfr.mjs +0 -155
- package/dist/record-coerce-DdXsgUd_.mjs +0 -23
- package/dist/src-D2H6yKkH.mjs +0 -2
- package/dist/stream-first-event-timeout-DvDeSucC.d.mts +0 -29
- package/dist/string-coerce-fsri9iCu.mjs +0 -34
- package/dist/types-BVVgDSdq.d.mts +0 -1
- package/dist/utf16-slice-CvGodqok.mjs +0 -29
package/dist/transports.mjs
CHANGED
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
import { n as getEnvApiKey } from "./env-api-keys-DrgeBuva.mjs";
|
|
2
|
-
import { d as resolveClaudeSonnet5ModelIdentity, g as supportsClaudeNativeXhighEffort, p as supportsClaudeAdaptiveThinking, u as resolveClaudeOpus5ModelIdentity } from "./
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { r as
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { i as canonicalizeBase64, n as projectProviderError, o as stableStringify } from "./provider-error-BUwEnjXq.mjs";
|
|
9
|
-
import { n as toErrorObject, t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-DgNTYnRY.mjs";
|
|
2
|
+
import { d as resolveClaudeSonnet5ModelIdentity, g as supportsClaudeNativeXhighEffort, p as supportsClaudeAdaptiveThinking, u as resolveClaudeOpus5ModelIdentity } from "./src-Bu3FiFAG.mjs";
|
|
3
|
+
import { c as normalizeLowercaseStringOrEmpty, o as isRecord, s as hasNonEmptyString } from "./utf16-slice-qz3nsy87.mjs";
|
|
4
|
+
import { r as calculateCost } from "./sanitize-unicode-DCkltN94.mjs";
|
|
5
|
+
import { S as usesClaudeStreamingRefusalContract, _ as prepareClaudeNoPrefillRequestContext, a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, f as ANTHROPIC_CLAUDE_CODE_BILLING_SYSTEM_BLOCK, g as mapAnthropicStopReason, h as defaultsClaudeAdaptiveThinking, m as applyClaudeRequestContract, n as getAiTransportHost, p as ANTHROPIC_CLAUDE_CODE_VERSION, r as resolveAiTransportHeaderSentinels, s as extractToolResultBlockText, v as requiresClaudeAdaptiveThinking, x as usesClaudeFable5MessagesContract, y as resolveAnthropicThinkingEffort } from "./host-D51fmkH6.mjs";
|
|
6
|
+
import { i as canonicalizeBase64, o as stableStringify } from "./provider-error-DDOs_Bz0.mjs";
|
|
7
|
+
import { n as toErrorObject, t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-Cd4hJG-S.mjs";
|
|
10
8
|
import { r as asNonNegativeFiniteNumber } from "./number-coercion-H9qHik3g.mjs";
|
|
11
|
-
import {
|
|
12
|
-
import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
|
|
9
|
+
import { n as uniqueStrings } from "./string-normalization--fwJ4S2q.mjs";
|
|
13
10
|
import { t as resolveCacheRetention } from "./cache-retention-0x979a5V.mjs";
|
|
14
|
-
import { f as sortPromptCacheToolsByName, l as stripSystemPromptCacheBoundary, t as adjustMaxTokensForThinking } from "./simple-options-
|
|
15
|
-
import { a as resolveProviderEndpoint, c as transformTransportMessages, i as resolveOpenAIStrictToolSetting, n as buildGuardedModelFetch
|
|
16
|
-
import {
|
|
17
|
-
import { a as
|
|
11
|
+
import { f as sortPromptCacheToolsByName, l as stripSystemPromptCacheBoundary, t as adjustMaxTokensForThinking } from "./simple-options-CFj7x3J4.mjs";
|
|
12
|
+
import { a as resolveProviderEndpoint, c as transformTransportMessages, i as resolveOpenAIStrictToolSetting, n as buildGuardedModelFetch } from "./tool-schema-json-projection-qvTEs5Am.mjs";
|
|
13
|
+
import { a as isGoogleGemini3FlashModel, c as parseRetryAfterSeconds, f as resolveModelHeaderSentinels$1, h as supportsModelTools, i as isCodeModeModelVisibleToolName, l as readResponseTextSnippet, m as sha256Hex, n as createAbortError$1, o as isGoogleGemini3ProModel, p as resolveSecretSentinel, r as estimateStringChars, t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, u as redactIdentifier } from "./transport-utils-LJ1_rbi-.mjs";
|
|
14
|
+
import { A as resolveAnthropicImageMediaType, C as readAnthropicFallbackBoundary, D as usesFoundryBearerAuth, E as omitFoundryBearerCredentialHeaders, F as resolveAnthropicPayloadPolicy, I as resolveAnthropicServerCompactionPlan, M as applyAnthropicEphemeralCacheControlMarkers, N as applyAnthropicPayloadPolicyToParams, O as createAnthropicInlineImageBudget, P as resolveAnthropicEphemeralCacheControl, S as applyAnthropicFallbackBoundary, T as applyAnthropicRefusal, _ as ANTHROPIC_OMITTED_REASONING_TEXT, a as applyAnthropicMessageDeltaUsage, b as ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, d as normalizeAnthropicToolCallId, f as normalizeAnthropicToolChoice, g as toClaudeCodeToolName, h as resolveOriginalAnthropicToolName, i as suppressAnthropicCompaction, j as applyAnthropicCacheControlToMessages, k as normalizeAnthropicInlineContent, m as reconcileAnthropicToolChoice, n as createCompactionCapture, o as applyAnthropicMessageStartUsage, p as projectAnthropicTools, r as isAnthropicReplayRejection, t as buildAnthropicReplayPlan, v as findActiveAnthropicToolTurnAssistantIndex, w as resolveAnthropicFallbackServingModelCost, y as ANTHROPIC_SERVER_SIDE_FALLBACKS } from "./anthropic-compaction-replay-nhKaCXu6.mjs";
|
|
15
|
+
import { S as quoteUnsafeIntegerLiterals, _ as transportAbortError, a as createWritableTransportEventStream, b as parseJsonObjectPreservingUnsafeIntegers, c as finalizeTransportStream, d as notifyProviderHttpMetadata, f as notifyProviderHttpResponse, g as sanitizeTransportPayloadText, h as sanitizeNonEmptyTransportPayloadText, i as createEmptyTransportUsage, l as mergeTransportHeaders, m as parseTerminalToolCallArguments, n as coerceTransportToolCallArguments, o as failTransportStream, p as notifyProviderStreamOpened, r as copyProviderAcceptanceObserver, s as finalizeTerminalToolCallArguments, t as assignTransportErrorDetails, u as mergeTransportMetadata, v as withProviderAcceptanceObserver, x as parseJsonPreservingUnsafeIntegers, y as withProviderResponseHook } from "./transport-stream-shared-ljShVIZB.mjs";
|
|
16
|
+
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-DUlGwRMz.mjs";
|
|
18
17
|
import { t as createDeferredEventBuffer } from "./deferred-event-buffer-DAvyP7qA.mjs";
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { B as buildResponsesInputMessage, C as summarizeResponsesTools, G as suppressOpenAIResponsesCompaction, H as createOpenAIResponsesAssistantOutput, I as createResponsesStreamWithEncryptedContentRetry, K as resolveReplayableResponsesMessageId, L as isInvalidEncryptedContentError, R as resolveAzureOpenAIApiVersion, S as summarizeResponsesPayload, U as buildOpenAIResponsesReasoningReplayMetadata, V as convertResponsesMessages, W as captureOpenAIResponsesCompaction, Y as normalizeOpenAIStrictToolParameters, Z as resolveOpenAIProjectedToolsStrictToolFlag, _ as safeDebugValue, b as summarizeOpenAITransportError, c as processResponsesStream, dt as resolveModelPayloadDebugMode, f as observeResponsesStream, ft as resolveModelSseDebugMode, g as normalizeResponsesFailedEvent, h as logResponsesFailedNoDetails, ht as quoteUnsafeIntegerLiterals, m as buildResponsesFailedNoDetailsObservation, mt as parseJsonPreservingUnsafeIntegers, n as applyResponsesServiceTierPricing, p as ResponsesStreamFailure, pt as parseJsonObjectPreservingUnsafeIntegers, q as findOpenAIStrictToolProjectionDiagnostics, ut as emitModelTransportDebug, v as stringifyRedactedEvent, x as summarizeResponsesFailedNoDetailsObservation, y as stringifyRedactedPayload, z as resolveNextResponsesEncryptedContentAttempt } from "./openai-responses-shared-DXIt3iY5.mjs";
|
|
22
|
-
import { a as createWritableTransportEventStream, c as mergeTransportHeaders, d as sanitizeTransportPayloadText, f as transportAbortError, i as createEmptyTransportUsage, l as mergeTransportMetadata, n as assignTransportErrorDetails, o as failTransportStream, p as withProviderResponseHook, r as coerceTransportToolCallArguments, s as finalizeTransportStream, u as sanitizeNonEmptyTransportPayloadText } from "./provider-transcript-transform-ePx-Bbfr.mjs";
|
|
23
|
-
import { a as isGoogleGemini3FlashModel, c as readResponseTextSnippet, d as resolveModelHeaderSentinels$1, f as resolveSecretSentinel, i as isCodeModeModelVisibleToolName, l as redactIdentifier, m as supportsModelTools, n as createAbortError$1, o as isGoogleGemini3ProModel, p as sha256Hex, r as estimateStringChars, s as parseRetryAfterSeconds, t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE } from "./transport-utils-DJqkxbhC.mjs";
|
|
18
|
+
import { r as parseStreamingJson, t as createToolArgumentPreviewSchedule } from "./json-parse-BuAJEbdW.mjs";
|
|
19
|
+
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
24
20
|
import { t as googleFlashSupportsMinimalThinking } from "./google-thinking-level-C-V3tecN.mjs";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import { i as
|
|
21
|
+
import { B as buildResponsesInputMessage, C as summarizeResponsesTools, G as suppressOpenAIResponsesCompaction, H as createOpenAIResponsesAssistantOutput, I as createResponsesStreamWithEncryptedContentRetry, J as resolveModelPayloadDebugMode, K as resolveReplayableResponsesMessageId, L as isInvalidEncryptedContentError, R as resolveAzureOpenAIApiVersion, S as summarizeResponsesPayload, U as buildOpenAIResponsesReasoningReplayMetadata, V as convertResponsesMessages, W as captureOpenAIResponsesCompaction, Y as resolveModelSseDebugMode, _ as safeDebugValue, b as summarizeOpenAITransportError, c as processResponsesStream, f as observeResponsesStream, g as normalizeResponsesFailedEvent, h as logResponsesFailedNoDetails, m as buildResponsesFailedNoDetailsObservation, n as applyResponsesServiceTierPricing, p as ResponsesStreamFailure, q as emitModelTransportDebug, v as stringifyRedactedEvent, x as summarizeResponsesFailedNoDetailsObservation, y as stringifyRedactedPayload, z as resolveNextResponsesEncryptedContentAttempt } from "./openai-responses-shared-DJThc6jW.mjs";
|
|
22
|
+
import { t as codeModeToolSurfaceObserver } from "./provider-options-AvldWZt8.mjs";
|
|
23
|
+
import { A as readOpenAICompletionsReasoningBatch, C as createOpenAIProviderAcceptanceHook, D as measureUtf8AppendBytes, E as log, M as resolvePromptCacheKey, N as throwIfModelStreamAborted, O as parseOpenAICompletionsUsage, S as createModelStreamCooperativeScheduler, T as isOpenAICompletionsThinkingEnabled, b as reconcileOpenAIResponsesToolChoice, j as resolveOpenAIClientBaseUrl, k as readOpenAICompletionsContentDeltas, r as normalizeOpenAIStrictToolParameters, v as projectOpenAITools, w as createOpenAIResponseHook, x as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, y as reconcileOpenAICompletionsToolChoice } from "./openai-tool-schema-ho-hIkQf.mjs";
|
|
24
|
+
import { i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-MK28puvq.mjs";
|
|
25
|
+
import { _ as isOpenAIGpt56Model, d as OpenAIResponsesWebSocketSafeRetryError, g as isOpenAIGpt55Model, h as isOpenAIGpt54MiniModel, 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, y as resolveOpenAIReasoningEffortForModel } from "./openai-responses-contracts-QUY12X0B.mjs";
|
|
26
|
+
import { i as resolveOpenAIResponsesServerCompactionPlan, n as resolveOpenAIResponsesCompactEndpointPlan, r as resolveOpenAIResponsesPayloadPolicy, t as applyOpenAIResponsesPayloadPolicy } from "./openai-responses-payload-policy-D8EdimYe.mjs";
|
|
29
27
|
import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
|
|
30
28
|
import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
|
|
31
29
|
import { randomUUID } from "node:crypto";
|
|
@@ -67,7 +65,7 @@ function isAnthropicOAuthToken(apiKey) {
|
|
|
67
65
|
}
|
|
68
66
|
function isDirectAnthropicModel(model) {
|
|
69
67
|
if (normalizeLowercaseStringOrEmpty(model.provider) !== "anthropic") return false;
|
|
70
|
-
const endpointClass = resolveProviderEndpoint(model
|
|
68
|
+
const endpointClass = resolveProviderEndpoint(model).endpointClass;
|
|
71
69
|
return endpointClass === "default" || endpointClass === "anthropic-public";
|
|
72
70
|
}
|
|
73
71
|
function isKimiAnthropicProvider(provider) {
|
|
@@ -82,7 +80,7 @@ function useAnthropicServerSideFallback(model) {
|
|
|
82
80
|
return (usesClaudeFable5MessagesContract(model) || resolveClaudeOpus5ModelIdentity(model) !== void 0) && isDirectAnthropicModel(model);
|
|
83
81
|
}
|
|
84
82
|
function supportsReasoningContentReplay(model) {
|
|
85
|
-
return resolveProviderEndpoint(model
|
|
83
|
+
return resolveProviderEndpoint(model).endpointClass === "xiaomi-native";
|
|
86
84
|
}
|
|
87
85
|
function buildAnthropicBetaHeader(model, betaFeatures, params) {
|
|
88
86
|
if (!isDirectAnthropicModel(model)) return;
|
|
@@ -304,7 +302,7 @@ function convertAnthropicTools(tools, isOAuthToken) {
|
|
|
304
302
|
};
|
|
305
303
|
}
|
|
306
304
|
function parseAnthropicToolCallArguments(inputJson) {
|
|
307
|
-
return parseJsonObjectPreservingUnsafeIntegers(inputJson) ?? parseStreamingJson(inputJson);
|
|
305
|
+
return coerceTransportToolCallArguments(parseJsonObjectPreservingUnsafeIntegers(inputJson) ?? parseStreamingJson(inputJson));
|
|
308
306
|
}
|
|
309
307
|
const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
|
|
310
308
|
/** Resolve the effective Anthropic API base URL from model or environment. */
|
|
@@ -407,7 +405,7 @@ async function* parseAnthropicSseBody(body, signal) {
|
|
|
407
405
|
}
|
|
408
406
|
function createAnthropicMessagesClient(params) {
|
|
409
407
|
const url = resolveAnthropicMessagesUrl(params.baseURL);
|
|
410
|
-
return { messages: { async
|
|
408
|
+
return { messages: { async stream(body, options) {
|
|
411
409
|
const headers = mergeTransportHeaders({
|
|
412
410
|
"content-type": "application/json",
|
|
413
411
|
"anthropic-version": "2023-06-01",
|
|
@@ -420,12 +418,10 @@ function createAnthropicMessagesClient(params) {
|
|
|
420
418
|
body: JSON.stringify(body),
|
|
421
419
|
signal: options?.signal
|
|
422
420
|
});
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
}
|
|
427
|
-
if (!response.body) return;
|
|
428
|
-
yield* parseAnthropicSseBody(response.body, options?.signal);
|
|
421
|
+
return {
|
|
422
|
+
response,
|
|
423
|
+
stream: response.body ? parseAnthropicSseBody(response.body, options?.signal) : []
|
|
424
|
+
};
|
|
429
425
|
} } };
|
|
430
426
|
}
|
|
431
427
|
function formatAnthropicMessagesHttpError(response, detail) {
|
|
@@ -536,7 +532,7 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
536
532
|
baseUrl: model.baseUrl,
|
|
537
533
|
cacheRetention: options?.cacheRetention,
|
|
538
534
|
enableCacheControl: true
|
|
539
|
-
});
|
|
535
|
+
}, model);
|
|
540
536
|
const cacheBreakpointOptOutMessageIndexes = /* @__PURE__ */ new Set();
|
|
541
537
|
const replayPlan = buildAnthropicReplayPlan(context.messages, model, {
|
|
542
538
|
enabled: !isOAuthToken && options?.anthropicServerCompaction === true,
|
|
@@ -620,7 +616,7 @@ function resolveAnthropicTransportOptions(model, options, apiKey) {
|
|
|
620
616
|
const reasoningModelMaxTokens = resolvePositiveAnthropicTokenLimit(model.maxTokens) ?? baseMaxTokens;
|
|
621
617
|
const mandatoryAdaptiveThinking = requiresClaudeAdaptiveThinking(model);
|
|
622
618
|
const reasoning = options?.reasoning === "off" && mandatoryAdaptiveThinking ? "low" : options?.reasoning;
|
|
623
|
-
const resolved = {
|
|
619
|
+
const resolved = copyProviderAcceptanceObserver(options, {
|
|
624
620
|
temperature: options?.temperature,
|
|
625
621
|
stop: options?.stop,
|
|
626
622
|
maxTokens: baseMaxTokens,
|
|
@@ -630,6 +626,7 @@ function resolveAnthropicTransportOptions(model, options, apiKey) {
|
|
|
630
626
|
sessionId: options?.sessionId,
|
|
631
627
|
headers: options?.headers,
|
|
632
628
|
onPayload: options?.onPayload,
|
|
629
|
+
onResponse: options?.onResponse,
|
|
633
630
|
maxRetryDelayMs: options?.maxRetryDelayMs,
|
|
634
631
|
metadata: options?.metadata,
|
|
635
632
|
interleavedThinking: options?.interleavedThinking,
|
|
@@ -638,7 +635,7 @@ function resolveAnthropicTransportOptions(model, options, apiKey) {
|
|
|
638
635
|
reasoning,
|
|
639
636
|
...options?.anthropicServerCompaction === true ? { anthropicServerCompaction: true } : {},
|
|
640
637
|
...options?.authProfileId ? { authProfileId: options.authProfileId } : {}
|
|
641
|
-
};
|
|
638
|
+
});
|
|
642
639
|
if (reasoning === "off") {
|
|
643
640
|
resolved.thinkingEnabled = false;
|
|
644
641
|
return resolved;
|
|
@@ -700,12 +697,23 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
700
697
|
const nextParams = await transportOptions.onPayload?.(params, model);
|
|
701
698
|
if (nextParams !== void 0) params = nextParams;
|
|
702
699
|
applyClaudeRequestContract(params, model);
|
|
703
|
-
const anthropicStream = client.messages.stream({
|
|
700
|
+
const { response, stream: anthropicStream } = await client.messages.stream({
|
|
704
701
|
...params,
|
|
705
702
|
stream: true
|
|
706
703
|
}, transportOptions.signal ? { signal: transportOptions.signal } : void 0);
|
|
704
|
+
await notifyProviderHttpResponse({
|
|
705
|
+
options: transportOptions,
|
|
706
|
+
response,
|
|
707
|
+
model
|
|
708
|
+
});
|
|
709
|
+
if (!response.ok) {
|
|
710
|
+
const detail = await readAnthropicMessagesErrorBodySnippet(response);
|
|
711
|
+
throw new Error(formatAnthropicMessagesHttpError(response, detail));
|
|
712
|
+
}
|
|
707
713
|
const blocks = output.content;
|
|
708
714
|
const blockIndexes = /* @__PURE__ */ new Map();
|
|
715
|
+
const toolArgumentPreviewSchedules = /* @__PURE__ */ new WeakMap();
|
|
716
|
+
const sealedToolCalls = [];
|
|
709
717
|
const compactionCapture = createCompactionCapture(output, model, transportOptions);
|
|
710
718
|
const pendingThinkingSignatures = /* @__PURE__ */ new Map();
|
|
711
719
|
const allowReasoningContentReplay = supportsReasoningContentReplay(model);
|
|
@@ -740,6 +748,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
740
748
|
partial: output
|
|
741
749
|
});
|
|
742
750
|
}
|
|
751
|
+
if (contentIndex === void 0) return false;
|
|
743
752
|
block.thinking += text;
|
|
744
753
|
block.thinkingSignature = "reasoning_content";
|
|
745
754
|
eventSink.push({
|
|
@@ -771,6 +780,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
771
780
|
partial: output
|
|
772
781
|
});
|
|
773
782
|
}
|
|
783
|
+
if (contentIndex === void 0) return false;
|
|
774
784
|
block.text += text;
|
|
775
785
|
eventSink.push({
|
|
776
786
|
type: "text_delta",
|
|
@@ -833,6 +843,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
833
843
|
const fallbackBoundary = refusalBuffer ? readAnthropicFallbackBoundary(contentBlock) : null;
|
|
834
844
|
if (fallbackBoundary) {
|
|
835
845
|
refusalBuffer?.discard();
|
|
846
|
+
sealedToolCalls.length = 0;
|
|
836
847
|
pendingTextEnds.length = 0;
|
|
837
848
|
blockIndexes.clear();
|
|
838
849
|
pendingThinkingSignatures.clear();
|
|
@@ -955,6 +966,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
955
966
|
};
|
|
956
967
|
output.content.push(block);
|
|
957
968
|
blockIndexes.set(index, output.content.length - 1);
|
|
969
|
+
toolArgumentPreviewSchedules.set(block, createToolArgumentPreviewSchedule());
|
|
958
970
|
eventSink.push({
|
|
959
971
|
type: "toolcall_start",
|
|
960
972
|
contentIndex: output.content.length - 1,
|
|
@@ -975,7 +987,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
975
987
|
let appendedContent = false;
|
|
976
988
|
if (!hasNativeAnthropicDelta && typeof delta?.content === "string" && delta.content.length > 0) {
|
|
977
989
|
const text = sanitizeTransportPayloadText(delta.content);
|
|
978
|
-
if (text.length > 0) if (block?.type === "text") {
|
|
990
|
+
if (text.length > 0) if (block?.type === "text" && index !== void 0) {
|
|
979
991
|
block.text += text;
|
|
980
992
|
eventSink.push({
|
|
981
993
|
type: "text_delta",
|
|
@@ -1003,6 +1015,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1003
1015
|
partial: output
|
|
1004
1016
|
});
|
|
1005
1017
|
}
|
|
1018
|
+
if (index === void 0) continue;
|
|
1006
1019
|
if (block?.type === "text" && delta?.type === "text_delta" && typeof delta.text === "string") {
|
|
1007
1020
|
block.text += delta.text;
|
|
1008
1021
|
eventSink.push({
|
|
@@ -1026,7 +1039,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1026
1039
|
if (block?.type === "toolCall" && delta?.type === "input_json_delta" && typeof delta.partial_json === "string") {
|
|
1027
1040
|
const partialJson = `${block.partialJson ?? ""}${delta.partial_json}`;
|
|
1028
1041
|
block.partialJson = partialJson;
|
|
1029
|
-
block.arguments = parseAnthropicToolCallArguments(partialJson);
|
|
1042
|
+
if (toolArgumentPreviewSchedules.get(block)?.(partialJson.length)) block.arguments = parseAnthropicToolCallArguments(partialJson);
|
|
1030
1043
|
eventSink.push({
|
|
1031
1044
|
type: "toolcall_delta",
|
|
1032
1045
|
contentIndex: index,
|
|
@@ -1080,12 +1093,9 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1080
1093
|
continue;
|
|
1081
1094
|
}
|
|
1082
1095
|
if (block.type === "toolCall") {
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
contentIndex: index,
|
|
1087
|
-
toolCall: block,
|
|
1088
|
-
partial: output
|
|
1096
|
+
sealedToolCalls.push({
|
|
1097
|
+
block,
|
|
1098
|
+
contentIndex: index
|
|
1089
1099
|
});
|
|
1090
1100
|
finishReasoningContentSidecars(event.index);
|
|
1091
1101
|
}
|
|
@@ -1105,6 +1115,17 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1105
1115
|
if (isDirectAnthropicModel(model) && !sawMessageStop) throw new Error("Anthropic stream ended before message_stop");
|
|
1106
1116
|
if (transportOptions.signal?.aborted) throw transportAbortError(transportOptions.signal);
|
|
1107
1117
|
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
|
|
1118
|
+
if ([...blockIndexes.values()].some((index) => blocks[index]?.type === "toolCall")) throw new Error("Provider completed stream with an incomplete tool call");
|
|
1119
|
+
finalizeTerminalToolCallArguments(sealedToolCalls.map(({ block }) => block), (block) => block.partialJson && block.partialJson.length > 0 ? block.partialJson : block.arguments);
|
|
1120
|
+
for (const sealed of sealedToolCalls) {
|
|
1121
|
+
delete sealed.block.partialJson;
|
|
1122
|
+
eventSink.push({
|
|
1123
|
+
type: "toolcall_end",
|
|
1124
|
+
contentIndex: sealed.contentIndex,
|
|
1125
|
+
toolCall: sealed.block,
|
|
1126
|
+
partial: output
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1108
1129
|
refusalBuffer?.flush();
|
|
1109
1130
|
if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
|
|
1110
1131
|
flushPendingTextEnds();
|
|
@@ -1116,7 +1137,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1116
1137
|
if (refusalBuffer) {
|
|
1117
1138
|
refusalBuffer.discard();
|
|
1118
1139
|
output.content = [];
|
|
1119
|
-
}
|
|
1140
|
+
} else output.content = output.content.filter((block) => block.type !== "toolCall");
|
|
1120
1141
|
if (usedCompactionReplay && isAnthropicReplayRejection(error)) suppressAnthropicCompaction(output, model, options);
|
|
1121
1142
|
failTransportStream({
|
|
1122
1143
|
stream,
|
|
@@ -1133,96 +1154,6 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1133
1154
|
};
|
|
1134
1155
|
}
|
|
1135
1156
|
//#endregion
|
|
1136
|
-
//#region packages/ai/src/transports/deepseek-text-filter.ts
|
|
1137
|
-
/**
|
|
1138
|
-
* DeepSeek DSML streaming text filter.
|
|
1139
|
-
* Removes provider-emitted DSML tool markup while buffering split tag prefixes
|
|
1140
|
-
* across streamed chunks.
|
|
1141
|
-
*/
|
|
1142
|
-
const DSML_KINDS = [
|
|
1143
|
-
"tool_use_error",
|
|
1144
|
-
"tool_calls",
|
|
1145
|
-
"tool_call",
|
|
1146
|
-
"function_calls"
|
|
1147
|
-
];
|
|
1148
|
-
const DSML_BARS = ["|", "|"];
|
|
1149
|
-
const DSML_OPEN_TOKENS = DSML_BARS.flatMap((bar) => DSML_KINDS.map((kind) => `<${bar}DSML${bar}${kind}>`));
|
|
1150
|
-
const DSML_CLOSE_TOKENS = DSML_BARS.flatMap((bar) => DSML_KINDS.map((kind) => `</${bar}DSML${bar}${kind}>`));
|
|
1151
|
-
const MAX_OPEN_TOKEN_LEN = Math.max(...DSML_OPEN_TOKENS.map((token) => token.length));
|
|
1152
|
-
const MAX_CLOSE_TOKEN_LEN = Math.max(...DSML_CLOSE_TOKENS.map((token) => token.length));
|
|
1153
|
-
/** Create an incremental text filter that strips DeepSeek DSML tool blocks. */
|
|
1154
|
-
function createDeepSeekTextFilter() {
|
|
1155
|
-
let buffer = "";
|
|
1156
|
-
let insideDsml = false;
|
|
1157
|
-
const consume = (final) => {
|
|
1158
|
-
const output = [];
|
|
1159
|
-
const emit = (text) => {
|
|
1160
|
-
if (text) output.push(text);
|
|
1161
|
-
};
|
|
1162
|
-
while (buffer) {
|
|
1163
|
-
if (insideDsml) {
|
|
1164
|
-
const close = findEarliestToken(buffer, DSML_CLOSE_TOKENS);
|
|
1165
|
-
if (close) {
|
|
1166
|
-
buffer = buffer.slice(close.index + close.token.length);
|
|
1167
|
-
insideDsml = false;
|
|
1168
|
-
continue;
|
|
1169
|
-
}
|
|
1170
|
-
const keep = final ? 0 : Math.min(buffer.length, MAX_CLOSE_TOKEN_LEN - 1);
|
|
1171
|
-
buffer = buffer.slice(buffer.length - keep);
|
|
1172
|
-
if (final) insideDsml = false;
|
|
1173
|
-
return output;
|
|
1174
|
-
}
|
|
1175
|
-
const open = findEarliestToken(buffer, DSML_OPEN_TOKENS);
|
|
1176
|
-
if (open) {
|
|
1177
|
-
emit(buffer.slice(0, open.index));
|
|
1178
|
-
buffer = buffer.slice(open.index + open.token.length);
|
|
1179
|
-
insideDsml = true;
|
|
1180
|
-
continue;
|
|
1181
|
-
}
|
|
1182
|
-
if (final) {
|
|
1183
|
-
emit(buffer);
|
|
1184
|
-
buffer = "";
|
|
1185
|
-
return output;
|
|
1186
|
-
}
|
|
1187
|
-
const keep = longestDsmlOpenPrefixSuffixLength(buffer);
|
|
1188
|
-
const emitLength = buffer.length - keep;
|
|
1189
|
-
if (emitLength <= 0) return output;
|
|
1190
|
-
emit(buffer.slice(0, emitLength));
|
|
1191
|
-
buffer = buffer.slice(emitLength);
|
|
1192
|
-
return output;
|
|
1193
|
-
}
|
|
1194
|
-
return output;
|
|
1195
|
-
};
|
|
1196
|
-
return {
|
|
1197
|
-
push(chunk) {
|
|
1198
|
-
buffer += chunk;
|
|
1199
|
-
return consume(false);
|
|
1200
|
-
},
|
|
1201
|
-
flush() {
|
|
1202
|
-
return consume(true);
|
|
1203
|
-
}
|
|
1204
|
-
};
|
|
1205
|
-
}
|
|
1206
|
-
function findEarliestToken(text, tokens) {
|
|
1207
|
-
let best = null;
|
|
1208
|
-
for (const token of tokens) {
|
|
1209
|
-
const index = text.indexOf(token);
|
|
1210
|
-
if (index !== -1 && (!best || index < best.index)) best = {
|
|
1211
|
-
index,
|
|
1212
|
-
token
|
|
1213
|
-
};
|
|
1214
|
-
}
|
|
1215
|
-
return best;
|
|
1216
|
-
}
|
|
1217
|
-
function longestDsmlOpenPrefixSuffixLength(text) {
|
|
1218
|
-
const maxLength = Math.min(text.length, MAX_OPEN_TOKEN_LEN - 1);
|
|
1219
|
-
for (let length = maxLength; length > 0; length--) {
|
|
1220
|
-
const suffix = text.slice(text.length - length);
|
|
1221
|
-
if (DSML_OPEN_TOKENS.some((token) => token.startsWith(suffix))) return length;
|
|
1222
|
-
}
|
|
1223
|
-
return 0;
|
|
1224
|
-
}
|
|
1225
|
-
//#endregion
|
|
1226
1157
|
//#region packages/ai/src/transports/model-max-tokens-params.ts
|
|
1227
1158
|
/**
|
|
1228
1159
|
* Max-token parameter normalization across provider/native naming variants.
|
|
@@ -1521,202 +1452,10 @@ function applyCompletionsReplay(outgoingMessages, context, model, compat) {
|
|
|
1521
1452
|
});
|
|
1522
1453
|
}
|
|
1523
1454
|
//#endregion
|
|
1524
|
-
//#region packages/ai/src/transports/openai-transport-params.ts
|
|
1525
|
-
const MAX_OPENAI_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS = 256;
|
|
1526
|
-
const OPENAI_CODEX_RESPONSES_PROVIDERS = /* @__PURE__ */ new Set(["openai"]);
|
|
1527
|
-
const loggedOpenAIStrictToolDowngradeDiagnosticKeys = /* @__PURE__ */ new Set();
|
|
1528
|
-
function readToolPayloadField(record, field) {
|
|
1529
|
-
try {
|
|
1530
|
-
return Object.hasOwn(record, field) ? record[field] : void 0;
|
|
1531
|
-
} catch {
|
|
1532
|
-
return;
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
function readCodeModePayloadToolName(tool) {
|
|
1536
|
-
if (!isRecord(tool)) return;
|
|
1537
|
-
const name = readToolPayloadField(tool, "name");
|
|
1538
|
-
if (typeof name === "string") return name;
|
|
1539
|
-
const fn = readToolPayloadField(tool, "function");
|
|
1540
|
-
if (!isRecord(fn)) return;
|
|
1541
|
-
const fnName = readToolPayloadField(fn, "name");
|
|
1542
|
-
return typeof fnName === "string" ? fnName : void 0;
|
|
1543
|
-
}
|
|
1544
|
-
function readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes) {
|
|
1545
|
-
if (!isRecord(tool)) return;
|
|
1546
|
-
const type = readToolPayloadField(tool, "type");
|
|
1547
|
-
if (typeof type === "string" && allowedHostedToolTypes?.has(type)) {
|
|
1548
|
-
try {
|
|
1549
|
-
if (Object.hasOwn(tool, "name") || Object.hasOwn(tool, "function") || Object.hasOwn(tool, "functionDeclarations") || Object.hasOwn(tool, "function_declarations")) return false;
|
|
1550
|
-
} catch {
|
|
1551
|
-
return false;
|
|
1552
|
-
}
|
|
1553
|
-
return `hosted:${type}`;
|
|
1554
|
-
}
|
|
1555
|
-
const name = readCodeModePayloadToolName(tool);
|
|
1556
|
-
return typeof name === "string" && isCodeModeModelVisibleToolName(name, visibleToolNames) ? `client:${name}` : void 0;
|
|
1557
|
-
}
|
|
1558
|
-
function filterCodeModePayloadTools(payload, visibleToolNames, allowedHostedToolTypes) {
|
|
1559
|
-
if (!isRecord(payload)) return;
|
|
1560
|
-
const tools = readToolPayloadField(payload, "tools");
|
|
1561
|
-
if (!Array.isArray(tools)) return;
|
|
1562
|
-
payload.tools = tools.flatMap((tool) => {
|
|
1563
|
-
const identity = readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes);
|
|
1564
|
-
if (identity) return [tool];
|
|
1565
|
-
if (identity === false) return [];
|
|
1566
|
-
if (!isRecord(tool)) return [];
|
|
1567
|
-
const filteredGroups = {};
|
|
1568
|
-
for (const key of ["functionDeclarations", "function_declarations"]) {
|
|
1569
|
-
const declarations = readToolPayloadField(tool, key);
|
|
1570
|
-
if (!Array.isArray(declarations)) continue;
|
|
1571
|
-
const filtered = declarations.filter((declaration) => {
|
|
1572
|
-
const declarationName = readCodeModePayloadToolName(declaration);
|
|
1573
|
-
return typeof declarationName === "string" && isCodeModeModelVisibleToolName(declarationName, visibleToolNames);
|
|
1574
|
-
});
|
|
1575
|
-
if (filtered.length > 0) filteredGroups[key] = filtered;
|
|
1576
|
-
}
|
|
1577
|
-
return Object.keys(filteredGroups).length > 0 ? [filteredGroups] : [];
|
|
1578
|
-
});
|
|
1579
|
-
}
|
|
1580
|
-
function resolveCodeModeResponsesVisibleToolNames(context) {
|
|
1581
|
-
return new Set((context.tools ?? []).map(readCodeModePayloadToolName).filter((name) => typeof name === "string"));
|
|
1582
|
-
}
|
|
1583
|
-
function enforceCodeModeResponsesToolSurface(payload, visibleToolNames, allowedHostedToolTypes) {
|
|
1584
|
-
if (!isRecord(payload)) return;
|
|
1585
|
-
const tools = readToolPayloadField(payload, "tools");
|
|
1586
|
-
if (!Array.isArray(tools)) return;
|
|
1587
|
-
payload.tools = tools.filter((tool) => Boolean(readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes)));
|
|
1588
|
-
}
|
|
1589
|
-
function assertCodeModeResponsesToolSurface(payload, visibleToolNames, allowedHostedToolTypes) {
|
|
1590
|
-
const tools = isRecord(payload) ? readToolPayloadField(payload, "tools") : void 0;
|
|
1591
|
-
if (!Array.isArray(tools)) throw new Error("Code mode payload tool surface violation: expected exec,wait; got no tools");
|
|
1592
|
-
const identities = tools.map((tool) => readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes));
|
|
1593
|
-
const names = identities.flatMap((identity) => typeof identity === "string" && identity.startsWith("client:") ? [identity.slice(7)] : []).toSorted((left, right) => left.localeCompare(right));
|
|
1594
|
-
if (names.length >= 2 && identities.every((identity) => typeof identity === "string") && new Set(identities).size === identities.length && names.includes("exec") && names.includes("wait")) return;
|
|
1595
|
-
throw new Error(`Code mode payload tool surface violation: expected exec,wait plus direct-only tools; got ${names.length > 0 ? names.join(",") : "none"}`);
|
|
1596
|
-
}
|
|
1597
|
-
function buildOpenAIStrictToolDowngradeDiagnosticKey(diagnostics, context) {
|
|
1598
|
-
return sha256Hex(JSON.stringify({
|
|
1599
|
-
transport: context.transport,
|
|
1600
|
-
provider: context.model.provider ?? null,
|
|
1601
|
-
model: context.model.id ?? null,
|
|
1602
|
-
diagnostics: diagnostics.map((entry) => ({
|
|
1603
|
-
toolIndex: entry.toolIndex,
|
|
1604
|
-
toolName: entry.toolName ?? null,
|
|
1605
|
-
violations: entry.violations
|
|
1606
|
-
}))
|
|
1607
|
-
}));
|
|
1608
|
-
}
|
|
1609
|
-
function shouldLogOpenAIStrictToolDowngradeDiagnostic(diagnostics, context) {
|
|
1610
|
-
const key = buildOpenAIStrictToolDowngradeDiagnosticKey(diagnostics, context);
|
|
1611
|
-
if (loggedOpenAIStrictToolDowngradeDiagnosticKeys.has(key)) return false;
|
|
1612
|
-
if (loggedOpenAIStrictToolDowngradeDiagnosticKeys.size >= MAX_OPENAI_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS) loggedOpenAIStrictToolDowngradeDiagnosticKeys.clear();
|
|
1613
|
-
loggedOpenAIStrictToolDowngradeDiagnosticKeys.add(key);
|
|
1614
|
-
return true;
|
|
1615
|
-
}
|
|
1616
|
-
function resolveOpenAIStrictToolFlagWithDiagnostics(projection, strictSetting, context) {
|
|
1617
|
-
const strict = resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
|
|
1618
|
-
if (strictSetting === true && strict === false) {
|
|
1619
|
-
const diagnostics = findOpenAIStrictToolProjectionDiagnostics(projection);
|
|
1620
|
-
getAiTransportHost().logDebug("openai-transport", () => {
|
|
1621
|
-
if (!shouldLogOpenAIStrictToolDowngradeDiagnostic(diagnostics, context)) return null;
|
|
1622
|
-
const sample = diagnostics.slice(0, 5).map((entry) => ({
|
|
1623
|
-
tool: entry.toolName ?? `tool[${entry.toolIndex}]`,
|
|
1624
|
-
violations: entry.violations.slice(0, 8)
|
|
1625
|
-
}));
|
|
1626
|
-
return {
|
|
1627
|
-
message: `OpenAI ${context.transport} tool schema strict mode downgraded to strict=false for ${context.model.provider ?? "unknown"}/${context.model.id ?? "unknown"} because ${diagnostics.length} tool schema(s) are not strict-compatible`,
|
|
1628
|
-
data: {
|
|
1629
|
-
transport: context.transport,
|
|
1630
|
-
provider: context.model.provider,
|
|
1631
|
-
model: context.model.id,
|
|
1632
|
-
incompatibleToolCount: diagnostics.length,
|
|
1633
|
-
sample
|
|
1634
|
-
}
|
|
1635
|
-
};
|
|
1636
|
-
});
|
|
1637
|
-
}
|
|
1638
|
-
return strict;
|
|
1639
|
-
}
|
|
1640
|
-
function isOpenAICodexResponsesModel(model) {
|
|
1641
|
-
return OPENAI_CODEX_RESPONSES_PROVIDERS.has(model.provider) && (model.api === "openai-chatgpt-responses" || model.api === "openclaw-openai-chatgpt-responses-transport");
|
|
1642
|
-
}
|
|
1643
|
-
function isNativeOpenAICodexResponsesBaseUrl(baseUrl) {
|
|
1644
|
-
const trimmed = typeof baseUrl === "string" ? baseUrl.trim() : "";
|
|
1645
|
-
if (!trimmed) return false;
|
|
1646
|
-
try {
|
|
1647
|
-
const url = new URL(trimmed);
|
|
1648
|
-
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
1649
|
-
if (url.hostname.toLowerCase() !== "chatgpt.com") return false;
|
|
1650
|
-
const pathname = url.pathname.replace(/\/+$/u, "").toLowerCase();
|
|
1651
|
-
return [
|
|
1652
|
-
"/backend-api",
|
|
1653
|
-
"/backend-api/v1",
|
|
1654
|
-
"/backend-api/codex",
|
|
1655
|
-
"/backend-api/codex/v1"
|
|
1656
|
-
].includes(pathname);
|
|
1657
|
-
} catch {
|
|
1658
|
-
return false;
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
function usesNativeOpenAICodexResponsesBackend(model) {
|
|
1662
|
-
return isOpenAICodexResponsesModel(model) && isNativeOpenAICodexResponsesBaseUrl(model.baseUrl);
|
|
1663
|
-
}
|
|
1664
|
-
function buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId) {
|
|
1665
|
-
const providerHeaders = { ...model.headers };
|
|
1666
|
-
if (model.provider === "github-copilot") Object.assign(providerHeaders, getAiTransportHost().buildCopilotDynamicHeaders(context.messages));
|
|
1667
|
-
const callerHeaders = {
|
|
1668
|
-
...optionHeaders,
|
|
1669
|
-
...turnHeaders
|
|
1670
|
-
};
|
|
1671
|
-
const resolvedHeaders = resolveProviderRequestPolicyConfig({
|
|
1672
|
-
provider: model.provider,
|
|
1673
|
-
api: model.api,
|
|
1674
|
-
baseUrl: model.baseUrl,
|
|
1675
|
-
capability: "llm",
|
|
1676
|
-
transport: "stream",
|
|
1677
|
-
providerHeaders,
|
|
1678
|
-
callerHeaders: Object.keys(callerHeaders).length > 0 ? callerHeaders : void 0,
|
|
1679
|
-
precedence: "caller-wins"
|
|
1680
|
-
}).headers ?? {};
|
|
1681
|
-
if (sessionId && !Object.keys(resolvedHeaders).some((key) => normalizeLowercaseStringOrEmpty(key) === "session_id") && usesNativeOpenAICodexResponsesBackend(model)) resolvedHeaders.session_id = clampOpenAIPromptCacheKey(sessionId) ?? sessionId;
|
|
1682
|
-
return resolvedHeaders;
|
|
1683
|
-
}
|
|
1684
|
-
function resolveOpenAISdkTimeoutMs(model, timeoutMs) {
|
|
1685
|
-
return resolveModelRequestTimeoutMs(model, timeoutMs);
|
|
1686
|
-
}
|
|
1687
|
-
function buildOpenAISdkClientOptions(model) {
|
|
1688
|
-
const timeout = resolveOpenAISdkTimeoutMs(model);
|
|
1689
|
-
return timeout === void 0 ? {} : { timeout };
|
|
1690
|
-
}
|
|
1691
|
-
function buildOpenAISdkRequestOptions(model, signal, options) {
|
|
1692
|
-
const timeout = resolveOpenAISdkTimeoutMs(model, options?.timeoutMs);
|
|
1693
|
-
const headers = options?.stream === true && usesNativeOpenAICodexResponsesBackend(model) ? { Accept: "text/event-stream" } : void 0;
|
|
1694
|
-
if (timeout === void 0 && options?.maxRetries === void 0 && !signal && !headers) return;
|
|
1695
|
-
return {
|
|
1696
|
-
...headers ? { headers } : {},
|
|
1697
|
-
...signal ? { signal } : {},
|
|
1698
|
-
...timeout !== void 0 ? { timeout } : {},
|
|
1699
|
-
...options?.maxRetries !== void 0 ? { maxRetries: options.maxRetries } : {}
|
|
1700
|
-
};
|
|
1701
|
-
}
|
|
1702
|
-
function getCompat(model) {
|
|
1703
|
-
const resolved = resolveOpenAICompletionsCompat(model);
|
|
1704
|
-
const compat = model.compat ?? {};
|
|
1705
|
-
return {
|
|
1706
|
-
...resolved,
|
|
1707
|
-
cacheControlFormat: resolved.cacheControlFormat,
|
|
1708
|
-
reasoningEffortMap: resolveOpenAIReasoningEffortMap(model, {}),
|
|
1709
|
-
openRouterRouting: resolved.openRouterRouting ?? {},
|
|
1710
|
-
vercelGatewayRouting: resolved.vercelGatewayRouting,
|
|
1711
|
-
requiresStringContent: compat.requiresStringContent ?? false,
|
|
1712
|
-
strictMessageKeys: compat.strictMessageKeys === true
|
|
1713
|
-
};
|
|
1714
|
-
}
|
|
1715
|
-
//#endregion
|
|
1716
1455
|
//#region packages/ai/src/transports/openai-completions-params.ts
|
|
1717
1456
|
function isKnownOpenAICompletionsEndpoint(model) {
|
|
1718
1457
|
if (!model.baseUrl.trim()) return true;
|
|
1719
|
-
const endpointClass = resolveProviderEndpoint(model
|
|
1458
|
+
const endpointClass = resolveProviderEndpoint(model).endpointClass;
|
|
1720
1459
|
if (endpointClass === "openai-public" || endpointClass === "azure-openai") return true;
|
|
1721
1460
|
try {
|
|
1722
1461
|
return isAzureOpenAICompatibleHost(new URL(model.baseUrl).hostname.toLowerCase());
|
|
@@ -1724,7 +1463,7 @@ function isKnownOpenAICompletionsEndpoint(model) {
|
|
|
1724
1463
|
return false;
|
|
1725
1464
|
}
|
|
1726
1465
|
}
|
|
1727
|
-
function resolveOpenAICompletionsReasoningEffort
|
|
1466
|
+
function resolveOpenAICompletionsReasoningEffort(options) {
|
|
1728
1467
|
return options?.reasoningEffort ?? options?.reasoning ?? "high";
|
|
1729
1468
|
}
|
|
1730
1469
|
function resolveOpenAICompletionsMaxTokens(model, options) {
|
|
@@ -1923,7 +1662,7 @@ function buildOpenAICompletionsParams(model, context, options) {
|
|
|
1923
1662
|
if (clampedMaxTokens) if (compat.maxTokensField === "max_tokens") params.max_tokens = clampedMaxTokens;
|
|
1924
1663
|
else params.max_completion_tokens = clampedMaxTokens;
|
|
1925
1664
|
}
|
|
1926
|
-
const completionsReasoningEffort = resolveOpenAICompletionsReasoningEffort
|
|
1665
|
+
const completionsReasoningEffort = resolveOpenAICompletionsReasoningEffort(options);
|
|
1927
1666
|
const resolvedCompletionsReasoningEffort = completionsReasoningEffort ? resolveOpenAIReasoningEffortForModel({
|
|
1928
1667
|
model,
|
|
1929
1668
|
effort: completionsReasoningEffort,
|
|
@@ -1949,713 +1688,6 @@ function buildOpenAICompletionsParams(model, context, options) {
|
|
|
1949
1688
|
return params;
|
|
1950
1689
|
}
|
|
1951
1690
|
//#endregion
|
|
1952
|
-
//#region packages/ai/src/transports/openai-completions-dsml.ts
|
|
1953
|
-
const DEEPSEEK_DSML_BARS = ["|", "|"];
|
|
1954
|
-
const DEEPSEEK_DSML_TOOL_KINDS = [
|
|
1955
|
-
"tool_calls",
|
|
1956
|
-
"tool_call",
|
|
1957
|
-
"function_calls"
|
|
1958
|
-
];
|
|
1959
|
-
const DEEPSEEK_DSML_TOOL_OPEN_TOKENS = DEEPSEEK_DSML_BARS.flatMap((bar) => DEEPSEEK_DSML_TOOL_KINDS.map((kind) => `<${bar}DSML${bar}${kind}>`));
|
|
1960
|
-
const DEEPSEEK_DSML_TOOL_CLOSE_TOKENS = DEEPSEEK_DSML_BARS.flatMap((bar) => DEEPSEEK_DSML_TOOL_KINDS.map((kind) => `</${bar}DSML${bar}${kind}>`));
|
|
1961
|
-
const DEEPSEEK_DSML_INVOKE_OPEN_PREFIXES = DEEPSEEK_DSML_BARS.map((bar) => `<${bar}DSML${bar}invoke`);
|
|
1962
|
-
const DEEPSEEK_DSML_INVOKE_CLOSE_TOKENS = DEEPSEEK_DSML_BARS.map((bar) => `</${bar}DSML${bar}invoke>`);
|
|
1963
|
-
const DEEPSEEK_DSML_TOOL_MAX_OPEN_TOKEN_LEN = Math.max(...DEEPSEEK_DSML_TOOL_OPEN_TOKENS.map((token) => token.length));
|
|
1964
|
-
const DEEPSEEK_DSML_RECOVERY_MAX_BOUNDARY_LEN = Math.max(...DEEPSEEK_DSML_TOOL_OPEN_TOKENS.map((token) => token.length), ...DEEPSEEK_DSML_TOOL_CLOSE_TOKENS.map((token) => token.length), ...DEEPSEEK_DSML_INVOKE_OPEN_PREFIXES.map((token) => token.length), ...DEEPSEEK_DSML_INVOKE_CLOSE_TOKENS.map((token) => token.length));
|
|
1965
|
-
const MAX_DSML_RECOVERY_BUFFER_BYTES = 256e3;
|
|
1966
|
-
const DEEPSEEK_DSML_SCAN_BATCH_CHARS = 64 * 1024;
|
|
1967
|
-
function createDsmlRecoverer() {
|
|
1968
|
-
let buffer = "";
|
|
1969
|
-
let bufferBytes = 0;
|
|
1970
|
-
let bufferEndsWithHighSurrogate = false;
|
|
1971
|
-
let pendingScanChars = 0;
|
|
1972
|
-
let activeOpenToken = null;
|
|
1973
|
-
let blockScanState = {
|
|
1974
|
-
offset: 0,
|
|
1975
|
-
mode: "outer",
|
|
1976
|
-
invokeOpenStart: -1
|
|
1977
|
-
};
|
|
1978
|
-
const resetBlockScan = () => {
|
|
1979
|
-
activeOpenToken = null;
|
|
1980
|
-
pendingScanChars = 0;
|
|
1981
|
-
blockScanState = {
|
|
1982
|
-
offset: 0,
|
|
1983
|
-
mode: "outer",
|
|
1984
|
-
invokeOpenStart: -1
|
|
1985
|
-
};
|
|
1986
|
-
};
|
|
1987
|
-
const consume = (final) => {
|
|
1988
|
-
const output = [];
|
|
1989
|
-
while (buffer) {
|
|
1990
|
-
const open = activeOpenToken ? {
|
|
1991
|
-
index: 0,
|
|
1992
|
-
token: activeOpenToken
|
|
1993
|
-
} : findEarliestStringToken(buffer, DEEPSEEK_DSML_TOOL_OPEN_TOKENS);
|
|
1994
|
-
if (!open) {
|
|
1995
|
-
resetBlockScan();
|
|
1996
|
-
if (final) {
|
|
1997
|
-
output.push({
|
|
1998
|
-
kind: "text",
|
|
1999
|
-
text: buffer
|
|
2000
|
-
});
|
|
2001
|
-
buffer = "";
|
|
2002
|
-
bufferBytes = 0;
|
|
2003
|
-
bufferEndsWithHighSurrogate = false;
|
|
2004
|
-
return output;
|
|
2005
|
-
}
|
|
2006
|
-
const keep = longestDeepSeekDsmlToolOpenPrefixSuffixLength(buffer);
|
|
2007
|
-
const emitLength = buffer.length - keep;
|
|
2008
|
-
if (emitLength > 0) {
|
|
2009
|
-
const emitted = buffer.slice(0, emitLength);
|
|
2010
|
-
output.push({
|
|
2011
|
-
kind: "text",
|
|
2012
|
-
text: emitted
|
|
2013
|
-
});
|
|
2014
|
-
bufferBytes -= Buffer.byteLength(emitted, "utf8");
|
|
2015
|
-
buffer = buffer.slice(emitted.length);
|
|
2016
|
-
if (!buffer) bufferEndsWithHighSurrogate = false;
|
|
2017
|
-
}
|
|
2018
|
-
return output;
|
|
2019
|
-
}
|
|
2020
|
-
if (open.index > 0) {
|
|
2021
|
-
const prefix = buffer.slice(0, open.index);
|
|
2022
|
-
output.push({
|
|
2023
|
-
kind: "text",
|
|
2024
|
-
text: prefix
|
|
2025
|
-
});
|
|
2026
|
-
bufferBytes -= Buffer.byteLength(prefix, "utf8");
|
|
2027
|
-
buffer = buffer.slice(prefix.length);
|
|
2028
|
-
resetBlockScan();
|
|
2029
|
-
}
|
|
2030
|
-
activeOpenToken = open.token;
|
|
2031
|
-
if (blockScanState.offset === 0) blockScanState.offset = open.token.length;
|
|
2032
|
-
const blockScan = scanDeepSeekDsmlToolBlock(buffer, open.token.replace("<", "</"), open.token.length, blockScanState);
|
|
2033
|
-
if (blockScan.kind === "nested-open") throw new Error("Nested DeepSeek DSML recovery wrappers are not supported");
|
|
2034
|
-
const close = blockScan.kind === "close" ? blockScan : null;
|
|
2035
|
-
if (!close) {
|
|
2036
|
-
if (final) {
|
|
2037
|
-
output.push({
|
|
2038
|
-
kind: "text",
|
|
2039
|
-
text: buffer
|
|
2040
|
-
});
|
|
2041
|
-
buffer = "";
|
|
2042
|
-
bufferBytes = 0;
|
|
2043
|
-
bufferEndsWithHighSurrogate = false;
|
|
2044
|
-
return output;
|
|
2045
|
-
}
|
|
2046
|
-
if (bufferBytes > MAX_DSML_RECOVERY_BUFFER_BYTES) throw new Error("Exceeded DeepSeek DSML recovery buffer limit");
|
|
2047
|
-
return output;
|
|
2048
|
-
}
|
|
2049
|
-
resetBlockScan();
|
|
2050
|
-
const body = buffer.slice(open.token.length, close.index);
|
|
2051
|
-
const blockText = buffer.slice(0, close.index + close.token.length);
|
|
2052
|
-
if (Buffer.byteLength(blockText, "utf8") > MAX_DSML_RECOVERY_BUFFER_BYTES) throw new Error("Exceeded DeepSeek DSML recovery buffer limit");
|
|
2053
|
-
const recoveredToolCalls = parseDeepSeekDsmlToolCallBlock(body);
|
|
2054
|
-
if (recoveredToolCalls.length > 0) output.push(...recoveredToolCalls);
|
|
2055
|
-
else output.push({
|
|
2056
|
-
kind: "text",
|
|
2057
|
-
text: blockText
|
|
2058
|
-
});
|
|
2059
|
-
bufferBytes -= Buffer.byteLength(blockText, "utf8");
|
|
2060
|
-
buffer = buffer.slice(blockText.length);
|
|
2061
|
-
if (!buffer) bufferEndsWithHighSurrogate = false;
|
|
2062
|
-
}
|
|
2063
|
-
return output;
|
|
2064
|
-
};
|
|
2065
|
-
return {
|
|
2066
|
-
push(chunk) {
|
|
2067
|
-
const append = measureUtf8AppendBytes(bufferEndsWithHighSurrogate, chunk);
|
|
2068
|
-
bufferBytes += append.bytes;
|
|
2069
|
-
bufferEndsWithHighSurrogate = append.endsWithHighSurrogate;
|
|
2070
|
-
buffer += chunk;
|
|
2071
|
-
pendingScanChars += chunk.length;
|
|
2072
|
-
if (activeOpenToken && pendingScanChars < DEEPSEEK_DSML_SCAN_BATCH_CHARS && !chunk.includes("<") && !chunk.includes(">") && bufferBytes <= MAX_DSML_RECOVERY_BUFFER_BYTES) return [];
|
|
2073
|
-
pendingScanChars = 0;
|
|
2074
|
-
return consume(false);
|
|
2075
|
-
},
|
|
2076
|
-
flush() {
|
|
2077
|
-
return consume(true);
|
|
2078
|
-
}
|
|
2079
|
-
};
|
|
2080
|
-
}
|
|
2081
|
-
function parseDeepSeekDsmlToolCallBlock(body) {
|
|
2082
|
-
const toolCalls = [];
|
|
2083
|
-
const invokeOpenRegex = /<[||]DSML[||]invoke\b([^<>]*)>/g;
|
|
2084
|
-
let openMatch;
|
|
2085
|
-
while ((openMatch = invokeOpenRegex.exec(body)) !== null) {
|
|
2086
|
-
const invokeBodyStart = openMatch.index + openMatch[0].length;
|
|
2087
|
-
const invokeClose = findEarliestStringToken(body.slice(invokeBodyStart), ["</|DSML|invoke>", "</|DSML|invoke>"]);
|
|
2088
|
-
if (!invokeClose) break;
|
|
2089
|
-
const invokeBody = body.slice(invokeBodyStart, invokeBodyStart + invokeClose.index);
|
|
2090
|
-
invokeOpenRegex.lastIndex = invokeBodyStart + invokeClose.index + invokeClose.token.length;
|
|
2091
|
-
const invokeName = parseXmlAttribute(openMatch[1] ?? "", "name");
|
|
2092
|
-
if (!invokeName) continue;
|
|
2093
|
-
const parsedArguments = parseDeepSeekDsmlInvokeArguments(invokeBody);
|
|
2094
|
-
if (!parsedArguments) continue;
|
|
2095
|
-
toolCalls.push({
|
|
2096
|
-
kind: "toolCall",
|
|
2097
|
-
name: invokeName,
|
|
2098
|
-
arguments: parsedArguments,
|
|
2099
|
-
partialArgs: JSON.stringify(parsedArguments)
|
|
2100
|
-
});
|
|
2101
|
-
}
|
|
2102
|
-
return toolCalls;
|
|
2103
|
-
}
|
|
2104
|
-
function parseDeepSeekDsmlInvokeArguments(body) {
|
|
2105
|
-
const args = {};
|
|
2106
|
-
const parameterRegex = /<[||]DSML[||]parameter\b([^>]*)>([\s\S]*?)<\/[||]DSML[||]parameter>/g;
|
|
2107
|
-
let parameterMatch;
|
|
2108
|
-
while ((parameterMatch = parameterRegex.exec(body)) !== null) {
|
|
2109
|
-
const name = parseXmlAttribute(parameterMatch[1] ?? "", "name");
|
|
2110
|
-
if (!name) continue;
|
|
2111
|
-
const rawValue = parameterMatch[2] ?? "";
|
|
2112
|
-
if (rawValue.length === 0) continue;
|
|
2113
|
-
args[name] = decodeDeepSeekDsmlText(rawValue);
|
|
2114
|
-
}
|
|
2115
|
-
if (Object.keys(args).length > 0) return args;
|
|
2116
|
-
const trimmed = body.trim();
|
|
2117
|
-
if (!trimmed.startsWith("{")) return null;
|
|
2118
|
-
try {
|
|
2119
|
-
const parsed = JSON.parse(trimmed);
|
|
2120
|
-
if (isRecord(parsed) && Object.keys(parsed).length > 0) return parsed;
|
|
2121
|
-
} catch {
|
|
2122
|
-
return null;
|
|
2123
|
-
}
|
|
2124
|
-
return null;
|
|
2125
|
-
}
|
|
2126
|
-
const xmlAttributeRegexCache = /* @__PURE__ */ new Map();
|
|
2127
|
-
function xmlAttributeRegex(name) {
|
|
2128
|
-
const cached = xmlAttributeRegexCache.get(name);
|
|
2129
|
-
if (cached) return cached;
|
|
2130
|
-
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2131
|
-
const pattern = new RegExp(`\\b${escaped}=("([^"]*)"|'([^']*)'|([^\\s>]+))`);
|
|
2132
|
-
xmlAttributeRegexCache.set(name, pattern);
|
|
2133
|
-
return pattern;
|
|
2134
|
-
}
|
|
2135
|
-
function parseXmlAttribute(attributes, name) {
|
|
2136
|
-
const match = xmlAttributeRegex(name).exec(attributes);
|
|
2137
|
-
const value = match?.[2] ?? match?.[3] ?? match?.[4];
|
|
2138
|
-
return value ? decodeDeepSeekDsmlText(value) : null;
|
|
2139
|
-
}
|
|
2140
|
-
function decodeDeepSeekDsmlText(value) {
|
|
2141
|
-
return value.replaceAll(""", "\"").replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">").replaceAll("&", "&");
|
|
2142
|
-
}
|
|
2143
|
-
function findEarliestStringToken(text, tokens, fromIndex = 0) {
|
|
2144
|
-
let best = null;
|
|
2145
|
-
for (const token of tokens) {
|
|
2146
|
-
const index = text.indexOf(token, fromIndex);
|
|
2147
|
-
if (index !== -1 && (!best || index < best.index)) best = {
|
|
2148
|
-
index,
|
|
2149
|
-
token
|
|
2150
|
-
};
|
|
2151
|
-
}
|
|
2152
|
-
return best;
|
|
2153
|
-
}
|
|
2154
|
-
function scanDeepSeekDsmlToolBlock(text, closeToken, contentStartIndex, state) {
|
|
2155
|
-
while (state.offset < text.length) {
|
|
2156
|
-
if (state.mode === "invoke-open") {
|
|
2157
|
-
const nextOpen = text.indexOf("<", state.offset);
|
|
2158
|
-
const nextClose = text.indexOf(">", state.offset);
|
|
2159
|
-
if (nextClose === -1 && nextOpen === -1) {
|
|
2160
|
-
state.offset = text.length;
|
|
2161
|
-
return { kind: "incomplete" };
|
|
2162
|
-
}
|
|
2163
|
-
if (nextOpen !== -1 && (nextClose === -1 || nextOpen < nextClose)) {
|
|
2164
|
-
state.mode = "outer";
|
|
2165
|
-
state.offset = nextOpen;
|
|
2166
|
-
state.invokeOpenStart = -1;
|
|
2167
|
-
continue;
|
|
2168
|
-
}
|
|
2169
|
-
const invokeOpenTag = text.slice(state.invokeOpenStart, nextClose + 1);
|
|
2170
|
-
if (!/^<[||]DSML[||]invoke\b[^<>]*>$/.test(invokeOpenTag)) {
|
|
2171
|
-
state.mode = "outer";
|
|
2172
|
-
state.offset = state.invokeOpenStart + 1;
|
|
2173
|
-
state.invokeOpenStart = -1;
|
|
2174
|
-
continue;
|
|
2175
|
-
}
|
|
2176
|
-
state.mode = "invoke-body";
|
|
2177
|
-
state.offset = nextClose + 1;
|
|
2178
|
-
state.invokeOpenStart = -1;
|
|
2179
|
-
continue;
|
|
2180
|
-
}
|
|
2181
|
-
if (state.mode === "invoke-body") {
|
|
2182
|
-
const invokeClose = findEarliestStringToken(text, DEEPSEEK_DSML_INVOKE_CLOSE_TOKENS, state.offset);
|
|
2183
|
-
if (!invokeClose) {
|
|
2184
|
-
state.offset = Math.max(0, text.length - DEEPSEEK_DSML_RECOVERY_MAX_BOUNDARY_LEN + 1);
|
|
2185
|
-
return { kind: "incomplete" };
|
|
2186
|
-
}
|
|
2187
|
-
state.mode = "outer";
|
|
2188
|
-
state.offset = invokeClose.index + invokeClose.token.length;
|
|
2189
|
-
continue;
|
|
2190
|
-
}
|
|
2191
|
-
const toolOpen = findEarliestStringToken(text, DEEPSEEK_DSML_TOOL_OPEN_TOKENS, state.offset);
|
|
2192
|
-
const toolCloseIndex = text.indexOf(closeToken, state.offset);
|
|
2193
|
-
const invokeOpen = findEarliestStringToken(text, DEEPSEEK_DSML_INVOKE_OPEN_PREFIXES, state.offset);
|
|
2194
|
-
const next = [
|
|
2195
|
-
toolOpen ? {
|
|
2196
|
-
kind: "nested-open",
|
|
2197
|
-
...toolOpen
|
|
2198
|
-
} : null,
|
|
2199
|
-
toolCloseIndex === -1 ? null : {
|
|
2200
|
-
kind: "close",
|
|
2201
|
-
index: toolCloseIndex,
|
|
2202
|
-
token: closeToken
|
|
2203
|
-
},
|
|
2204
|
-
invokeOpen ? {
|
|
2205
|
-
kind: "invoke-open",
|
|
2206
|
-
...invokeOpen
|
|
2207
|
-
} : null
|
|
2208
|
-
].filter((candidate) => candidate !== null).toSorted((left, right) => left.index - right.index)[0];
|
|
2209
|
-
if (!next) {
|
|
2210
|
-
state.offset = Math.max(contentStartIndex, text.length - DEEPSEEK_DSML_RECOVERY_MAX_BOUNDARY_LEN + 1);
|
|
2211
|
-
return { kind: "incomplete" };
|
|
2212
|
-
}
|
|
2213
|
-
if (next.kind === "invoke-open") {
|
|
2214
|
-
state.mode = "invoke-open";
|
|
2215
|
-
state.invokeOpenStart = next.index;
|
|
2216
|
-
state.offset = next.index + next.token.length;
|
|
2217
|
-
continue;
|
|
2218
|
-
}
|
|
2219
|
-
return next;
|
|
2220
|
-
}
|
|
2221
|
-
return { kind: "incomplete" };
|
|
2222
|
-
}
|
|
2223
|
-
function longestDeepSeekDsmlToolOpenPrefixSuffixLength(text) {
|
|
2224
|
-
const maxLength = Math.min(text.length, DEEPSEEK_DSML_TOOL_MAX_OPEN_TOKEN_LEN - 1);
|
|
2225
|
-
for (let length = maxLength; length > 0; length -= 1) {
|
|
2226
|
-
const suffix = text.slice(text.length - length);
|
|
2227
|
-
if (DEEPSEEK_DSML_TOOL_OPEN_TOKENS.some((token) => token.startsWith(suffix))) return length;
|
|
2228
|
-
}
|
|
2229
|
-
return 0;
|
|
2230
|
-
}
|
|
2231
|
-
//#endregion
|
|
2232
|
-
//#region packages/ai/src/transports/openai-completions-stream.ts
|
|
2233
|
-
function extractToolCallThoughtSignature(toolCall) {
|
|
2234
|
-
const tc = toolCall;
|
|
2235
|
-
if (!tc) return;
|
|
2236
|
-
const fromExtra = (tc.extra_content?.google)?.thought_signature;
|
|
2237
|
-
if (typeof fromExtra === "string" && fromExtra.length > 0) return fromExtra;
|
|
2238
|
-
const fromFunction = tc.function?.thought_signature;
|
|
2239
|
-
if (typeof fromFunction === "string" && fromFunction.length > 0) return fromFunction;
|
|
2240
|
-
const fromToolCall = tc.thought_signature;
|
|
2241
|
-
return typeof fromToolCall === "string" && fromToolCall.length > 0 ? fromToolCall : void 0;
|
|
2242
|
-
}
|
|
2243
|
-
async function processCompletionsStream(responseStream, output, model, stream, options) {
|
|
2244
|
-
const MAX_POST_TOOL_CALL_BUFFER_BYTES = 256e3;
|
|
2245
|
-
const emitReasoning = options?.emitReasoning ?? true;
|
|
2246
|
-
const compat = getCompat(model);
|
|
2247
|
-
const shouldFilterDeepSeekDsmlText = compat.thinkingFormat === "deepseek";
|
|
2248
|
-
const deepSeekTextFilter = shouldFilterDeepSeekDsmlText ? createDeepSeekTextFilter() : null;
|
|
2249
|
-
const deepSeekToolCallRecoverer = shouldFilterDeepSeekDsmlText ? createDsmlRecoverer() : null;
|
|
2250
|
-
const reasoningTagTextPartitioner = createReasoningTagTextPartitioner();
|
|
2251
|
-
let currentBlock = null;
|
|
2252
|
-
let pendingPostToolCallDeltas = [];
|
|
2253
|
-
let pendingPostToolCallBytes = 0;
|
|
2254
|
-
let isFlushingPendingPostToolCallDeltas = false;
|
|
2255
|
-
const toolCallBlocksByIndex = /* @__PURE__ */ new Map();
|
|
2256
|
-
const toolCallBlocksById = /* @__PURE__ */ new Map();
|
|
2257
|
-
const provisionalCommentaryTags = /* @__PURE__ */ new Map();
|
|
2258
|
-
const toolCallBlockIndices = /* @__PURE__ */ new WeakMap();
|
|
2259
|
-
const normalizeToolCallDeltas = createOpenAICompletionsToolCallDeltaNormalizer();
|
|
2260
|
-
let sawStopFinishReason = false;
|
|
2261
|
-
let sawNativeToolCallDelta = false;
|
|
2262
|
-
const blockIndex = () => output.content.length - 1;
|
|
2263
|
-
const measureUtf8Bytes = (text) => Buffer.byteLength(text, "utf8");
|
|
2264
|
-
let chunkPushedEvent = false;
|
|
2265
|
-
const pushStreamEvent = (event) => {
|
|
2266
|
-
chunkPushedEvent = true;
|
|
2267
|
-
stream.push(event);
|
|
2268
|
-
};
|
|
2269
|
-
const queuePostToolCallDelta = (next) => {
|
|
2270
|
-
const nextBytes = measureUtf8Bytes(next.text);
|
|
2271
|
-
if (pendingPostToolCallBytes + nextBytes > MAX_POST_TOOL_CALL_BUFFER_BYTES) throw new Error("Exceeded post-tool-call delta buffer limit");
|
|
2272
|
-
pendingPostToolCallBytes += nextBytes;
|
|
2273
|
-
const previous = pendingPostToolCallDeltas[pendingPostToolCallDeltas.length - 1];
|
|
2274
|
-
if (!previous || previous.kind !== next.kind) {
|
|
2275
|
-
pendingPostToolCallDeltas.push(next);
|
|
2276
|
-
return;
|
|
2277
|
-
}
|
|
2278
|
-
if (next.kind === "thinking" && previous.kind === "thinking") {
|
|
2279
|
-
if (previous.signature !== next.signature) {
|
|
2280
|
-
pendingPostToolCallDeltas.push(next);
|
|
2281
|
-
return;
|
|
2282
|
-
}
|
|
2283
|
-
previous.text += next.text;
|
|
2284
|
-
return;
|
|
2285
|
-
}
|
|
2286
|
-
previous.text += next.text;
|
|
2287
|
-
};
|
|
2288
|
-
const appendThinkingDeltaInternal = (reasoningDelta) => {
|
|
2289
|
-
if (!currentBlock || currentBlock.type !== "thinking") {
|
|
2290
|
-
currentBlock = {
|
|
2291
|
-
type: "thinking",
|
|
2292
|
-
thinking: "",
|
|
2293
|
-
...reasoningDelta.signature ? { thinkingSignature: reasoningDelta.signature } : {}
|
|
2294
|
-
};
|
|
2295
|
-
output.content.push(currentBlock);
|
|
2296
|
-
pushStreamEvent({
|
|
2297
|
-
type: "thinking_start",
|
|
2298
|
-
contentIndex: blockIndex(),
|
|
2299
|
-
partial: output
|
|
2300
|
-
});
|
|
2301
|
-
}
|
|
2302
|
-
currentBlock.thinking += reasoningDelta.text;
|
|
2303
|
-
pushStreamEvent({
|
|
2304
|
-
type: "thinking_delta",
|
|
2305
|
-
contentIndex: blockIndex(),
|
|
2306
|
-
delta: reasoningDelta.text,
|
|
2307
|
-
partial: output
|
|
2308
|
-
});
|
|
2309
|
-
};
|
|
2310
|
-
const appendTextDeltaInternal = (text) => {
|
|
2311
|
-
if (!currentBlock || currentBlock.type !== "text") {
|
|
2312
|
-
currentBlock = {
|
|
2313
|
-
type: "text",
|
|
2314
|
-
text: ""
|
|
2315
|
-
};
|
|
2316
|
-
output.content.push(currentBlock);
|
|
2317
|
-
pushStreamEvent({
|
|
2318
|
-
type: "text_start",
|
|
2319
|
-
contentIndex: blockIndex(),
|
|
2320
|
-
partial: output
|
|
2321
|
-
});
|
|
2322
|
-
}
|
|
2323
|
-
currentBlock.text += text;
|
|
2324
|
-
pushStreamEvent({
|
|
2325
|
-
type: "text_delta",
|
|
2326
|
-
contentIndex: blockIndex(),
|
|
2327
|
-
delta: text
|
|
2328
|
-
});
|
|
2329
|
-
};
|
|
2330
|
-
const flushPendingPostToolCallDeltas = () => {
|
|
2331
|
-
if (isFlushingPendingPostToolCallDeltas || currentBlock?.type === "toolCall" || pendingPostToolCallDeltas.length === 0) return;
|
|
2332
|
-
isFlushingPendingPostToolCallDeltas = true;
|
|
2333
|
-
const bufferedDeltas = pendingPostToolCallDeltas;
|
|
2334
|
-
pendingPostToolCallDeltas = [];
|
|
2335
|
-
pendingPostToolCallBytes = 0;
|
|
2336
|
-
for (const delta of bufferedDeltas) if (delta.kind === "text") appendTextDeltaInternal(delta.text);
|
|
2337
|
-
else if (emitReasoning) appendThinkingDeltaInternal(delta);
|
|
2338
|
-
isFlushingPendingPostToolCallDeltas = false;
|
|
2339
|
-
};
|
|
2340
|
-
const appendThinkingDelta = (reasoningDelta) => {
|
|
2341
|
-
flushPendingPostToolCallDeltas();
|
|
2342
|
-
appendThinkingDeltaInternal(reasoningDelta);
|
|
2343
|
-
};
|
|
2344
|
-
const appendTextDelta = (text) => {
|
|
2345
|
-
flushPendingPostToolCallDeltas();
|
|
2346
|
-
appendTextDeltaInternal(text);
|
|
2347
|
-
};
|
|
2348
|
-
const appendVisibleTextDelta = (text) => {
|
|
2349
|
-
if (!text) return;
|
|
2350
|
-
if (currentBlock?.type === "toolCall") queuePostToolCallDelta({
|
|
2351
|
-
kind: "text",
|
|
2352
|
-
text
|
|
2353
|
-
});
|
|
2354
|
-
else appendTextDelta(text);
|
|
2355
|
-
};
|
|
2356
|
-
const appendRecoveredToolCall = (toolCall) => {
|
|
2357
|
-
if (currentBlock?.type === "toolCall") {
|
|
2358
|
-
currentBlock = null;
|
|
2359
|
-
flushPendingPostToolCallDeltas();
|
|
2360
|
-
}
|
|
2361
|
-
rememberPendingCommentaryTags(provisionalCommentaryTags, tagPendingCommentaryText(output.content));
|
|
2362
|
-
const block = {
|
|
2363
|
-
type: "toolCall",
|
|
2364
|
-
id: `call_${randomUUID().replaceAll("-", "").slice(0, 24)}`,
|
|
2365
|
-
name: toolCall.name,
|
|
2366
|
-
arguments: toolCall.arguments,
|
|
2367
|
-
partialArgs: toolCall.partialArgs
|
|
2368
|
-
};
|
|
2369
|
-
currentBlock = block;
|
|
2370
|
-
output.content.push(block);
|
|
2371
|
-
toolCallBlockIndices.set(block, output.content.length - 1);
|
|
2372
|
-
pushStreamEvent({
|
|
2373
|
-
type: "toolcall_start",
|
|
2374
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2375
|
-
partial: output
|
|
2376
|
-
});
|
|
2377
|
-
pushStreamEvent({
|
|
2378
|
-
type: "toolcall_delta",
|
|
2379
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2380
|
-
delta: toolCall.partialArgs,
|
|
2381
|
-
partial: output
|
|
2382
|
-
});
|
|
2383
|
-
};
|
|
2384
|
-
const appendFilteredVisibleTextDelta = (text) => {
|
|
2385
|
-
const recoveredParts = deepSeekToolCallRecoverer?.push(text) ?? [{
|
|
2386
|
-
kind: "text",
|
|
2387
|
-
text
|
|
2388
|
-
}];
|
|
2389
|
-
for (const recoveredPart of recoveredParts) {
|
|
2390
|
-
if (recoveredPart.kind === "toolCall") {
|
|
2391
|
-
appendRecoveredToolCall(recoveredPart);
|
|
2392
|
-
continue;
|
|
2393
|
-
}
|
|
2394
|
-
const parts = deepSeekTextFilter?.push(recoveredPart.text) ?? [recoveredPart.text];
|
|
2395
|
-
for (const part of parts) appendVisibleTextDelta(part);
|
|
2396
|
-
}
|
|
2397
|
-
};
|
|
2398
|
-
const flushDeepSeekToolCallRecovererAtEnd = () => {
|
|
2399
|
-
const recoveredParts = deepSeekToolCallRecoverer?.flush();
|
|
2400
|
-
if (!recoveredParts) return;
|
|
2401
|
-
for (const recoveredPart of recoveredParts) {
|
|
2402
|
-
if (recoveredPart.kind === "toolCall") {
|
|
2403
|
-
appendRecoveredToolCall(recoveredPart);
|
|
2404
|
-
continue;
|
|
2405
|
-
}
|
|
2406
|
-
const parts = deepSeekTextFilter?.push(recoveredPart.text) ?? [recoveredPart.text];
|
|
2407
|
-
for (const part of parts) appendVisibleTextDelta(part);
|
|
2408
|
-
}
|
|
2409
|
-
};
|
|
2410
|
-
const flushDeepSeekTextFilterAtEnd = () => {
|
|
2411
|
-
const parts = deepSeekTextFilter?.flush();
|
|
2412
|
-
if (!parts) return;
|
|
2413
|
-
for (const part of parts) appendVisibleTextDelta(part);
|
|
2414
|
-
};
|
|
2415
|
-
const appendRoutedContentDelta = (delta) => {
|
|
2416
|
-
if (delta.kind === "text") {
|
|
2417
|
-
appendFilteredVisibleTextDelta(delta.text);
|
|
2418
|
-
return;
|
|
2419
|
-
}
|
|
2420
|
-
if (!emitReasoning) return;
|
|
2421
|
-
if (currentBlock?.type === "toolCall") queuePostToolCallDelta(delta);
|
|
2422
|
-
else appendThinkingDelta(delta);
|
|
2423
|
-
};
|
|
2424
|
-
const appendPartitionedVisibleDelta = (delta) => {
|
|
2425
|
-
if (delta.kind === "text") appendFilteredVisibleTextDelta(delta.text);
|
|
2426
|
-
};
|
|
2427
|
-
const emitReasoningUsageActivity = (hasReasoningUsageActivity) => {
|
|
2428
|
-
if (!hasReasoningUsageActivity || chunkPushedEvent || !emitReasoning) return;
|
|
2429
|
-
const latestBlock = output.content[output.content.length - 1];
|
|
2430
|
-
if (currentBlock?.type === "text" || currentBlock?.type === "toolCall") return;
|
|
2431
|
-
if (latestBlock?.type === "text" || latestBlock?.type === "toolCall") return;
|
|
2432
|
-
appendThinkingDelta({ text: "" });
|
|
2433
|
-
};
|
|
2434
|
-
const flushReasoningTagTextPartitionerAtEnd = () => {
|
|
2435
|
-
for (const delta of reasoningTagTextPartitioner.flush()) appendPartitionedVisibleDelta(delta);
|
|
2436
|
-
};
|
|
2437
|
-
const cooperativeScheduler = createModelStreamCooperativeScheduler(options?.signal);
|
|
2438
|
-
const guardedStream = withFirstStreamEventTimeout(responseStream, {
|
|
2439
|
-
provider: model.provider,
|
|
2440
|
-
api: model.api,
|
|
2441
|
-
model: model.id,
|
|
2442
|
-
timeoutMs: options?.firstEventTimeoutMs ?? 0,
|
|
2443
|
-
stage: "completions",
|
|
2444
|
-
abort: options?.abortFirstEventStream,
|
|
2445
|
-
onTimeout: options?.onFirstEventTimeout,
|
|
2446
|
-
hint: "The provider may be stalled while parsing the tool payload; retry with a smaller tool surface or enable OPENCLAW_DEBUG_MODEL_PAYLOAD=tools to inspect exposed tools."
|
|
2447
|
-
});
|
|
2448
|
-
for await (const rawChunk of guardedStream) {
|
|
2449
|
-
throwIfModelStreamAborted(options?.signal);
|
|
2450
|
-
chunkPushedEvent = false;
|
|
2451
|
-
if (!rawChunk || typeof rawChunk !== "object") {
|
|
2452
|
-
await cooperativeScheduler.afterEvent();
|
|
2453
|
-
continue;
|
|
2454
|
-
}
|
|
2455
|
-
notifyLlmRequestActivity(options?.signal);
|
|
2456
|
-
const chunk = rawChunk;
|
|
2457
|
-
output.responseId ||= chunk.id;
|
|
2458
|
-
let hasReasoningUsageActivity = false;
|
|
2459
|
-
if (chunk.usage) {
|
|
2460
|
-
output.usage = parseOpenAICompletionsUsage(chunk.usage, model);
|
|
2461
|
-
hasReasoningUsageActivity = hasOpenAICompletionsReasoningUsageActivity(chunk.usage);
|
|
2462
|
-
}
|
|
2463
|
-
const choice = Array.isArray(chunk.choices) ? chunk.choices[0] : void 0;
|
|
2464
|
-
if (!choice) {
|
|
2465
|
-
emitReasoningUsageActivity(hasReasoningUsageActivity);
|
|
2466
|
-
await cooperativeScheduler.afterEvent();
|
|
2467
|
-
continue;
|
|
2468
|
-
}
|
|
2469
|
-
const choiceUsage = choice.usage;
|
|
2470
|
-
if (!chunk.usage && choiceUsage) {
|
|
2471
|
-
output.usage = parseOpenAICompletionsUsage(choiceUsage, model);
|
|
2472
|
-
hasReasoningUsageActivity = hasOpenAICompletionsReasoningUsageActivity(choiceUsage);
|
|
2473
|
-
}
|
|
2474
|
-
if (choice.finish_reason) {
|
|
2475
|
-
const finishReasonResult = mapOpenAIStopReason(choice.finish_reason, { allowSingularToolCall: true });
|
|
2476
|
-
output.stopReason = finishReasonResult.stopReason;
|
|
2477
|
-
if (finishReasonResult.stopReason === "stop") sawStopFinishReason = true;
|
|
2478
|
-
if (finishReasonResult.errorMessage) output.errorMessage = finishReasonResult.errorMessage;
|
|
2479
|
-
}
|
|
2480
|
-
const rawChoiceDelta = choice.delta ?? choice.message;
|
|
2481
|
-
if (!rawChoiceDelta) {
|
|
2482
|
-
emitReasoningUsageActivity(hasReasoningUsageActivity);
|
|
2483
|
-
await cooperativeScheduler.afterEvent();
|
|
2484
|
-
continue;
|
|
2485
|
-
}
|
|
2486
|
-
for (const normalizedDelta of normalizeToolCallDeltas(rawChoiceDelta, choice.finish_reason)) {
|
|
2487
|
-
const choiceDelta = normalizedDelta.delta;
|
|
2488
|
-
const reasoningDeltas = getCompletionsReasoningDeltas(choiceDelta, compat.visibleReasoningDetailTypes);
|
|
2489
|
-
const hasMirroredReasoning = reasoningDeltas.some((delta) => delta.kind === "thinking");
|
|
2490
|
-
if (hasMirroredReasoning) reasoningTagTextPartitioner.markStrict();
|
|
2491
|
-
const contentDeltas = readOpenAICompletionsContentDeltas(choiceDelta.content, choiceDelta.refusal, reasoningDeltas.filter((reasoningDelta) => reasoningDelta.kind === "thinking").map((reasoningDelta) => reasoningDelta.text));
|
|
2492
|
-
const appendReasoningDeltas = () => {
|
|
2493
|
-
for (const reasoningDelta of reasoningDeltas) {
|
|
2494
|
-
if (reasoningDelta.kind === "thinking" && !emitReasoning) continue;
|
|
2495
|
-
if (currentBlock?.type === "toolCall") {
|
|
2496
|
-
queuePostToolCallDelta({ ...reasoningDelta });
|
|
2497
|
-
continue;
|
|
2498
|
-
}
|
|
2499
|
-
if (reasoningDelta.kind === "text") appendTextDelta(reasoningDelta.text);
|
|
2500
|
-
else if (emitReasoning) appendThinkingDelta(reasoningDelta);
|
|
2501
|
-
}
|
|
2502
|
-
};
|
|
2503
|
-
if (hasMirroredReasoning) appendReasoningDeltas();
|
|
2504
|
-
for (const contentDelta of contentDeltas) if (contentDelta.kind === "text") {
|
|
2505
|
-
const routedDeltas = hasMirroredReasoning ? reasoningTagTextPartitioner.push(contentDelta.text) : reasoningTagTextPartitioner.pushVisible(contentDelta.text);
|
|
2506
|
-
for (const routedDelta of routedDeltas) appendPartitionedVisibleDelta(routedDelta);
|
|
2507
|
-
} else {
|
|
2508
|
-
if (reasoningTagTextPartitioner.hasPending()) reasoningTagTextPartitioner.markStrict();
|
|
2509
|
-
appendRoutedContentDelta(contentDelta);
|
|
2510
|
-
}
|
|
2511
|
-
if (!hasMirroredReasoning) appendReasoningDeltas();
|
|
2512
|
-
const toolCallDeltas = normalizedDelta.toolCalls;
|
|
2513
|
-
if (toolCallDeltas.length > 0) {
|
|
2514
|
-
sawNativeToolCallDelta = true;
|
|
2515
|
-
flushReasoningTagTextPartitionerAtEnd();
|
|
2516
|
-
rememberPendingCommentaryTags(provisionalCommentaryTags, tagPendingCommentaryText(output.content));
|
|
2517
|
-
for (const toolCall of toolCallDeltas) {
|
|
2518
|
-
const streamIndex = typeof toolCall.index === "number" ? toolCall.index : void 0;
|
|
2519
|
-
let block = streamIndex !== void 0 ? toolCallBlocksByIndex.get(streamIndex) : void 0;
|
|
2520
|
-
if (!block && toolCall.id) block = toolCallBlocksById.get(toolCall.id);
|
|
2521
|
-
if (!block) {
|
|
2522
|
-
if (currentBlock?.type === "toolCall") {
|
|
2523
|
-
currentBlock = null;
|
|
2524
|
-
flushPendingPostToolCallDeltas();
|
|
2525
|
-
}
|
|
2526
|
-
const initialSig = extractToolCallThoughtSignature(toolCall);
|
|
2527
|
-
block = {
|
|
2528
|
-
type: "toolCall",
|
|
2529
|
-
id: toolCall.id || "",
|
|
2530
|
-
name: toolCall.function?.name || "",
|
|
2531
|
-
arguments: {},
|
|
2532
|
-
partialArgs: "",
|
|
2533
|
-
...initialSig ? { thoughtSignature: initialSig } : {}
|
|
2534
|
-
};
|
|
2535
|
-
output.content.push(block);
|
|
2536
|
-
toolCallBlockIndices.set(block, output.content.length - 1);
|
|
2537
|
-
pushStreamEvent({
|
|
2538
|
-
type: "toolcall_start",
|
|
2539
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2540
|
-
partial: output
|
|
2541
|
-
});
|
|
2542
|
-
}
|
|
2543
|
-
if (streamIndex !== void 0 && !toolCallBlocksByIndex.has(streamIndex)) toolCallBlocksByIndex.set(streamIndex, block);
|
|
2544
|
-
if (toolCall.id) {
|
|
2545
|
-
block.id = toolCall.id;
|
|
2546
|
-
toolCallBlocksById.set(toolCall.id, block);
|
|
2547
|
-
}
|
|
2548
|
-
currentBlock = block;
|
|
2549
|
-
if (toolCall.function?.name) block.name = toolCall.function.name;
|
|
2550
|
-
const deltaSig = extractToolCallThoughtSignature(toolCall);
|
|
2551
|
-
if (deltaSig) block.thoughtSignature = deltaSig;
|
|
2552
|
-
if (toolCall.function?.arguments) {
|
|
2553
|
-
block.partialArgs += toolCall.function.arguments;
|
|
2554
|
-
block.arguments = parseStreamingJson(block.partialArgs);
|
|
2555
|
-
pushStreamEvent({
|
|
2556
|
-
type: "toolcall_delta",
|
|
2557
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2558
|
-
delta: toolCall.function.arguments,
|
|
2559
|
-
partial: output
|
|
2560
|
-
});
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
}
|
|
2564
|
-
}
|
|
2565
|
-
flushPendingPostToolCallDeltas();
|
|
2566
|
-
emitReasoningUsageActivity(hasReasoningUsageActivity);
|
|
2567
|
-
await cooperativeScheduler.afterEvent();
|
|
2568
|
-
}
|
|
2569
|
-
flushReasoningTagTextPartitionerAtEnd();
|
|
2570
|
-
flushDeepSeekToolCallRecovererAtEnd();
|
|
2571
|
-
flushDeepSeekTextFilterAtEnd();
|
|
2572
|
-
currentBlock = null;
|
|
2573
|
-
flushPendingPostToolCallDeltas();
|
|
2574
|
-
finalizeOpenAICompletionsToolCalls(output, {
|
|
2575
|
-
allowSilentToolCallPromotion: sawStopFinishReason || sawNativeToolCallDelta && (options?.sawStreamDONE?.() ?? false),
|
|
2576
|
-
onConfirmedToolCall(block, contentIndex) {
|
|
2577
|
-
pushStreamEvent({
|
|
2578
|
-
type: "toolcall_end",
|
|
2579
|
-
contentIndex,
|
|
2580
|
-
toolCall: block,
|
|
2581
|
-
partial: output
|
|
2582
|
-
});
|
|
2583
|
-
}
|
|
2584
|
-
});
|
|
2585
|
-
if (output.stopReason !== "toolUse") clearPendingCommentaryText(provisionalCommentaryTags);
|
|
2586
|
-
if (output.stopReason === "toolUse") tagPendingCommentaryText(output.content);
|
|
2587
|
-
}
|
|
2588
|
-
function getCompletionsReasoningDeltas(delta, visibleReasoningDetailTypes) {
|
|
2589
|
-
const output = [];
|
|
2590
|
-
const pushDelta = (next) => {
|
|
2591
|
-
const previous = output[output.length - 1];
|
|
2592
|
-
if (!previous || previous.kind !== next.kind) {
|
|
2593
|
-
output.push(next);
|
|
2594
|
-
return;
|
|
2595
|
-
}
|
|
2596
|
-
if (next.kind === "thinking" && previous.kind === "thinking") {
|
|
2597
|
-
if (previous.signature !== next.signature) {
|
|
2598
|
-
output.push(next);
|
|
2599
|
-
return;
|
|
2600
|
-
}
|
|
2601
|
-
previous.text += next.text;
|
|
2602
|
-
return;
|
|
2603
|
-
}
|
|
2604
|
-
previous.text += next.text;
|
|
2605
|
-
};
|
|
2606
|
-
const reasoningDetails = delta.reasoning_details;
|
|
2607
|
-
let usedReasoningThinkingDetails = false;
|
|
2608
|
-
if (Array.isArray(reasoningDetails)) {
|
|
2609
|
-
const visibleTypes = new Set(visibleReasoningDetailTypes);
|
|
2610
|
-
for (const item of reasoningDetails) {
|
|
2611
|
-
const detail = item;
|
|
2612
|
-
if (typeof detail.text !== "string" || !detail.text) continue;
|
|
2613
|
-
if (detail.type === "reasoning.text") {
|
|
2614
|
-
usedReasoningThinkingDetails = true;
|
|
2615
|
-
pushDelta({
|
|
2616
|
-
kind: "thinking",
|
|
2617
|
-
signature: "reasoning_details",
|
|
2618
|
-
text: detail.text
|
|
2619
|
-
});
|
|
2620
|
-
continue;
|
|
2621
|
-
}
|
|
2622
|
-
if (typeof detail.type === "string" && visibleTypes.has(detail.type)) pushDelta({
|
|
2623
|
-
kind: "text",
|
|
2624
|
-
text: detail.text
|
|
2625
|
-
});
|
|
2626
|
-
}
|
|
2627
|
-
}
|
|
2628
|
-
if (!usedReasoningThinkingDetails) for (const field of [
|
|
2629
|
-
"reasoning_content",
|
|
2630
|
-
"reasoning",
|
|
2631
|
-
"reasoning_text"
|
|
2632
|
-
]) {
|
|
2633
|
-
const value = delta[field];
|
|
2634
|
-
if (typeof value === "string" && value.length > 0) {
|
|
2635
|
-
pushDelta({
|
|
2636
|
-
kind: "thinking",
|
|
2637
|
-
signature: field,
|
|
2638
|
-
text: value
|
|
2639
|
-
});
|
|
2640
|
-
break;
|
|
2641
|
-
}
|
|
2642
|
-
}
|
|
2643
|
-
return output;
|
|
2644
|
-
}
|
|
2645
|
-
function resolveOpenAICompletionsReasoningEffort(options) {
|
|
2646
|
-
return options?.reasoningEffort ?? options?.reasoning ?? "high";
|
|
2647
|
-
}
|
|
2648
|
-
function shouldEmitOpenAICompletionsReasoning(model, options) {
|
|
2649
|
-
if (!model.reasoning) return false;
|
|
2650
|
-
const effort = resolveOpenAICompletionsReasoningEffort(options);
|
|
2651
|
-
if (!effort || !isOpenAICompletionsThinkingEnabled(effort)) return false;
|
|
2652
|
-
return true;
|
|
2653
|
-
}
|
|
2654
|
-
function hasOpenAICompletionsReasoningUsageActivity(rawUsage) {
|
|
2655
|
-
const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens;
|
|
2656
|
-
return typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) && reasoningTokens > 0;
|
|
2657
|
-
}
|
|
2658
|
-
//#endregion
|
|
2659
1691
|
//#region packages/ai/src/transports/openai-completions-transport.ts
|
|
2660
1692
|
function assertOpenAICompletionsPayloadHasConversationTurn(params, model) {
|
|
2661
1693
|
const messages = params.messages;
|
|
@@ -2731,15 +1763,14 @@ function buildOpenAICompletionsClientConfig(model, context, optionHeaders) {
|
|
|
2731
1763
|
}
|
|
2732
1764
|
}
|
|
2733
1765
|
return {
|
|
2734
|
-
baseURL,
|
|
1766
|
+
baseURL: resolveOpenAIClientBaseUrl(model, baseURL),
|
|
2735
1767
|
defaultHeaders: headers,
|
|
2736
1768
|
defaultQuery: Object.keys(defaultQuery).length > 0 ? defaultQuery : void 0
|
|
2737
1769
|
};
|
|
2738
1770
|
}
|
|
2739
1771
|
function createOpenAICompletionsTransportStreamFn() {
|
|
2740
1772
|
return (model, context, options) => {
|
|
2741
|
-
const eventStream =
|
|
2742
|
-
const stream = eventStream;
|
|
1773
|
+
const { eventStream, stream } = createWritableTransportEventStream();
|
|
2743
1774
|
(async () => {
|
|
2744
1775
|
const output = {
|
|
2745
1776
|
role: "assistant",
|
|
@@ -2794,7 +1825,7 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
2794
1825
|
if (nextParams !== void 0) params = nextParams;
|
|
2795
1826
|
if (options?.openclawCodeModeToolSurface === true) {
|
|
2796
1827
|
const visibleToolNames = resolveCodeModeResponsesVisibleToolNames(context);
|
|
2797
|
-
enforceCodeModeResponsesToolSurface(params, visibleToolNames);
|
|
1828
|
+
enforceCodeModeResponsesToolSurface(params, visibleToolNames, void 0, codeModeToolSurfaceObserver.get(options));
|
|
2798
1829
|
assertCodeModeResponsesToolSurface(params, visibleToolNames);
|
|
2799
1830
|
}
|
|
2800
1831
|
if (getCompat(model).requiresNonEmptyUserOrAssistantMessage) assertOpenAICompletionsPayloadHasConversationTurn(params, model);
|
|
@@ -2808,7 +1839,7 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
2808
1839
|
stream: responseStream,
|
|
2809
1840
|
signal: firstEventAbort.signal,
|
|
2810
1841
|
abort: firstEventAbort.abort,
|
|
2811
|
-
hook:
|
|
1842
|
+
hook: createOpenAIProviderAcceptanceHook(options, response, model),
|
|
2812
1843
|
onReady: () => stream.push({
|
|
2813
1844
|
type: "start",
|
|
2814
1845
|
partial: output
|
|
@@ -2835,6 +1866,7 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
2835
1866
|
cleanup: () => {
|
|
2836
1867
|
output.stopReason = options?.signal?.aborted ? "aborted" : "error";
|
|
2837
1868
|
finalizeOpenAICompletionsToolCalls(output, { allowSilentToolCallPromotion: false });
|
|
1869
|
+
tagUnresolvedTextAsCommentary(output);
|
|
2838
1870
|
}
|
|
2839
1871
|
});
|
|
2840
1872
|
} finally {
|
|
@@ -3405,9 +2437,8 @@ function createOpenAIResponsesWebSocketStream(params) {
|
|
|
3405
2437
|
}
|
|
3406
2438
|
const event = readServerEvent(next.value);
|
|
3407
2439
|
if (!event) continue;
|
|
3408
|
-
if (event.type === "response.failed") throw new OpenAIResponsesWebSocketResponseFailedError(event.response.output.length > 0);
|
|
3409
2440
|
if (event.type === "response.completed") terminalResponse = event.response;
|
|
3410
|
-
terminalReceived = event.type === "response.completed" || event.type === "response.incomplete";
|
|
2441
|
+
terminalReceived = event.type === "response.completed" || event.type === "response.incomplete" || event.type === "response.failed";
|
|
3411
2442
|
yield event;
|
|
3412
2443
|
if (terminalReceived) {
|
|
3413
2444
|
degradedWebSocketConnections.delete(degradationKey);
|
|
@@ -3419,7 +2450,7 @@ function createOpenAIResponsesWebSocketStream(params) {
|
|
|
3419
2450
|
const safeRetry = error instanceof OpenAIResponsesWebSocketSafeRetryError;
|
|
3420
2451
|
if (!params.callerSignal?.aborted && !safeRetry) markDegraded();
|
|
3421
2452
|
if (!requestDispatched && !params.signal?.aborted) throw new OpenAIResponsesWebSocketPreDispatchError(error);
|
|
3422
|
-
if (!requestDispatched || params.callerSignal?.aborted ||
|
|
2453
|
+
if (!requestDispatched || params.callerSignal?.aborted || safeRetry) throw error;
|
|
3423
2454
|
throw new OpenAIResponsesWebSocketPostDispatchError(error);
|
|
3424
2455
|
} finally {
|
|
3425
2456
|
await iterator.return?.().catch(() => void 0);
|
|
@@ -3620,7 +2651,7 @@ function resolveProviderTransportTurnState(model, params) {
|
|
|
3620
2651
|
function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId) {
|
|
3621
2652
|
return new OpenAI({
|
|
3622
2653
|
apiKey,
|
|
3623
|
-
baseURL: model
|
|
2654
|
+
baseURL: resolveOpenAIClientBaseUrl(model),
|
|
3624
2655
|
dangerouslyAllowBrowser: true,
|
|
3625
2656
|
defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId),
|
|
3626
2657
|
fetch: buildGuardedModelFetch(model),
|
|
@@ -3639,11 +2670,17 @@ async function postOpenAIResponsesCompaction(params) {
|
|
|
3639
2670
|
}
|
|
3640
2671
|
});
|
|
3641
2672
|
const output = isRecord(response) && Array.isArray(response.output) ? response.output : [];
|
|
3642
|
-
const item = output
|
|
2673
|
+
const item = output.at(-1);
|
|
2674
|
+
const retainedItems = output.slice(0, -1);
|
|
2675
|
+
const retainedMessagesAreValid = retainedItems.every((candidate) => isRecord(candidate) && candidate.type === "message" && (candidate.role === "user" || candidate.role === "developer" || candidate.role === "system") && Array.isArray(candidate.content));
|
|
2676
|
+
const retainedUserMessageCount = retainedItems.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user" && Array.isArray(candidate.content)).length;
|
|
2677
|
+
const inputUserMessageCount = Array.isArray(params.request.input) ? params.request.input.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user").length : 0;
|
|
2678
|
+
const retainedMessagePrefixSupported = supportsNativeOpenAIResponsesEndpoint(params.model);
|
|
3643
2679
|
const usage = isRecord(response) && isRecord(response.usage) ? response.usage : void 0;
|
|
3644
|
-
if (!isRecord(response) || response.object !== "response.compaction" ||
|
|
2680
|
+
if (!isRecord(response) || response.object !== "response.compaction" || !retainedMessagesAreValid || retainedItems.length > 0 && (!retainedMessagePrefixSupported || retainedUserMessageCount !== inputUserMessageCount) || !isRecord(item) || item.type !== "compaction" || typeof item.encrypted_content !== "string" || item.encrypted_content.length === 0 || !usage || typeof usage.input_tokens !== "number" || typeof usage.output_tokens !== "number") throw new Error("Responses compact endpoint did not return one trailing compaction item");
|
|
3645
2681
|
return {
|
|
3646
2682
|
item,
|
|
2683
|
+
historyMode: retainedUserMessageCount > 0 ? "retained-users" : "compacted-prefix",
|
|
3647
2684
|
usage,
|
|
3648
2685
|
model: params.model,
|
|
3649
2686
|
replayMetadata: buildOpenAIResponsesReasoningReplayMetadata(params.model, {
|
|
@@ -3656,8 +2693,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
3656
2693
|
return (model, context, options) => {
|
|
3657
2694
|
const responsesOptions = options;
|
|
3658
2695
|
const compactRequest = claimResponsesCompactRequest(responsesOptions);
|
|
3659
|
-
const eventStream =
|
|
3660
|
-
const stream = eventStream;
|
|
2696
|
+
const { eventStream, stream } = createWritableTransportEventStream();
|
|
3661
2697
|
(async () => {
|
|
3662
2698
|
const output = createOpenAIResponsesAssistantOutput(model, config.outputApi);
|
|
3663
2699
|
let firstEventAbort;
|
|
@@ -3684,7 +2720,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
3684
2720
|
if (options?.openclawCodeModeToolSurface === true) {
|
|
3685
2721
|
const visibleToolNames = resolveCodeModeResponsesVisibleToolNames(context);
|
|
3686
2722
|
const allowedHostedToolTypes = responsesOptions?.openclawCodeModeAllowedHostedToolTypes;
|
|
3687
|
-
enforceCodeModeResponsesToolSurface(params, visibleToolNames, allowedHostedToolTypes);
|
|
2723
|
+
enforceCodeModeResponsesToolSurface(params, visibleToolNames, allowedHostedToolTypes, codeModeToolSurfaceObserver.get(options));
|
|
3688
2724
|
assertCodeModeResponsesToolSurface(params, visibleToolNames, allowedHostedToolTypes);
|
|
3689
2725
|
}
|
|
3690
2726
|
return params;
|
|
@@ -3701,12 +2737,11 @@ function createResponsesTransportExecutor(config) {
|
|
|
3701
2737
|
output.usage.output = compacted.usage.output_tokens;
|
|
3702
2738
|
output.usage.totalTokens = compacted.usage.input_tokens + compacted.usage.output_tokens;
|
|
3703
2739
|
compactRequest.resolve(compacted);
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
2740
|
+
finalizeTransportStream({
|
|
2741
|
+
stream,
|
|
2742
|
+
output,
|
|
2743
|
+
signal: options?.signal
|
|
3708
2744
|
});
|
|
3709
|
-
stream.end();
|
|
3710
2745
|
return;
|
|
3711
2746
|
}
|
|
3712
2747
|
const sessionId = options?.sessionId;
|
|
@@ -3744,7 +2779,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
3744
2779
|
emitModelTransportDebug(log, `[responses] start provider=${model.provider} api=${model.api} model=${model.id} requestIdHash=${redactIdentifier(options?.requestId, { len: 64 })} baseUrl=${formatModelTransportDebugBaseUrl(model.baseUrl)} timeoutMs=${safeDebugValue(requestOptions?.timeout)} apiKey=${apiKey ? "present" : "missing"} ${summarizeResponsesPayload(params)}`);
|
|
3745
2780
|
let continuationBaseline;
|
|
3746
2781
|
const createSseStream = async (initialRequest = continuationClaim?.request ?? params, initialAttemptKind = "initial", initialRejectedCompaction) => {
|
|
3747
|
-
const { stream:
|
|
2782
|
+
const { stream: responseStream } = await config.createResponseStream({
|
|
3748
2783
|
client,
|
|
3749
2784
|
request: initialRequest,
|
|
3750
2785
|
requestOptions,
|
|
@@ -3753,19 +2788,23 @@ function createResponsesTransportExecutor(config) {
|
|
|
3753
2788
|
initialAttemptKind,
|
|
3754
2789
|
initialRejectedCompaction,
|
|
3755
2790
|
buildFullHistoryRequest: () => buildRequest("full-history"),
|
|
3756
|
-
onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, responsesOptions, checkpoint)
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
2791
|
+
onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, responsesOptions, checkpoint),
|
|
2792
|
+
canRetryStream: () => output.content.length === 0,
|
|
2793
|
+
wrapStream: ({ stream: rawResponseStream, response, attempt }) => {
|
|
2794
|
+
if (continuationClaim) continuationBaseline = attempt.request.previous_response_id ? params : attempt.request;
|
|
2795
|
+
return withProviderResponseHook({
|
|
2796
|
+
stream: observeResponsesStream(rawResponseStream, model, requestStartedAt),
|
|
2797
|
+
signal: firstEvent.signal,
|
|
2798
|
+
abort: firstEvent.abort,
|
|
2799
|
+
hook: createOpenAIProviderAcceptanceHook(options, response, model),
|
|
2800
|
+
onReady: () => {
|
|
2801
|
+
emitModelTransportDebug(log, `[responses] headers provider=${model.provider} api=${model.api} model=${model.id} transport=sse elapsedMs=${Date.now() - requestStartedAt}`);
|
|
2802
|
+
startStream();
|
|
2803
|
+
}
|
|
2804
|
+
});
|
|
3767
2805
|
}
|
|
3768
2806
|
});
|
|
2807
|
+
return responseStream;
|
|
3769
2808
|
};
|
|
3770
2809
|
let responseStream;
|
|
3771
2810
|
let finishWebSocket;
|
|
@@ -3796,8 +2835,16 @@ function createResponsesTransportExecutor(config) {
|
|
|
3796
2835
|
transport = "websocket";
|
|
3797
2836
|
emitModelTransportDebug(log, `[responses] websocket_selected provider=${model.provider} api=${model.api} model=${model.id} mode=${websocketMode} reused=${websocket.reusedConnection} continuation=${websocket.continuationStatus === "continued"} continuationStatus=${websocket.continuationStatus} sessionIdHash=${redactIdentifier(options?.sessionId)} headersHash=${redactIdentifier(JSON.stringify(Object.entries(websocketHeaders ?? {}).toSorted(([a], [b]) => a.localeCompare(b))))}`);
|
|
3798
2837
|
responseStream = { async *[Symbol.asyncIterator]() {
|
|
2838
|
+
let providerAccepted = false;
|
|
3799
2839
|
try {
|
|
3800
2840
|
for await (const event of websocket.stream) {
|
|
2841
|
+
if (!providerAccepted) {
|
|
2842
|
+
providerAccepted = true;
|
|
2843
|
+
await notifyProviderStreamOpened({
|
|
2844
|
+
options,
|
|
2845
|
+
cancelStream: () => websocket.finish({ keep: false })
|
|
2846
|
+
});
|
|
2847
|
+
}
|
|
3801
2848
|
startStream();
|
|
3802
2849
|
yield event;
|
|
3803
2850
|
}
|
|
@@ -3848,33 +2895,30 @@ function createResponsesTransportExecutor(config) {
|
|
|
3848
2895
|
throw error;
|
|
3849
2896
|
}
|
|
3850
2897
|
emitModelTransportDebug(log, `[responses] completed provider=${model.provider} api=${model.api} model=${model.id} transport=${transport} elapsedMs=${Date.now() - requestStartedAt}`);
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
2898
|
+
finalizeTransportStream({
|
|
2899
|
+
stream,
|
|
2900
|
+
output,
|
|
2901
|
+
signal: options?.signal
|
|
3855
2902
|
});
|
|
3856
|
-
stream.end();
|
|
3857
2903
|
} catch (error) {
|
|
3858
2904
|
if (compactRequest) {
|
|
3859
2905
|
compactRequest.reject(error);
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
error
|
|
2906
|
+
failTransportStream({
|
|
2907
|
+
stream,
|
|
2908
|
+
output,
|
|
2909
|
+
signal: options?.signal,
|
|
2910
|
+
error
|
|
3865
2911
|
});
|
|
3866
|
-
stream.end();
|
|
3867
2912
|
return;
|
|
3868
2913
|
}
|
|
3869
2914
|
if (error instanceof ResponsesStreamFailure && error.observation) logResponsesFailedNoDetails(error.observation);
|
|
3870
2915
|
log.warn(`[responses] error provider=${model.provider} api=${model.api} model=${model.id} ` + summarizeOpenAITransportError(error));
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
error
|
|
2916
|
+
failTransportStream({
|
|
2917
|
+
stream,
|
|
2918
|
+
output,
|
|
2919
|
+
signal: options?.signal,
|
|
2920
|
+
error
|
|
3876
2921
|
});
|
|
3877
|
-
stream.end();
|
|
3878
2922
|
} finally {
|
|
3879
2923
|
continuationClaim?.release();
|
|
3880
2924
|
firstEventAbort?.dispose();
|
|
@@ -3970,7 +3014,7 @@ if (process.env.VITEST || false) globalThis.openclawOpenAIResponsesTransportTest
|
|
|
3970
3014
|
/** Whether provider replay state is a prefix-bound server compaction checkpoint. */
|
|
3971
3015
|
function isCompactionReplayCheckpoint(replay) {
|
|
3972
3016
|
const type = replay && typeof replay === "object" ? replay.type : void 0;
|
|
3973
|
-
return type === "anthropic-compaction" || type === "openai-responses-compaction";
|
|
3017
|
+
return type === "anthropic-compaction" || type === "openai-responses-compaction" || type === "openai-responses-retained-compaction";
|
|
3974
3018
|
}
|
|
3975
3019
|
/** Strip prefix-bound checkpoints after local history rewrites. */
|
|
3976
3020
|
function stripCompactionReplayCheckpoint(message) {
|
|
@@ -3991,8 +3035,9 @@ function replaceCompactionReplayOwnerContent(message, content) {
|
|
|
3991
3035
|
};
|
|
3992
3036
|
const replay = message.providerReplay;
|
|
3993
3037
|
if (!isCompactionReplayCheckpoint(replay)) return next;
|
|
3038
|
+
if (replay.type === "openai-responses-retained-compaction") return next;
|
|
3994
3039
|
const replayIndex = replay.replayIndex ?? 0;
|
|
3995
|
-
if (content.length === 0 || replayIndex > message.content.length) return stripCompactionReplayCheckpoint(next);
|
|
3040
|
+
if (content.length === 0 && message.content.length > 0 || replayIndex > message.content.length) return stripCompactionReplayCheckpoint(next);
|
|
3996
3041
|
let sourceIndex = 0;
|
|
3997
3042
|
let nextReplayIndex = 0;
|
|
3998
3043
|
if (!content.every((block) => {
|
|
@@ -4261,4 +3306,4 @@ function prepareModelForSimpleCompletion(params) {
|
|
|
4261
3306
|
return applyProviderSimpleCompletionWrapper(apiRegistry, model, cfg);
|
|
4262
3307
|
}
|
|
4263
3308
|
//#endregion
|
|
4264
|
-
export { GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, applyAnthropicCacheControlToMessages, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, captureOpenAIResponsesCompaction, coerceTransportToolCallArguments, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIResponseHook, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, filterCodeModePayloadTools, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, googleFlashSupportsMinimalThinking, hasOpenAICompatibleConversationTurn, isCodeModeModelVisibleToolName, isCompactionReplayCheckpoint, isOpenAICodexResponsesModel, isOpenAICompletionsThinkingEnabled, log, measureUtf8AppendBytes, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, parseOpenAICompletionsUsage, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, replaceCompactionReplayOwnerContent, requestPreparedOpenAIResponsesCompaction, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveAnthropicServerCompactionPlan, resolveCodeModeResponsesVisibleToolNames, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAICompletionsCompat, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesCompactEndpointPlan, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIResponsesServerCompactionPlan, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompactionReplayCheckpoint, stripCompactionReplayCheckpointInPlace, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend, withProviderResponseHook };
|
|
3309
|
+
export { GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, applyAnthropicCacheControlToMessages, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, captureOpenAIResponsesCompaction, coerceTransportToolCallArguments, 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, isCodeModeModelVisibleToolName, isCompactionReplayCheckpoint, isOpenAICodexResponsesModel, isOpenAICompletionsThinkingEnabled, log, measureUtf8AppendBytes, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, notifyProviderHttpMetadata, notifyProviderHttpResponse, notifyProviderStreamOpened, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, parseOpenAICompletionsUsage, parseTerminalToolCallArguments, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, readOpenAICompletionsReasoningBatch, replaceCompactionReplayOwnerContent, requestPreparedOpenAIResponsesCompaction, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveAnthropicServerCompactionPlan, resolveCodeModeResponsesVisibleToolNames, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAIClientBaseUrl, resolveOpenAICompletionsCompat, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesCompactEndpointPlan, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIResponsesServerCompactionPlan, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompactionReplayCheckpoint, stripCompactionReplayCheckpointInPlace, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend, withProviderAcceptanceObserver, withProviderResponseHook };
|