@openclaw/ai 2026.8.1-beta.3 → 2026.8.2
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-B8KwTtlb.mjs → anthropic-DTGZ4VMY.mjs} +25 -23
- package/dist/{anthropic-compaction-replay-4Zx7-aCr.mjs → anthropic-compaction-replay-CKCDrZJv.mjs} +34 -35
- package/dist/{anthropic-payload-policy-CSx7MoKH.d.mts → anthropic-payload-policy-BTzmNC14.d.mts} +3 -2
- package/dist/{api-registry-DFxSnFqG.d.mts → api-registry-BbUHEKER.d.mts} +2 -1
- package/dist/{azure-openai-responses-Aa4mVcYG.mjs → azure-openai-responses-BmqaDXM1.mjs} +6 -5
- package/dist/{number-coercion-H9qHik3g.mjs → base64-CEFBpSkN.mjs} +73 -1
- package/dist/diagnostics.d.mts +2 -3
- package/dist/diagnostics.mjs +1 -1
- package/dist/{env-api-keys-DrgeBuva.mjs → env-api-keys-bktO00EJ.mjs} +2 -15
- package/dist/{event-stream-D91-ohD_.d.mts → event-stream-DcvAPSBe.d.mts} +1 -2
- package/dist/event-stream-pXT3FI6X.d.mts +1 -0
- package/dist/event-stream.d.mts +2 -1
- package/dist/{google-yDRnipeq.mjs → google-CqjVZMwo.mjs} +8 -6
- package/dist/{google-shared-M1dl64nz.mjs → google-shared-Bnqni5j3.mjs} +34 -25
- package/dist/{google-vertex-DCJHM_a5.mjs → google-vertex-D_WREEJi.mjs} +8 -6
- package/dist/{host-DF_yxOsA.mjs → host-BIaiBURL.mjs} +4 -8
- package/dist/{host-DJq_FGcz.d.mts → host-DKFUAmCn.d.mts} +3 -3
- package/dist/index-CefaUGSS.d.mts +111 -0
- package/dist/index.d.mts +9 -10
- package/dist/index.mjs +4 -5
- package/dist/internal/anthropic.d.mts +51 -49
- package/dist/internal/anthropic.mjs +5 -5
- package/dist/internal/openai-responses-payload-policy.d.mts +3 -3
- package/dist/internal/openai-responses-payload-policy.mjs +2 -3
- package/dist/internal/openai.d.mts +65 -63
- package/dist/internal/openai.mjs +10 -9
- package/dist/internal/retry-after.d.mts +2 -3
- package/dist/internal/runtime.d.mts +51 -40
- package/dist/internal/runtime.mjs +9 -9
- package/dist/internal/shared.d.mts +25 -25
- package/dist/internal/shared.mjs +3 -3
- package/dist/{json-parse-CDnesDM_.mjs → json-parse-BuAJEbdW.mjs} +18 -2
- package/dist/{mistral-D6hRXI7A.mjs → mistral-C24jVd6f.mjs} +34 -32
- package/dist/{openai-chatgpt-responses-C339VIfT.mjs → openai-chatgpt-responses-Czum0oXz.mjs} +38 -20
- package/dist/openai-completions-BfFwac6f.mjs +404 -0
- package/dist/{openai-completions-compat-B0KTleXp.d.mts → openai-completions-compat-SZhi0Lf4.d.mts} +3 -3
- package/dist/openai-completions-stream-DGOvau4J.mjs +1625 -0
- package/dist/{openai-responses-BXEcr-Tp.mjs → openai-responses-BAryVEJM.mjs} +11 -7
- package/dist/openai-responses-compaction-window-DO7yV7az.mjs +686 -0
- package/dist/{openai-responses-contracts-CD75pQ0m.d.mts → openai-responses-contracts-BthRXano.d.mts} +14 -5
- package/dist/{openai-responses-payload-policy-CNGFT9zr.d.mts → openai-responses-payload-policy-rLRPsSmB.d.mts} +1 -0
- package/dist/{openai-responses-prompt-observer-internal-BG-1AsBI.mjs → openai-responses-prompt-observer-internal--R0kZLOZ.mjs} +3 -2
- package/dist/{openai-responses-shared-Cvt5MgEm.mjs → openai-responses-shared-CxgdGBvm.mjs} +332 -1484
- package/dist/openai-stop-reason-Drnn_6Qj.mjs +28 -0
- package/dist/openai-tool-schema-CSMh5e9O.mjs +1697 -0
- package/dist/{provider-error-C8mBRJDl.mjs → provider-error-BI8kIViN.mjs} +14 -88
- package/dist/{provider-options-Cc5ZQ6Aa.d.mts → provider-options-DJd_9euj.d.mts} +13 -4
- package/dist/{provider-transcript-transform--gtf0ZbR.mjs → provider-transcript-transform-WvJmFUAf.mjs} +1 -1
- package/dist/provider-types.d.mts +18 -17
- package/dist/providers.d.mts +5 -6
- package/dist/providers.mjs +9 -9
- package/dist/{reasoning-tag-text-partitioner-5ygO2rZc.mjs → reasoning-tag-text-partitioner-BsUX44Tq.mjs} +30 -20
- package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
- package/dist/{sanitize-unicode-BP7HLLZn.mjs → sanitize-unicode-S6binQG-.mjs} +2 -9
- package/dist/simple-options-rdOPzr7Z.mjs +155 -0
- package/dist/{anthropic-BQXQudmA.mjs → src-C8U7lkoa.mjs} +75 -1
- package/dist/{stream-first-event-timeout-MK28puvq.mjs → stream-first-event-timeout-DcNjoFQE.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-FEr-jOoZ.mjs → tool-schema-json-projection-BtZiml7r.mjs} +22 -32
- package/dist/transport-stream-shared-BbG7PThh.d.mts +138 -0
- package/dist/{simple-options-oqsXB6U3.mjs → transport-stream-shared-D8nQWCUo.mjs} +10 -118
- package/dist/{transport-utils-Bv0FHkd0.mjs → transport-utils-CtuS1Upe.mjs} +10 -10
- package/dist/transports.d.mts +130 -189
- package/dist/transports.mjs +227 -1249
- package/dist/{types-DTAP49HF.d.mts → types-Beemor2E.d.mts} +58 -24
- package/dist/types-COdhCX0U.d.mts +1 -0
- package/dist/types.d.mts +6 -5
- package/dist/types.mjs +3 -4
- package/dist/utf16-slice-qz3nsy87.mjs +84 -0
- package/dist/{validation-DYNNrU9u.d.mts → validation-CC6s7Smp.d.mts} +1 -2
- package/dist/{validation-B61OhAio.mjs → validation-CJZtym2g.mjs} +7 -5
- package/dist/validation.d.mts +1 -1
- package/dist/validation.mjs +1 -1
- package/package.json +6 -6
- package/dist/anthropic-BECQCNdF.d.mts +0 -98
- package/dist/event-stream-BVVgDSdq.d.mts +0 -1
- package/dist/headers-B_e4-1J0.mjs +0 -9
- package/dist/index-BVVgDSdq.d.mts +0 -1
- package/dist/openai-completions-D88orSJ9.mjs +0 -632
- package/dist/openai-responses-contracts-DvILoqBk.mjs +0 -247
- package/dist/openai-responses-payload-policy-BDo8CQsx.mjs +0 -208
- package/dist/openai-stop-reason-9OONKyAm.mjs +0 -579
- package/dist/openai-tool-projection-CHGLt03m.mjs +0 -426
- package/dist/provider-options-AvldWZt8.mjs +0 -21
- 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,30 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { r as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { n as
|
|
9
|
-
import { r as
|
|
10
|
-
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, w as uniqueStrings, y as resolveOpenAIReasoningEffortForModel } from "./openai-responses-contracts-DvILoqBk.mjs";
|
|
11
|
-
import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
|
|
1
|
+
import { g as supportsClaudeAdaptiveThinking, m as resolveClaudeSonnet5ModelIdentity, p as resolveClaudeOpus5ModelIdentity, y as supportsClaudeNativeXhighEffort } from "./src-C8U7lkoa.mjs";
|
|
2
|
+
import { c as normalizeLowercaseStringOrEmpty, o as isRecord, s as hasNonEmptyString } from "./utf16-slice-qz3nsy87.mjs";
|
|
3
|
+
import { r as calculateCost } from "./sanitize-unicode-S6binQG-.mjs";
|
|
4
|
+
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-BIaiBURL.mjs";
|
|
5
|
+
import { i as stableStringify } from "./provider-error-BI8kIViN.mjs";
|
|
6
|
+
import { n as toErrorObject, t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal--R0kZLOZ.mjs";
|
|
7
|
+
import { a as asNonNegativeFiniteNumber } from "./base64-CEFBpSkN.mjs";
|
|
8
|
+
import { n as uniqueStrings } from "./string-normalization--fwJ4S2q.mjs";
|
|
9
|
+
import { A as applyAnthropicCacheControlToMessages, C as applyAnthropicFallbackBoundary, D as createAnthropicInlineImageBudget, E as applyAnthropicRefusal, F as resolveAnthropicServerCompactionPlan, I as isAnthropicOAuthApiKey, L as omitFoundryBearerCredentialHeaders, M as applyAnthropicPayloadPolicyToParams, N as resolveAnthropicEphemeralCacheControl, O as normalizeAnthropicInlineContent, P as resolveAnthropicPayloadPolicy, R as usesFoundryBearerAuth, T as resolveAnthropicFallbackServingModelCost, _ as toClaudeCodeToolName, a as suppressAnthropicCompaction, b as ANTHROPIC_SERVER_SIDE_FALLBACKS, f as normalizeAnthropicToolCallId, g as resolveOriginalAnthropicToolName, h as reconcileAnthropicToolChoice, i as resolveNewestAnthropicCompaction, j as applyAnthropicEphemeralCacheControlMarkers, k as resolveAnthropicImageMediaType, m as projectAnthropicTools, n as createCompactionCapture, o as applyAnthropicMessageDeltaUsage, p as normalizeAnthropicToolChoice, r as isAnthropicReplayRejection, s as applyAnthropicMessageStartUsage, t as buildAnthropicReplayPlan, v as ANTHROPIC_OMITTED_REASONING_TEXT, w as readAnthropicFallbackBoundary, x as ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, y as findActiveAnthropicToolTurnAssistantIndex } from "./anthropic-compaction-replay-CKCDrZJv.mjs";
|
|
12
10
|
import { t as resolveCacheRetention } from "./cache-retention-0x979a5V.mjs";
|
|
13
|
-
import {
|
|
14
|
-
import { a as resolveProviderEndpoint, c as transformTransportMessages, i as resolveOpenAIStrictToolSetting, n as buildGuardedModelFetch
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
11
|
+
import { a as codeModeToolSurfaceObserver, d as stripSystemPromptCacheBoundary, m as sortPromptCacheToolsByName, o as reasoningTagTextPolicy, t as adjustMaxTokensForThinking } from "./simple-options-rdOPzr7Z.mjs";
|
|
12
|
+
import { a as resolveProviderEndpoint, c as transformTransportMessages, i as resolveOpenAIStrictToolSetting, n as buildGuardedModelFetch } from "./tool-schema-json-projection-BtZiml7r.mjs";
|
|
13
|
+
import { a as isGoogleGemini3FlashModel, c as parseRetryAfterSeconds, f as resolveModelHeaderSentinels$1, i as isCodeModeModelVisibleToolName, l as readResponseTextSnippet, m as supportsModelTools, n as createAbortError$1, o as isGoogleGemini3ProModel, p as sha256Hex, r as estimateStringChars, t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, u as redactIdentifier } from "./transport-utils-CtuS1Upe.mjs";
|
|
14
|
+
import { n as getEnvApiKey } from "./env-api-keys-bktO00EJ.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-D8nQWCUo.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-DGOvau4J.mjs";
|
|
17
17
|
import { t as createDeferredEventBuffer } from "./deferred-event-buffer-DAvyP7qA.mjs";
|
|
18
|
-
import {
|
|
18
|
+
import { r as parseStreamingJson, t as createToolArgumentPreviewSchedule } from "./json-parse-BuAJEbdW.mjs";
|
|
19
19
|
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
20
|
-
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-Bv0FHkd0.mjs";
|
|
21
20
|
import { t as googleFlashSupportsMinimalThinking } from "./google-thinking-level-C-V3tecN.mjs";
|
|
22
|
-
import { B as buildResponsesInputMessage, C as summarizeResponsesTools, G as
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import { a as
|
|
26
|
-
import { t as createReasoningTagTextPartitioner } from "./reasoning-tag-text-partitioner-5ygO2rZc.mjs";
|
|
27
|
-
import { i as resolveOpenAIResponsesServerCompactionPlan, n as resolveOpenAIResponsesCompactEndpointPlan, r as resolveOpenAIResponsesPayloadPolicy, t as applyOpenAIResponsesPayloadPolicy } from "./openai-responses-payload-policy-BDo8CQsx.mjs";
|
|
21
|
+
import { B as buildResponsesInputMessage, C as summarizeResponsesTools, G as captureOpenAIResponsesCompaction, H as createOpenAIResponsesAssistantOutput, I as createResponsesStreamWithEncryptedContentRetry, J as resolveReplayableResponsesMessageId, K as resolveNewestOpenAIResponsesCompactionReplay, L as isInvalidEncryptedContentError, R as resolveAzureOpenAIApiVersion, S as summarizeResponsesPayload, U as CompactionReplayRefreshRequiredError, V as convertResponsesMessages, W as buildOpenAIResponsesReasoningReplayMetadata, X as resolveModelPayloadDebugMode, Y as emitModelTransportDebug, Z 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 suppressOpenAIResponsesCompaction, v as stringifyRedactedEvent, x as summarizeResponsesFailedNoDetailsObservation, y as stringifyRedactedPayload, z as resolveNextResponsesEncryptedContentAttempt } from "./openai-responses-shared-CxgdGBvm.mjs";
|
|
22
|
+
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-CSMh5e9O.mjs";
|
|
23
|
+
import { i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-DcNjoFQE.mjs";
|
|
24
|
+
import { C as isOpenAIGpt54MiniModel, D as resolveOpenAIReasoningEffortForModel, E as normalizeOpenAIReasoningEffort, T as isOpenAIGpt56Model, _ as OpenAIResponsesWebSocketPostDispatchError, a as applyOpenAIResponsesPayloadPolicy, c as resolveOpenAIResponsesServerCompactionPlan, d as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS, f as OPENAI_RESPONSES_APIS, i as sanitizeResponsesImagePayload, l as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, n as isOpenAIResponsesCompactionOutput, o as resolveOpenAIResponsesCompactEndpointPlan, s as resolveOpenAIResponsesPayloadPolicy, t as createBoundedOpenAIResponsesCompactionFetch, v as OpenAIResponsesWebSocketPreDispatchError, w as isOpenAIGpt55Model, x as parseOpenAIResponsesWebSocketServerError, y as OpenAIResponsesWebSocketSafeRetryError } from "./openai-responses-compaction-window-DO7yV7az.mjs";
|
|
28
25
|
import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
|
|
29
26
|
import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
|
|
30
27
|
import { randomUUID } from "node:crypto";
|
|
@@ -36,12 +33,12 @@ import { ResponsesWS } from "openai/resources/responses/ws.js";
|
|
|
36
33
|
* Converts OpenClaw contexts/tools into Anthropic payloads, streams SSE events
|
|
37
34
|
* back into runtime output blocks, and applies provider request policy.
|
|
38
35
|
*/
|
|
39
|
-
const ANTHROPIC_MESSAGES_ERROR_BODY_MAX_BYTES =
|
|
36
|
+
const ANTHROPIC_MESSAGES_ERROR_BODY_MAX_BYTES = 8192;
|
|
40
37
|
const ANTHROPIC_MESSAGES_ERROR_BODY_MAX_CHARS = 400;
|
|
41
38
|
const ANTHROPIC_MESSAGES_ERROR_BODY_READ_IDLE_TIMEOUT_MS = 1e4;
|
|
42
39
|
const ANTHROPIC_MESSAGES_DEFAULT_MAX_TOKENS = 4096;
|
|
43
40
|
const ANTHROPIC_MESSAGES_FALLBACK_CONTEXT_DIVISOR = 4;
|
|
44
|
-
const ANTHROPIC_MESSAGES_SSE_PENDING_BUFFER_MAX_CHARS =
|
|
41
|
+
const ANTHROPIC_MESSAGES_SSE_PENDING_BUFFER_MAX_CHARS = 16777216;
|
|
45
42
|
function resolveAnthropicRequestModelId(model) {
|
|
46
43
|
if (isDirectAnthropicModel(model) && /^anthropic\//i.test(model.id)) return model.id.replace(/^anthropic\//i, "");
|
|
47
44
|
return model.id;
|
|
@@ -61,9 +58,6 @@ function resolveAnthropicMessagesMaxTokens(params) {
|
|
|
61
58
|
const contextWindow = resolvePositiveAnthropicTokenLimit(params.modelContextWindow);
|
|
62
59
|
return contextWindow === void 0 ? ANTHROPIC_MESSAGES_DEFAULT_MAX_TOKENS : Math.max(1, Math.min(ANTHROPIC_MESSAGES_DEFAULT_MAX_TOKENS, Math.floor(contextWindow / ANTHROPIC_MESSAGES_FALLBACK_CONTEXT_DIVISOR)));
|
|
63
60
|
}
|
|
64
|
-
function isAnthropicOAuthToken(apiKey) {
|
|
65
|
-
return (resolveSecretSentinel(apiKey) ?? apiKey).includes("sk-ant-oat");
|
|
66
|
-
}
|
|
67
61
|
function isDirectAnthropicModel(model) {
|
|
68
62
|
if (normalizeLowercaseStringOrEmpty(model.provider) !== "anthropic") return false;
|
|
69
63
|
const endpointClass = resolveProviderEndpoint(model).endpointClass;
|
|
@@ -483,7 +477,7 @@ function createAnthropicTransportClient(params) {
|
|
|
483
477
|
}
|
|
484
478
|
const betaFeatures = ["fine-grained-tool-streaming-2025-05-14"];
|
|
485
479
|
if (needsInterleavedBeta) betaFeatures.push("interleaved-thinking-2025-05-14");
|
|
486
|
-
if (
|
|
480
|
+
if (isAnthropicOAuthApiKey(apiKey)) {
|
|
487
481
|
const betaHeader = buildAnthropicBetaHeader(model, betaFeatures, { oauth: true });
|
|
488
482
|
return {
|
|
489
483
|
client: createAnthropicMessagesClient({
|
|
@@ -580,18 +574,19 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
580
574
|
if (convertedTools.tools.length > 0) params.tools = convertedTools.tools;
|
|
581
575
|
}
|
|
582
576
|
if (mandatoryAdaptiveThinking || model.reasoning || supportsClaudeAdaptiveThinking(model)) {
|
|
583
|
-
if (mandatoryAdaptiveThinking || options?.thinkingEnabled)
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
577
|
+
if (mandatoryAdaptiveThinking || options?.thinkingEnabled) {
|
|
578
|
+
if (supportsClaudeAdaptiveThinking(model)) {
|
|
579
|
+
params.thinking = {
|
|
580
|
+
type: "adaptive",
|
|
581
|
+
display: options?.thinkingDisplay ?? "summarized"
|
|
582
|
+
};
|
|
583
|
+
const effort = options?.effort ?? (mandatoryAdaptiveThinking ? "high" : void 0);
|
|
584
|
+
if (effort) params.output_config = { effort };
|
|
585
|
+
} else params.thinking = {
|
|
586
|
+
type: "enabled",
|
|
587
|
+
budget_tokens: options?.thinkingBudgetTokens ?? 1024
|
|
587
588
|
};
|
|
588
|
-
|
|
589
|
-
if (effort) params.output_config = { effort };
|
|
590
|
-
} else params.thinking = {
|
|
591
|
-
type: "enabled",
|
|
592
|
-
budget_tokens: options?.thinkingBudgetTokens ?? 1024
|
|
593
|
-
};
|
|
594
|
-
else if (options?.thinkingEnabled === false) params.thinking = { type: "disabled" };
|
|
589
|
+
} else if (options?.thinkingEnabled === false) params.thinking = { type: "disabled" };
|
|
595
590
|
}
|
|
596
591
|
if (options?.metadata && typeof options.metadata.user_id === "string") params.metadata = { user_id: options.metadata.user_id };
|
|
597
592
|
if (options?.toolChoice) {
|
|
@@ -713,6 +708,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
713
708
|
}
|
|
714
709
|
const blocks = output.content;
|
|
715
710
|
const blockIndexes = /* @__PURE__ */ new Map();
|
|
711
|
+
const toolArgumentPreviewSchedules = /* @__PURE__ */ new WeakMap();
|
|
716
712
|
const sealedToolCalls = [];
|
|
717
713
|
const compactionCapture = createCompactionCapture(output, model, transportOptions);
|
|
718
714
|
const pendingThinkingSignatures = /* @__PURE__ */ new Map();
|
|
@@ -966,6 +962,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
966
962
|
};
|
|
967
963
|
output.content.push(block);
|
|
968
964
|
blockIndexes.set(index, output.content.length - 1);
|
|
965
|
+
toolArgumentPreviewSchedules.set(block, createToolArgumentPreviewSchedule());
|
|
969
966
|
eventSink.push({
|
|
970
967
|
type: "toolcall_start",
|
|
971
968
|
contentIndex: output.content.length - 1,
|
|
@@ -986,16 +983,18 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
986
983
|
let appendedContent = false;
|
|
987
984
|
if (!hasNativeAnthropicDelta && typeof delta?.content === "string" && delta.content.length > 0) {
|
|
988
985
|
const text = sanitizeTransportPayloadText(delta.content);
|
|
989
|
-
if (text.length > 0)
|
|
990
|
-
block
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
986
|
+
if (text.length > 0) {
|
|
987
|
+
if (block?.type === "text" && index !== void 0) {
|
|
988
|
+
block.text += text;
|
|
989
|
+
eventSink.push({
|
|
990
|
+
type: "text_delta",
|
|
991
|
+
contentIndex: index,
|
|
992
|
+
delta: text,
|
|
993
|
+
partial: output
|
|
994
|
+
});
|
|
995
|
+
appendedContent = true;
|
|
996
|
+
} else appendedContent = appendReasoningContentTextDelta(event.index, text);
|
|
997
|
+
}
|
|
999
998
|
}
|
|
1000
999
|
if ((appendedThinking || appendedContent) && !hasNativeAnthropicDelta) continue;
|
|
1001
1000
|
}
|
|
@@ -1038,7 +1037,7 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1038
1037
|
if (block?.type === "toolCall" && delta?.type === "input_json_delta" && typeof delta.partial_json === "string") {
|
|
1039
1038
|
const partialJson = `${block.partialJson ?? ""}${delta.partial_json}`;
|
|
1040
1039
|
block.partialJson = partialJson;
|
|
1041
|
-
block.arguments = parseAnthropicToolCallArguments(partialJson);
|
|
1040
|
+
if (toolArgumentPreviewSchedules.get(block)?.(partialJson.length)) block.arguments = parseAnthropicToolCallArguments(partialJson);
|
|
1042
1041
|
eventSink.push({
|
|
1043
1042
|
type: "toolcall_delta",
|
|
1044
1043
|
contentIndex: index,
|
|
@@ -1103,8 +1102,10 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1103
1102
|
if (event.type === "message_delta") {
|
|
1104
1103
|
const delta = event.delta;
|
|
1105
1104
|
const usage = event.usage;
|
|
1106
|
-
if (delta?.stop_reason)
|
|
1107
|
-
|
|
1105
|
+
if (delta?.stop_reason) {
|
|
1106
|
+
if (delta.stop_reason === "refusal") applyAnthropicRefusal(output, delta.stop_details, model.provider);
|
|
1107
|
+
else output.stopReason = mapAnthropicStopReason(delta.stop_reason);
|
|
1108
|
+
}
|
|
1108
1109
|
applyAnthropicMessageDeltaUsage(output.usage, usage, messageStartPromptUsage);
|
|
1109
1110
|
calculateCost(costModel, output.usage);
|
|
1110
1111
|
if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
|
|
@@ -1153,96 +1154,6 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1153
1154
|
};
|
|
1154
1155
|
}
|
|
1155
1156
|
//#endregion
|
|
1156
|
-
//#region packages/ai/src/transports/deepseek-text-filter.ts
|
|
1157
|
-
/**
|
|
1158
|
-
* DeepSeek DSML streaming text filter.
|
|
1159
|
-
* Removes provider-emitted DSML tool markup while buffering split tag prefixes
|
|
1160
|
-
* across streamed chunks.
|
|
1161
|
-
*/
|
|
1162
|
-
const DSML_KINDS = [
|
|
1163
|
-
"tool_use_error",
|
|
1164
|
-
"tool_calls",
|
|
1165
|
-
"tool_call",
|
|
1166
|
-
"function_calls"
|
|
1167
|
-
];
|
|
1168
|
-
const DSML_BARS = ["|", "|"];
|
|
1169
|
-
const DSML_OPEN_TOKENS = DSML_BARS.flatMap((bar) => DSML_KINDS.map((kind) => `<${bar}DSML${bar}${kind}>`));
|
|
1170
|
-
const DSML_CLOSE_TOKENS = DSML_BARS.flatMap((bar) => DSML_KINDS.map((kind) => `</${bar}DSML${bar}${kind}>`));
|
|
1171
|
-
const MAX_OPEN_TOKEN_LEN = Math.max(...DSML_OPEN_TOKENS.map((token) => token.length));
|
|
1172
|
-
const MAX_CLOSE_TOKEN_LEN = Math.max(...DSML_CLOSE_TOKENS.map((token) => token.length));
|
|
1173
|
-
/** Create an incremental text filter that strips DeepSeek DSML tool blocks. */
|
|
1174
|
-
function createDeepSeekTextFilter() {
|
|
1175
|
-
let buffer = "";
|
|
1176
|
-
let insideDsml = false;
|
|
1177
|
-
const consume = (final) => {
|
|
1178
|
-
const output = [];
|
|
1179
|
-
const emit = (text) => {
|
|
1180
|
-
if (text) output.push(text);
|
|
1181
|
-
};
|
|
1182
|
-
while (buffer) {
|
|
1183
|
-
if (insideDsml) {
|
|
1184
|
-
const close = findEarliestToken(buffer, DSML_CLOSE_TOKENS);
|
|
1185
|
-
if (close) {
|
|
1186
|
-
buffer = buffer.slice(close.index + close.token.length);
|
|
1187
|
-
insideDsml = false;
|
|
1188
|
-
continue;
|
|
1189
|
-
}
|
|
1190
|
-
const keep = final ? 0 : Math.min(buffer.length, MAX_CLOSE_TOKEN_LEN - 1);
|
|
1191
|
-
buffer = buffer.slice(buffer.length - keep);
|
|
1192
|
-
if (final) insideDsml = false;
|
|
1193
|
-
return output;
|
|
1194
|
-
}
|
|
1195
|
-
const open = findEarliestToken(buffer, DSML_OPEN_TOKENS);
|
|
1196
|
-
if (open) {
|
|
1197
|
-
emit(buffer.slice(0, open.index));
|
|
1198
|
-
buffer = buffer.slice(open.index + open.token.length);
|
|
1199
|
-
insideDsml = true;
|
|
1200
|
-
continue;
|
|
1201
|
-
}
|
|
1202
|
-
if (final) {
|
|
1203
|
-
emit(buffer);
|
|
1204
|
-
buffer = "";
|
|
1205
|
-
return output;
|
|
1206
|
-
}
|
|
1207
|
-
const keep = longestDsmlOpenPrefixSuffixLength(buffer);
|
|
1208
|
-
const emitLength = buffer.length - keep;
|
|
1209
|
-
if (emitLength <= 0) return output;
|
|
1210
|
-
emit(buffer.slice(0, emitLength));
|
|
1211
|
-
buffer = buffer.slice(emitLength);
|
|
1212
|
-
return output;
|
|
1213
|
-
}
|
|
1214
|
-
return output;
|
|
1215
|
-
};
|
|
1216
|
-
return {
|
|
1217
|
-
push(chunk) {
|
|
1218
|
-
buffer += chunk;
|
|
1219
|
-
return consume(false);
|
|
1220
|
-
},
|
|
1221
|
-
flush() {
|
|
1222
|
-
return consume(true);
|
|
1223
|
-
}
|
|
1224
|
-
};
|
|
1225
|
-
}
|
|
1226
|
-
function findEarliestToken(text, tokens) {
|
|
1227
|
-
let best = null;
|
|
1228
|
-
for (const token of tokens) {
|
|
1229
|
-
const index = text.indexOf(token);
|
|
1230
|
-
if (index !== -1 && (!best || index < best.index)) best = {
|
|
1231
|
-
index,
|
|
1232
|
-
token
|
|
1233
|
-
};
|
|
1234
|
-
}
|
|
1235
|
-
return best;
|
|
1236
|
-
}
|
|
1237
|
-
function longestDsmlOpenPrefixSuffixLength(text) {
|
|
1238
|
-
const maxLength = Math.min(text.length, MAX_OPEN_TOKEN_LEN - 1);
|
|
1239
|
-
for (let length = maxLength; length > 0; length--) {
|
|
1240
|
-
const suffix = text.slice(text.length - length);
|
|
1241
|
-
if (DSML_OPEN_TOKENS.some((token) => token.startsWith(suffix))) return length;
|
|
1242
|
-
}
|
|
1243
|
-
return 0;
|
|
1244
|
-
}
|
|
1245
|
-
//#endregion
|
|
1246
1157
|
//#region packages/ai/src/transports/model-max-tokens-params.ts
|
|
1247
1158
|
/**
|
|
1248
1159
|
* Max-token parameter normalization across provider/native naming variants.
|
|
@@ -1541,230 +1452,6 @@ function applyCompletionsReplay(outgoingMessages, context, model, compat) {
|
|
|
1541
1452
|
});
|
|
1542
1453
|
}
|
|
1543
1454
|
//#endregion
|
|
1544
|
-
//#region packages/ai/src/transports/openai-transport-params.ts
|
|
1545
|
-
const MAX_OPENAI_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS = 256;
|
|
1546
|
-
const OPENAI_CODEX_RESPONSES_PROVIDERS = /* @__PURE__ */ new Set(["openai"]);
|
|
1547
|
-
const loggedOpenAIStrictToolDowngradeDiagnosticKeys = /* @__PURE__ */ new Set();
|
|
1548
|
-
function readToolPayloadField(record, field) {
|
|
1549
|
-
try {
|
|
1550
|
-
return Object.hasOwn(record, field) ? record[field] : void 0;
|
|
1551
|
-
} catch {
|
|
1552
|
-
return;
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
function readCodeModePayloadToolName(tool) {
|
|
1556
|
-
if (!isRecord(tool)) return;
|
|
1557
|
-
const name = readToolPayloadField(tool, "name");
|
|
1558
|
-
if (typeof name === "string") return name;
|
|
1559
|
-
const fn = readToolPayloadField(tool, "function");
|
|
1560
|
-
if (!isRecord(fn)) return;
|
|
1561
|
-
const fnName = readToolPayloadField(fn, "name");
|
|
1562
|
-
return typeof fnName === "string" ? fnName : void 0;
|
|
1563
|
-
}
|
|
1564
|
-
function readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes) {
|
|
1565
|
-
if (!isRecord(tool)) return;
|
|
1566
|
-
const type = readToolPayloadField(tool, "type");
|
|
1567
|
-
if (typeof type === "string" && allowedHostedToolTypes?.has(type)) {
|
|
1568
|
-
try {
|
|
1569
|
-
if (Object.hasOwn(tool, "name") || Object.hasOwn(tool, "function") || Object.hasOwn(tool, "functionDeclarations") || Object.hasOwn(tool, "function_declarations")) return false;
|
|
1570
|
-
} catch {
|
|
1571
|
-
return false;
|
|
1572
|
-
}
|
|
1573
|
-
return `hosted:${type}`;
|
|
1574
|
-
}
|
|
1575
|
-
const name = readCodeModePayloadToolName(tool);
|
|
1576
|
-
return typeof name === "string" && isCodeModeModelVisibleToolName(name, visibleToolNames) ? `client:${name}` : void 0;
|
|
1577
|
-
}
|
|
1578
|
-
function readCodeModePayloadToolIdentities(payload) {
|
|
1579
|
-
if (!isRecord(payload)) return [];
|
|
1580
|
-
const tools = readToolPayloadField(payload, "tools");
|
|
1581
|
-
if (!Array.isArray(tools)) return [];
|
|
1582
|
-
return tools.flatMap((tool) => {
|
|
1583
|
-
if (!isRecord(tool)) return [];
|
|
1584
|
-
const identities = [];
|
|
1585
|
-
const name = readCodeModePayloadToolName(tool);
|
|
1586
|
-
if (name) identities.push(`client:${name}`);
|
|
1587
|
-
for (const key of ["functionDeclarations", "function_declarations"]) {
|
|
1588
|
-
const declarations = readToolPayloadField(tool, key);
|
|
1589
|
-
if (!Array.isArray(declarations)) continue;
|
|
1590
|
-
for (const declaration of declarations) {
|
|
1591
|
-
const declarationName = readCodeModePayloadToolName(declaration);
|
|
1592
|
-
if (declarationName) identities.push(`client:${declarationName}`);
|
|
1593
|
-
}
|
|
1594
|
-
}
|
|
1595
|
-
const type = readToolPayloadField(tool, "type");
|
|
1596
|
-
if (typeof type === "string" && type !== "function") identities.push(`hosted:${type}`);
|
|
1597
|
-
return identities;
|
|
1598
|
-
});
|
|
1599
|
-
}
|
|
1600
|
-
function filterCodeModePayloadTools(payload, visibleToolNames, allowedHostedToolTypes, observer) {
|
|
1601
|
-
if (!isRecord(payload)) return;
|
|
1602
|
-
const tools = readToolPayloadField(payload, "tools");
|
|
1603
|
-
if (!Array.isArray(tools)) return;
|
|
1604
|
-
const beforeToolIdentities = observer ? readCodeModePayloadToolIdentities(payload) : void 0;
|
|
1605
|
-
payload.tools = tools.flatMap((tool) => {
|
|
1606
|
-
const identity = readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes);
|
|
1607
|
-
if (identity) return [tool];
|
|
1608
|
-
if (identity === false) return [];
|
|
1609
|
-
if (!isRecord(tool)) return [];
|
|
1610
|
-
const filteredGroups = {};
|
|
1611
|
-
for (const key of ["functionDeclarations", "function_declarations"]) {
|
|
1612
|
-
const declarations = readToolPayloadField(tool, key);
|
|
1613
|
-
if (!Array.isArray(declarations)) continue;
|
|
1614
|
-
const filtered = declarations.filter((declaration) => {
|
|
1615
|
-
const declarationName = readCodeModePayloadToolName(declaration);
|
|
1616
|
-
return typeof declarationName === "string" && isCodeModeModelVisibleToolName(declarationName, visibleToolNames);
|
|
1617
|
-
});
|
|
1618
|
-
if (filtered.length > 0) filteredGroups[key] = filtered;
|
|
1619
|
-
}
|
|
1620
|
-
return Object.keys(filteredGroups).length > 0 ? [filteredGroups] : [];
|
|
1621
|
-
});
|
|
1622
|
-
if (beforeToolIdentities) observer?.({
|
|
1623
|
-
beforeToolIdentities,
|
|
1624
|
-
afterToolIdentities: readCodeModePayloadToolIdentities(payload)
|
|
1625
|
-
});
|
|
1626
|
-
}
|
|
1627
|
-
function resolveCodeModeResponsesVisibleToolNames(context) {
|
|
1628
|
-
return new Set((context.tools ?? []).map(readCodeModePayloadToolName).filter((name) => typeof name === "string"));
|
|
1629
|
-
}
|
|
1630
|
-
function enforceCodeModeResponsesToolSurface(payload, visibleToolNames, allowedHostedToolTypes, observer) {
|
|
1631
|
-
if (!isRecord(payload)) return;
|
|
1632
|
-
const tools = readToolPayloadField(payload, "tools");
|
|
1633
|
-
if (!Array.isArray(tools)) return;
|
|
1634
|
-
const beforeToolIdentities = observer ? readCodeModePayloadToolIdentities(payload) : void 0;
|
|
1635
|
-
payload.tools = tools.filter((tool) => Boolean(readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes)));
|
|
1636
|
-
if (beforeToolIdentities) observer?.({
|
|
1637
|
-
beforeToolIdentities,
|
|
1638
|
-
afterToolIdentities: readCodeModePayloadToolIdentities(payload)
|
|
1639
|
-
});
|
|
1640
|
-
}
|
|
1641
|
-
function assertCodeModeResponsesToolSurface(payload, visibleToolNames, allowedHostedToolTypes) {
|
|
1642
|
-
const tools = isRecord(payload) ? readToolPayloadField(payload, "tools") : void 0;
|
|
1643
|
-
if (!Array.isArray(tools)) throw new Error("Code mode payload tool surface violation: expected exec,wait; got no tools");
|
|
1644
|
-
const identities = tools.map((tool) => readCodeModePayloadToolIdentity(tool, visibleToolNames, allowedHostedToolTypes));
|
|
1645
|
-
const names = identities.flatMap((identity) => typeof identity === "string" && identity.startsWith("client:") ? [identity.slice(7)] : []).toSorted((left, right) => left.localeCompare(right));
|
|
1646
|
-
if (names.length >= 2 && identities.every((identity) => typeof identity === "string") && new Set(identities).size === identities.length && names.includes("exec") && names.includes("wait")) return;
|
|
1647
|
-
throw new Error(`Code mode payload tool surface violation: expected exec,wait plus direct-only tools; got ${names.length > 0 ? names.join(",") : "none"}`);
|
|
1648
|
-
}
|
|
1649
|
-
function buildOpenAIStrictToolDowngradeDiagnosticKey(diagnostics, context) {
|
|
1650
|
-
return sha256Hex(JSON.stringify({
|
|
1651
|
-
transport: context.transport,
|
|
1652
|
-
provider: context.model.provider ?? null,
|
|
1653
|
-
model: context.model.id ?? null,
|
|
1654
|
-
diagnostics: diagnostics.map((entry) => ({
|
|
1655
|
-
toolIndex: entry.toolIndex,
|
|
1656
|
-
toolName: entry.toolName ?? null,
|
|
1657
|
-
violations: entry.violations
|
|
1658
|
-
}))
|
|
1659
|
-
}));
|
|
1660
|
-
}
|
|
1661
|
-
function shouldLogOpenAIStrictToolDowngradeDiagnostic(diagnostics, context) {
|
|
1662
|
-
const key = buildOpenAIStrictToolDowngradeDiagnosticKey(diagnostics, context);
|
|
1663
|
-
if (loggedOpenAIStrictToolDowngradeDiagnosticKeys.has(key)) return false;
|
|
1664
|
-
if (loggedOpenAIStrictToolDowngradeDiagnosticKeys.size >= MAX_OPENAI_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS) loggedOpenAIStrictToolDowngradeDiagnosticKeys.clear();
|
|
1665
|
-
loggedOpenAIStrictToolDowngradeDiagnosticKeys.add(key);
|
|
1666
|
-
return true;
|
|
1667
|
-
}
|
|
1668
|
-
function resolveOpenAIStrictToolFlagWithDiagnostics(projection, strictSetting, context) {
|
|
1669
|
-
const strict = resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
|
|
1670
|
-
if (strictSetting === true && strict === false) {
|
|
1671
|
-
const diagnostics = findOpenAIStrictToolProjectionDiagnostics(projection);
|
|
1672
|
-
getAiTransportHost().logDebug("openai-transport", () => {
|
|
1673
|
-
if (!shouldLogOpenAIStrictToolDowngradeDiagnostic(diagnostics, context)) return null;
|
|
1674
|
-
const sample = diagnostics.slice(0, 5).map((entry) => ({
|
|
1675
|
-
tool: entry.toolName ?? `tool[${entry.toolIndex}]`,
|
|
1676
|
-
violations: entry.violations.slice(0, 8)
|
|
1677
|
-
}));
|
|
1678
|
-
return {
|
|
1679
|
-
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`,
|
|
1680
|
-
data: {
|
|
1681
|
-
transport: context.transport,
|
|
1682
|
-
provider: context.model.provider,
|
|
1683
|
-
model: context.model.id,
|
|
1684
|
-
incompatibleToolCount: diagnostics.length,
|
|
1685
|
-
sample
|
|
1686
|
-
}
|
|
1687
|
-
};
|
|
1688
|
-
});
|
|
1689
|
-
}
|
|
1690
|
-
return strict;
|
|
1691
|
-
}
|
|
1692
|
-
function isOpenAICodexResponsesModel(model) {
|
|
1693
|
-
return OPENAI_CODEX_RESPONSES_PROVIDERS.has(model.provider) && (model.api === "openai-chatgpt-responses" || model.api === "openclaw-openai-chatgpt-responses-transport");
|
|
1694
|
-
}
|
|
1695
|
-
function isNativeOpenAICodexResponsesBaseUrl(baseUrl) {
|
|
1696
|
-
const trimmed = typeof baseUrl === "string" ? baseUrl.trim() : "";
|
|
1697
|
-
if (!trimmed) return false;
|
|
1698
|
-
try {
|
|
1699
|
-
const url = new URL(trimmed);
|
|
1700
|
-
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
|
1701
|
-
if (url.hostname.toLowerCase() !== "chatgpt.com") return false;
|
|
1702
|
-
const pathname = url.pathname.replace(/\/+$/u, "").toLowerCase();
|
|
1703
|
-
return [
|
|
1704
|
-
"/backend-api",
|
|
1705
|
-
"/backend-api/v1",
|
|
1706
|
-
"/backend-api/codex",
|
|
1707
|
-
"/backend-api/codex/v1"
|
|
1708
|
-
].includes(pathname);
|
|
1709
|
-
} catch {
|
|
1710
|
-
return false;
|
|
1711
|
-
}
|
|
1712
|
-
}
|
|
1713
|
-
function usesNativeOpenAICodexResponsesBackend(model) {
|
|
1714
|
-
return isOpenAICodexResponsesModel(model) && isNativeOpenAICodexResponsesBaseUrl(model.baseUrl);
|
|
1715
|
-
}
|
|
1716
|
-
function buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId) {
|
|
1717
|
-
const providerHeaders = { ...model.headers };
|
|
1718
|
-
if (model.provider === "github-copilot") Object.assign(providerHeaders, getAiTransportHost().buildCopilotDynamicHeaders(context.messages));
|
|
1719
|
-
const callerHeaders = {
|
|
1720
|
-
...optionHeaders,
|
|
1721
|
-
...turnHeaders
|
|
1722
|
-
};
|
|
1723
|
-
const resolvedHeaders = resolveProviderRequestPolicyConfig(model, {
|
|
1724
|
-
provider: model.provider,
|
|
1725
|
-
api: model.api,
|
|
1726
|
-
baseUrl: model.baseUrl,
|
|
1727
|
-
capability: "llm",
|
|
1728
|
-
transport: "stream",
|
|
1729
|
-
providerHeaders,
|
|
1730
|
-
callerHeaders: Object.keys(callerHeaders).length > 0 ? callerHeaders : void 0,
|
|
1731
|
-
precedence: "caller-wins"
|
|
1732
|
-
}).headers ?? {};
|
|
1733
|
-
if (sessionId && !Object.keys(resolvedHeaders).some((key) => normalizeLowercaseStringOrEmpty(key) === "session_id") && usesNativeOpenAICodexResponsesBackend(model)) resolvedHeaders.session_id = clampOpenAIPromptCacheKey(sessionId) ?? sessionId;
|
|
1734
|
-
return resolvedHeaders;
|
|
1735
|
-
}
|
|
1736
|
-
function resolveOpenAISdkTimeoutMs(model, timeoutMs) {
|
|
1737
|
-
return resolveModelRequestTimeoutMs(model, timeoutMs);
|
|
1738
|
-
}
|
|
1739
|
-
function buildOpenAISdkClientOptions(model) {
|
|
1740
|
-
const timeout = resolveOpenAISdkTimeoutMs(model);
|
|
1741
|
-
return timeout === void 0 ? {} : { timeout };
|
|
1742
|
-
}
|
|
1743
|
-
function buildOpenAISdkRequestOptions(model, signal, options) {
|
|
1744
|
-
const timeout = resolveOpenAISdkTimeoutMs(model, options?.timeoutMs);
|
|
1745
|
-
const headers = options?.stream === true && usesNativeOpenAICodexResponsesBackend(model) ? { Accept: "text/event-stream" } : void 0;
|
|
1746
|
-
if (timeout === void 0 && options?.maxRetries === void 0 && !signal && !headers) return;
|
|
1747
|
-
return {
|
|
1748
|
-
...headers ? { headers } : {},
|
|
1749
|
-
...signal ? { signal } : {},
|
|
1750
|
-
...timeout !== void 0 ? { timeout } : {},
|
|
1751
|
-
...options?.maxRetries !== void 0 ? { maxRetries: options.maxRetries } : {}
|
|
1752
|
-
};
|
|
1753
|
-
}
|
|
1754
|
-
function getCompat(model) {
|
|
1755
|
-
const resolved = resolveOpenAICompletionsCompat(model);
|
|
1756
|
-
const compat = model.compat ?? {};
|
|
1757
|
-
return {
|
|
1758
|
-
...resolved,
|
|
1759
|
-
cacheControlFormat: resolved.cacheControlFormat,
|
|
1760
|
-
reasoningEffortMap: resolveOpenAIReasoningEffortMap(model, {}),
|
|
1761
|
-
openRouterRouting: resolved.openRouterRouting ?? {},
|
|
1762
|
-
vercelGatewayRouting: resolved.vercelGatewayRouting,
|
|
1763
|
-
requiresStringContent: compat.requiresStringContent ?? false,
|
|
1764
|
-
strictMessageKeys: compat.strictMessageKeys === true
|
|
1765
|
-
};
|
|
1766
|
-
}
|
|
1767
|
-
//#endregion
|
|
1768
1455
|
//#region packages/ai/src/transports/openai-completions-params.ts
|
|
1769
1456
|
function isKnownOpenAICompletionsEndpoint(model) {
|
|
1770
1457
|
if (!model.baseUrl.trim()) return true;
|
|
@@ -1776,7 +1463,7 @@ function isKnownOpenAICompletionsEndpoint(model) {
|
|
|
1776
1463
|
return false;
|
|
1777
1464
|
}
|
|
1778
1465
|
}
|
|
1779
|
-
function resolveOpenAICompletionsReasoningEffort
|
|
1466
|
+
function resolveOpenAICompletionsReasoningEffort(options) {
|
|
1780
1467
|
return options?.reasoningEffort ?? options?.reasoning ?? "high";
|
|
1781
1468
|
}
|
|
1782
1469
|
function resolveOpenAICompletionsMaxTokens(model, options) {
|
|
@@ -1908,10 +1595,11 @@ function convertTools(tools, compat, model) {
|
|
|
1908
1595
|
function buildOpenAICompletionsParams(model, context, options) {
|
|
1909
1596
|
const compat = getCompat(model);
|
|
1910
1597
|
const compatDetection = detectOpenAICompletionsCompat(model);
|
|
1911
|
-
|
|
1598
|
+
const completionsContext = context.systemPrompt ? {
|
|
1912
1599
|
...context,
|
|
1913
1600
|
systemPrompt: stripSystemPromptCacheBoundary(context.systemPrompt)
|
|
1914
|
-
} : context
|
|
1601
|
+
} : context;
|
|
1602
|
+
let messages = convertMessages(model, completionsContext, compat);
|
|
1915
1603
|
applyCompletionsReplay(messages, context, model, compat);
|
|
1916
1604
|
if (compat.strictMessageKeys) messages = stripCompletionMessagesToRoleContent(messages);
|
|
1917
1605
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention);
|
|
@@ -1972,10 +1660,12 @@ function buildOpenAICompletionsParams(model, context, options) {
|
|
|
1972
1660
|
emitModelTransportDebug(log, `[completions] clamp_max_tokens provider=${model.provider} api=${model.api} model=${model.id} requested=${effectiveMaxTokens} output=${clampedMaxTokens} effectiveContext=${effectiveContextTokens} estimatedInput=${estimatedInputTokens}`);
|
|
1973
1661
|
}
|
|
1974
1662
|
}
|
|
1975
|
-
if (clampedMaxTokens)
|
|
1976
|
-
|
|
1663
|
+
if (clampedMaxTokens) {
|
|
1664
|
+
if (compat.maxTokensField === "max_tokens") params.max_tokens = clampedMaxTokens;
|
|
1665
|
+
else params.max_completion_tokens = clampedMaxTokens;
|
|
1666
|
+
}
|
|
1977
1667
|
}
|
|
1978
|
-
const completionsReasoningEffort = resolveOpenAICompletionsReasoningEffort
|
|
1668
|
+
const completionsReasoningEffort = resolveOpenAICompletionsReasoningEffort(options);
|
|
1979
1669
|
const resolvedCompletionsReasoningEffort = completionsReasoningEffort ? resolveOpenAIReasoningEffortForModel({
|
|
1980
1670
|
model,
|
|
1981
1671
|
effort: completionsReasoningEffort,
|
|
@@ -2001,692 +1691,6 @@ function buildOpenAICompletionsParams(model, context, options) {
|
|
|
2001
1691
|
return params;
|
|
2002
1692
|
}
|
|
2003
1693
|
//#endregion
|
|
2004
|
-
//#region packages/ai/src/transports/openai-completions-dsml.ts
|
|
2005
|
-
const DEEPSEEK_DSML_BARS = ["|", "|"];
|
|
2006
|
-
const DEEPSEEK_DSML_TOOL_KINDS = [
|
|
2007
|
-
"tool_calls",
|
|
2008
|
-
"tool_call",
|
|
2009
|
-
"function_calls"
|
|
2010
|
-
];
|
|
2011
|
-
const DEEPSEEK_DSML_TOOL_OPEN_TOKENS = DEEPSEEK_DSML_BARS.flatMap((bar) => DEEPSEEK_DSML_TOOL_KINDS.map((kind) => `<${bar}DSML${bar}${kind}>`));
|
|
2012
|
-
const DEEPSEEK_DSML_TOOL_CLOSE_TOKENS = DEEPSEEK_DSML_BARS.flatMap((bar) => DEEPSEEK_DSML_TOOL_KINDS.map((kind) => `</${bar}DSML${bar}${kind}>`));
|
|
2013
|
-
const DEEPSEEK_DSML_INVOKE_OPEN_PREFIXES = DEEPSEEK_DSML_BARS.map((bar) => `<${bar}DSML${bar}invoke`);
|
|
2014
|
-
const DEEPSEEK_DSML_INVOKE_CLOSE_TOKENS = DEEPSEEK_DSML_BARS.map((bar) => `</${bar}DSML${bar}invoke>`);
|
|
2015
|
-
const DEEPSEEK_DSML_TOOL_MAX_OPEN_TOKEN_LEN = Math.max(...DEEPSEEK_DSML_TOOL_OPEN_TOKENS.map((token) => token.length));
|
|
2016
|
-
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));
|
|
2017
|
-
const MAX_DSML_RECOVERY_BUFFER_BYTES = 256e3;
|
|
2018
|
-
const DEEPSEEK_DSML_SCAN_BATCH_CHARS = 64 * 1024;
|
|
2019
|
-
function createDsmlRecoverer() {
|
|
2020
|
-
let buffer = "";
|
|
2021
|
-
let bufferBytes = 0;
|
|
2022
|
-
let bufferEndsWithHighSurrogate = false;
|
|
2023
|
-
let pendingScanChars = 0;
|
|
2024
|
-
let activeOpenToken = null;
|
|
2025
|
-
let blockScanState = {
|
|
2026
|
-
offset: 0,
|
|
2027
|
-
mode: "outer",
|
|
2028
|
-
invokeOpenStart: -1
|
|
2029
|
-
};
|
|
2030
|
-
const resetBlockScan = () => {
|
|
2031
|
-
activeOpenToken = null;
|
|
2032
|
-
pendingScanChars = 0;
|
|
2033
|
-
blockScanState = {
|
|
2034
|
-
offset: 0,
|
|
2035
|
-
mode: "outer",
|
|
2036
|
-
invokeOpenStart: -1
|
|
2037
|
-
};
|
|
2038
|
-
};
|
|
2039
|
-
const consume = (final) => {
|
|
2040
|
-
const output = [];
|
|
2041
|
-
while (buffer) {
|
|
2042
|
-
const open = activeOpenToken ? {
|
|
2043
|
-
index: 0,
|
|
2044
|
-
token: activeOpenToken
|
|
2045
|
-
} : findEarliestStringToken(buffer, DEEPSEEK_DSML_TOOL_OPEN_TOKENS);
|
|
2046
|
-
if (!open) {
|
|
2047
|
-
resetBlockScan();
|
|
2048
|
-
if (final) {
|
|
2049
|
-
output.push({
|
|
2050
|
-
kind: "text",
|
|
2051
|
-
text: buffer
|
|
2052
|
-
});
|
|
2053
|
-
buffer = "";
|
|
2054
|
-
bufferBytes = 0;
|
|
2055
|
-
bufferEndsWithHighSurrogate = false;
|
|
2056
|
-
return output;
|
|
2057
|
-
}
|
|
2058
|
-
const keep = longestDeepSeekDsmlToolOpenPrefixSuffixLength(buffer);
|
|
2059
|
-
const emitLength = buffer.length - keep;
|
|
2060
|
-
if (emitLength > 0) {
|
|
2061
|
-
const emitted = buffer.slice(0, emitLength);
|
|
2062
|
-
output.push({
|
|
2063
|
-
kind: "text",
|
|
2064
|
-
text: emitted
|
|
2065
|
-
});
|
|
2066
|
-
bufferBytes -= Buffer.byteLength(emitted, "utf8");
|
|
2067
|
-
buffer = buffer.slice(emitted.length);
|
|
2068
|
-
if (!buffer) bufferEndsWithHighSurrogate = false;
|
|
2069
|
-
}
|
|
2070
|
-
return output;
|
|
2071
|
-
}
|
|
2072
|
-
if (open.index > 0) {
|
|
2073
|
-
const prefix = buffer.slice(0, open.index);
|
|
2074
|
-
output.push({
|
|
2075
|
-
kind: "text",
|
|
2076
|
-
text: prefix
|
|
2077
|
-
});
|
|
2078
|
-
bufferBytes -= Buffer.byteLength(prefix, "utf8");
|
|
2079
|
-
buffer = buffer.slice(prefix.length);
|
|
2080
|
-
resetBlockScan();
|
|
2081
|
-
}
|
|
2082
|
-
activeOpenToken = open.token;
|
|
2083
|
-
if (blockScanState.offset === 0) blockScanState.offset = open.token.length;
|
|
2084
|
-
const blockScan = scanDeepSeekDsmlToolBlock(buffer, open.token.replace("<", "</"), open.token.length, blockScanState);
|
|
2085
|
-
if (blockScan.kind === "nested-open") throw new Error("Nested DeepSeek DSML recovery wrappers are not supported");
|
|
2086
|
-
const close = blockScan.kind === "close" ? blockScan : null;
|
|
2087
|
-
if (!close) {
|
|
2088
|
-
if (final) {
|
|
2089
|
-
output.push({
|
|
2090
|
-
kind: "text",
|
|
2091
|
-
text: buffer
|
|
2092
|
-
});
|
|
2093
|
-
buffer = "";
|
|
2094
|
-
bufferBytes = 0;
|
|
2095
|
-
bufferEndsWithHighSurrogate = false;
|
|
2096
|
-
return output;
|
|
2097
|
-
}
|
|
2098
|
-
if (bufferBytes > MAX_DSML_RECOVERY_BUFFER_BYTES) throw new Error("Exceeded DeepSeek DSML recovery buffer limit");
|
|
2099
|
-
return output;
|
|
2100
|
-
}
|
|
2101
|
-
resetBlockScan();
|
|
2102
|
-
const body = buffer.slice(open.token.length, close.index);
|
|
2103
|
-
const blockText = buffer.slice(0, close.index + close.token.length);
|
|
2104
|
-
if (Buffer.byteLength(blockText, "utf8") > MAX_DSML_RECOVERY_BUFFER_BYTES) throw new Error("Exceeded DeepSeek DSML recovery buffer limit");
|
|
2105
|
-
const recoveredToolCalls = parseDeepSeekDsmlToolCallBlock(body);
|
|
2106
|
-
if (recoveredToolCalls.length > 0) output.push(...recoveredToolCalls);
|
|
2107
|
-
else output.push({
|
|
2108
|
-
kind: "text",
|
|
2109
|
-
text: blockText
|
|
2110
|
-
});
|
|
2111
|
-
bufferBytes -= Buffer.byteLength(blockText, "utf8");
|
|
2112
|
-
buffer = buffer.slice(blockText.length);
|
|
2113
|
-
if (!buffer) bufferEndsWithHighSurrogate = false;
|
|
2114
|
-
}
|
|
2115
|
-
return output;
|
|
2116
|
-
};
|
|
2117
|
-
return {
|
|
2118
|
-
push(chunk) {
|
|
2119
|
-
const append = measureUtf8AppendBytes(bufferEndsWithHighSurrogate, chunk);
|
|
2120
|
-
bufferBytes += append.bytes;
|
|
2121
|
-
bufferEndsWithHighSurrogate = append.endsWithHighSurrogate;
|
|
2122
|
-
buffer += chunk;
|
|
2123
|
-
pendingScanChars += chunk.length;
|
|
2124
|
-
if (activeOpenToken && pendingScanChars < DEEPSEEK_DSML_SCAN_BATCH_CHARS && !chunk.includes("<") && !chunk.includes(">") && bufferBytes <= MAX_DSML_RECOVERY_BUFFER_BYTES) return [];
|
|
2125
|
-
pendingScanChars = 0;
|
|
2126
|
-
return consume(false);
|
|
2127
|
-
},
|
|
2128
|
-
flush() {
|
|
2129
|
-
return consume(true);
|
|
2130
|
-
}
|
|
2131
|
-
};
|
|
2132
|
-
}
|
|
2133
|
-
function parseDeepSeekDsmlToolCallBlock(body) {
|
|
2134
|
-
const toolCalls = [];
|
|
2135
|
-
const invokeOpenRegex = /<[||]DSML[||]invoke\b([^<>]*)>/g;
|
|
2136
|
-
let openMatch;
|
|
2137
|
-
while ((openMatch = invokeOpenRegex.exec(body)) !== null) {
|
|
2138
|
-
const invokeBodyStart = openMatch.index + openMatch[0].length;
|
|
2139
|
-
const invokeClose = findEarliestStringToken(body.slice(invokeBodyStart), ["</|DSML|invoke>", "</|DSML|invoke>"]);
|
|
2140
|
-
if (!invokeClose) break;
|
|
2141
|
-
const invokeBody = body.slice(invokeBodyStart, invokeBodyStart + invokeClose.index);
|
|
2142
|
-
invokeOpenRegex.lastIndex = invokeBodyStart + invokeClose.index + invokeClose.token.length;
|
|
2143
|
-
const invokeName = parseXmlAttribute(openMatch[1] ?? "", "name");
|
|
2144
|
-
if (!invokeName) continue;
|
|
2145
|
-
const parsedArguments = parseDeepSeekDsmlInvokeArguments(invokeBody);
|
|
2146
|
-
if (!parsedArguments) continue;
|
|
2147
|
-
toolCalls.push({
|
|
2148
|
-
kind: "toolCall",
|
|
2149
|
-
name: invokeName,
|
|
2150
|
-
arguments: parsedArguments,
|
|
2151
|
-
partialArgs: JSON.stringify(parsedArguments)
|
|
2152
|
-
});
|
|
2153
|
-
}
|
|
2154
|
-
return toolCalls;
|
|
2155
|
-
}
|
|
2156
|
-
function parseDeepSeekDsmlInvokeArguments(body) {
|
|
2157
|
-
const args = {};
|
|
2158
|
-
const parameterRegex = /<[||]DSML[||]parameter\b([^>]*)>([\s\S]*?)<\/[||]DSML[||]parameter>/g;
|
|
2159
|
-
let parameterMatch;
|
|
2160
|
-
while ((parameterMatch = parameterRegex.exec(body)) !== null) {
|
|
2161
|
-
const name = parseXmlAttribute(parameterMatch[1] ?? "", "name");
|
|
2162
|
-
if (!name) continue;
|
|
2163
|
-
const rawValue = parameterMatch[2] ?? "";
|
|
2164
|
-
if (rawValue.length === 0) continue;
|
|
2165
|
-
args[name] = decodeDeepSeekDsmlText(rawValue);
|
|
2166
|
-
}
|
|
2167
|
-
if (Object.keys(args).length > 0) return args;
|
|
2168
|
-
const trimmed = body.trim();
|
|
2169
|
-
if (!trimmed.startsWith("{")) return null;
|
|
2170
|
-
try {
|
|
2171
|
-
const parsed = JSON.parse(trimmed);
|
|
2172
|
-
if (isRecord(parsed) && Object.keys(parsed).length > 0) return parsed;
|
|
2173
|
-
} catch {
|
|
2174
|
-
return null;
|
|
2175
|
-
}
|
|
2176
|
-
return null;
|
|
2177
|
-
}
|
|
2178
|
-
const xmlAttributeRegexCache = /* @__PURE__ */ new Map();
|
|
2179
|
-
function xmlAttributeRegex(name) {
|
|
2180
|
-
const cached = xmlAttributeRegexCache.get(name);
|
|
2181
|
-
if (cached) return cached;
|
|
2182
|
-
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2183
|
-
const pattern = new RegExp(`\\b${escaped}=("([^"]*)"|'([^']*)'|([^\\s>]+))`);
|
|
2184
|
-
xmlAttributeRegexCache.set(name, pattern);
|
|
2185
|
-
return pattern;
|
|
2186
|
-
}
|
|
2187
|
-
function parseXmlAttribute(attributes, name) {
|
|
2188
|
-
const match = xmlAttributeRegex(name).exec(attributes);
|
|
2189
|
-
const value = match?.[2] ?? match?.[3] ?? match?.[4];
|
|
2190
|
-
return value ? decodeDeepSeekDsmlText(value) : null;
|
|
2191
|
-
}
|
|
2192
|
-
function decodeDeepSeekDsmlText(value) {
|
|
2193
|
-
return value.replaceAll(""", "\"").replaceAll("'", "'").replaceAll("<", "<").replaceAll(">", ">").replaceAll("&", "&");
|
|
2194
|
-
}
|
|
2195
|
-
function findEarliestStringToken(text, tokens, fromIndex = 0) {
|
|
2196
|
-
let best = null;
|
|
2197
|
-
for (const token of tokens) {
|
|
2198
|
-
const index = text.indexOf(token, fromIndex);
|
|
2199
|
-
if (index !== -1 && (!best || index < best.index)) best = {
|
|
2200
|
-
index,
|
|
2201
|
-
token
|
|
2202
|
-
};
|
|
2203
|
-
}
|
|
2204
|
-
return best;
|
|
2205
|
-
}
|
|
2206
|
-
function scanDeepSeekDsmlToolBlock(text, closeToken, contentStartIndex, state) {
|
|
2207
|
-
while (state.offset < text.length) {
|
|
2208
|
-
if (state.mode === "invoke-open") {
|
|
2209
|
-
const nextOpen = text.indexOf("<", state.offset);
|
|
2210
|
-
const nextClose = text.indexOf(">", state.offset);
|
|
2211
|
-
if (nextClose === -1 && nextOpen === -1) {
|
|
2212
|
-
state.offset = text.length;
|
|
2213
|
-
return { kind: "incomplete" };
|
|
2214
|
-
}
|
|
2215
|
-
if (nextOpen !== -1 && (nextClose === -1 || nextOpen < nextClose)) {
|
|
2216
|
-
state.mode = "outer";
|
|
2217
|
-
state.offset = nextOpen;
|
|
2218
|
-
state.invokeOpenStart = -1;
|
|
2219
|
-
continue;
|
|
2220
|
-
}
|
|
2221
|
-
const invokeOpenTag = text.slice(state.invokeOpenStart, nextClose + 1);
|
|
2222
|
-
if (!/^<[||]DSML[||]invoke\b[^<>]*>$/.test(invokeOpenTag)) {
|
|
2223
|
-
state.mode = "outer";
|
|
2224
|
-
state.offset = state.invokeOpenStart + 1;
|
|
2225
|
-
state.invokeOpenStart = -1;
|
|
2226
|
-
continue;
|
|
2227
|
-
}
|
|
2228
|
-
state.mode = "invoke-body";
|
|
2229
|
-
state.offset = nextClose + 1;
|
|
2230
|
-
state.invokeOpenStart = -1;
|
|
2231
|
-
continue;
|
|
2232
|
-
}
|
|
2233
|
-
if (state.mode === "invoke-body") {
|
|
2234
|
-
const invokeClose = findEarliestStringToken(text, DEEPSEEK_DSML_INVOKE_CLOSE_TOKENS, state.offset);
|
|
2235
|
-
if (!invokeClose) {
|
|
2236
|
-
state.offset = Math.max(0, text.length - DEEPSEEK_DSML_RECOVERY_MAX_BOUNDARY_LEN + 1);
|
|
2237
|
-
return { kind: "incomplete" };
|
|
2238
|
-
}
|
|
2239
|
-
state.mode = "outer";
|
|
2240
|
-
state.offset = invokeClose.index + invokeClose.token.length;
|
|
2241
|
-
continue;
|
|
2242
|
-
}
|
|
2243
|
-
const toolOpen = findEarliestStringToken(text, DEEPSEEK_DSML_TOOL_OPEN_TOKENS, state.offset);
|
|
2244
|
-
const toolCloseIndex = text.indexOf(closeToken, state.offset);
|
|
2245
|
-
const invokeOpen = findEarliestStringToken(text, DEEPSEEK_DSML_INVOKE_OPEN_PREFIXES, state.offset);
|
|
2246
|
-
const next = [
|
|
2247
|
-
toolOpen ? {
|
|
2248
|
-
kind: "nested-open",
|
|
2249
|
-
...toolOpen
|
|
2250
|
-
} : null,
|
|
2251
|
-
toolCloseIndex === -1 ? null : {
|
|
2252
|
-
kind: "close",
|
|
2253
|
-
index: toolCloseIndex,
|
|
2254
|
-
token: closeToken
|
|
2255
|
-
},
|
|
2256
|
-
invokeOpen ? {
|
|
2257
|
-
kind: "invoke-open",
|
|
2258
|
-
...invokeOpen
|
|
2259
|
-
} : null
|
|
2260
|
-
].filter((candidate) => candidate !== null).toSorted((left, right) => left.index - right.index)[0];
|
|
2261
|
-
if (!next) {
|
|
2262
|
-
state.offset = Math.max(contentStartIndex, text.length - DEEPSEEK_DSML_RECOVERY_MAX_BOUNDARY_LEN + 1);
|
|
2263
|
-
return { kind: "incomplete" };
|
|
2264
|
-
}
|
|
2265
|
-
if (next.kind === "invoke-open") {
|
|
2266
|
-
state.mode = "invoke-open";
|
|
2267
|
-
state.invokeOpenStart = next.index;
|
|
2268
|
-
state.offset = next.index + next.token.length;
|
|
2269
|
-
continue;
|
|
2270
|
-
}
|
|
2271
|
-
return next;
|
|
2272
|
-
}
|
|
2273
|
-
return { kind: "incomplete" };
|
|
2274
|
-
}
|
|
2275
|
-
function longestDeepSeekDsmlToolOpenPrefixSuffixLength(text) {
|
|
2276
|
-
const maxLength = Math.min(text.length, DEEPSEEK_DSML_TOOL_MAX_OPEN_TOKEN_LEN - 1);
|
|
2277
|
-
for (let length = maxLength; length > 0; length -= 1) {
|
|
2278
|
-
const suffix = text.slice(text.length - length);
|
|
2279
|
-
if (DEEPSEEK_DSML_TOOL_OPEN_TOKENS.some((token) => token.startsWith(suffix))) return length;
|
|
2280
|
-
}
|
|
2281
|
-
return 0;
|
|
2282
|
-
}
|
|
2283
|
-
//#endregion
|
|
2284
|
-
//#region packages/ai/src/transports/openai-completions-stream.ts
|
|
2285
|
-
function extractToolCallThoughtSignature(toolCall) {
|
|
2286
|
-
const tc = toolCall;
|
|
2287
|
-
if (!tc) return;
|
|
2288
|
-
const fromExtra = (tc.extra_content?.google)?.thought_signature;
|
|
2289
|
-
if (typeof fromExtra === "string" && fromExtra.length > 0) return fromExtra;
|
|
2290
|
-
const fromFunction = tc.function?.thought_signature;
|
|
2291
|
-
if (typeof fromFunction === "string" && fromFunction.length > 0) return fromFunction;
|
|
2292
|
-
const fromToolCall = tc.thought_signature;
|
|
2293
|
-
return typeof fromToolCall === "string" && fromToolCall.length > 0 ? fromToolCall : void 0;
|
|
2294
|
-
}
|
|
2295
|
-
async function processCompletionsStream(responseStream, output, model, stream, options) {
|
|
2296
|
-
const MAX_POST_TOOL_CALL_BUFFER_BYTES = 256e3;
|
|
2297
|
-
const emitReasoning = options?.emitReasoning ?? true;
|
|
2298
|
-
const compat = getCompat(model);
|
|
2299
|
-
const visibleReasoningDetailTypes = new Set(compat.visibleReasoningDetailTypes);
|
|
2300
|
-
const shouldFilterDeepSeekDsmlText = compat.thinkingFormat === "deepseek";
|
|
2301
|
-
const deepSeekTextFilter = shouldFilterDeepSeekDsmlText ? createDeepSeekTextFilter() : null;
|
|
2302
|
-
const deepSeekToolCallRecoverer = shouldFilterDeepSeekDsmlText ? createDsmlRecoverer() : null;
|
|
2303
|
-
const reasoningTagTextPartitioner = createReasoningTagTextPartitioner();
|
|
2304
|
-
let currentBlock = null;
|
|
2305
|
-
let currentTextSource;
|
|
2306
|
-
let pendingInterruptedTextBlock = null;
|
|
2307
|
-
let confirmedInterruptedTextBlock = null;
|
|
2308
|
-
let pendingPostToolCallDeltas = [];
|
|
2309
|
-
let pendingPostToolCallBytes = 0;
|
|
2310
|
-
let isFlushingPendingPostToolCallDeltas = false;
|
|
2311
|
-
const toolCallBlocksByIndex = /* @__PURE__ */ new Map();
|
|
2312
|
-
const toolCallBlocksById = /* @__PURE__ */ new Map();
|
|
2313
|
-
const provisionalCommentaryTags = /* @__PURE__ */ new Map();
|
|
2314
|
-
const toolCallBlockIndices = /* @__PURE__ */ new WeakMap();
|
|
2315
|
-
let explicitVisibleTextBlocks;
|
|
2316
|
-
const normalizeToolCallDeltas = createOpenAICompletionsToolCallDeltaNormalizer();
|
|
2317
|
-
let sawStopFinishReason = false;
|
|
2318
|
-
let sawNativeToolCallDelta = false;
|
|
2319
|
-
const blockIndex = () => output.content.length - 1;
|
|
2320
|
-
const measureUtf8Bytes = (text) => Buffer.byteLength(text, "utf8");
|
|
2321
|
-
let chunkPushedEvent = false;
|
|
2322
|
-
const pushStreamEvent = (event) => {
|
|
2323
|
-
chunkPushedEvent = true;
|
|
2324
|
-
stream.push(event);
|
|
2325
|
-
};
|
|
2326
|
-
const queuePostToolCallDelta = (next) => {
|
|
2327
|
-
const nextBytes = measureUtf8Bytes(next.text);
|
|
2328
|
-
if (pendingPostToolCallBytes + nextBytes > MAX_POST_TOOL_CALL_BUFFER_BYTES) throw new Error("Exceeded post-tool-call delta buffer limit");
|
|
2329
|
-
pendingPostToolCallBytes += nextBytes;
|
|
2330
|
-
const previous = pendingPostToolCallDeltas[pendingPostToolCallDeltas.length - 1];
|
|
2331
|
-
if (!previous || previous.kind !== next.kind || previous.kind === "text" && next.kind === "text" && previous.source !== next.source) {
|
|
2332
|
-
pendingPostToolCallDeltas.push(next);
|
|
2333
|
-
return;
|
|
2334
|
-
}
|
|
2335
|
-
if (next.kind === "thinking" && previous.kind === "thinking") {
|
|
2336
|
-
if (previous.signature !== next.signature) {
|
|
2337
|
-
pendingPostToolCallDeltas.push(next);
|
|
2338
|
-
return;
|
|
2339
|
-
}
|
|
2340
|
-
previous.text += next.text;
|
|
2341
|
-
return;
|
|
2342
|
-
}
|
|
2343
|
-
previous.text += next.text;
|
|
2344
|
-
};
|
|
2345
|
-
const appendThinkingDeltaInternal = (reasoningDelta) => {
|
|
2346
|
-
if (!currentBlock || currentBlock.type !== "thinking") {
|
|
2347
|
-
currentBlock = {
|
|
2348
|
-
type: "thinking",
|
|
2349
|
-
thinking: "",
|
|
2350
|
-
...reasoningDelta.signature ? { thinkingSignature: reasoningDelta.signature } : {}
|
|
2351
|
-
};
|
|
2352
|
-
output.content.push(currentBlock);
|
|
2353
|
-
pushStreamEvent({
|
|
2354
|
-
type: "thinking_start",
|
|
2355
|
-
contentIndex: blockIndex(),
|
|
2356
|
-
partial: output
|
|
2357
|
-
});
|
|
2358
|
-
}
|
|
2359
|
-
currentBlock.thinking += reasoningDelta.text;
|
|
2360
|
-
pushStreamEvent({
|
|
2361
|
-
type: "thinking_delta",
|
|
2362
|
-
contentIndex: blockIndex(),
|
|
2363
|
-
delta: reasoningDelta.text,
|
|
2364
|
-
partial: output
|
|
2365
|
-
});
|
|
2366
|
-
};
|
|
2367
|
-
const appendTextDeltaInternal = (text, source) => {
|
|
2368
|
-
if (currentBlock?.type === "text" && currentTextSource !== source) currentBlock = null;
|
|
2369
|
-
if (!currentBlock || currentBlock.type !== "text") {
|
|
2370
|
-
currentBlock = {
|
|
2371
|
-
type: "text",
|
|
2372
|
-
text: ""
|
|
2373
|
-
};
|
|
2374
|
-
currentTextSource = source;
|
|
2375
|
-
if (source === "reasoning_detail") (explicitVisibleTextBlocks ??= /* @__PURE__ */ new Set()).add(currentBlock);
|
|
2376
|
-
output.content.push(currentBlock);
|
|
2377
|
-
pushStreamEvent({
|
|
2378
|
-
type: "text_start",
|
|
2379
|
-
contentIndex: blockIndex(),
|
|
2380
|
-
partial: output
|
|
2381
|
-
});
|
|
2382
|
-
}
|
|
2383
|
-
currentBlock.text += text;
|
|
2384
|
-
if (pendingInterruptedTextBlock && text.trim()) {
|
|
2385
|
-
confirmedInterruptedTextBlock = pendingInterruptedTextBlock;
|
|
2386
|
-
pendingInterruptedTextBlock = null;
|
|
2387
|
-
}
|
|
2388
|
-
pushStreamEvent({
|
|
2389
|
-
type: "text_delta",
|
|
2390
|
-
contentIndex: blockIndex(),
|
|
2391
|
-
delta: text
|
|
2392
|
-
});
|
|
2393
|
-
};
|
|
2394
|
-
const flushPendingPostToolCallDeltas = () => {
|
|
2395
|
-
if (isFlushingPendingPostToolCallDeltas || currentBlock?.type === "toolCall" || pendingPostToolCallDeltas.length === 0) return;
|
|
2396
|
-
isFlushingPendingPostToolCallDeltas = true;
|
|
2397
|
-
const bufferedDeltas = pendingPostToolCallDeltas;
|
|
2398
|
-
pendingPostToolCallDeltas = [];
|
|
2399
|
-
pendingPostToolCallBytes = 0;
|
|
2400
|
-
for (const delta of bufferedDeltas) if (delta.kind === "text") appendTextDeltaInternal(delta.text, delta.source);
|
|
2401
|
-
else if (emitReasoning) appendThinkingDeltaInternal(delta);
|
|
2402
|
-
isFlushingPendingPostToolCallDeltas = false;
|
|
2403
|
-
};
|
|
2404
|
-
const appendThinkingDelta = (reasoningDelta) => {
|
|
2405
|
-
flushPendingPostToolCallDeltas();
|
|
2406
|
-
appendThinkingDeltaInternal(reasoningDelta);
|
|
2407
|
-
};
|
|
2408
|
-
const appendTextDelta = (text, source) => {
|
|
2409
|
-
flushPendingPostToolCallDeltas();
|
|
2410
|
-
appendTextDeltaInternal(text, source);
|
|
2411
|
-
};
|
|
2412
|
-
const appendVisibleTextDelta = (text) => {
|
|
2413
|
-
if (!text) return;
|
|
2414
|
-
if (currentBlock?.type === "toolCall") queuePostToolCallDelta({
|
|
2415
|
-
kind: "text",
|
|
2416
|
-
text
|
|
2417
|
-
});
|
|
2418
|
-
else appendTextDelta(text);
|
|
2419
|
-
};
|
|
2420
|
-
const appendReasoningDeltas = (reasoningDeltas) => {
|
|
2421
|
-
for (const reasoningDelta of reasoningDeltas) {
|
|
2422
|
-
if (reasoningDelta.kind === "thinking" && !emitReasoning) continue;
|
|
2423
|
-
if (currentBlock?.type === "toolCall") {
|
|
2424
|
-
queuePostToolCallDelta({ ...reasoningDelta });
|
|
2425
|
-
continue;
|
|
2426
|
-
}
|
|
2427
|
-
if (reasoningDelta.kind === "text") appendTextDelta(reasoningDelta.text, reasoningDelta.source);
|
|
2428
|
-
else if (emitReasoning) appendThinkingDelta(reasoningDelta);
|
|
2429
|
-
}
|
|
2430
|
-
};
|
|
2431
|
-
const appendRecoveredToolCall = (toolCall) => {
|
|
2432
|
-
if (currentBlock?.type === "toolCall") {
|
|
2433
|
-
currentBlock = null;
|
|
2434
|
-
flushPendingPostToolCallDeltas();
|
|
2435
|
-
}
|
|
2436
|
-
rememberPendingCommentaryTags(provisionalCommentaryTags, tagPendingCommentaryText(output.content));
|
|
2437
|
-
const block = {
|
|
2438
|
-
type: "toolCall",
|
|
2439
|
-
id: `call_${randomUUID().replaceAll("-", "").slice(0, 24)}`,
|
|
2440
|
-
name: toolCall.name,
|
|
2441
|
-
arguments: toolCall.arguments,
|
|
2442
|
-
partialArgs: toolCall.partialArgs
|
|
2443
|
-
};
|
|
2444
|
-
currentBlock = block;
|
|
2445
|
-
output.content.push(block);
|
|
2446
|
-
toolCallBlockIndices.set(block, output.content.length - 1);
|
|
2447
|
-
pushStreamEvent({
|
|
2448
|
-
type: "toolcall_start",
|
|
2449
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2450
|
-
partial: output
|
|
2451
|
-
});
|
|
2452
|
-
pushStreamEvent({
|
|
2453
|
-
type: "toolcall_delta",
|
|
2454
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2455
|
-
delta: toolCall.partialArgs,
|
|
2456
|
-
partial: output
|
|
2457
|
-
});
|
|
2458
|
-
};
|
|
2459
|
-
const appendFilteredVisibleTextDelta = (text) => {
|
|
2460
|
-
const recoveredParts = deepSeekToolCallRecoverer?.push(text) ?? [{
|
|
2461
|
-
kind: "text",
|
|
2462
|
-
text
|
|
2463
|
-
}];
|
|
2464
|
-
for (const recoveredPart of recoveredParts) {
|
|
2465
|
-
if (recoveredPart.kind === "toolCall") {
|
|
2466
|
-
appendRecoveredToolCall(recoveredPart);
|
|
2467
|
-
continue;
|
|
2468
|
-
}
|
|
2469
|
-
const parts = deepSeekTextFilter?.push(recoveredPart.text) ?? [recoveredPart.text];
|
|
2470
|
-
for (const part of parts) appendVisibleTextDelta(part);
|
|
2471
|
-
}
|
|
2472
|
-
};
|
|
2473
|
-
const flushDeepSeekToolCallRecovererAtEnd = () => {
|
|
2474
|
-
const recoveredParts = deepSeekToolCallRecoverer?.flush();
|
|
2475
|
-
if (!recoveredParts) return;
|
|
2476
|
-
for (const recoveredPart of recoveredParts) {
|
|
2477
|
-
if (recoveredPart.kind === "toolCall") {
|
|
2478
|
-
appendRecoveredToolCall(recoveredPart);
|
|
2479
|
-
continue;
|
|
2480
|
-
}
|
|
2481
|
-
const parts = deepSeekTextFilter?.push(recoveredPart.text) ?? [recoveredPart.text];
|
|
2482
|
-
for (const part of parts) appendVisibleTextDelta(part);
|
|
2483
|
-
}
|
|
2484
|
-
};
|
|
2485
|
-
const flushDeepSeekTextFilterAtEnd = () => {
|
|
2486
|
-
const parts = deepSeekTextFilter?.flush();
|
|
2487
|
-
if (!parts) return;
|
|
2488
|
-
for (const part of parts) appendVisibleTextDelta(part);
|
|
2489
|
-
};
|
|
2490
|
-
const appendRoutedContentDelta = (delta) => {
|
|
2491
|
-
if (delta.kind === "text") {
|
|
2492
|
-
appendFilteredVisibleTextDelta(delta.text);
|
|
2493
|
-
return;
|
|
2494
|
-
}
|
|
2495
|
-
if (!emitReasoning) return;
|
|
2496
|
-
if (currentBlock?.type === "toolCall") queuePostToolCallDelta(delta);
|
|
2497
|
-
else appendThinkingDelta(delta);
|
|
2498
|
-
};
|
|
2499
|
-
const appendPartitionedVisibleDelta = (delta) => {
|
|
2500
|
-
if (delta.kind === "text") appendFilteredVisibleTextDelta(delta.text);
|
|
2501
|
-
};
|
|
2502
|
-
const emitReasoningUsageActivity = (hasReasoningUsageActivity) => {
|
|
2503
|
-
if (!hasReasoningUsageActivity || chunkPushedEvent || !emitReasoning) return;
|
|
2504
|
-
const latestBlock = output.content[output.content.length - 1];
|
|
2505
|
-
if (currentBlock?.type === "text" || currentBlock?.type === "toolCall") return;
|
|
2506
|
-
if (latestBlock?.type === "text" || latestBlock?.type === "toolCall") return;
|
|
2507
|
-
appendThinkingDelta({ text: "" });
|
|
2508
|
-
};
|
|
2509
|
-
const flushReasoningTagTextPartitioner = () => {
|
|
2510
|
-
for (const delta of reasoningTagTextPartitioner.flush()) appendPartitionedVisibleDelta(delta);
|
|
2511
|
-
};
|
|
2512
|
-
const sealTextBeforeReasoning = () => {
|
|
2513
|
-
if (currentBlock?.type !== "text" && !reasoningTagTextPartitioner.hasPending()) return;
|
|
2514
|
-
flushReasoningTagTextPartitioner();
|
|
2515
|
-
if (currentBlock?.type !== "text") return;
|
|
2516
|
-
if (currentTextSource !== "reasoning_detail" && currentBlock.text.trim()) pendingInterruptedTextBlock = currentBlock;
|
|
2517
|
-
currentBlock = null;
|
|
2518
|
-
currentTextSource = void 0;
|
|
2519
|
-
};
|
|
2520
|
-
const beginReasoning = (hasFollowingVisibleText, forceStrict = false) => {
|
|
2521
|
-
if (!output.openclawDelivery?.textPhaseRequiresTerminal) output.openclawDelivery = {
|
|
2522
|
-
...output.openclawDelivery,
|
|
2523
|
-
textPhaseRequiresTerminal: true
|
|
2524
|
-
};
|
|
2525
|
-
if (forceStrict || reasoningTagTextPartitioner.hasPending()) reasoningTagTextPartitioner.markStrict();
|
|
2526
|
-
if (!hasFollowingVisibleText || !reasoningTagTextPartitioner.hasPendingSyntax()) sealTextBeforeReasoning();
|
|
2527
|
-
};
|
|
2528
|
-
const cooperativeScheduler = createModelStreamCooperativeScheduler(options?.signal);
|
|
2529
|
-
const guardedStream = withFirstStreamEventTimeout(responseStream, {
|
|
2530
|
-
provider: model.provider,
|
|
2531
|
-
api: model.api,
|
|
2532
|
-
model: model.id,
|
|
2533
|
-
timeoutMs: options?.firstEventTimeoutMs ?? 0,
|
|
2534
|
-
stage: "completions",
|
|
2535
|
-
abort: options?.abortFirstEventStream,
|
|
2536
|
-
onTimeout: options?.onFirstEventTimeout,
|
|
2537
|
-
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."
|
|
2538
|
-
});
|
|
2539
|
-
for await (const rawChunk of guardedStream) {
|
|
2540
|
-
throwIfModelStreamAborted(options?.signal);
|
|
2541
|
-
chunkPushedEvent = false;
|
|
2542
|
-
if (!rawChunk || typeof rawChunk !== "object") {
|
|
2543
|
-
await cooperativeScheduler.afterEvent();
|
|
2544
|
-
continue;
|
|
2545
|
-
}
|
|
2546
|
-
notifyLlmRequestActivity(options?.signal);
|
|
2547
|
-
const chunk = rawChunk;
|
|
2548
|
-
output.responseId ||= chunk.id;
|
|
2549
|
-
let hasReasoningUsageActivity = false;
|
|
2550
|
-
if (chunk.usage) {
|
|
2551
|
-
output.usage = parseOpenAICompletionsUsage(chunk.usage, model);
|
|
2552
|
-
hasReasoningUsageActivity = hasOpenAICompletionsReasoningUsageActivity(chunk.usage);
|
|
2553
|
-
}
|
|
2554
|
-
const choice = Array.isArray(chunk.choices) ? chunk.choices[0] : void 0;
|
|
2555
|
-
if (!choice) {
|
|
2556
|
-
emitReasoningUsageActivity(hasReasoningUsageActivity);
|
|
2557
|
-
await cooperativeScheduler.afterEvent();
|
|
2558
|
-
continue;
|
|
2559
|
-
}
|
|
2560
|
-
const choiceUsage = choice.usage;
|
|
2561
|
-
if (!chunk.usage && choiceUsage) {
|
|
2562
|
-
output.usage = parseOpenAICompletionsUsage(choiceUsage, model);
|
|
2563
|
-
hasReasoningUsageActivity = hasOpenAICompletionsReasoningUsageActivity(choiceUsage);
|
|
2564
|
-
}
|
|
2565
|
-
if (choice.finish_reason) {
|
|
2566
|
-
const finishReasonResult = mapOpenAIStopReason(choice.finish_reason, { allowSingularToolCall: true });
|
|
2567
|
-
output.stopReason = finishReasonResult.stopReason;
|
|
2568
|
-
if (finishReasonResult.stopReason === "stop") sawStopFinishReason = true;
|
|
2569
|
-
if (finishReasonResult.errorMessage) output.errorMessage = finishReasonResult.errorMessage;
|
|
2570
|
-
}
|
|
2571
|
-
const rawChoiceDelta = choice.delta ?? choice.message;
|
|
2572
|
-
if (!rawChoiceDelta) {
|
|
2573
|
-
emitReasoningUsageActivity(hasReasoningUsageActivity);
|
|
2574
|
-
await cooperativeScheduler.afterEvent();
|
|
2575
|
-
continue;
|
|
2576
|
-
}
|
|
2577
|
-
for (const normalizedDelta of normalizeToolCallDeltas(rawChoiceDelta, choice.finish_reason)) {
|
|
2578
|
-
const choiceDelta = normalizedDelta.delta;
|
|
2579
|
-
const reasoningBatch = readOpenAICompletionsReasoningBatch(choiceDelta, visibleReasoningDetailTypes);
|
|
2580
|
-
const reasoningDeltas = reasoningBatch.deltas;
|
|
2581
|
-
const hasReasoningThinking = reasoningBatch.hasThinking;
|
|
2582
|
-
const contentDeltas = readOpenAICompletionsContentDeltas(choiceDelta.content, choiceDelta.refusal, reasoningBatch.mirroredThinking);
|
|
2583
|
-
const lastVisibleTextIndex = contentDeltas.findLastIndex((delta) => delta.kind === "text");
|
|
2584
|
-
const hasSameChunkVisibleText = reasoningBatch.hasVisibleText || lastVisibleTextIndex !== -1;
|
|
2585
|
-
if (hasReasoningThinking) {
|
|
2586
|
-
beginReasoning(hasSameChunkVisibleText, true);
|
|
2587
|
-
appendReasoningDeltas(reasoningDeltas);
|
|
2588
|
-
}
|
|
2589
|
-
for (const [contentDeltaIndex, contentDelta] of contentDeltas.entries()) if (contentDelta.kind === "text") {
|
|
2590
|
-
const routedDeltas = hasReasoningThinking ? reasoningTagTextPartitioner.push(contentDelta.text) : reasoningTagTextPartitioner.pushVisible(contentDelta.text);
|
|
2591
|
-
for (const routedDelta of routedDeltas) appendPartitionedVisibleDelta(routedDelta);
|
|
2592
|
-
} else {
|
|
2593
|
-
beginReasoning(contentDeltaIndex < lastVisibleTextIndex);
|
|
2594
|
-
appendRoutedContentDelta(contentDelta);
|
|
2595
|
-
}
|
|
2596
|
-
if (!hasReasoningThinking) appendReasoningDeltas(reasoningDeltas);
|
|
2597
|
-
const toolCallDeltas = normalizedDelta.toolCalls;
|
|
2598
|
-
if (toolCallDeltas.length > 0) {
|
|
2599
|
-
sawNativeToolCallDelta = true;
|
|
2600
|
-
flushReasoningTagTextPartitioner();
|
|
2601
|
-
rememberPendingCommentaryTags(provisionalCommentaryTags, tagPendingCommentaryText(output.content));
|
|
2602
|
-
for (const toolCall of toolCallDeltas) {
|
|
2603
|
-
const streamIndex = typeof toolCall.index === "number" ? toolCall.index : void 0;
|
|
2604
|
-
let block = streamIndex !== void 0 ? toolCallBlocksByIndex.get(streamIndex) : void 0;
|
|
2605
|
-
if (!block && toolCall.id) block = toolCallBlocksById.get(toolCall.id);
|
|
2606
|
-
if (!block) {
|
|
2607
|
-
if (currentBlock?.type === "toolCall") {
|
|
2608
|
-
currentBlock = null;
|
|
2609
|
-
flushPendingPostToolCallDeltas();
|
|
2610
|
-
}
|
|
2611
|
-
const initialSig = extractToolCallThoughtSignature(toolCall);
|
|
2612
|
-
block = {
|
|
2613
|
-
type: "toolCall",
|
|
2614
|
-
id: toolCall.id || "",
|
|
2615
|
-
name: toolCall.function?.name || "",
|
|
2616
|
-
arguments: {},
|
|
2617
|
-
partialArgs: "",
|
|
2618
|
-
...initialSig ? { thoughtSignature: initialSig } : {}
|
|
2619
|
-
};
|
|
2620
|
-
output.content.push(block);
|
|
2621
|
-
toolCallBlockIndices.set(block, output.content.length - 1);
|
|
2622
|
-
pushStreamEvent({
|
|
2623
|
-
type: "toolcall_start",
|
|
2624
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2625
|
-
partial: output
|
|
2626
|
-
});
|
|
2627
|
-
}
|
|
2628
|
-
if (streamIndex !== void 0 && !toolCallBlocksByIndex.has(streamIndex)) toolCallBlocksByIndex.set(streamIndex, block);
|
|
2629
|
-
if (toolCall.id) {
|
|
2630
|
-
block.id = toolCall.id;
|
|
2631
|
-
toolCallBlocksById.set(toolCall.id, block);
|
|
2632
|
-
}
|
|
2633
|
-
currentBlock = block;
|
|
2634
|
-
if (toolCall.function?.name) block.name = toolCall.function.name;
|
|
2635
|
-
const deltaSig = extractToolCallThoughtSignature(toolCall);
|
|
2636
|
-
if (deltaSig) block.thoughtSignature = deltaSig;
|
|
2637
|
-
if (toolCall.function?.arguments) {
|
|
2638
|
-
block.partialArgs += toolCall.function.arguments;
|
|
2639
|
-
block.arguments = parseStreamingJson(block.partialArgs);
|
|
2640
|
-
pushStreamEvent({
|
|
2641
|
-
type: "toolcall_delta",
|
|
2642
|
-
contentIndex: toolCallBlockIndices.get(block) ?? -1,
|
|
2643
|
-
delta: toolCall.function.arguments,
|
|
2644
|
-
partial: output
|
|
2645
|
-
});
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2648
|
-
}
|
|
2649
|
-
}
|
|
2650
|
-
flushPendingPostToolCallDeltas();
|
|
2651
|
-
emitReasoningUsageActivity(hasReasoningUsageActivity);
|
|
2652
|
-
await cooperativeScheduler.afterEvent();
|
|
2653
|
-
}
|
|
2654
|
-
flushReasoningTagTextPartitioner();
|
|
2655
|
-
flushDeepSeekToolCallRecovererAtEnd();
|
|
2656
|
-
flushDeepSeekTextFilterAtEnd();
|
|
2657
|
-
currentBlock = null;
|
|
2658
|
-
flushPendingPostToolCallDeltas();
|
|
2659
|
-
finalizeOpenAICompletionsToolCalls(output, {
|
|
2660
|
-
allowSilentToolCallPromotion: sawStopFinishReason || sawNativeToolCallDelta && (options?.sawStreamDONE?.() ?? false),
|
|
2661
|
-
onConfirmedToolCall(block, contentIndex) {
|
|
2662
|
-
if (block.type !== "toolCall") return;
|
|
2663
|
-
pushStreamEvent({
|
|
2664
|
-
type: "toolcall_end",
|
|
2665
|
-
contentIndex,
|
|
2666
|
-
toolCall: block,
|
|
2667
|
-
partial: output
|
|
2668
|
-
});
|
|
2669
|
-
}
|
|
2670
|
-
});
|
|
2671
|
-
if (confirmedInterruptedTextBlock && output.stopReason !== "toolUse" && output.stopReason !== "error" && output.stopReason !== "aborted") tagInterruptedTextPhases(output.content, confirmedInterruptedTextBlock, explicitVisibleTextBlocks);
|
|
2672
|
-
if (output.stopReason !== "toolUse") clearPendingCommentaryText(provisionalCommentaryTags);
|
|
2673
|
-
if (output.stopReason === "error" || output.stopReason === "aborted") tagUnresolvedTextAsCommentary(output);
|
|
2674
|
-
if (output.stopReason === "toolUse") tagPendingCommentaryText(output.content);
|
|
2675
|
-
}
|
|
2676
|
-
function resolveOpenAICompletionsReasoningEffort(options) {
|
|
2677
|
-
return options?.reasoningEffort ?? options?.reasoning ?? "high";
|
|
2678
|
-
}
|
|
2679
|
-
function shouldEmitOpenAICompletionsReasoning(model, options) {
|
|
2680
|
-
if (!model.reasoning) return false;
|
|
2681
|
-
const effort = resolveOpenAICompletionsReasoningEffort(options);
|
|
2682
|
-
if (!effort || !isOpenAICompletionsThinkingEnabled(effort)) return false;
|
|
2683
|
-
return true;
|
|
2684
|
-
}
|
|
2685
|
-
function hasOpenAICompletionsReasoningUsageActivity(rawUsage) {
|
|
2686
|
-
const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens;
|
|
2687
|
-
return typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) && reasoningTokens > 0;
|
|
2688
|
-
}
|
|
2689
|
-
//#endregion
|
|
2690
1694
|
//#region packages/ai/src/transports/openai-completions-transport.ts
|
|
2691
1695
|
function assertOpenAICompletionsPayloadHasConversationTurn(params, model) {
|
|
2692
1696
|
const messages = params.messages;
|
|
@@ -2762,7 +1766,7 @@ function buildOpenAICompletionsClientConfig(model, context, optionHeaders) {
|
|
|
2762
1766
|
}
|
|
2763
1767
|
}
|
|
2764
1768
|
return {
|
|
2765
|
-
baseURL,
|
|
1769
|
+
baseURL: resolveOpenAIClientBaseUrl(model, baseURL),
|
|
2766
1770
|
defaultHeaders: headers,
|
|
2767
1771
|
defaultQuery: Object.keys(defaultQuery).length > 0 ? defaultQuery : void 0
|
|
2768
1772
|
};
|
|
@@ -2834,7 +1838,7 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
2834
1838
|
timeoutMs: options?.timeoutMs,
|
|
2835
1839
|
maxRetries: options?.maxRetries
|
|
2836
1840
|
})).withResponse();
|
|
2837
|
-
|
|
1841
|
+
const hookedResponseStream = withProviderResponseHook({
|
|
2838
1842
|
stream: responseStream,
|
|
2839
1843
|
signal: firstEventAbort.signal,
|
|
2840
1844
|
abort: firstEventAbort.abort,
|
|
@@ -2843,9 +1847,11 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
2843
1847
|
type: "start",
|
|
2844
1848
|
partial: output
|
|
2845
1849
|
})
|
|
2846
|
-
})
|
|
1850
|
+
});
|
|
1851
|
+
await processCompletionsStream(hookedResponseStream, output, model, stream, {
|
|
2847
1852
|
signal: options?.signal,
|
|
2848
1853
|
emitReasoning,
|
|
1854
|
+
strictReasoningTags: reasoningTagTextPolicy.isStrict(options),
|
|
2849
1855
|
firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options),
|
|
2850
1856
|
abortFirstEventStream: firstEventAbort.abort,
|
|
2851
1857
|
onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
|
|
@@ -2910,7 +1916,7 @@ async function requestPreparedOpenAIResponsesCompaction(streamFn, model, context
|
|
|
2910
1916
|
}
|
|
2911
1917
|
//#endregion
|
|
2912
1918
|
//#region packages/ai/src/transports/openai-responses-continuation.ts
|
|
2913
|
-
const HTTP_CONTINUATION_IDLE_TTL_MS =
|
|
1919
|
+
const HTTP_CONTINUATION_IDLE_TTL_MS = 3e5;
|
|
2914
1920
|
const TURN_HEADERS = /* @__PURE__ */ new Set([
|
|
2915
1921
|
"traceparent",
|
|
2916
1922
|
"x-openclaw-turn-id",
|
|
@@ -2920,7 +1926,7 @@ function jsonValuesEqual(left, right) {
|
|
|
2920
1926
|
return stableStringify(JSON.parse(JSON.stringify(left))) === stableStringify(JSON.parse(JSON.stringify(right)));
|
|
2921
1927
|
}
|
|
2922
1928
|
function requestWithoutInput(request) {
|
|
2923
|
-
const { input: _input, previous_response_id: _previousResponseId, ...rest } = request;
|
|
1929
|
+
const { input: _input, previous_response_id: _previousResponseId, instructions: _instructions, ...rest } = request;
|
|
2924
1930
|
if (!isRecord(rest.metadata)) return rest;
|
|
2925
1931
|
const metadata = Object.fromEntries(Object.entries(rest.metadata).filter(([key]) => key !== "openclaw_turn_id" && key !== "openclaw_turn_attempt"));
|
|
2926
1932
|
return {
|
|
@@ -3111,18 +2117,28 @@ function sanitizeOpenAICodexResponsesParams(model, params) {
|
|
|
3111
2117
|
stripOpenAICodexResponsesUnsupportedTextFields(params);
|
|
3112
2118
|
return params;
|
|
3113
2119
|
}
|
|
3114
|
-
function
|
|
2120
|
+
function buildOpenAIResponsesInstructionsText(context) {
|
|
3115
2121
|
if (!context.systemPrompt) return;
|
|
3116
2122
|
return sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt));
|
|
3117
2123
|
}
|
|
3118
|
-
function
|
|
3119
|
-
|
|
2124
|
+
function resolveOpenAIResponsesInstructions(model, context, usesInstructionsField) {
|
|
2125
|
+
if (!usesInstructionsField) return;
|
|
2126
|
+
const instructions = buildOpenAIResponsesInstructionsText(context);
|
|
3120
2127
|
if (instructions && instructions.trim().length > 0) return instructions;
|
|
3121
2128
|
return usesNativeOpenAICodexResponsesBackend(model) ? OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS : void 0;
|
|
3122
2129
|
}
|
|
3123
|
-
function
|
|
2130
|
+
function buildOpenAIResponsesCompactSystemMessage(model, instructions) {
|
|
2131
|
+
const compat = getCompat(model);
|
|
2132
|
+
const supportsDeveloperRole = typeof compat.supportsDeveloperRole === "boolean" ? compat.supportsDeveloperRole : void 0;
|
|
2133
|
+
const role = model.reasoning && supportsDeveloperRole !== false ? "developer" : "system";
|
|
2134
|
+
return buildResponsesInputMessage(role, [{
|
|
2135
|
+
type: "input_text",
|
|
2136
|
+
text: instructions
|
|
2137
|
+
}]);
|
|
2138
|
+
}
|
|
2139
|
+
function ensureOpenAIResponsesNonEmptyInput(messages, context) {
|
|
3124
2140
|
if (messages.length > 0 || !context.systemPrompt) return;
|
|
3125
|
-
if (!
|
|
2141
|
+
if (!buildOpenAIResponsesInstructionsText(context)) throw new Error("OpenAI Responses requires non-empty input when only systemPrompt is provided.");
|
|
3126
2142
|
messages.push(buildResponsesInputMessage("user", [{
|
|
3127
2143
|
type: "input_text",
|
|
3128
2144
|
text: " "
|
|
@@ -3136,16 +2152,12 @@ function resolveOpenAIResponsesTextFormat(responseFormat) {
|
|
|
3136
2152
|
return responseFormat;
|
|
3137
2153
|
}
|
|
3138
2154
|
function convertOpenAIResponsesMessagesForRequest(model, context, options, replayMode) {
|
|
3139
|
-
const isCodexResponses = isOpenAICodexResponsesModel(model);
|
|
3140
2155
|
const isNativeCodexResponses = usesNativeOpenAICodexResponsesBackend(model);
|
|
3141
|
-
const compat = getCompat(model);
|
|
3142
|
-
const supportsDeveloperRole = typeof compat.supportsDeveloperRole === "boolean" ? compat.supportsDeveloperRole : void 0;
|
|
3143
2156
|
const payloadPolicy = resolveOpenAIResponsesPayloadPolicy(model, { storeMode: "disable" });
|
|
3144
2157
|
const policyAllowsReplayIds = payloadPolicy.explicitStore !== false && !payloadPolicy.shouldStripStore;
|
|
3145
2158
|
const replayResponsesItemIds = !isNativeCodexResponses && (options?.replayResponsesItemIds ?? policyAllowsReplayIds);
|
|
3146
2159
|
return convertResponsesMessages(model, context, OPENAI_RESPONSES_TOOL_CALL_PROVIDERS, {
|
|
3147
|
-
includeSystemPrompt: !
|
|
3148
|
-
supportsDeveloperRole,
|
|
2160
|
+
includeSystemPrompt: !payloadPolicy.usesInstructionsField,
|
|
3149
2161
|
replayReasoningItems: true,
|
|
3150
2162
|
replayResponsesItemIds,
|
|
3151
2163
|
authProfileId: options?.authProfileId,
|
|
@@ -3154,19 +2166,19 @@ function convertOpenAIResponsesMessagesForRequest(model, context, options, repla
|
|
|
3154
2166
|
});
|
|
3155
2167
|
}
|
|
3156
2168
|
function buildOpenAIResponsesParams(model, context, options, metadata, replayMode = "checkpoint") {
|
|
3157
|
-
const isCodexResponses = isOpenAICodexResponsesModel(model);
|
|
3158
2169
|
const payloadPolicy = resolveOpenAIResponsesPayloadPolicy(model, { storeMode: "disable" });
|
|
3159
2170
|
const messages = convertOpenAIResponsesMessagesForRequest(model, context, options, replayMode);
|
|
3160
|
-
|
|
2171
|
+
ensureOpenAIResponsesNonEmptyInput(messages, context);
|
|
3161
2172
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention);
|
|
3162
2173
|
const promptCacheKey = resolvePromptCacheKey(options, cacheRetention);
|
|
2174
|
+
const instructions = resolveOpenAIResponsesInstructions(model, context, payloadPolicy.usesInstructionsField);
|
|
3163
2175
|
const params = {
|
|
3164
2176
|
model: model.id,
|
|
3165
2177
|
input: messages,
|
|
3166
2178
|
stream: true,
|
|
3167
2179
|
prompt_cache_key: promptCacheKey,
|
|
3168
2180
|
prompt_cache_retention: getPromptCacheRetention(model.baseUrl, cacheRetention),
|
|
3169
|
-
...
|
|
2181
|
+
...instructions ? { instructions } : {},
|
|
3170
2182
|
...metadata ? { metadata } : {}
|
|
3171
2183
|
};
|
|
3172
2184
|
const effectiveMaxTokens = options?.maxTokens || model.maxTokens;
|
|
@@ -3188,9 +2200,10 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
|
|
|
3188
2200
|
}
|
|
3189
2201
|
if (model.reasoning) {
|
|
3190
2202
|
if (options?.reasoningEffort || options?.reasoning || options?.reasoningSummary) {
|
|
2203
|
+
const requestedReasoningEffort = resolveOpenAIReasoningEffort(options);
|
|
3191
2204
|
const resolvedReasoningEffort = resolveOpenAIReasoningEffortForModel({
|
|
3192
2205
|
model,
|
|
3193
|
-
effort:
|
|
2206
|
+
effort: requestedReasoningEffort
|
|
3194
2207
|
});
|
|
3195
2208
|
const reasoningEffort = resolvedReasoningEffort ? raiseMinimalReasoningForResponsesWebSearch({
|
|
3196
2209
|
model,
|
|
@@ -3217,8 +2230,8 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
|
|
|
3217
2230
|
}
|
|
3218
2231
|
//#endregion
|
|
3219
2232
|
//#region packages/ai/src/transports/openai-responses-websocket.ts
|
|
3220
|
-
const SESSION_WEBSOCKET_CACHE_TTL_MS =
|
|
3221
|
-
const SESSION_WEBSOCKET_MAX_AGE_MS =
|
|
2233
|
+
const SESSION_WEBSOCKET_CACHE_TTL_MS = 3e5;
|
|
2234
|
+
const SESSION_WEBSOCKET_MAX_AGE_MS = 33e5;
|
|
3222
2235
|
const WEBSOCKET_OPEN_STATE = 1;
|
|
3223
2236
|
const websocketSessionCache = /* @__PURE__ */ new Map();
|
|
3224
2237
|
const degradedWebSocketConnections = /* @__PURE__ */ new Map();
|
|
@@ -3471,149 +2484,6 @@ function closeOpenAIResponsesWebSocketSessions(sessionId) {
|
|
|
3471
2484
|
}
|
|
3472
2485
|
registerSessionResourceCleanup(closeOpenAIResponsesWebSocketSessions);
|
|
3473
2486
|
//#endregion
|
|
3474
|
-
//#region packages/media-core/src/inline-image-data-url.ts
|
|
3475
|
-
/** Prefix used to distinguish inline data URLs from remote/local image references. */
|
|
3476
|
-
const INLINE_IMAGE_DATA_URL_PREFIX = "data:";
|
|
3477
|
-
const IMAGE_SIGNATURES = [
|
|
3478
|
-
{
|
|
3479
|
-
mime: "image/png",
|
|
3480
|
-
matches: (buffer) => buffer.length >= 8 && buffer[0] === 137 && buffer[1] === 80 && buffer[2] === 78 && buffer[3] === 71 && buffer[4] === 13 && buffer[5] === 10 && buffer[6] === 26 && buffer[7] === 10
|
|
3481
|
-
},
|
|
3482
|
-
{
|
|
3483
|
-
mime: "image/jpeg",
|
|
3484
|
-
matches: (buffer) => buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255
|
|
3485
|
-
},
|
|
3486
|
-
{
|
|
3487
|
-
mime: "image/webp",
|
|
3488
|
-
matches: (buffer) => buffer.length >= 12 && buffer.subarray(0, 4).toString("ascii") === "RIFF" && buffer.subarray(8, 12).toString("ascii") === "WEBP"
|
|
3489
|
-
},
|
|
3490
|
-
{
|
|
3491
|
-
mime: "image/gif",
|
|
3492
|
-
matches: (buffer) => buffer.length >= 6 && (buffer.subarray(0, 6).toString("ascii") === "GIF87a" || buffer.subarray(0, 6).toString("ascii") === "GIF89a")
|
|
3493
|
-
},
|
|
3494
|
-
{
|
|
3495
|
-
mime: "image/bmp",
|
|
3496
|
-
matches: (buffer) => buffer.length >= 2 && buffer[0] === 66 && buffer[1] === 77
|
|
3497
|
-
}
|
|
3498
|
-
];
|
|
3499
|
-
const HEIC_BRANDS = /* @__PURE__ */ new Set([
|
|
3500
|
-
"heic",
|
|
3501
|
-
"heix",
|
|
3502
|
-
"hevc",
|
|
3503
|
-
"hevx",
|
|
3504
|
-
"heis",
|
|
3505
|
-
"heim",
|
|
3506
|
-
"hevm",
|
|
3507
|
-
"hevs"
|
|
3508
|
-
]);
|
|
3509
|
-
const HEIF_BRANDS = /* @__PURE__ */ new Set(["mif1", "msf1"]);
|
|
3510
|
-
const IMAGE_SIGNATURE_PREFIX_BASE64_CHARS = 128;
|
|
3511
|
-
const INLINE_IMAGE_DATA_URL_MIMES = /* @__PURE__ */ new Set([
|
|
3512
|
-
"image/png",
|
|
3513
|
-
"image/jpeg",
|
|
3514
|
-
"image/webp",
|
|
3515
|
-
"image/gif"
|
|
3516
|
-
]);
|
|
3517
|
-
function startsWithDataUrl(value) {
|
|
3518
|
-
return value.slice(0, 5).toLowerCase() === INLINE_IMAGE_DATA_URL_PREFIX;
|
|
3519
|
-
}
|
|
3520
|
-
function sniffIsoBmffImageMime(buffer) {
|
|
3521
|
-
if (buffer.length < 12 || buffer.subarray(4, 8).toString("ascii") !== "ftyp") return;
|
|
3522
|
-
const brands = [buffer.subarray(8, 12).toString("ascii")];
|
|
3523
|
-
for (let offset = 16; offset + 4 <= buffer.length; offset += 4) brands.push(buffer.subarray(offset, offset + 4).toString("ascii"));
|
|
3524
|
-
if (brands.some((brand) => HEIC_BRANDS.has(brand))) return "image/heic";
|
|
3525
|
-
if (brands.some((brand) => HEIF_BRANDS.has(brand))) return "image/heif";
|
|
3526
|
-
}
|
|
3527
|
-
/** Sniffs supported inline image formats from decoded bytes. */
|
|
3528
|
-
function sniffInlineImageMime(buffer) {
|
|
3529
|
-
return IMAGE_SIGNATURES.find((signature) => signature.matches(buffer))?.mime ?? sniffIsoBmffImageMime(buffer);
|
|
3530
|
-
}
|
|
3531
|
-
function isImageMimeType(value) {
|
|
3532
|
-
return value.trim().toLowerCase().startsWith("image/");
|
|
3533
|
-
}
|
|
3534
|
-
/** Canonicalizes trusted inline image base64 and rejects malformed or non-image payloads. */
|
|
3535
|
-
function sanitizeInlineImageBase64(params) {
|
|
3536
|
-
if (!isImageMimeType(params.mimeType)) return;
|
|
3537
|
-
const canonicalPayload = canonicalizeBase64(params.base64);
|
|
3538
|
-
if (!canonicalPayload) return;
|
|
3539
|
-
const sniffedMimeType = sniffInlineImageMime(Buffer.from(canonicalPayload.slice(0, IMAGE_SIGNATURE_PREFIX_BASE64_CHARS), "base64"));
|
|
3540
|
-
if (!sniffedMimeType) return;
|
|
3541
|
-
return {
|
|
3542
|
-
mimeType: sniffedMimeType,
|
|
3543
|
-
base64: canonicalPayload
|
|
3544
|
-
};
|
|
3545
|
-
}
|
|
3546
|
-
function parseInlineImageDataUrl(value) {
|
|
3547
|
-
if (!startsWithDataUrl(value)) return {
|
|
3548
|
-
metadata: [],
|
|
3549
|
-
payload: value
|
|
3550
|
-
};
|
|
3551
|
-
const commaIndex = value.indexOf(",");
|
|
3552
|
-
if (commaIndex < 0) return;
|
|
3553
|
-
return {
|
|
3554
|
-
metadata: value.slice(5, commaIndex).split(";").map((part) => part.trim()),
|
|
3555
|
-
payload: value.slice(commaIndex + 1)
|
|
3556
|
-
};
|
|
3557
|
-
}
|
|
3558
|
-
function metadataAllowsImageBase64(metadata) {
|
|
3559
|
-
const [mimeType, ...options] = metadata;
|
|
3560
|
-
return mimeType !== void 0 && isImageMimeType(mimeType) && options.some((part) => part.toLowerCase() === "base64");
|
|
3561
|
-
}
|
|
3562
|
-
function sanitizeInlineImageDataUrlWithAllowedMimes(imageUrl, allowedMimes) {
|
|
3563
|
-
const parsed = parseInlineImageDataUrl(imageUrl);
|
|
3564
|
-
if (!parsed) return;
|
|
3565
|
-
if (parsed.metadata.length === 0) return imageUrl;
|
|
3566
|
-
if (!metadataAllowsImageBase64(parsed.metadata)) return;
|
|
3567
|
-
const [mimeType] = parsed.metadata;
|
|
3568
|
-
const sanitized = sanitizeInlineImageBase64({
|
|
3569
|
-
mimeType: mimeType ?? "",
|
|
3570
|
-
base64: parsed.payload
|
|
3571
|
-
});
|
|
3572
|
-
if (!sanitized) return;
|
|
3573
|
-
if (allowedMimes && !allowedMimes.has(sanitized.mimeType)) return;
|
|
3574
|
-
return `data:${sanitized.mimeType};base64,${sanitized.base64}`;
|
|
3575
|
-
}
|
|
3576
|
-
/** Canonicalizes provider-safe inline image data URLs and rejects unsupported formats. */
|
|
3577
|
-
function sanitizeInlineImageDataUrl(imageUrl) {
|
|
3578
|
-
return sanitizeInlineImageDataUrlWithAllowedMimes(imageUrl, INLINE_IMAGE_DATA_URL_MIMES);
|
|
3579
|
-
}
|
|
3580
|
-
//#endregion
|
|
3581
|
-
//#region packages/ai/src/transports/responses-image-payload-sanitizer.ts
|
|
3582
|
-
/**
|
|
3583
|
-
* Sanitizes OpenAI Responses payloads before transport. Invalid inline images
|
|
3584
|
-
* are replaced with text placeholders so the request remains valid and
|
|
3585
|
-
* auditable.
|
|
3586
|
-
*/
|
|
3587
|
-
const IMAGE_OMITTED_TEXT = "omitted image payload: invalid inline image data";
|
|
3588
|
-
function invalidSnakeImage() {
|
|
3589
|
-
return {
|
|
3590
|
-
type: "input_text",
|
|
3591
|
-
text: `[${IMAGE_OMITTED_TEXT}]`
|
|
3592
|
-
};
|
|
3593
|
-
}
|
|
3594
|
-
function sanitizeValue(value) {
|
|
3595
|
-
if (Array.isArray(value)) return value.map(sanitizeValue);
|
|
3596
|
-
if (!isRecord(value)) return value;
|
|
3597
|
-
if (value.type === "input_image" && typeof value.image_url === "string") {
|
|
3598
|
-
const imageUrl = sanitizeInlineImageDataUrl(value.image_url);
|
|
3599
|
-
return imageUrl ? {
|
|
3600
|
-
...value,
|
|
3601
|
-
image_url: imageUrl
|
|
3602
|
-
} : invalidSnakeImage();
|
|
3603
|
-
}
|
|
3604
|
-
const next = {};
|
|
3605
|
-
for (const [key, child] of Object.entries(value)) next[key] = sanitizeValue(child);
|
|
3606
|
-
return next;
|
|
3607
|
-
}
|
|
3608
|
-
/** Sanitize inline image fields inside a Responses API payload. */
|
|
3609
|
-
function sanitizeResponsesImagePayload(params) {
|
|
3610
|
-
if (!Array.isArray(params.input)) return params;
|
|
3611
|
-
return {
|
|
3612
|
-
...params,
|
|
3613
|
-
input: sanitizeValue(params.input)
|
|
3614
|
-
};
|
|
3615
|
-
}
|
|
3616
|
-
//#endregion
|
|
3617
2487
|
//#region packages/ai/src/transports/openai-responses-client.ts
|
|
3618
2488
|
function resolveNativeOpenAIResponsesWebSocketMode(model, transport) {
|
|
3619
2489
|
if (transport !== "websocket" && transport !== "websocket-cached" && transport !== "auto") return;
|
|
@@ -3647,17 +2517,18 @@ function resolveProviderTransportTurnState(model, params) {
|
|
|
3647
2517
|
}
|
|
3648
2518
|
});
|
|
3649
2519
|
}
|
|
3650
|
-
function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId) {
|
|
2520
|
+
function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId, fetchOverride) {
|
|
3651
2521
|
return new OpenAI({
|
|
3652
2522
|
apiKey,
|
|
3653
|
-
baseURL: model
|
|
2523
|
+
baseURL: resolveOpenAIClientBaseUrl(model),
|
|
3654
2524
|
dangerouslyAllowBrowser: true,
|
|
3655
2525
|
defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId),
|
|
3656
|
-
fetch: buildGuardedModelFetch(model),
|
|
2526
|
+
fetch: fetchOverride ?? buildGuardedModelFetch(model),
|
|
3657
2527
|
...buildOpenAISdkClientOptions(model)
|
|
3658
2528
|
});
|
|
3659
2529
|
}
|
|
3660
2530
|
async function postOpenAIResponsesCompaction(params) {
|
|
2531
|
+
const compactInput = typeof params.request.instructions === "string" && params.request.instructions.length > 0 ? [buildOpenAIResponsesCompactSystemMessage(params.model, params.request.instructions), ...params.request.input ?? []] : params.request.input;
|
|
3661
2532
|
const response = await params.client.post("/responses/compact", {
|
|
3662
2533
|
...buildOpenAISdkRequestOptions(params.model, params.options?.signal, {
|
|
3663
2534
|
timeoutMs: params.options?.timeoutMs,
|
|
@@ -3665,19 +2536,19 @@ async function postOpenAIResponsesCompaction(params) {
|
|
|
3665
2536
|
}),
|
|
3666
2537
|
body: {
|
|
3667
2538
|
model: params.request.model,
|
|
3668
|
-
input:
|
|
2539
|
+
input: compactInput
|
|
3669
2540
|
}
|
|
3670
2541
|
});
|
|
3671
2542
|
const output = isRecord(response) && Array.isArray(response.output) ? response.output : [];
|
|
3672
2543
|
const item = output.at(-1);
|
|
3673
2544
|
const retainedItems = output.slice(0, -1);
|
|
3674
|
-
const retainedMessagesAreValid = retainedItems.every((candidate) => isRecord(candidate) && candidate.type === "message" && (candidate.role === "user" || candidate.role === "developer" || candidate.role === "system") && Array.isArray(candidate.content));
|
|
3675
2545
|
const retainedUserMessageCount = retainedItems.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user" && Array.isArray(candidate.content)).length;
|
|
3676
2546
|
const inputUserMessageCount = Array.isArray(params.request.input) ? params.request.input.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user").length : 0;
|
|
3677
2547
|
const retainedMessagePrefixSupported = supportsNativeOpenAIResponsesEndpoint(params.model);
|
|
3678
2548
|
const usage = isRecord(response) && isRecord(response.usage) ? response.usage : void 0;
|
|
3679
|
-
if (!isRecord(response) || response.object !== "response.compaction" || !
|
|
2549
|
+
if (!isRecord(response) || response.object !== "response.compaction" || !isOpenAIResponsesCompactionOutput(output, params.model) || 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");
|
|
3680
2550
|
return {
|
|
2551
|
+
output,
|
|
3681
2552
|
item,
|
|
3682
2553
|
historyMode: retainedUserMessageCount > 0 ? "retained-users" : "compacted-prefix",
|
|
3683
2554
|
usage,
|
|
@@ -3708,7 +2579,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
3708
2579
|
});
|
|
3709
2580
|
const websocketSessionPolicy = websocketMode ? turnState?.websocket : void 0;
|
|
3710
2581
|
const websocketHeaders = websocketMode ? buildOpenAIClientHeaders(model, context, options?.headers, websocketSessionPolicy?.headers, options?.sessionId) : void 0;
|
|
3711
|
-
const client = config.createClient(model, context, apiKey, options?.headers, turnState?.headers, options?.sessionId);
|
|
2582
|
+
const client = config.createClient(model, context, apiKey, options?.headers, turnState?.headers, options?.sessionId, compactRequest ? createBoundedOpenAIResponsesCompactionFetch(buildGuardedModelFetch(model)) : void 0);
|
|
3712
2583
|
const buildRequest = async (replayMode) => {
|
|
3713
2584
|
let params = config.buildRequest(model, context, responsesOptions, turnState?.metadata, replayMode);
|
|
3714
2585
|
const nextParams = await options?.onPayload?.(params, model);
|
|
@@ -3778,7 +2649,7 @@ function createResponsesTransportExecutor(config) {
|
|
|
3778
2649
|
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)}`);
|
|
3779
2650
|
let continuationBaseline;
|
|
3780
2651
|
const createSseStream = async (initialRequest = continuationClaim?.request ?? params, initialAttemptKind = "initial", initialRejectedCompaction) => {
|
|
3781
|
-
const { stream:
|
|
2652
|
+
const { stream: responseStream } = await config.createResponseStream({
|
|
3782
2653
|
client,
|
|
3783
2654
|
request: initialRequest,
|
|
3784
2655
|
requestOptions,
|
|
@@ -3787,19 +2658,23 @@ function createResponsesTransportExecutor(config) {
|
|
|
3787
2658
|
initialAttemptKind,
|
|
3788
2659
|
initialRejectedCompaction,
|
|
3789
2660
|
buildFullHistoryRequest: () => buildRequest("full-history"),
|
|
3790
|
-
onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, responsesOptions, checkpoint)
|
|
3791
|
-
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
2661
|
+
onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, responsesOptions, checkpoint),
|
|
2662
|
+
canRetryStream: () => output.content.length === 0,
|
|
2663
|
+
wrapStream: ({ stream: rawResponseStream, response, attempt }) => {
|
|
2664
|
+
if (continuationClaim) continuationBaseline = attempt.request.previous_response_id ? params : attempt.request;
|
|
2665
|
+
return withProviderResponseHook({
|
|
2666
|
+
stream: observeResponsesStream(rawResponseStream, model, requestStartedAt),
|
|
2667
|
+
signal: firstEvent.signal,
|
|
2668
|
+
abort: firstEvent.abort,
|
|
2669
|
+
hook: createOpenAIProviderAcceptanceHook(options, response, model),
|
|
2670
|
+
onReady: () => {
|
|
2671
|
+
emitModelTransportDebug(log, `[responses] headers provider=${model.provider} api=${model.api} model=${model.id} transport=sse elapsedMs=${Date.now() - requestStartedAt}`);
|
|
2672
|
+
startStream();
|
|
2673
|
+
}
|
|
2674
|
+
});
|
|
3801
2675
|
}
|
|
3802
2676
|
});
|
|
2677
|
+
return responseStream;
|
|
3803
2678
|
};
|
|
3804
2679
|
let responseStream;
|
|
3805
2680
|
let finishWebSocket;
|
|
@@ -3944,23 +2819,20 @@ function createAzureOpenAIResponsesTransportStreamFn() {
|
|
|
3944
2819
|
createResponseStream: createResponsesStreamWithEncryptedContentRetry
|
|
3945
2820
|
});
|
|
3946
2821
|
}
|
|
3947
|
-
function normalizeAzureBaseUrl(baseUrl) {
|
|
3948
|
-
return baseUrl.replace(/\/+$/, "");
|
|
3949
|
-
}
|
|
3950
2822
|
function resolveAzureDeploymentName(model) {
|
|
3951
2823
|
return resolveAzureDeploymentNameFromMap({
|
|
3952
2824
|
modelId: model.id,
|
|
3953
2825
|
deploymentMap: process.env.AZURE_OPENAI_DEPLOYMENT_NAME_MAP
|
|
3954
2826
|
});
|
|
3955
2827
|
}
|
|
3956
|
-
function createAzureOpenAIClient(model, context, apiKey, optionHeaders, turnHeaders) {
|
|
3957
|
-
const baseURL =
|
|
2828
|
+
function createAzureOpenAIClient(model, context, apiKey, optionHeaders, turnHeaders, _sessionId, fetchOverride) {
|
|
2829
|
+
const baseURL = model.baseUrl.replace(/\/+$/, "");
|
|
3958
2830
|
const clientOptions = {
|
|
3959
2831
|
apiKey,
|
|
3960
2832
|
dangerouslyAllowBrowser: true,
|
|
3961
2833
|
defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders),
|
|
3962
2834
|
baseURL,
|
|
3963
|
-
fetch: buildGuardedModelFetch(model),
|
|
2835
|
+
fetch: fetchOverride ?? buildGuardedModelFetch(model),
|
|
3964
2836
|
...buildOpenAISdkClientOptions(model)
|
|
3965
2837
|
};
|
|
3966
2838
|
if (isOpenAICompatibleAzureResponsesBaseUrl(baseURL)) return new OpenAI(clientOptions);
|
|
@@ -4006,6 +2878,112 @@ const responsesTesting = {
|
|
|
4006
2878
|
if (process.env.VITEST || false) globalThis.openclawOpenAIResponsesTransportTestApi = responsesTesting;
|
|
4007
2879
|
//#endregion
|
|
4008
2880
|
//#region packages/ai/src/transports/provider-compaction-replay.ts
|
|
2881
|
+
function isAssistantReplayMessage(message) {
|
|
2882
|
+
return message.role === "assistant";
|
|
2883
|
+
}
|
|
2884
|
+
/** Resolve from prepared transport facts; never retain or return credential material. */
|
|
2885
|
+
function resolveCompactionReplayEligibility(model, options) {
|
|
2886
|
+
if (OPENAI_RESPONSES_APIS.has(model.api)) return true;
|
|
2887
|
+
return Boolean(options.apiKey?.trim()) && resolveAnthropicServerCompactionPlan(model, options.extraParams, options.apiKey).enabled;
|
|
2888
|
+
}
|
|
2889
|
+
function resolveCompactionSource(messages, model, identity) {
|
|
2890
|
+
if (identity.enabled === false) return;
|
|
2891
|
+
const assistants = messages.filter(isAssistantReplayMessage);
|
|
2892
|
+
const selected = (() => {
|
|
2893
|
+
if (OPENAI_RESPONSES_APIS.has(model.api)) {
|
|
2894
|
+
const responses = resolveNewestOpenAIResponsesCompactionReplay(assistants, model, identity);
|
|
2895
|
+
return responses ? {
|
|
2896
|
+
family: "responses",
|
|
2897
|
+
...responses
|
|
2898
|
+
} : void 0;
|
|
2899
|
+
}
|
|
2900
|
+
if (identity.enabled !== true) return;
|
|
2901
|
+
const anthropic = resolveNewestAnthropicCompaction(assistants, model, identity);
|
|
2902
|
+
return anthropic ? {
|
|
2903
|
+
family: "anthropic",
|
|
2904
|
+
...anthropic
|
|
2905
|
+
} : void 0;
|
|
2906
|
+
})();
|
|
2907
|
+
if (!selected) return;
|
|
2908
|
+
const owner = assistants.find((message) => message === selected.owner);
|
|
2909
|
+
return owner ? {
|
|
2910
|
+
...selected,
|
|
2911
|
+
owner
|
|
2912
|
+
} : void 0;
|
|
2913
|
+
}
|
|
2914
|
+
/** Manual recovery uses the durable client compactor, never a guessed retained-user prefix. */
|
|
2915
|
+
function requiresCompactionReplayRefresh(messages, model, identity) {
|
|
2916
|
+
const checkpoint = resolveCompactionSource(messages, model, identity);
|
|
2917
|
+
return checkpoint?.family === "responses" && checkpoint.mode === "refresh-required";
|
|
2918
|
+
}
|
|
2919
|
+
/** Carry a checkpoint immediately after reference-preserving history limiting, before repair. */
|
|
2920
|
+
function preserveCompactionReplayWindow(source, windowed, model, identity) {
|
|
2921
|
+
const checkpoint = resolveCompactionSource(source, model, identity);
|
|
2922
|
+
if (!checkpoint || windowed.some((message) => message === checkpoint.owner)) return windowed;
|
|
2923
|
+
const owner = checkpoint.owner;
|
|
2924
|
+
const replay = checkpoint.owner.providerReplay;
|
|
2925
|
+
const providerReplay = replay?.type === "openai-responses-retained-compaction" ? replay : {
|
|
2926
|
+
...replay,
|
|
2927
|
+
replayIndex: 0
|
|
2928
|
+
};
|
|
2929
|
+
const suffix = new Set(source.slice(source.indexOf(owner) + 1));
|
|
2930
|
+
return [{
|
|
2931
|
+
...owner,
|
|
2932
|
+
content: [],
|
|
2933
|
+
providerReplay
|
|
2934
|
+
}, ...windowed.filter((message) => suffix.has(message))];
|
|
2935
|
+
}
|
|
2936
|
+
function estimateResponsesWindow(checkpoint, estimate) {
|
|
2937
|
+
return checkpoint.output.reduce((tokens, entry) => {
|
|
2938
|
+
if (entry.type === "compaction") {
|
|
2939
|
+
const { encrypted_content, ...metadata } = entry;
|
|
2940
|
+
return tokens + estimate.text(encrypted_content) + estimate.json(metadata);
|
|
2941
|
+
}
|
|
2942
|
+
const { content, ...metadata } = entry;
|
|
2943
|
+
return tokens + estimate.json(metadata) + content.reduce((sum, block) => {
|
|
2944
|
+
if (block.type === "input_text") {
|
|
2945
|
+
const { text, ...fields } = block;
|
|
2946
|
+
return sum + estimate.text(text) + estimate.json(fields);
|
|
2947
|
+
}
|
|
2948
|
+
if (block.type === "input_image") {
|
|
2949
|
+
const { image_url: _imageUrl, ...fields } = block;
|
|
2950
|
+
return sum + estimate.image() + estimate.json(block.image_url?.startsWith("data:") ? fields : block);
|
|
2951
|
+
}
|
|
2952
|
+
return sum + estimate.json(block);
|
|
2953
|
+
}, 0);
|
|
2954
|
+
}, 0);
|
|
2955
|
+
}
|
|
2956
|
+
/** Estimate the canonical prefix and its tail once, independent of unbound usage snapshots. */
|
|
2957
|
+
function resolveCompactionReplayPressure(messages, model, identity, estimate) {
|
|
2958
|
+
const checkpoint = resolveCompactionSource(messages, model, identity);
|
|
2959
|
+
if (!checkpoint) return;
|
|
2960
|
+
if (checkpoint.family === "responses" && checkpoint.mode === "refresh-required") throw new CompactionReplayRefreshRequiredError();
|
|
2961
|
+
const ownerIndex = messages.findIndex((message) => message === checkpoint.owner);
|
|
2962
|
+
const owner = messages[ownerIndex];
|
|
2963
|
+
if (!owner) return;
|
|
2964
|
+
const prefixTokens = checkpoint.family === "anthropic" ? estimate.text(checkpoint.summary) : checkpoint.mode === "complete-window" ? estimateResponsesWindow(checkpoint, estimate) : estimate.text(checkpoint.item.encrypted_content);
|
|
2965
|
+
const { contextUsage: _staleContextUsage, ...usage } = checkpoint.owner.usage;
|
|
2966
|
+
const tail = [];
|
|
2967
|
+
for (const message of messages.slice(ownerIndex + 1)) {
|
|
2968
|
+
if (!isAssistantReplayMessage(message) || message.usage.contextUsage === void 0) {
|
|
2969
|
+
tail.push(message);
|
|
2970
|
+
continue;
|
|
2971
|
+
}
|
|
2972
|
+
const { contextUsage: _unboundContextUsage, ...billedUsage } = message.usage;
|
|
2973
|
+
tail.push({
|
|
2974
|
+
...message,
|
|
2975
|
+
usage: billedUsage
|
|
2976
|
+
});
|
|
2977
|
+
}
|
|
2978
|
+
return {
|
|
2979
|
+
messages: [{
|
|
2980
|
+
...owner,
|
|
2981
|
+
content: checkpoint.owner.content.slice(checkpoint.replayIndex),
|
|
2982
|
+
usage
|
|
2983
|
+
}, ...tail],
|
|
2984
|
+
prefixTokens
|
|
2985
|
+
};
|
|
2986
|
+
}
|
|
4009
2987
|
/** Whether provider replay state is a prefix-bound server compaction checkpoint. */
|
|
4010
2988
|
function isCompactionReplayCheckpoint(replay) {
|
|
4011
2989
|
const type = replay && typeof replay === "object" ? replay.type : void 0;
|
|
@@ -4301,4 +3279,4 @@ function prepareModelForSimpleCompletion(params) {
|
|
|
4301
3279
|
return applyProviderSimpleCompletionWrapper(apiRegistry, model, cfg);
|
|
4302
3280
|
}
|
|
4303
3281
|
//#endregion
|
|
4304
|
-
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, resolveOpenAICompletionsCompat, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesCompactEndpointPlan, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIResponsesServerCompactionPlan, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompactionReplayCheckpoint, stripCompactionReplayCheckpointInPlace, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend, withProviderAcceptanceObserver, withProviderResponseHook };
|
|
3282
|
+
export { CompactionReplayRefreshRequiredError, 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, preserveCompactionReplayWindow, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, readOpenAICompletionsReasoningBatch, replaceCompactionReplayOwnerContent, requestPreparedOpenAIResponsesCompaction, requiresCompactionReplayRefresh, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveAnthropicServerCompactionPlan, resolveCodeModeResponsesVisibleToolNames, resolveCompactionReplayEligibility, resolveCompactionReplayPressure, 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 };
|