@openclaw/ai 2026.9.1-beta.1 → 2026.9.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-DI4PZKKB.mjs → anthropic-BDdqdVLK.mjs} +222 -216
- package/dist/{anthropic-compaction-replay-nhKaCXu6.mjs → anthropic-compaction-replay-DB2FGLQc.mjs} +160 -68
- package/dist/{anthropic-payload-policy-B_0n0enE.d.mts → anthropic-payload-policy-d46X2pR0.d.mts} +28 -4
- package/dist/{api-registry-CTd8NzcD.d.mts → api-registry-DWtPjzyn.d.mts} +2 -2
- package/dist/{azure-openai-responses-D8dI0ekg.mjs → azure-openai-responses-C5bZRfAP.mjs} +12 -9
- package/dist/{number-coercion-H9qHik3g.mjs → base64-CEFBpSkN.mjs} +73 -1
- package/dist/{diagnostics-COpOtRwq.mjs → diagnostics-CPeq9F7y.mjs} +5 -1
- package/dist/diagnostics-DfFyKeX_.mjs +136 -0
- package/dist/{diagnostics-BaTA9eVl.d.mts → diagnostics-DnPnOui6.d.mts} +5 -1
- package/dist/diagnostics.d.mts +8 -3
- package/dist/diagnostics.mjs +4 -3
- package/dist/{env-api-keys-DrgeBuva.mjs → env-api-keys-bktO00EJ.mjs} +2 -15
- package/dist/{event-stream-uSMZJ3FA.mjs → event-stream-BgDvQeum.mjs} +3 -9
- package/dist/{event-stream-LiXePESD.d.mts → event-stream-BhT5T1Ay.d.mts} +1 -1
- package/dist/event-stream-zctLx0yr.d.mts +1 -0
- package/dist/event-stream.d.mts +2 -2
- package/dist/event-stream.mjs +1 -1
- package/dist/{google-Od-LLdVK.mjs → google-4qeuE8iX.mjs} +9 -7
- package/dist/{google-shared-Bgr9lFPw.mjs → google-shared-CWeG8RIl.mjs} +27 -23
- package/dist/{google-vertex-aerRSXc4.mjs → google-vertex-O9BcnB6X.mjs} +8 -6
- package/dist/{host-D51fmkH6.mjs → host-CEvLw30U.mjs} +54 -9
- package/dist/{host-DsbPMFU6.d.mts → host-DjzGmdZ2.d.mts} +3 -3
- package/dist/index-FnHM2FcI.d.mts +117 -0
- package/dist/index.d.mts +10 -11
- package/dist/index.mjs +6 -6
- package/dist/internal/anthropic.d.mts +59 -55
- 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 +66 -64
- package/dist/internal/openai.mjs +10 -10
- package/dist/internal/retry-after.d.mts +2 -3
- package/dist/internal/runtime.d.mts +43 -43
- package/dist/internal/runtime.mjs +10 -8
- package/dist/internal/shared.d.mts +25 -25
- package/dist/internal/shared.mjs +95 -4
- package/dist/{mistral-EiHdymeb.mjs → mistral-Tb6oalqH.mjs} +30 -23
- package/dist/{openai-chatgpt-responses-DHpF9o1e.mjs → openai-chatgpt-responses-yUXjPNfu.mjs} +76 -137
- package/dist/{openai-completions-EFPiUGfS.mjs → openai-completions-BIUV3RDT.mjs} +26 -22
- package/dist/{openai-completions-compat-BefmHT26.d.mts → openai-completions-compat-CpjYUArk.d.mts} +5 -5
- package/dist/{openai-completions-stream-DUlGwRMz.mjs → openai-completions-stream-BsrBe3Gg.mjs} +103 -96
- package/dist/openai-prompt-cache-CGnVB74a.mjs +21 -0
- package/dist/openai-prompt-cache-CNoIfHYC.d.mts +16 -0
- package/dist/{openai-responses-BogP8OjX.mjs → openai-responses-CCL41ALM.mjs} +15 -14
- package/dist/openai-responses-compaction-window-BMVHFOtq.mjs +697 -0
- package/dist/{openai-responses-contracts-Dvj_UtPy.d.mts → openai-responses-contracts-rF5DDRNS.d.mts} +23 -6
- 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-Cd4hJG-S.mjs → openai-responses-prompt-observer-internal-D0bhBfgL.mjs} +4 -18
- package/dist/{openai-responses-shared-DJThc6jW.mjs → openai-responses-shared-Bmma_3Qc.mjs} +438 -309
- package/dist/{openai-tool-schema-ho-hIkQf.mjs → openai-tool-schema-_pTAJqKF.mjs} +30 -40
- package/dist/{provider-error-DDOs_Bz0.mjs → provider-error-9TraxGvt.mjs} +20 -92
- package/dist/{provider-options-MdMBLzlU.d.mts → provider-options-Bcc_p-TU.d.mts} +26 -6
- package/dist/provider-replay-context-BuSUaAk5.mjs +21 -0
- package/dist/{provider-transcript-transform-C01bQ5a3.mjs → provider-transcript-transform-BaMbI1hr.mjs} +1 -1
- package/dist/provider-types.d.mts +19 -20
- package/dist/providers.d.mts +6 -6
- package/dist/providers.mjs +11 -11
- package/dist/{reasoning-tag-text-partitioner-5ygO2rZc.mjs → reasoning-tag-text-partitioner-DLCNXki6.mjs} +158 -94
- package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
- package/dist/{sanitize-unicode-DCkltN94.mjs → sanitize-unicode-D6xUvZaS.mjs} +2 -8
- package/dist/{simple-options-CFj7x3J4.mjs → simple-options-BjHCCh4v.mjs} +42 -6
- package/dist/{src-Bu3FiFAG.mjs → src-2qBGKg8O.mjs} +83 -2
- package/dist/{stream-first-event-timeout-MK28puvq.mjs → stream-first-event-timeout-DcNjoFQE.mjs} +1 -1
- package/dist/{tool-schema-json-projection-qvTEs5Am.mjs → tool-schema-json-projection-mJhXDcyz.mjs} +21 -31
- package/dist/{transport-stream-shared-ljShVIZB.mjs → transport-stream-shared-CZqMhfIw.mjs} +19 -6
- package/dist/{transport-stream-shared-rvaCyFYt.d.mts → transport-stream-shared-xnaqxmbP.d.mts} +5 -5
- package/dist/{transport-utils-LJ1_rbi-.mjs → transport-utils-7il795_9.mjs} +5 -8
- package/dist/transports.d.mts +121 -85
- package/dist/transports.mjs +747 -464
- package/dist/types-3Lnm-QSJ.d.mts +1 -0
- package/dist/{types-DhLoJbFm.d.mts → types-CJ1-Ht7A.d.mts} +55 -19
- package/dist/types.d.mts +7 -7
- package/dist/types.mjs +5 -5
- package/dist/{validation-Dk7q7NMN.d.mts → validation-AKZBDGQd.d.mts} +1 -1
- 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 +5 -5
- package/dist/anthropic-BECQCNdF.d.mts +0 -98
- package/dist/event-stream-BKp4fOt_.d.mts +0 -1
- package/dist/index-Qbej8io0.d.mts +0 -3
- package/dist/openai-prompt-cache-2uo_1OR1.d.mts +0 -7
- package/dist/openai-prompt-cache-mZTCdRPo.mjs +0 -12
- package/dist/openai-responses-contracts-QUY12X0B.mjs +0 -233
- package/dist/openai-responses-payload-policy-D8EdimYe.mjs +0 -204
- package/dist/provider-options-AvldWZt8.mjs +0 -21
- package/dist/tls-certificate-errors-DXSpluKI.mjs +0 -93
- package/dist/types-GiAjXatj.d.mts +0 -1
package/dist/transports.mjs
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { d as resolveClaudeSonnet5ModelIdentity, g as supportsClaudeNativeXhighEffort, p as supportsClaudeAdaptiveThinking, u as resolveClaudeOpus5ModelIdentity } from "./src-Bu3FiFAG.mjs";
|
|
1
|
+
import { _ as supportsClaudeAdaptiveThinking, b as supportsClaudeNativeXhighEffort, h as resolveClaudeSonnet5ModelIdentity, m as resolveClaudeOpus5ModelIdentity } from "./src-2qBGKg8O.mjs";
|
|
3
2
|
import { c as normalizeLowercaseStringOrEmpty, o as isRecord, s as hasNonEmptyString } from "./utf16-slice-qz3nsy87.mjs";
|
|
4
|
-
import { r as calculateCost } from "./sanitize-unicode-
|
|
5
|
-
import { S as usesClaudeStreamingRefusalContract, _ as prepareClaudeNoPrefillRequestContext, a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, f as ANTHROPIC_CLAUDE_CODE_BILLING_SYSTEM_BLOCK, g as mapAnthropicStopReason, h as defaultsClaudeAdaptiveThinking, m as applyClaudeRequestContract, n as getAiTransportHost, p as ANTHROPIC_CLAUDE_CODE_VERSION, r as resolveAiTransportHeaderSentinels, s as extractToolResultBlockText, v as requiresClaudeAdaptiveThinking, x as usesClaudeFable5MessagesContract, y as resolveAnthropicThinkingEffort } from "./host-
|
|
6
|
-
import { i as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
3
|
+
import { r as calculateCost } from "./sanitize-unicode-D6xUvZaS.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-CEvLw30U.mjs";
|
|
5
|
+
import { i as stableStringify } from "./provider-error-9TraxGvt.mjs";
|
|
6
|
+
import { r as toErrorObject } from "./diagnostics-DfFyKeX_.mjs";
|
|
7
|
+
import { a as asNonNegativeFiniteNumber } from "./base64-CEFBpSkN.mjs";
|
|
9
8
|
import { n as uniqueStrings } from "./string-normalization--fwJ4S2q.mjs";
|
|
9
|
+
import { r as resolveOpenAIResponsesCacheParams } from "./openai-prompt-cache-CGnVB74a.mjs";
|
|
10
|
+
import { A as createAnthropicInlineImageBudget, B as resolveAnthropicContextManagementBetaHeader, C as ANTHROPIC_SERVER_SIDE_FALLBACKS, D as readAnthropicFallbackBoundary, E as applyAnthropicFallbackBoundary, F as applyAnthropicEphemeralCacheControlMarkers, G as omitFoundryBearerCredentialHeaders, H as resolveAnthropicPayloadPolicy, I as applyAnthropicPayloadPolicyToParams, K as usesFoundryBearerAuth, L as isAnthropicServerToolClearingEnabled, M as resolveAnthropicImageMediaType, N as applyAnthropicCacheControlToMessages, O as resolveAnthropicFallbackServingModelCost, P as applyAnthropicContextManagementToRequest, R as isDirectAnthropicModel, S as readAnthropicInputTransformations, U as resolveAnthropicServerCompactionPlan, V as resolveAnthropicEphemeralCacheControl, W as isAnthropicOAuthApiKey, _ as toClaudeCodeToolName, a as suppressAnthropicCompaction, b as findActiveAnthropicToolTurnAssistantIndex, f as normalizeAnthropicToolCallId, g as resolveOriginalAnthropicToolName, h as reconcileAnthropicToolChoice, i as resolveNewestAnthropicCompaction, j as normalizeAnthropicInlineContent, k as applyAnthropicRefusal, 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 ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, x as logAnthropicThinkingDrops, y as applyAnthropicThinkingBindingControls, z as logAnthropicContextEdits } from "./anthropic-compaction-replay-DB2FGLQc.mjs";
|
|
10
11
|
import { t as resolveCacheRetention } from "./cache-retention-0x979a5V.mjs";
|
|
11
|
-
import {
|
|
12
|
-
import { a as resolveProviderEndpoint, c as transformTransportMessages, i as resolveOpenAIStrictToolSetting, n as buildGuardedModelFetch } from "./tool-schema-json-projection-
|
|
13
|
-
import { a as isGoogleGemini3FlashModel, c as parseRetryAfterSeconds, f as resolveModelHeaderSentinels$1,
|
|
14
|
-
import {
|
|
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-
|
|
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-
|
|
12
|
+
import { a as codeModeToolSurfaceObserver, d as stripSystemPromptCacheBoundary, m as sortPromptCacheToolsByName, o as reasoningTagTextPolicy, t as adjustMaxTokensForThinking } from "./simple-options-BjHCCh4v.mjs";
|
|
13
|
+
import { a as resolveProviderEndpoint, c as transformTransportMessages, i as resolveOpenAIStrictToolSetting, n as buildGuardedModelFetch } from "./tool-schema-json-projection-mJhXDcyz.mjs";
|
|
14
|
+
import { a as isGoogleGemini3FlashModel, c as parseRetryAfterSeconds, f as resolveModelHeaderSentinels$1, i as isCodeModeModelVisibleToolName, l as readResponseTextSnippet, m as supportsModelTools, n as createAbortError$1, o as isGoogleGemini3ProModel, p as sha256Hex, r as estimateStringChars, t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, u as redactIdentifier } from "./transport-utils-7il795_9.mjs";
|
|
15
|
+
import { n as getEnvApiKey } from "./env-api-keys-bktO00EJ.mjs";
|
|
16
|
+
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-CZqMhfIw.mjs";
|
|
17
|
+
import { C as createDeepSeekTextFilter, E as tagUnresolvedTextAsCommentary, S as shouldOmitOllamaCompatResponseFormat, T as tagPendingCommentaryText, _ as hasToolCallHistory, a as buildOpenAISdkClientOptions, b as resolveOpenAICompletionsCompat, c as filterCodeModePayloadTools, d as readCodeModePayloadToolName, f as resolveCodeModeResponsesVisibleToolNames, g as convertMessages, h as resolveOpenAIReasoningEffortMap, i as buildOpenAIClientHeaders, l as getCompat, m as usesNativeOpenAICodexResponsesBackend, n as shouldEmitOpenAICompletionsReasoning, o as buildOpenAISdkRequestOptions, p as resolveOpenAIStrictToolFlagWithDiagnostics, r as assertCodeModeResponsesToolSurface, s as enforceCodeModeResponsesToolSurface, t as processCompletionsStream, u as isOpenAICodexResponsesModel, v as finalizeOpenAICompletionsToolCalls, x as resolveOpenAICompletionsResponseFormat, y as detectOpenAICompletionsCompat } from "./openai-completions-stream-BsrBe3Gg.mjs";
|
|
17
18
|
import { t as createDeferredEventBuffer } from "./deferred-event-buffer-DAvyP7qA.mjs";
|
|
18
19
|
import { r as parseStreamingJson, t as createToolArgumentPreviewSchedule } from "./json-parse-BuAJEbdW.mjs";
|
|
19
20
|
import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
|
|
20
21
|
import { t as googleFlashSupportsMinimalThinking } from "./google-thinking-level-C-V3tecN.mjs";
|
|
21
|
-
import { B as
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { i as
|
|
25
|
-
import { _ as isOpenAIGpt56Model, d as OpenAIResponsesWebSocketSafeRetryError, g as isOpenAIGpt55Model, h as isOpenAIGpt54MiniModel, i as OPENAI_RESPONSES_APIS, l as OpenAIResponsesWebSocketPostDispatchError, p as parseOpenAIResponsesWebSocketServerError, r as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS, t as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, u as OpenAIResponsesWebSocketPreDispatchError, v as normalizeOpenAIReasoningEffort, y as resolveOpenAIReasoningEffortForModel } from "./openai-responses-contracts-QUY12X0B.mjs";
|
|
26
|
-
import { i as resolveOpenAIResponsesServerCompactionPlan, n as resolveOpenAIResponsesCompactEndpointPlan, r as resolveOpenAIResponsesPayloadPolicy, t as applyOpenAIResponsesPayloadPolicy } from "./openai-responses-payload-policy-D8EdimYe.mjs";
|
|
22
|
+
import { $ as resolveModelPayloadDebugMode, B as resolveNextResponsesEncryptedContentAttempt, C as summarizeResponsesPayload, G as responsesInputFingerprint, H as convertResponsesMessages, J as captureOpenAIResponsesCompaction, K as CompactionReplayRefreshRequiredError, L as createResponsesStreamWithEncryptedContentRetry, Q as emitModelTransportDebug, R as isInvalidEncryptedContentError, S as summarizeResponsesFailedNoDetailsObservation, U as createOpenAIResponsesAssistantOutput, V as buildResponsesInputMessage, W as recordResponsesInputReplay, X as suppressOpenAIResponsesCompaction, Y as resolveNewestOpenAIResponsesCompactionReplay, Z as resolveReplayableResponsesMessageId, _ as normalizeResponsesFailedEvent, b as stringifyRedactedPayload, et as resolveModelSseDebugMode, g as logResponsesFailedNoDetails, h as buildResponsesFailedNoDetailsObservation, l as processResponsesStream, m as ResponsesStreamFailure, n as applyResponsesServiceTierPricing, p as observeResponsesStream, q as buildOpenAIResponsesReasoningReplayMetadata, v as safeDebugValue, w as summarizeResponsesTools, x as summarizeOpenAITransportError, y as stringifyRedactedEvent, z as resolveAzureOpenAIApiVersion } from "./openai-responses-shared-Bmma_3Qc.mjs";
|
|
23
|
+
import { A as readOpenAICompletionsReasoningBatch, C as createOpenAIProviderAcceptanceHook, D as measureUtf8AppendBytes, E as log, M as resolvePromptCacheKey, N as throwIfModelStreamAborted, O as parseOpenAICompletionsUsage, S as createModelStreamCooperativeScheduler, T as isOpenAICompletionsThinkingEnabled, b as reconcileOpenAIResponsesToolChoice, j as resolveOpenAIClientBaseUrl, k as readOpenAICompletionsContentDeltas, r as normalizeOpenAIStrictToolParameters, v as projectOpenAITools, w as createOpenAIResponseHook, x as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, y as reconcileOpenAICompletionsToolChoice } from "./openai-tool-schema-_pTAJqKF.mjs";
|
|
24
|
+
import { i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-DcNjoFQE.mjs";
|
|
25
|
+
import { C as isOpenAIGpt54MiniModel, E as normalizeOpenAIReasoningEffort, O as resolveOpenAIReasoningEffortForModel, 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, j as supportsOpenAITemperature, 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-BMVHFOtq.mjs";
|
|
27
26
|
import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
|
|
28
27
|
import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
|
|
28
|
+
import { t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-D0bhBfgL.mjs";
|
|
29
29
|
import { randomUUID } from "node:crypto";
|
|
30
30
|
import OpenAI, { AzureOpenAI } from "openai";
|
|
31
31
|
import { ResponsesWS } from "openai/resources/responses/ws.js";
|
|
@@ -35,12 +35,12 @@ import { ResponsesWS } from "openai/resources/responses/ws.js";
|
|
|
35
35
|
* Converts OpenClaw contexts/tools into Anthropic payloads, streams SSE events
|
|
36
36
|
* back into runtime output blocks, and applies provider request policy.
|
|
37
37
|
*/
|
|
38
|
-
const ANTHROPIC_MESSAGES_ERROR_BODY_MAX_BYTES =
|
|
38
|
+
const ANTHROPIC_MESSAGES_ERROR_BODY_MAX_BYTES = 8192;
|
|
39
39
|
const ANTHROPIC_MESSAGES_ERROR_BODY_MAX_CHARS = 400;
|
|
40
40
|
const ANTHROPIC_MESSAGES_ERROR_BODY_READ_IDLE_TIMEOUT_MS = 1e4;
|
|
41
41
|
const ANTHROPIC_MESSAGES_DEFAULT_MAX_TOKENS = 4096;
|
|
42
42
|
const ANTHROPIC_MESSAGES_FALLBACK_CONTEXT_DIVISOR = 4;
|
|
43
|
-
const ANTHROPIC_MESSAGES_SSE_PENDING_BUFFER_MAX_CHARS =
|
|
43
|
+
const ANTHROPIC_MESSAGES_SSE_PENDING_BUFFER_MAX_CHARS = 16777216;
|
|
44
44
|
function resolveAnthropicRequestModelId(model) {
|
|
45
45
|
if (isDirectAnthropicModel(model) && /^anthropic\//i.test(model.id)) return model.id.replace(/^anthropic\//i, "");
|
|
46
46
|
return model.id;
|
|
@@ -60,14 +60,6 @@ function resolveAnthropicMessagesMaxTokens(params) {
|
|
|
60
60
|
const contextWindow = resolvePositiveAnthropicTokenLimit(params.modelContextWindow);
|
|
61
61
|
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)));
|
|
62
62
|
}
|
|
63
|
-
function isAnthropicOAuthToken(apiKey) {
|
|
64
|
-
return (resolveSecretSentinel(apiKey) ?? apiKey).includes("sk-ant-oat");
|
|
65
|
-
}
|
|
66
|
-
function isDirectAnthropicModel(model) {
|
|
67
|
-
if (normalizeLowercaseStringOrEmpty(model.provider) !== "anthropic") return false;
|
|
68
|
-
const endpointClass = resolveProviderEndpoint(model).endpointClass;
|
|
69
|
-
return endpointClass === "default" || endpointClass === "anthropic-public";
|
|
70
|
-
}
|
|
71
63
|
function isKimiAnthropicProvider(provider) {
|
|
72
64
|
return /^kimi(?:-|$)/.test(normalizeLowercaseStringOrEmpty(provider ?? ""));
|
|
73
65
|
}
|
|
@@ -137,14 +129,12 @@ async function convertAnthropicMessages(messages, model, isOAuthToken, options)
|
|
|
137
129
|
const msg = transformedMessages[i];
|
|
138
130
|
if (!msg) continue;
|
|
139
131
|
if (msg.role === "user") {
|
|
140
|
-
const isRuntimeContextCarrier = msg.runtimeContextCarrier === true;
|
|
141
132
|
if (typeof msg.content === "string") {
|
|
142
133
|
if (msg.content.trim().length > 0) {
|
|
143
134
|
const userParam = {
|
|
144
135
|
role: "user",
|
|
145
136
|
content: sanitizeTransportPayloadText(msg.content)
|
|
146
137
|
};
|
|
147
|
-
if (isRuntimeContextCarrier) options.cacheBreakpointOptOutMessageIndexes.add(params.length);
|
|
148
138
|
params.push(userParam);
|
|
149
139
|
}
|
|
150
140
|
continue;
|
|
@@ -170,7 +160,6 @@ async function convertAnthropicMessages(messages, model, isOAuthToken, options)
|
|
|
170
160
|
role: "user",
|
|
171
161
|
content: filteredBlocks
|
|
172
162
|
};
|
|
173
|
-
if (isRuntimeContextCarrier) options.cacheBreakpointOptOutMessageIndexes.add(params.length);
|
|
174
163
|
params.push(userParam);
|
|
175
164
|
continue;
|
|
176
165
|
}
|
|
@@ -406,12 +395,13 @@ async function* parseAnthropicSseBody(body, signal) {
|
|
|
406
395
|
function createAnthropicMessagesClient(params) {
|
|
407
396
|
const url = resolveAnthropicMessagesUrl(params.baseURL);
|
|
408
397
|
return { messages: { async stream(body, options) {
|
|
409
|
-
const headers = mergeTransportHeaders({
|
|
398
|
+
const headers = new Headers(mergeTransportHeaders({
|
|
410
399
|
"content-type": "application/json",
|
|
411
400
|
"anthropic-version": "2023-06-01",
|
|
412
401
|
...params.apiKey ? { "x-api-key": params.apiKey } : {},
|
|
413
402
|
...params.authToken ? { authorization: `Bearer ${params.authToken}` } : {}
|
|
414
|
-
}, params.defaultHeaders);
|
|
403
|
+
}, params.defaultHeaders));
|
|
404
|
+
for (const [name, value] of Object.entries(options?.headers ?? {})) headers.set(name, value);
|
|
415
405
|
const response = await params.fetch(url, {
|
|
416
406
|
method: "POST",
|
|
417
407
|
headers,
|
|
@@ -482,7 +472,7 @@ function createAnthropicTransportClient(params) {
|
|
|
482
472
|
}
|
|
483
473
|
const betaFeatures = ["fine-grained-tool-streaming-2025-05-14"];
|
|
484
474
|
if (needsInterleavedBeta) betaFeatures.push("interleaved-thinking-2025-05-14");
|
|
485
|
-
if (
|
|
475
|
+
if (isAnthropicOAuthApiKey(apiKey)) {
|
|
486
476
|
const betaHeader = buildAnthropicBetaHeader(model, betaFeatures, { oauth: true });
|
|
487
477
|
return {
|
|
488
478
|
client: createAnthropicMessagesClient({
|
|
@@ -503,18 +493,20 @@ function createAnthropicTransportClient(params) {
|
|
|
503
493
|
}
|
|
504
494
|
if (useAnthropicServerSideFallback(model)) betaFeatures.push(ANTHROPIC_SERVER_SIDE_FALLBACK_BETA);
|
|
505
495
|
const betaHeader = buildAnthropicBetaHeader(model, betaFeatures, { oauth: false });
|
|
496
|
+
const defaultHeaders = mergeTransportHeaders({
|
|
497
|
+
accept: "application/json",
|
|
498
|
+
"anthropic-dangerous-direct-browser-access": "true",
|
|
499
|
+
...betaHeader ? { "anthropic-beta": betaHeader } : {}
|
|
500
|
+
}, model.headers, options?.headers);
|
|
506
501
|
return {
|
|
507
502
|
client: createAnthropicMessagesClient({
|
|
508
503
|
apiKey,
|
|
509
504
|
baseURL: model.baseUrl,
|
|
510
|
-
defaultHeaders
|
|
511
|
-
accept: "application/json",
|
|
512
|
-
"anthropic-dangerous-direct-browser-access": "true",
|
|
513
|
-
...betaHeader ? { "anthropic-beta": betaHeader } : {}
|
|
514
|
-
}, model.headers, options?.headers),
|
|
505
|
+
defaultHeaders,
|
|
515
506
|
fetch
|
|
516
507
|
}),
|
|
517
|
-
isOAuthToken: false
|
|
508
|
+
isOAuthToken: false,
|
|
509
|
+
directApiKeyBetaHeader: isDirectAnthropicModel(model) ? new Headers(defaultHeaders).get("anthropic-beta") ?? "" : void 0
|
|
518
510
|
};
|
|
519
511
|
}
|
|
520
512
|
async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
@@ -533,7 +525,6 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
533
525
|
cacheRetention: options?.cacheRetention,
|
|
534
526
|
enableCacheControl: true
|
|
535
527
|
}, model);
|
|
536
|
-
const cacheBreakpointOptOutMessageIndexes = /* @__PURE__ */ new Set();
|
|
537
528
|
const replayPlan = buildAnthropicReplayPlan(context.messages, model, {
|
|
538
529
|
enabled: !isOAuthToken && options?.anthropicServerCompaction === true,
|
|
539
530
|
authProfileId: options?.authProfileId,
|
|
@@ -541,7 +532,6 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
541
532
|
});
|
|
542
533
|
const messages = await convertAnthropicMessages(replayPlan.messages, model, isOAuthToken, {
|
|
543
534
|
allowReasoningContentReplay: supportsReasoningContentReplay(model),
|
|
544
|
-
cacheBreakpointOptOutMessageIndexes,
|
|
545
535
|
compaction: replayPlan.compaction,
|
|
546
536
|
replayThinkingEnabled
|
|
547
537
|
});
|
|
@@ -579,18 +569,19 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
579
569
|
if (convertedTools.tools.length > 0) params.tools = convertedTools.tools;
|
|
580
570
|
}
|
|
581
571
|
if (mandatoryAdaptiveThinking || model.reasoning || supportsClaudeAdaptiveThinking(model)) {
|
|
582
|
-
if (mandatoryAdaptiveThinking || options?.thinkingEnabled)
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
572
|
+
if (mandatoryAdaptiveThinking || options?.thinkingEnabled) {
|
|
573
|
+
if (supportsClaudeAdaptiveThinking(model)) {
|
|
574
|
+
params.thinking = {
|
|
575
|
+
type: "adaptive",
|
|
576
|
+
display: options?.thinkingDisplay ?? "summarized"
|
|
577
|
+
};
|
|
578
|
+
const effort = options?.effort ?? (mandatoryAdaptiveThinking ? "high" : void 0);
|
|
579
|
+
if (effort) params.output_config = { effort };
|
|
580
|
+
} else params.thinking = {
|
|
581
|
+
type: "enabled",
|
|
582
|
+
budget_tokens: options?.thinkingBudgetTokens ?? 1024
|
|
586
583
|
};
|
|
587
|
-
|
|
588
|
-
if (effort) params.output_config = { effort };
|
|
589
|
-
} else params.thinking = {
|
|
590
|
-
type: "enabled",
|
|
591
|
-
budget_tokens: options?.thinkingBudgetTokens ?? 1024
|
|
592
|
-
};
|
|
593
|
-
else if (options?.thinkingEnabled === false) params.thinking = { type: "disabled" };
|
|
584
|
+
} else if (options?.thinkingEnabled === false) params.thinking = { type: "disabled" };
|
|
594
585
|
}
|
|
595
586
|
if (options?.metadata && typeof options.metadata.user_id === "string") params.metadata = { user_id: options.metadata.user_id };
|
|
596
587
|
if (options?.toolChoice) {
|
|
@@ -598,7 +589,7 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
|
|
|
598
589
|
const projectedToolChoice = toolProjection ? reconcileAnthropicToolChoice(normalizedToolChoice, toolProjection) : normalizedToolChoice;
|
|
599
590
|
if (projectedToolChoice) params.tool_choice = projectedToolChoice;
|
|
600
591
|
}
|
|
601
|
-
applyAnthropicPayloadPolicyToParams(params, payloadPolicy,
|
|
592
|
+
applyAnthropicPayloadPolicyToParams(params, payloadPolicy, /* @__PURE__ */ new Set());
|
|
602
593
|
return {
|
|
603
594
|
params,
|
|
604
595
|
toolProjection,
|
|
@@ -633,7 +624,9 @@ function resolveAnthropicTransportOptions(model, options, apiKey) {
|
|
|
633
624
|
toolChoice: options?.toolChoice,
|
|
634
625
|
thinkingBudgets: options?.thinkingBudgets,
|
|
635
626
|
reasoning,
|
|
636
|
-
|
|
627
|
+
anthropicServerCompaction: options?.anthropicServerCompaction,
|
|
628
|
+
anthropicCompactThreshold: options?.anthropicCompactThreshold,
|
|
629
|
+
cacheTtlPruning: options?.cacheTtlPruning,
|
|
637
630
|
...options?.authProfileId ? { authProfileId: options.authProfileId } : {}
|
|
638
631
|
});
|
|
639
632
|
if (reasoning === "off") {
|
|
@@ -674,17 +667,18 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
674
667
|
stopReason: "stop",
|
|
675
668
|
timestamp: Date.now()
|
|
676
669
|
};
|
|
677
|
-
const refusalBuffer = usesClaudeStreamingRefusalContract(model) ? createDeferredEventBuffer(stream
|
|
670
|
+
const refusalBuffer = usesClaudeStreamingRefusalContract(model) ? createDeferredEventBuffer(stream) : void 0;
|
|
678
671
|
const eventSink = refusalBuffer ?? stream;
|
|
679
672
|
let costModel = model;
|
|
680
673
|
let messageStartPromptUsage;
|
|
681
674
|
let usedCompactionReplay = false;
|
|
675
|
+
let inputTransformations;
|
|
682
676
|
try {
|
|
683
677
|
const apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? "";
|
|
684
678
|
if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
|
|
685
679
|
const transportOptions = resolveAnthropicTransportOptions(model, options, apiKey);
|
|
686
680
|
const requestContext = prepareClaudeNoPrefillRequestContext(model, context);
|
|
687
|
-
const { client, isOAuthToken } = createAnthropicTransportClient({
|
|
681
|
+
const { client, isOAuthToken, directApiKeyBetaHeader } = createAnthropicTransportClient({
|
|
688
682
|
model,
|
|
689
683
|
context: requestContext,
|
|
690
684
|
apiKey,
|
|
@@ -694,13 +688,19 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
694
688
|
usedCompactionReplay = builtParams.usedCompactionReplay;
|
|
695
689
|
let params = builtParams.params;
|
|
696
690
|
const toolProjection = builtParams.toolProjection;
|
|
691
|
+
applyAnthropicContextManagementToRequest(params, model, transportOptions, directApiKeyBetaHeader);
|
|
697
692
|
const nextParams = await transportOptions.onPayload?.(params, model);
|
|
698
693
|
if (nextParams !== void 0) params = nextParams;
|
|
699
694
|
applyClaudeRequestContract(params, model);
|
|
695
|
+
const betaHeader = resolveAnthropicContextManagementBetaHeader(params, directApiKeyBetaHeader);
|
|
696
|
+
const bindingHeaders = applyAnthropicThinkingBindingControls(params, betaHeader) ?? (betaHeader !== void 0 ? { "anthropic-beta": betaHeader } : void 0);
|
|
700
697
|
const { response, stream: anthropicStream } = await client.messages.stream({
|
|
701
698
|
...params,
|
|
702
699
|
stream: true
|
|
703
|
-
},
|
|
700
|
+
}, {
|
|
701
|
+
signal: transportOptions.signal,
|
|
702
|
+
headers: bindingHeaders
|
|
703
|
+
});
|
|
704
704
|
await notifyProviderHttpResponse({
|
|
705
705
|
options: transportOptions,
|
|
706
706
|
response,
|
|
@@ -815,6 +815,8 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
815
815
|
});
|
|
816
816
|
};
|
|
817
817
|
for await (const event of anthropicStream) {
|
|
818
|
+
inputTransformations = readAnthropicInputTransformations(event) ?? inputTransformations;
|
|
819
|
+
notifyLlmRequestActivity(transportOptions.signal);
|
|
818
820
|
if (event.type === "error") {
|
|
819
821
|
const error = event.error;
|
|
820
822
|
throw new Error(error?.message || "Anthropic Messages stream failed");
|
|
@@ -987,16 +989,18 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
987
989
|
let appendedContent = false;
|
|
988
990
|
if (!hasNativeAnthropicDelta && typeof delta?.content === "string" && delta.content.length > 0) {
|
|
989
991
|
const text = sanitizeTransportPayloadText(delta.content);
|
|
990
|
-
if (text.length > 0)
|
|
991
|
-
block
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
992
|
+
if (text.length > 0) {
|
|
993
|
+
if (block?.type === "text" && index !== void 0) {
|
|
994
|
+
block.text += text;
|
|
995
|
+
eventSink.push({
|
|
996
|
+
type: "text_delta",
|
|
997
|
+
contentIndex: index,
|
|
998
|
+
delta: text,
|
|
999
|
+
partial: output
|
|
1000
|
+
});
|
|
1001
|
+
appendedContent = true;
|
|
1002
|
+
} else appendedContent = appendReasoningContentTextDelta(event.index, text);
|
|
1003
|
+
}
|
|
1000
1004
|
}
|
|
1001
1005
|
if ((appendedThinking || appendedContent) && !hasNativeAnthropicDelta) continue;
|
|
1002
1006
|
}
|
|
@@ -1102,10 +1106,13 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1102
1106
|
continue;
|
|
1103
1107
|
}
|
|
1104
1108
|
if (event.type === "message_delta") {
|
|
1109
|
+
logAnthropicContextEdits(event);
|
|
1105
1110
|
const delta = event.delta;
|
|
1106
1111
|
const usage = event.usage;
|
|
1107
|
-
if (delta?.stop_reason)
|
|
1108
|
-
|
|
1112
|
+
if (delta?.stop_reason) {
|
|
1113
|
+
if (delta.stop_reason === "refusal") applyAnthropicRefusal(output, delta.stop_details, model.provider);
|
|
1114
|
+
else output.stopReason = mapAnthropicStopReason(delta.stop_reason);
|
|
1115
|
+
}
|
|
1109
1116
|
applyAnthropicMessageDeltaUsage(output.usage, usage, messageStartPromptUsage);
|
|
1110
1117
|
calculateCost(costModel, output.usage);
|
|
1111
1118
|
if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
|
|
@@ -1134,20 +1141,22 @@ function createAnthropicMessagesTransportStreamFn() {
|
|
|
1134
1141
|
output
|
|
1135
1142
|
});
|
|
1136
1143
|
} catch (error) {
|
|
1137
|
-
if (refusalBuffer) {
|
|
1138
|
-
refusalBuffer.discard();
|
|
1139
|
-
output.content = [];
|
|
1140
|
-
} else output.content = output.content.filter((block) => block.type !== "toolCall");
|
|
1141
|
-
if (usedCompactionReplay && isAnthropicReplayRejection(error)) suppressAnthropicCompaction(output, model, options);
|
|
1142
1144
|
failTransportStream({
|
|
1143
1145
|
stream,
|
|
1144
1146
|
output,
|
|
1145
1147
|
signal: options?.signal,
|
|
1146
1148
|
error,
|
|
1147
1149
|
cleanup: () => {
|
|
1150
|
+
if (refusalBuffer) {
|
|
1151
|
+
refusalBuffer.discard();
|
|
1152
|
+
output.content = [];
|
|
1153
|
+
} else output.content = output.content.filter((block) => block.type !== "toolCall");
|
|
1154
|
+
if (usedCompactionReplay && isAnthropicReplayRejection(error)) suppressAnthropicCompaction(output, model, options);
|
|
1148
1155
|
for (const block of output.content) delete block.index;
|
|
1149
1156
|
}
|
|
1150
1157
|
});
|
|
1158
|
+
} finally {
|
|
1159
|
+
logAnthropicThinkingDrops(inputTransformations);
|
|
1151
1160
|
}
|
|
1152
1161
|
})();
|
|
1153
1162
|
return eventStream;
|
|
@@ -1595,10 +1604,11 @@ function convertTools(tools, compat, model) {
|
|
|
1595
1604
|
function buildOpenAICompletionsParams(model, context, options) {
|
|
1596
1605
|
const compat = getCompat(model);
|
|
1597
1606
|
const compatDetection = detectOpenAICompletionsCompat(model);
|
|
1598
|
-
|
|
1607
|
+
const completionsContext = context.systemPrompt ? {
|
|
1599
1608
|
...context,
|
|
1600
1609
|
systemPrompt: stripSystemPromptCacheBoundary(context.systemPrompt)
|
|
1601
|
-
} : context
|
|
1610
|
+
} : context;
|
|
1611
|
+
let messages = convertMessages(model, completionsContext, compat);
|
|
1602
1612
|
applyCompletionsReplay(messages, context, model, compat);
|
|
1603
1613
|
if (compat.strictMessageKeys) messages = stripCompletionMessagesToRoleContent(messages);
|
|
1604
1614
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention);
|
|
@@ -1659,8 +1669,10 @@ function buildOpenAICompletionsParams(model, context, options) {
|
|
|
1659
1669
|
emitModelTransportDebug(log, `[completions] clamp_max_tokens provider=${model.provider} api=${model.api} model=${model.id} requested=${effectiveMaxTokens} output=${clampedMaxTokens} effectiveContext=${effectiveContextTokens} estimatedInput=${estimatedInputTokens}`);
|
|
1660
1670
|
}
|
|
1661
1671
|
}
|
|
1662
|
-
if (clampedMaxTokens)
|
|
1663
|
-
|
|
1672
|
+
if (clampedMaxTokens) {
|
|
1673
|
+
if (compat.maxTokensField === "max_tokens") params.max_tokens = clampedMaxTokens;
|
|
1674
|
+
else params.max_completion_tokens = clampedMaxTokens;
|
|
1675
|
+
}
|
|
1664
1676
|
}
|
|
1665
1677
|
const completionsReasoningEffort = resolveOpenAICompletionsReasoningEffort(options);
|
|
1666
1678
|
const resolvedCompletionsReasoningEffort = completionsReasoningEffort ? resolveOpenAIReasoningEffortForModel({
|
|
@@ -1831,11 +1843,8 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
1831
1843
|
if (getCompat(model).requiresNonEmptyUserOrAssistantMessage) assertOpenAICompletionsPayloadHasConversationTurn(params, model);
|
|
1832
1844
|
const emitReasoning = shouldEmitOpenAICompletionsReasoning(model, options);
|
|
1833
1845
|
firstEventAbort = createFirstStreamEventAbortController(options?.signal);
|
|
1834
|
-
const { data: responseStream, response } = await client.chat.completions.create(params, buildOpenAISdkRequestOptions(model, firstEventAbort.signal, {
|
|
1835
|
-
|
|
1836
|
-
maxRetries: options?.maxRetries
|
|
1837
|
-
})).withResponse();
|
|
1838
|
-
await processCompletionsStream(withProviderResponseHook({
|
|
1846
|
+
const { data: responseStream, response } = await client.chat.completions.create(params, buildOpenAISdkRequestOptions(model, firstEventAbort.signal, { timeoutMs: options?.timeoutMs })).withResponse();
|
|
1847
|
+
const hookedResponseStream = withProviderResponseHook({
|
|
1839
1848
|
stream: responseStream,
|
|
1840
1849
|
signal: firstEventAbort.signal,
|
|
1841
1850
|
abort: firstEventAbort.abort,
|
|
@@ -1844,9 +1853,11 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
1844
1853
|
type: "start",
|
|
1845
1854
|
partial: output
|
|
1846
1855
|
})
|
|
1847
|
-
})
|
|
1856
|
+
});
|
|
1857
|
+
await processCompletionsStream(hookedResponseStream, output, model, stream, {
|
|
1848
1858
|
signal: options?.signal,
|
|
1849
1859
|
emitReasoning,
|
|
1860
|
+
strictReasoningTags: reasoningTagTextPolicy.isStrict(options),
|
|
1850
1861
|
firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options),
|
|
1851
1862
|
abortFirstEventStream: firstEventAbort.abort,
|
|
1852
1863
|
onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
|
|
@@ -1877,160 +1888,6 @@ function createOpenAICompletionsTransportStreamFn() {
|
|
|
1877
1888
|
};
|
|
1878
1889
|
}
|
|
1879
1890
|
//#endregion
|
|
1880
|
-
//#region packages/ai/src/transports/openai-responses-compact-request.ts
|
|
1881
|
-
const COMPACT_REQUEST = Symbol("openaiResponsesCompactRequest");
|
|
1882
|
-
function claimResponsesCompactRequest(options) {
|
|
1883
|
-
const controller = options ? Reflect.get(options, COMPACT_REQUEST) : void 0;
|
|
1884
|
-
if (controller?.claimed === false) {
|
|
1885
|
-
controller.claimed = true;
|
|
1886
|
-
return controller;
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1889
|
-
/** Run a compact-endpoint request through the session's prepared stream stack. */
|
|
1890
|
-
async function requestPreparedOpenAIResponsesCompaction(streamFn, model, context, options) {
|
|
1891
|
-
const preparedOptions = { ...options };
|
|
1892
|
-
let resolveResult;
|
|
1893
|
-
let rejectResult;
|
|
1894
|
-
const result = new Promise((resolve, reject) => {
|
|
1895
|
-
resolveResult = resolve;
|
|
1896
|
-
rejectResult = reject;
|
|
1897
|
-
});
|
|
1898
|
-
const controller = {
|
|
1899
|
-
claimed: false,
|
|
1900
|
-
resolve: resolveResult,
|
|
1901
|
-
reject: rejectResult
|
|
1902
|
-
};
|
|
1903
|
-
Reflect.set(preparedOptions, COMPACT_REQUEST, controller);
|
|
1904
|
-
const stream = await Promise.resolve(streamFn(model, context, preparedOptions));
|
|
1905
|
-
if (!controller.claimed) throw new Error("Prepared stream did not reach an OpenAI Responses transport");
|
|
1906
|
-
try {
|
|
1907
|
-
return await result;
|
|
1908
|
-
} finally {
|
|
1909
|
-
await stream.result().catch(() => void 0);
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
//#endregion
|
|
1913
|
-
//#region packages/ai/src/transports/openai-responses-continuation.ts
|
|
1914
|
-
const HTTP_CONTINUATION_IDLE_TTL_MS = 300 * 1e3;
|
|
1915
|
-
const TURN_HEADERS = /* @__PURE__ */ new Set([
|
|
1916
|
-
"traceparent",
|
|
1917
|
-
"x-openclaw-turn-id",
|
|
1918
|
-
"x-openclaw-turn-attempt"
|
|
1919
|
-
]);
|
|
1920
|
-
function jsonValuesEqual(left, right) {
|
|
1921
|
-
return stableStringify(JSON.parse(JSON.stringify(left))) === stableStringify(JSON.parse(JSON.stringify(right)));
|
|
1922
|
-
}
|
|
1923
|
-
function requestWithoutInput(request) {
|
|
1924
|
-
const { input: _input, previous_response_id: _previousResponseId, ...rest } = request;
|
|
1925
|
-
if (!isRecord(rest.metadata)) return rest;
|
|
1926
|
-
const metadata = Object.fromEntries(Object.entries(rest.metadata).filter(([key]) => key !== "openclaw_turn_id" && key !== "openclaw_turn_attempt"));
|
|
1927
|
-
return {
|
|
1928
|
-
...rest,
|
|
1929
|
-
metadata
|
|
1930
|
-
};
|
|
1931
|
-
}
|
|
1932
|
-
function normalizeAssistantReplayInput(input) {
|
|
1933
|
-
return input.map((item) => {
|
|
1934
|
-
if (!isRecord(item)) return item;
|
|
1935
|
-
if (item.type === "reasoning") return { type: "reasoning" };
|
|
1936
|
-
if (item.type !== "function_call" && !(item.type === "message" && item.role === "assistant")) return item;
|
|
1937
|
-
const { id: _id, status: _status, ...stableItem } = item;
|
|
1938
|
-
if (item.type === "message" && Array.isArray(stableItem.content)) stableItem.content = stableItem.content.map((part) => {
|
|
1939
|
-
if (!isRecord(part) || part.type !== "output_text") return part;
|
|
1940
|
-
const { annotations: _annotations, logprobs: _logprobs, ...stablePart } = part;
|
|
1941
|
-
return stablePart;
|
|
1942
|
-
});
|
|
1943
|
-
return stableItem;
|
|
1944
|
-
});
|
|
1945
|
-
}
|
|
1946
|
-
function resolveResponsesContinuationRequest(continuation, request) {
|
|
1947
|
-
if (!continuation) return {
|
|
1948
|
-
request,
|
|
1949
|
-
continuationStatus: "no_previous_response"
|
|
1950
|
-
};
|
|
1951
|
-
if (request.previous_response_id) return {
|
|
1952
|
-
request,
|
|
1953
|
-
continuationStatus: "explicit_previous_response_id"
|
|
1954
|
-
};
|
|
1955
|
-
if (!jsonValuesEqual(requestWithoutInput(request), requestWithoutInput(continuation.lastRequest))) return {
|
|
1956
|
-
request,
|
|
1957
|
-
continuationStatus: "request_changed"
|
|
1958
|
-
};
|
|
1959
|
-
const currentInput = request.input ?? [];
|
|
1960
|
-
const previousInput = continuation.lastRequest.input ?? [];
|
|
1961
|
-
const baselineLength = previousInput.length + continuation.lastResponseItems.length;
|
|
1962
|
-
if (currentInput.length < baselineLength) return {
|
|
1963
|
-
request,
|
|
1964
|
-
continuationStatus: "history_shorter"
|
|
1965
|
-
};
|
|
1966
|
-
if (!jsonValuesEqual(normalizeAssistantReplayInput(currentInput.slice(0, previousInput.length)), normalizeAssistantReplayInput(previousInput)) || !jsonValuesEqual(normalizeAssistantReplayInput(currentInput.slice(previousInput.length, baselineLength)), normalizeAssistantReplayInput(continuation.lastResponseItems))) return {
|
|
1967
|
-
request,
|
|
1968
|
-
continuationStatus: "history_changed"
|
|
1969
|
-
};
|
|
1970
|
-
return {
|
|
1971
|
-
request: {
|
|
1972
|
-
...request,
|
|
1973
|
-
previous_response_id: continuation.lastResponseId,
|
|
1974
|
-
input: currentInput.slice(baselineLength)
|
|
1975
|
-
},
|
|
1976
|
-
continuationStatus: "continued"
|
|
1977
|
-
};
|
|
1978
|
-
}
|
|
1979
|
-
const httpContinuationEntries = /* @__PURE__ */ new Map();
|
|
1980
|
-
let nextHttpContinuationGeneration = 1;
|
|
1981
|
-
function connectionIdentity(params) {
|
|
1982
|
-
const headers = Object.entries(resolveAiTransportHeaderSentinels(params.headers) ?? {}).map(([name, value]) => [name.toLowerCase(), value]).filter(([name]) => !TURN_HEADERS.has(name)).toSorted(([a], [b]) => a.localeCompare(b));
|
|
1983
|
-
return sha256Hex(JSON.stringify([
|
|
1984
|
-
getAiTransportHost().resolveSecretSentinel(params.apiKey),
|
|
1985
|
-
params.baseUrl,
|
|
1986
|
-
headers
|
|
1987
|
-
]));
|
|
1988
|
-
}
|
|
1989
|
-
function claimOpenAIResponsesHttpContinuation(params) {
|
|
1990
|
-
const key = `${params.sessionId}\0${connectionIdentity(params)}`;
|
|
1991
|
-
const previous = httpContinuationEntries.get(key);
|
|
1992
|
-
if (previous?.kind === "claimed") return;
|
|
1993
|
-
if (previous?.kind === "ready") clearTimeout(previous.idleTimer);
|
|
1994
|
-
const generation = nextHttpContinuationGeneration++;
|
|
1995
|
-
const claimed = {
|
|
1996
|
-
kind: "claimed",
|
|
1997
|
-
sessionId: params.sessionId,
|
|
1998
|
-
generation
|
|
1999
|
-
};
|
|
2000
|
-
httpContinuationEntries.set(key, claimed);
|
|
2001
|
-
return {
|
|
2002
|
-
request: resolveResponsesContinuationRequest(previous?.kind === "ready" ? previous.state : void 0, params.request).request,
|
|
2003
|
-
commit: (effectiveRequest, response) => {
|
|
2004
|
-
if (httpContinuationEntries.get(key) !== claimed) return;
|
|
2005
|
-
const idleTimer = setTimeout(() => {
|
|
2006
|
-
const current = httpContinuationEntries.get(key);
|
|
2007
|
-
if (current?.kind === "ready" && current.generation === generation) httpContinuationEntries.delete(key);
|
|
2008
|
-
}, HTTP_CONTINUATION_IDLE_TTL_MS);
|
|
2009
|
-
idleTimer.unref?.();
|
|
2010
|
-
const ready = {
|
|
2011
|
-
...claimed,
|
|
2012
|
-
kind: "ready",
|
|
2013
|
-
state: {
|
|
2014
|
-
lastRequest: effectiveRequest,
|
|
2015
|
-
lastResponseId: response.id,
|
|
2016
|
-
lastResponseItems: response.output
|
|
2017
|
-
},
|
|
2018
|
-
idleTimer
|
|
2019
|
-
};
|
|
2020
|
-
httpContinuationEntries.set(key, ready);
|
|
2021
|
-
},
|
|
2022
|
-
release: () => {
|
|
2023
|
-
if (httpContinuationEntries.get(key) === claimed) httpContinuationEntries.delete(key);
|
|
2024
|
-
}
|
|
2025
|
-
};
|
|
2026
|
-
}
|
|
2027
|
-
registerSessionResourceCleanup((sessionId) => {
|
|
2028
|
-
for (const [key, entry] of httpContinuationEntries) if (!sessionId || entry.sessionId === sessionId) {
|
|
2029
|
-
if (entry.kind === "ready") clearTimeout(entry.idleTimer);
|
|
2030
|
-
httpContinuationEntries.delete(key);
|
|
2031
|
-
}
|
|
2032
|
-
});
|
|
2033
|
-
//#endregion
|
|
2034
1891
|
//#region packages/ai/src/transports/openai-responses-params-internal.ts
|
|
2035
1892
|
const OPENAI_RESPONSES_TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set([
|
|
2036
1893
|
"openai",
|
|
@@ -2058,10 +1915,6 @@ function convertResponsesTools(tools, model, options) {
|
|
|
2058
1915
|
})
|
|
2059
1916
|
};
|
|
2060
1917
|
}
|
|
2061
|
-
function getPromptCacheRetention(baseUrl, cacheRetention) {
|
|
2062
|
-
if (cacheRetention !== "long") return;
|
|
2063
|
-
return baseUrl?.includes("api.openai.com") ? "24h" : void 0;
|
|
2064
|
-
}
|
|
2065
1918
|
function resolveOpenAIReasoningEffort(options) {
|
|
2066
1919
|
return normalizeOpenAIReasoningEffort(options?.reasoningEffort ?? options?.reasoning ?? "high");
|
|
2067
1920
|
}
|
|
@@ -2112,18 +1965,28 @@ function sanitizeOpenAICodexResponsesParams(model, params) {
|
|
|
2112
1965
|
stripOpenAICodexResponsesUnsupportedTextFields(params);
|
|
2113
1966
|
return params;
|
|
2114
1967
|
}
|
|
2115
|
-
function
|
|
1968
|
+
function buildOpenAIResponsesInstructionsText(context) {
|
|
2116
1969
|
if (!context.systemPrompt) return;
|
|
2117
1970
|
return sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt));
|
|
2118
1971
|
}
|
|
2119
|
-
function
|
|
2120
|
-
|
|
1972
|
+
function resolveOpenAIResponsesInstructions(model, context, usesInstructionsField) {
|
|
1973
|
+
if (!usesInstructionsField) return;
|
|
1974
|
+
const instructions = buildOpenAIResponsesInstructionsText(context);
|
|
2121
1975
|
if (instructions && instructions.trim().length > 0) return instructions;
|
|
2122
1976
|
return usesNativeOpenAICodexResponsesBackend(model) ? OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS : void 0;
|
|
2123
1977
|
}
|
|
2124
|
-
function
|
|
1978
|
+
function buildOpenAIResponsesCompactSystemMessage(model, instructions) {
|
|
1979
|
+
const compat = getCompat(model);
|
|
1980
|
+
const supportsDeveloperRole = typeof compat.supportsDeveloperRole === "boolean" ? compat.supportsDeveloperRole : void 0;
|
|
1981
|
+
const role = model.reasoning && supportsDeveloperRole !== false ? "developer" : "system";
|
|
1982
|
+
return buildResponsesInputMessage(role, [{
|
|
1983
|
+
type: "input_text",
|
|
1984
|
+
text: instructions
|
|
1985
|
+
}]);
|
|
1986
|
+
}
|
|
1987
|
+
function ensureOpenAIResponsesNonEmptyInput(messages, context) {
|
|
2125
1988
|
if (messages.length > 0 || !context.systemPrompt) return;
|
|
2126
|
-
if (!
|
|
1989
|
+
if (!buildOpenAIResponsesInstructionsText(context)) throw new Error("OpenAI Responses requires non-empty input when only systemPrompt is provided.");
|
|
2127
1990
|
messages.push(buildResponsesInputMessage("user", [{
|
|
2128
1991
|
type: "input_text",
|
|
2129
1992
|
text: " "
|
|
@@ -2137,16 +2000,12 @@ function resolveOpenAIResponsesTextFormat(responseFormat) {
|
|
|
2137
2000
|
return responseFormat;
|
|
2138
2001
|
}
|
|
2139
2002
|
function convertOpenAIResponsesMessagesForRequest(model, context, options, replayMode) {
|
|
2140
|
-
const isCodexResponses = isOpenAICodexResponsesModel(model);
|
|
2141
2003
|
const isNativeCodexResponses = usesNativeOpenAICodexResponsesBackend(model);
|
|
2142
|
-
const compat = getCompat(model);
|
|
2143
|
-
const supportsDeveloperRole = typeof compat.supportsDeveloperRole === "boolean" ? compat.supportsDeveloperRole : void 0;
|
|
2144
2004
|
const payloadPolicy = resolveOpenAIResponsesPayloadPolicy(model, { storeMode: "disable" });
|
|
2145
2005
|
const policyAllowsReplayIds = payloadPolicy.explicitStore !== false && !payloadPolicy.shouldStripStore;
|
|
2146
2006
|
const replayResponsesItemIds = !isNativeCodexResponses && (options?.replayResponsesItemIds ?? policyAllowsReplayIds);
|
|
2147
2007
|
return convertResponsesMessages(model, context, OPENAI_RESPONSES_TOOL_CALL_PROVIDERS, {
|
|
2148
|
-
includeSystemPrompt: !
|
|
2149
|
-
supportsDeveloperRole,
|
|
2008
|
+
includeSystemPrompt: !payloadPolicy.usesInstructionsField,
|
|
2150
2009
|
replayReasoningItems: true,
|
|
2151
2010
|
replayResponsesItemIds,
|
|
2152
2011
|
authProfileId: options?.authProfileId,
|
|
@@ -2155,25 +2014,25 @@ function convertOpenAIResponsesMessagesForRequest(model, context, options, repla
|
|
|
2155
2014
|
});
|
|
2156
2015
|
}
|
|
2157
2016
|
function buildOpenAIResponsesParams(model, context, options, metadata, replayMode = "checkpoint") {
|
|
2158
|
-
const isCodexResponses = isOpenAICodexResponsesModel(model);
|
|
2159
2017
|
const payloadPolicy = resolveOpenAIResponsesPayloadPolicy(model, { storeMode: "disable" });
|
|
2160
2018
|
const messages = convertOpenAIResponsesMessagesForRequest(model, context, options, replayMode);
|
|
2161
|
-
|
|
2019
|
+
ensureOpenAIResponsesNonEmptyInput(messages, context);
|
|
2162
2020
|
const cacheRetention = resolveCacheRetention(options?.cacheRetention);
|
|
2163
2021
|
const promptCacheKey = resolvePromptCacheKey(options, cacheRetention);
|
|
2022
|
+
const instructions = resolveOpenAIResponsesInstructions(model, context, payloadPolicy.usesInstructionsField);
|
|
2164
2023
|
const params = {
|
|
2165
2024
|
model: model.id,
|
|
2166
2025
|
input: messages,
|
|
2167
2026
|
stream: true,
|
|
2168
2027
|
prompt_cache_key: promptCacheKey,
|
|
2169
|
-
|
|
2170
|
-
...
|
|
2028
|
+
...resolveOpenAIResponsesCacheParams(model, cacheRetention, model.baseUrl?.includes("api.openai.com")),
|
|
2029
|
+
...instructions ? { instructions } : {},
|
|
2171
2030
|
...metadata ? { metadata } : {}
|
|
2172
2031
|
};
|
|
2173
2032
|
const effectiveMaxTokens = options?.maxTokens || model.maxTokens;
|
|
2174
|
-
if (effectiveMaxTokens) params.max_output_tokens = effectiveMaxTokens;
|
|
2175
|
-
if (options?.temperature !== void 0) params.temperature = options.temperature;
|
|
2176
|
-
if (options?.topP !== void 0) params.top_p = options.topP;
|
|
2033
|
+
if (effectiveMaxTokens) params.max_output_tokens = Math.max(effectiveMaxTokens, 16);
|
|
2034
|
+
if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
|
|
2035
|
+
if (options?.topP !== void 0 && model.id !== "gpt-6-astra") params.top_p = options.topP;
|
|
2177
2036
|
if (options?.responseFormat !== void 0) params.text = {
|
|
2178
2037
|
...params.text,
|
|
2179
2038
|
format: resolveOpenAIResponsesTextFormat(options.responseFormat)
|
|
@@ -2189,9 +2048,10 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
|
|
|
2189
2048
|
}
|
|
2190
2049
|
if (model.reasoning) {
|
|
2191
2050
|
if (options?.reasoningEffort || options?.reasoning || options?.reasoningSummary) {
|
|
2051
|
+
const requestedReasoningEffort = resolveOpenAIReasoningEffort(options);
|
|
2192
2052
|
const resolvedReasoningEffort = resolveOpenAIReasoningEffortForModel({
|
|
2193
2053
|
model,
|
|
2194
|
-
effort:
|
|
2054
|
+
effort: requestedReasoningEffort
|
|
2195
2055
|
});
|
|
2196
2056
|
const reasoningEffort = resolvedReasoningEffort ? raiseMinimalReasoningForResponsesWebSearch({
|
|
2197
2057
|
model,
|
|
@@ -2217,9 +2077,311 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
|
|
|
2217
2077
|
return sanitizeOpenAICodexResponsesParams(model, params);
|
|
2218
2078
|
}
|
|
2219
2079
|
//#endregion
|
|
2080
|
+
//#region packages/ai/src/transports/openai-responses-reasoning-update.ts
|
|
2081
|
+
function isConfigurationUpdate(value) {
|
|
2082
|
+
return isRecord(value) && value.type === "configuration_update" && isRecord(value.reasoning) && typeof value.reasoning.effort === "string";
|
|
2083
|
+
}
|
|
2084
|
+
function isResponsesReasoningUpdateCompatible(request) {
|
|
2085
|
+
const mode = isRecord(request.reasoning) ? request.reasoning.mode : void 0;
|
|
2086
|
+
return request.model === "gpt-6-astra" && (mode === void 0 || mode === "standard") && (!isRecord(request.multi_agent) || request.multi_agent.enabled !== true) && request.truncation !== "auto" && (!Array.isArray(request.context_management) || !request.context_management.some((item) => isRecord(item) && item.type === "compaction"));
|
|
2087
|
+
}
|
|
2088
|
+
function supportsResponsesReasoningUpdate(request) {
|
|
2089
|
+
return isResponsesReasoningUpdateCompatible(request) && isRecord(request.reasoning) && typeof request.reasoning.effort === "string";
|
|
2090
|
+
}
|
|
2091
|
+
function canReferenceResponsesReasoningHistory(previous, request) {
|
|
2092
|
+
return !previous.input?.some(isConfigurationUpdate) || isResponsesReasoningUpdateCompatible(request);
|
|
2093
|
+
}
|
|
2094
|
+
/** Rehydrate input controls only provisionally; continuation must validate the full prefix. */
|
|
2095
|
+
function replayResponsesReasoningUpdates(previous, request, previousOutputLength, steering) {
|
|
2096
|
+
if (steering !== "required-input" && (!supportsResponsesReasoningUpdate(previous) || !supportsResponsesReasoningUpdate(request)) || !Array.isArray(previous.input) || !Array.isArray(request.input) || request.input.some(isConfigurationUpdate)) return request;
|
|
2097
|
+
const input = [...request.input];
|
|
2098
|
+
let activeEffort = isRecord(previous.reasoning) ? previous.reasoning.effort : void 0;
|
|
2099
|
+
for (const [index, item] of previous.input.entries()) if (isConfigurationUpdate(item)) {
|
|
2100
|
+
input.splice(index, 0, item);
|
|
2101
|
+
activeEffort = item.reasoning.effort;
|
|
2102
|
+
}
|
|
2103
|
+
if (steering === "required-input") return input.length === request.input.length ? request : {
|
|
2104
|
+
...request,
|
|
2105
|
+
input
|
|
2106
|
+
};
|
|
2107
|
+
if (!isRecord(previous.reasoning) || !isRecord(request.reasoning) || typeof request.reasoning.effort !== "string") return request;
|
|
2108
|
+
if (activeEffort !== request.reasoning.effort && steering !== "automatic") {
|
|
2109
|
+
const baselineLength = previous.input.length + previousOutputLength;
|
|
2110
|
+
const nextUser = input.findIndex((item, index) => index >= baselineLength && "role" in item && item.role === "user");
|
|
2111
|
+
if (nextUser === -1) return request;
|
|
2112
|
+
input.splice(nextUser, 0, {
|
|
2113
|
+
type: "configuration_update",
|
|
2114
|
+
reasoning: { effort: request.reasoning.effort }
|
|
2115
|
+
});
|
|
2116
|
+
}
|
|
2117
|
+
if (input.length === request.input.length && activeEffort === request.reasoning.effort) return request;
|
|
2118
|
+
return {
|
|
2119
|
+
...request,
|
|
2120
|
+
reasoning: {
|
|
2121
|
+
...request.reasoning,
|
|
2122
|
+
effort: previous.reasoning.effort
|
|
2123
|
+
},
|
|
2124
|
+
input
|
|
2125
|
+
};
|
|
2126
|
+
}
|
|
2127
|
+
//#endregion
|
|
2128
|
+
//#region packages/ai/src/transports/openai-responses-continuation.ts
|
|
2129
|
+
const HTTP_CONTINUATION_IDLE_TTL_MS = 3e5;
|
|
2130
|
+
const TURN_HEADERS = /* @__PURE__ */ new Set([
|
|
2131
|
+
"traceparent",
|
|
2132
|
+
"x-openclaw-turn-id",
|
|
2133
|
+
"x-openclaw-turn-attempt"
|
|
2134
|
+
]);
|
|
2135
|
+
function jsonValuesEqual(left, right) {
|
|
2136
|
+
const leftJson = JSON.stringify(left);
|
|
2137
|
+
const normalizedLeft = stableStringify(JSON.parse(leftJson));
|
|
2138
|
+
const rightJson = JSON.stringify(right);
|
|
2139
|
+
return leftJson === rightJson || normalizedLeft === stableStringify(JSON.parse(rightJson));
|
|
2140
|
+
}
|
|
2141
|
+
function requestWithoutInput(request) {
|
|
2142
|
+
const { input: _input, previous_response_id: _previousResponseId, instructions: _instructions, tools: _tools, ...rest } = request;
|
|
2143
|
+
if (!isRecord(rest.metadata)) return rest;
|
|
2144
|
+
const metadata = Object.fromEntries(Object.entries(rest.metadata).filter(([key]) => key !== "openclaw_turn_id" && key !== "openclaw_turn_attempt"));
|
|
2145
|
+
return {
|
|
2146
|
+
...rest,
|
|
2147
|
+
metadata
|
|
2148
|
+
};
|
|
2149
|
+
}
|
|
2150
|
+
function normalizeAssistantReplayInput(input, fromResponse = false) {
|
|
2151
|
+
return input.map((item) => {
|
|
2152
|
+
if (!isRecord(item)) return item;
|
|
2153
|
+
if (item.type === "reasoning") return { type: "reasoning" };
|
|
2154
|
+
if (item.type !== "function_call" && !(item.type === "message" && item.role === "assistant")) return item;
|
|
2155
|
+
const { id: _id, status: _status, ...stableItem } = item;
|
|
2156
|
+
if (fromResponse && item.type === "function_call") {
|
|
2157
|
+
const args = parseJsonObjectPreservingUnsafeIntegers(stableItem.arguments);
|
|
2158
|
+
stableItem.arguments = args ? JSON.stringify(args) : stableItem.arguments;
|
|
2159
|
+
}
|
|
2160
|
+
if (item.type === "message" && Array.isArray(stableItem.content)) stableItem.content = stableItem.content.map((part) => {
|
|
2161
|
+
if (!isRecord(part) || part.type !== "output_text") return part;
|
|
2162
|
+
const { annotations: _annotations, logprobs: _logprobs, ...stablePart } = part;
|
|
2163
|
+
return stablePart;
|
|
2164
|
+
});
|
|
2165
|
+
return stableItem;
|
|
2166
|
+
});
|
|
2167
|
+
}
|
|
2168
|
+
function resolveResponsesContinuationRequest(continuation, request, steering) {
|
|
2169
|
+
if (!continuation) return {
|
|
2170
|
+
request,
|
|
2171
|
+
continuationStatus: "no_previous_response"
|
|
2172
|
+
};
|
|
2173
|
+
if (request.previous_response_id) return {
|
|
2174
|
+
request,
|
|
2175
|
+
continuationStatus: "explicit_previous_response_id"
|
|
2176
|
+
};
|
|
2177
|
+
if (!canReferenceResponsesReasoningHistory(continuation.lastRequest, request)) return {
|
|
2178
|
+
request,
|
|
2179
|
+
continuationStatus: "request_changed"
|
|
2180
|
+
};
|
|
2181
|
+
const prepared = replayResponsesReasoningUpdates(continuation.lastRequest, request, continuation.lastResponseItems.length, steering);
|
|
2182
|
+
if (steering !== "required-input" && !jsonValuesEqual(requestWithoutInput(prepared), requestWithoutInput(continuation.lastRequest))) return {
|
|
2183
|
+
request,
|
|
2184
|
+
continuationStatus: "request_changed"
|
|
2185
|
+
};
|
|
2186
|
+
const currentInput = prepared.input ?? [];
|
|
2187
|
+
const previousInput = continuation.lastRequest.input ?? [];
|
|
2188
|
+
const baselineLength = previousInput.length + continuation.lastResponseItems.length;
|
|
2189
|
+
if (currentInput.length < baselineLength) return {
|
|
2190
|
+
request,
|
|
2191
|
+
continuationStatus: "history_shorter"
|
|
2192
|
+
};
|
|
2193
|
+
if (!jsonValuesEqual(normalizeAssistantReplayInput(currentInput.slice(0, previousInput.length)), normalizeAssistantReplayInput(previousInput)) || !jsonValuesEqual(normalizeAssistantReplayInput(currentInput.slice(previousInput.length, baselineLength)), normalizeAssistantReplayInput(continuation.lastResponseItems, true))) return {
|
|
2194
|
+
request,
|
|
2195
|
+
continuationStatus: "history_changed"
|
|
2196
|
+
};
|
|
2197
|
+
return {
|
|
2198
|
+
request: {
|
|
2199
|
+
...prepared,
|
|
2200
|
+
previous_response_id: continuation.lastResponseId,
|
|
2201
|
+
input: currentInput.slice(baselineLength)
|
|
2202
|
+
},
|
|
2203
|
+
...prepared !== request ? { fullRequest: prepared } : {},
|
|
2204
|
+
continuationStatus: "continued"
|
|
2205
|
+
};
|
|
2206
|
+
}
|
|
2207
|
+
const httpContinuationEntries = /* @__PURE__ */ new Map();
|
|
2208
|
+
function deleteHttpContinuationIfOwned(key, entry) {
|
|
2209
|
+
if (httpContinuationEntries.get(key) === entry) httpContinuationEntries.delete(key);
|
|
2210
|
+
}
|
|
2211
|
+
function connectionIdentity(params) {
|
|
2212
|
+
const headers = Object.entries(resolveAiTransportHeaderSentinels(params.headers) ?? {}).map(([name, value]) => [name.toLowerCase(), value]).filter(([name]) => !TURN_HEADERS.has(name)).toSorted(([a], [b]) => a.localeCompare(b));
|
|
2213
|
+
return sha256Hex(JSON.stringify([
|
|
2214
|
+
getAiTransportHost().resolveSecretSentinel(params.apiKey),
|
|
2215
|
+
params.baseUrl,
|
|
2216
|
+
headers
|
|
2217
|
+
]));
|
|
2218
|
+
}
|
|
2219
|
+
function claimOpenAIResponsesHttpContinuation(params) {
|
|
2220
|
+
const key = `${params.sessionId}\0${connectionIdentity(params)}`;
|
|
2221
|
+
const previous = httpContinuationEntries.get(key);
|
|
2222
|
+
if (previous?.kind === "claimed") return;
|
|
2223
|
+
if (previous?.kind === "ready") clearTimeout(previous.idleTimer);
|
|
2224
|
+
const claimed = {
|
|
2225
|
+
kind: "claimed",
|
|
2226
|
+
sessionId: params.sessionId
|
|
2227
|
+
};
|
|
2228
|
+
httpContinuationEntries.set(key, claimed);
|
|
2229
|
+
try {
|
|
2230
|
+
const resolved = resolveResponsesContinuationRequest(previous?.kind === "ready" ? previous.state : void 0, params.request);
|
|
2231
|
+
const fullRequest = resolved.fullRequest ?? params.request;
|
|
2232
|
+
return {
|
|
2233
|
+
request: params.request.store === false ? fullRequest : resolved.request,
|
|
2234
|
+
fullRequest,
|
|
2235
|
+
commit: (effectiveRequest, response) => {
|
|
2236
|
+
if (httpContinuationEntries.get(key) !== claimed) return;
|
|
2237
|
+
const ready = {
|
|
2238
|
+
...claimed,
|
|
2239
|
+
kind: "ready",
|
|
2240
|
+
state: {
|
|
2241
|
+
lastRequest: effectiveRequest,
|
|
2242
|
+
lastResponseId: response.id,
|
|
2243
|
+
lastResponseItems: response.output
|
|
2244
|
+
},
|
|
2245
|
+
idleTimer: setTimeout(() => deleteHttpContinuationIfOwned(key, ready), HTTP_CONTINUATION_IDLE_TTL_MS)
|
|
2246
|
+
};
|
|
2247
|
+
ready.idleTimer.unref?.();
|
|
2248
|
+
httpContinuationEntries.set(key, ready);
|
|
2249
|
+
},
|
|
2250
|
+
release: () => deleteHttpContinuationIfOwned(key, claimed)
|
|
2251
|
+
};
|
|
2252
|
+
} catch (error) {
|
|
2253
|
+
deleteHttpContinuationIfOwned(key, claimed);
|
|
2254
|
+
throw error;
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
registerSessionResourceCleanup((sessionId) => {
|
|
2258
|
+
for (const [key, entry] of httpContinuationEntries) if (!sessionId || entry.sessionId === sessionId) {
|
|
2259
|
+
if (entry.kind === "ready") clearTimeout(entry.idleTimer);
|
|
2260
|
+
httpContinuationEntries.delete(key);
|
|
2261
|
+
}
|
|
2262
|
+
});
|
|
2263
|
+
//#endregion
|
|
2264
|
+
//#region packages/ai/src/transports/openai-responses-steering.ts
|
|
2265
|
+
function cloneWireRequest(request) {
|
|
2266
|
+
const serialized = JSON.stringify(request);
|
|
2267
|
+
return JSON.parse(serialized);
|
|
2268
|
+
}
|
|
2269
|
+
async function projectResponsesSteeringInput(request, project) {
|
|
2270
|
+
const { input: activeInput, ...activeSettings } = cloneWireRequest(request);
|
|
2271
|
+
if (!Array.isArray(activeInput)) return [];
|
|
2272
|
+
const { input, ...settings } = cloneWireRequest(await project());
|
|
2273
|
+
if (!Array.isArray(input) || stableStringify(settings) !== stableStringify(activeSettings) || stableStringify(input.slice(0, activeInput.length)) !== stableStringify(activeInput)) return [];
|
|
2274
|
+
const projected = input.slice(activeInput.length);
|
|
2275
|
+
return projected.every((item) => isRecord(item) && item.role === "user") ? projected : [];
|
|
2276
|
+
}
|
|
2277
|
+
/** One response owns admission; accepted input stays on this connection until continuation. */
|
|
2278
|
+
function createResponsesSteering(params) {
|
|
2279
|
+
let responseId;
|
|
2280
|
+
let sealed = false;
|
|
2281
|
+
let unsubscribe;
|
|
2282
|
+
const pending = [];
|
|
2283
|
+
const accepted = /* @__PURE__ */ new Map();
|
|
2284
|
+
const acknowledged = /* @__PURE__ */ new Set();
|
|
2285
|
+
const seal = () => {
|
|
2286
|
+
sealed = true;
|
|
2287
|
+
const cleanup = unsubscribe;
|
|
2288
|
+
unsubscribe = void 0;
|
|
2289
|
+
cleanup?.();
|
|
2290
|
+
};
|
|
2291
|
+
return {
|
|
2292
|
+
get responseId() {
|
|
2293
|
+
return responseId;
|
|
2294
|
+
},
|
|
2295
|
+
get pending() {
|
|
2296
|
+
return pending.length > 0;
|
|
2297
|
+
},
|
|
2298
|
+
get acceptedInput() {
|
|
2299
|
+
return [...accepted.values()].flat();
|
|
2300
|
+
},
|
|
2301
|
+
seal,
|
|
2302
|
+
close(error) {
|
|
2303
|
+
seal();
|
|
2304
|
+
for (const submission of pending.splice(0)) submission.reject(error);
|
|
2305
|
+
},
|
|
2306
|
+
handle(event) {
|
|
2307
|
+
if (!isRecord(event)) return false;
|
|
2308
|
+
if (event.type === "response.created" && !responseId && !sealed) {
|
|
2309
|
+
const response = isRecord(event.response) ? event.response : void 0;
|
|
2310
|
+
if (typeof response?.id !== "string" || !response.id.trim()) throw new Error("Responses steering requires a response identity");
|
|
2311
|
+
const activeResponseId = response.id;
|
|
2312
|
+
responseId = activeResponseId;
|
|
2313
|
+
const cleanup = params.onActiveResponse({
|
|
2314
|
+
needsContinuation: params.needsContinuation,
|
|
2315
|
+
steer(messages) {
|
|
2316
|
+
if (sealed || messages.length === 0) return Promise.resolve(false);
|
|
2317
|
+
params.assertActive();
|
|
2318
|
+
const converted = params.toInput(messages);
|
|
2319
|
+
const submit = (input) => {
|
|
2320
|
+
if (sealed || input.length === 0) return Promise.resolve(false);
|
|
2321
|
+
params.assertActive();
|
|
2322
|
+
return new Promise((resolve, reject) => {
|
|
2323
|
+
pending.push({
|
|
2324
|
+
input,
|
|
2325
|
+
resolve,
|
|
2326
|
+
reject
|
|
2327
|
+
});
|
|
2328
|
+
params.send({
|
|
2329
|
+
type: "response.steer",
|
|
2330
|
+
previous_response_id: activeResponseId,
|
|
2331
|
+
input
|
|
2332
|
+
});
|
|
2333
|
+
});
|
|
2334
|
+
};
|
|
2335
|
+
return Array.isArray(converted) ? submit(converted) : converted.then(submit);
|
|
2336
|
+
}
|
|
2337
|
+
});
|
|
2338
|
+
if (sealed) cleanup?.();
|
|
2339
|
+
else unsubscribe = cleanup;
|
|
2340
|
+
return false;
|
|
2341
|
+
}
|
|
2342
|
+
if (event.type !== "response.steer.accepted" && event.type !== "response.steer.failed" && event.type !== "response.steer.pending") return false;
|
|
2343
|
+
const steer = isRecord(event.steer) ? event.steer : void 0;
|
|
2344
|
+
if (!responseId || steer?.previous_response_id !== responseId) throw new Error("Responses steering acknowledgement has an unexpected identity");
|
|
2345
|
+
if (event.type === "response.steer.failed" && steer.id === void 0) {
|
|
2346
|
+
const index = pending.findIndex((submission) => stableStringify(submission.input) === stableStringify(steer.input));
|
|
2347
|
+
const submission = pending[index];
|
|
2348
|
+
if (!submission) throw new Error("Responses steering acknowledgement has no pending submission");
|
|
2349
|
+
pending.splice(index, 1);
|
|
2350
|
+
submission.resolve(false);
|
|
2351
|
+
return true;
|
|
2352
|
+
}
|
|
2353
|
+
if (typeof steer.id !== "string" || !steer.id.trim()) throw new Error("Responses steering acknowledgement has an unexpected identity");
|
|
2354
|
+
if (event.type === "response.steer.pending") {
|
|
2355
|
+
if (!accepted.has(steer.id)) throw new Error("Responses steering pending event has no accepted submission");
|
|
2356
|
+
return true;
|
|
2357
|
+
}
|
|
2358
|
+
if (event.type === "response.steer.failed" && accepted.has(steer.id)) throw new Error("OpenAI could not apply accepted steering; the queued message remains in the conversation");
|
|
2359
|
+
if (acknowledged.has(steer.id)) throw new Error("Responses steering acknowledgement was already applied");
|
|
2360
|
+
const submission = pending.shift();
|
|
2361
|
+
if (!submission) throw new Error("Responses steering acknowledgement has no pending submission");
|
|
2362
|
+
acknowledged.add(steer.id);
|
|
2363
|
+
if (event.type === "response.steer.accepted") {
|
|
2364
|
+
accepted.set(steer.id, submission.input);
|
|
2365
|
+
submission.resolve(true);
|
|
2366
|
+
} else submission.resolve(false);
|
|
2367
|
+
return true;
|
|
2368
|
+
}
|
|
2369
|
+
};
|
|
2370
|
+
}
|
|
2371
|
+
/** Accepted steering is prepended by the server, so never repeat it in response.create. */
|
|
2372
|
+
function omitAcceptedSteering(input, accepted) {
|
|
2373
|
+
const remaining = [...input];
|
|
2374
|
+
for (const message of accepted) {
|
|
2375
|
+
const index = remaining.findIndex((item) => stableStringify(item) === stableStringify(message));
|
|
2376
|
+
if (index < 0) throw new Error("Responses steering continuation no longer contains the accepted user input");
|
|
2377
|
+
remaining.splice(index, 1);
|
|
2378
|
+
}
|
|
2379
|
+
return remaining;
|
|
2380
|
+
}
|
|
2381
|
+
//#endregion
|
|
2220
2382
|
//#region packages/ai/src/transports/openai-responses-websocket.ts
|
|
2221
|
-
const SESSION_WEBSOCKET_CACHE_TTL_MS =
|
|
2222
|
-
const SESSION_WEBSOCKET_MAX_AGE_MS =
|
|
2383
|
+
const SESSION_WEBSOCKET_CACHE_TTL_MS = 3e5;
|
|
2384
|
+
const SESSION_WEBSOCKET_MAX_AGE_MS = 33e5;
|
|
2223
2385
|
const WEBSOCKET_OPEN_STATE = 1;
|
|
2224
2386
|
const websocketSessionCache = /* @__PURE__ */ new Map();
|
|
2225
2387
|
const degradedWebSocketConnections = /* @__PURE__ */ new Map();
|
|
@@ -2249,6 +2411,9 @@ function invalidateOwnedWebSocketSession(cacheKey, entry, reason = "done") {
|
|
|
2249
2411
|
entry.idleTimer = void 0;
|
|
2250
2412
|
}
|
|
2251
2413
|
closeWebSocketSilently(entry.socket, reason);
|
|
2414
|
+
entry.steeringContinuation?.steering.close(/* @__PURE__ */ new Error("Responses steering connection closed"));
|
|
2415
|
+
entry.steeringContinuation?.iterator.return?.().catch(() => void 0);
|
|
2416
|
+
entry.steeringContinuation = void 0;
|
|
2252
2417
|
if (websocketSessionCache.get(cacheKey) === entry) websocketSessionCache.delete(cacheKey);
|
|
2253
2418
|
}
|
|
2254
2419
|
function scheduleSessionWebSocketExpiry(cacheKey, entry) {
|
|
@@ -2298,11 +2463,14 @@ function createTransientWebSocketLease(connection) {
|
|
|
2298
2463
|
}
|
|
2299
2464
|
function createCachedWebSocketLease(cacheKey, entry, reusedConnection) {
|
|
2300
2465
|
entry.busy = true;
|
|
2466
|
+
const steeringContinuation = entry.steeringContinuation;
|
|
2467
|
+
entry.steeringContinuation = void 0;
|
|
2301
2468
|
return {
|
|
2302
2469
|
socket: entry.socket,
|
|
2303
|
-
iterator: entry.socket.stream(),
|
|
2470
|
+
iterator: steeringContinuation?.iterator ?? entry.socket.stream(),
|
|
2304
2471
|
entry,
|
|
2305
2472
|
reusedConnection,
|
|
2473
|
+
steeringContinuation,
|
|
2306
2474
|
release: ({ keep } = {}) => {
|
|
2307
2475
|
if (!keep || entry.socket.socket.readyState !== WEBSOCKET_OPEN_STATE) {
|
|
2308
2476
|
invalidateOwnedWebSocketSession(cacheKey, entry);
|
|
@@ -2386,11 +2554,13 @@ function createOpenAIResponsesWebSocketStream(params) {
|
|
|
2386
2554
|
throw new OpenAIResponsesWebSocketPreDispatchError(error);
|
|
2387
2555
|
}
|
|
2388
2556
|
let prepared;
|
|
2557
|
+
const resumedSteering = lease.steeringContinuation;
|
|
2558
|
+
const steeringMode = resumedSteering ? resumedSteering.requiresInput ? "required-input" : "automatic" : void 0;
|
|
2389
2559
|
try {
|
|
2390
2560
|
const continuation = lease.entry?.continuation;
|
|
2391
2561
|
if (continuation && lease.entry) {
|
|
2392
2562
|
lease.entry.continuation = void 0;
|
|
2393
|
-
prepared = resolveResponsesContinuationRequest(continuation, fullRequest);
|
|
2563
|
+
prepared = resolveResponsesContinuationRequest(continuation, fullRequest, steeringMode);
|
|
2394
2564
|
} else prepared = {
|
|
2395
2565
|
request: fullRequest,
|
|
2396
2566
|
continuationStatus: lease.entry ? "no_previous_response" : "socket_not_cached"
|
|
@@ -2404,11 +2574,54 @@ function createOpenAIResponsesWebSocketStream(params) {
|
|
|
2404
2574
|
let terminalResponse;
|
|
2405
2575
|
let terminalReceived = false;
|
|
2406
2576
|
let released = false;
|
|
2577
|
+
let retainIterator = false;
|
|
2578
|
+
let deferredInput = false;
|
|
2579
|
+
let inputReplay;
|
|
2580
|
+
if (resumedSteering) try {
|
|
2581
|
+
if (prepared.continuationStatus !== "continued" || !prepared.request.previous_response_id) throw new Error("Responses steering continuation changed its request or history");
|
|
2582
|
+
const input = omitAcceptedSteering(prepared.request.input ?? [], resumedSteering.acceptedInput);
|
|
2583
|
+
if (!resumedSteering.requiresInput && (stableStringify(fullRequest.instructions) !== stableStringify(resumedSteering.instructions) || stableStringify(fullRequest.tools) !== stableStringify(resumedSteering.tools))) throw new Error("Responses automatic steering continuation cannot change instructions or tools");
|
|
2584
|
+
const baseline = prepared.fullRequest ?? fullRequest;
|
|
2585
|
+
const priorLength = (baseline.input?.length ?? 0) - (prepared.request.input?.length ?? 0);
|
|
2586
|
+
const fingerprints = input.map(responsesInputFingerprint);
|
|
2587
|
+
if (fingerprints.length > 0) inputReplay = {
|
|
2588
|
+
afterResponseId: prepared.request.previous_response_id,
|
|
2589
|
+
before: resumedSteering.requiresInput ? fingerprints : [],
|
|
2590
|
+
after: resumedSteering.requiresInput ? [] : fingerprints
|
|
2591
|
+
};
|
|
2592
|
+
const delivered = resumedSteering.requiresInput ? input : [];
|
|
2593
|
+
prepared.fullRequest = {
|
|
2594
|
+
...baseline,
|
|
2595
|
+
input: [
|
|
2596
|
+
...(baseline.input ?? []).slice(0, priorLength),
|
|
2597
|
+
...resumedSteering.acceptedInput,
|
|
2598
|
+
...delivered
|
|
2599
|
+
]
|
|
2600
|
+
};
|
|
2601
|
+
prepared.request = {
|
|
2602
|
+
...prepared.request,
|
|
2603
|
+
input: delivered
|
|
2604
|
+
};
|
|
2605
|
+
deferredInput = !resumedSteering.requiresInput && input.length > 0;
|
|
2606
|
+
} catch (error) {
|
|
2607
|
+
lease.iterator.return?.().catch(() => void 0);
|
|
2608
|
+
lease.release({ keep: false });
|
|
2609
|
+
throw new OpenAIResponsesWebSocketPostDispatchError(error);
|
|
2610
|
+
}
|
|
2611
|
+
const steering = lease.entry && params.onActiveResponse && params.steeringInput ? createResponsesSteering({
|
|
2612
|
+
onActiveResponse: params.onActiveResponse,
|
|
2613
|
+
toInput: params.steeringInput,
|
|
2614
|
+
send: (event) => lease.socket.sendRaw(JSON.stringify(event)),
|
|
2615
|
+
needsContinuation: () => deferredInput,
|
|
2616
|
+
assertActive: () => {
|
|
2617
|
+
if (released || terminalReceived || params.signal?.aborted) throw new Error("Responses steering is no longer active");
|
|
2618
|
+
}
|
|
2619
|
+
}) : void 0;
|
|
2407
2620
|
const finish = ({ keep = true } = {}) => {
|
|
2408
2621
|
if (released) return;
|
|
2409
2622
|
released = true;
|
|
2410
2623
|
if (keep && lease.entry && terminalResponse) lease.entry.continuation = {
|
|
2411
|
-
lastRequest: fullRequest,
|
|
2624
|
+
lastRequest: prepared.fullRequest ?? fullRequest,
|
|
2412
2625
|
lastResponseId: terminalResponse.id,
|
|
2413
2626
|
lastResponseItems: terminalResponse.output
|
|
2414
2627
|
};
|
|
@@ -2422,8 +2635,19 @@ function createOpenAIResponsesWebSocketStream(params) {
|
|
|
2422
2635
|
let requestDispatched = false;
|
|
2423
2636
|
try {
|
|
2424
2637
|
if (params.signal?.aborted) throw transportAbortError(params.signal);
|
|
2638
|
+
if (resumedSteering) {
|
|
2639
|
+
requestDispatched = true;
|
|
2640
|
+
if (resumedSteering.requiresInput) lease.socket.send({
|
|
2641
|
+
...prepared.request,
|
|
2642
|
+
type: "response.create"
|
|
2643
|
+
});
|
|
2644
|
+
}
|
|
2425
2645
|
for (;;) {
|
|
2426
|
-
const
|
|
2646
|
+
const buffered = resumedSteering?.buffered.shift();
|
|
2647
|
+
const next = buffered ? {
|
|
2648
|
+
value: buffered,
|
|
2649
|
+
done: false
|
|
2650
|
+
} : await nextWebSocketMessage(iterator, params.signal);
|
|
2427
2651
|
if (next.done) throw new Error("OpenAI Responses WebSocket closed before a terminal response event");
|
|
2428
2652
|
if (next.value.type === "open") {
|
|
2429
2653
|
if (!requestDispatched) {
|
|
@@ -2437,8 +2661,51 @@ function createOpenAIResponsesWebSocketStream(params) {
|
|
|
2437
2661
|
}
|
|
2438
2662
|
const event = readServerEvent(next.value);
|
|
2439
2663
|
if (!event) continue;
|
|
2664
|
+
if (isRecord(event) && typeof event.type === "string" && event.type.startsWith("response.steer.")) {
|
|
2665
|
+
if ((isRecord(event.steer) && event.steer.previous_response_id === steering?.responseId ? steering : resumedSteering?.steering ?? steering)?.handle(event)) continue;
|
|
2666
|
+
}
|
|
2667
|
+
steering?.handle(event);
|
|
2440
2668
|
if (event.type === "response.completed") terminalResponse = event.response;
|
|
2441
2669
|
terminalReceived = event.type === "response.completed" || event.type === "response.incomplete" || event.type === "response.failed";
|
|
2670
|
+
if (terminalReceived) {
|
|
2671
|
+
steering?.seal();
|
|
2672
|
+
if (event.type === "response.failed") steering?.close(/* @__PURE__ */ new Error("Responses failed before steering could be applied"));
|
|
2673
|
+
const continuationBuffer = [];
|
|
2674
|
+
for (;;) {
|
|
2675
|
+
if (!steering?.pending) break;
|
|
2676
|
+
const acknowledgement = await nextWebSocketMessage(iterator, params.signal);
|
|
2677
|
+
if (acknowledgement.done) throw new Error("Responses closed before acknowledging steering");
|
|
2678
|
+
const acknowledgedEvent = readServerEvent(acknowledgement.value);
|
|
2679
|
+
if (!steering.handle(acknowledgedEvent)) continuationBuffer.push(acknowledgement.value);
|
|
2680
|
+
}
|
|
2681
|
+
const acceptedInput = steering?.acceptedInput ?? [];
|
|
2682
|
+
const isSteered = event.type === "response.incomplete" && isRecord(event.response.incomplete_details) && event.response.incomplete_details.reason === "steered";
|
|
2683
|
+
if (lease.entry && steering && acceptedInput.length > 0 && (event.type === "response.completed" || isSteered)) {
|
|
2684
|
+
if (event.type === "response.incomplete") terminalResponse = event.response;
|
|
2685
|
+
lease.entry.steeringContinuation = {
|
|
2686
|
+
iterator,
|
|
2687
|
+
buffered: continuationBuffer,
|
|
2688
|
+
acceptedInput,
|
|
2689
|
+
requiresInput: (terminalResponse?.output ?? []).some((item) => (item.type === "function_call" || item.type === "custom_tool_call") && !(isRecord(item) && item.async === true) || item.type === "mcp_approval_request"),
|
|
2690
|
+
steering,
|
|
2691
|
+
instructions: fullRequest.instructions,
|
|
2692
|
+
tools: fullRequest.tools
|
|
2693
|
+
};
|
|
2694
|
+
retainIterator = true;
|
|
2695
|
+
if (isSteered) {
|
|
2696
|
+
yield {
|
|
2697
|
+
...event,
|
|
2698
|
+
type: "response.completed",
|
|
2699
|
+
response: {
|
|
2700
|
+
...event.response,
|
|
2701
|
+
status: "completed",
|
|
2702
|
+
incomplete_details: null
|
|
2703
|
+
}
|
|
2704
|
+
};
|
|
2705
|
+
return;
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2442
2709
|
yield event;
|
|
2443
2710
|
if (terminalReceived) {
|
|
2444
2711
|
degradedWebSocketConnections.delete(degradationKey);
|
|
@@ -2446,20 +2713,27 @@ function createOpenAIResponsesWebSocketStream(params) {
|
|
|
2446
2713
|
}
|
|
2447
2714
|
}
|
|
2448
2715
|
} catch (error) {
|
|
2716
|
+
const steeringDispatched = Boolean(steering?.pending || steering?.acceptedInput.length || resumedSteering);
|
|
2717
|
+
steering?.close(error instanceof Error ? error : /* @__PURE__ */ new Error("Responses steering failed"));
|
|
2449
2718
|
if (lease.entry) lease.entry.continuation = void 0;
|
|
2450
|
-
const safeRetry = error instanceof OpenAIResponsesWebSocketSafeRetryError;
|
|
2719
|
+
const safeRetry = error instanceof OpenAIResponsesWebSocketSafeRetryError && !steeringDispatched;
|
|
2451
2720
|
if (!params.callerSignal?.aborted && !safeRetry) markDegraded();
|
|
2452
2721
|
if (!requestDispatched && !params.signal?.aborted) throw new OpenAIResponsesWebSocketPreDispatchError(error);
|
|
2453
2722
|
if (!requestDispatched || params.callerSignal?.aborted || safeRetry) throw error;
|
|
2454
2723
|
throw new OpenAIResponsesWebSocketPostDispatchError(error);
|
|
2455
2724
|
} finally {
|
|
2456
|
-
|
|
2725
|
+
steering?.seal();
|
|
2726
|
+
if (!retainIterator) {
|
|
2727
|
+
steering?.close(/* @__PURE__ */ new Error("Responses stream ended before steering was confirmed"));
|
|
2728
|
+
await iterator.return?.().catch(() => void 0);
|
|
2729
|
+
}
|
|
2457
2730
|
if (!terminalReceived) finish({ keep: false });
|
|
2458
2731
|
}
|
|
2459
2732
|
} },
|
|
2460
2733
|
request: prepared.request,
|
|
2461
2734
|
reusedConnection: lease.reusedConnection,
|
|
2462
2735
|
continuationStatus: prepared.continuationStatus,
|
|
2736
|
+
inputReplay,
|
|
2463
2737
|
finish
|
|
2464
2738
|
};
|
|
2465
2739
|
}
|
|
@@ -2472,147 +2746,68 @@ function closeOpenAIResponsesWebSocketSessions(sessionId) {
|
|
|
2472
2746
|
}
|
|
2473
2747
|
registerSessionResourceCleanup(closeOpenAIResponsesWebSocketSessions);
|
|
2474
2748
|
//#endregion
|
|
2475
|
-
//#region packages/
|
|
2476
|
-
|
|
2477
|
-
const
|
|
2478
|
-
const
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
mime: "image/jpeg",
|
|
2485
|
-
matches: (buffer) => buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255
|
|
2486
|
-
},
|
|
2487
|
-
{
|
|
2488
|
-
mime: "image/webp",
|
|
2489
|
-
matches: (buffer) => buffer.length >= 12 && buffer.subarray(0, 4).toString("ascii") === "RIFF" && buffer.subarray(8, 12).toString("ascii") === "WEBP"
|
|
2490
|
-
},
|
|
2491
|
-
{
|
|
2492
|
-
mime: "image/gif",
|
|
2493
|
-
matches: (buffer) => buffer.length >= 6 && (buffer.subarray(0, 6).toString("ascii") === "GIF87a" || buffer.subarray(0, 6).toString("ascii") === "GIF89a")
|
|
2494
|
-
},
|
|
2495
|
-
{
|
|
2496
|
-
mime: "image/bmp",
|
|
2497
|
-
matches: (buffer) => buffer.length >= 2 && buffer[0] === 66 && buffer[1] === 77
|
|
2498
|
-
}
|
|
2499
|
-
];
|
|
2500
|
-
const HEIC_BRANDS = /* @__PURE__ */ new Set([
|
|
2501
|
-
"heic",
|
|
2502
|
-
"heix",
|
|
2503
|
-
"hevc",
|
|
2504
|
-
"hevx",
|
|
2505
|
-
"heis",
|
|
2506
|
-
"heim",
|
|
2507
|
-
"hevm",
|
|
2508
|
-
"hevs"
|
|
2509
|
-
]);
|
|
2510
|
-
const HEIF_BRANDS = /* @__PURE__ */ new Set(["mif1", "msf1"]);
|
|
2511
|
-
const IMAGE_SIGNATURE_PREFIX_BASE64_CHARS = 128;
|
|
2512
|
-
const INLINE_IMAGE_DATA_URL_MIMES = /* @__PURE__ */ new Set([
|
|
2513
|
-
"image/png",
|
|
2514
|
-
"image/jpeg",
|
|
2515
|
-
"image/webp",
|
|
2516
|
-
"image/gif"
|
|
2517
|
-
]);
|
|
2518
|
-
function startsWithDataUrl(value) {
|
|
2519
|
-
return value.slice(0, 5).toLowerCase() === INLINE_IMAGE_DATA_URL_PREFIX;
|
|
2520
|
-
}
|
|
2521
|
-
function sniffIsoBmffImageMime(buffer) {
|
|
2522
|
-
if (buffer.length < 12 || buffer.subarray(4, 8).toString("ascii") !== "ftyp") return;
|
|
2523
|
-
const brands = [buffer.subarray(8, 12).toString("ascii")];
|
|
2524
|
-
for (let offset = 16; offset + 4 <= buffer.length; offset += 4) brands.push(buffer.subarray(offset, offset + 4).toString("ascii"));
|
|
2525
|
-
if (brands.some((brand) => HEIC_BRANDS.has(brand))) return "image/heic";
|
|
2526
|
-
if (brands.some((brand) => HEIF_BRANDS.has(brand))) return "image/heif";
|
|
2527
|
-
}
|
|
2528
|
-
/** Sniffs supported inline image formats from decoded bytes. */
|
|
2529
|
-
function sniffInlineImageMime(buffer) {
|
|
2530
|
-
return IMAGE_SIGNATURES.find((signature) => signature.matches(buffer))?.mime ?? sniffIsoBmffImageMime(buffer);
|
|
2531
|
-
}
|
|
2532
|
-
function isImageMimeType(value) {
|
|
2533
|
-
return value.trim().toLowerCase().startsWith("image/");
|
|
2534
|
-
}
|
|
2535
|
-
/** Canonicalizes trusted inline image base64 and rejects malformed or non-image payloads. */
|
|
2536
|
-
function sanitizeInlineImageBase64(params) {
|
|
2537
|
-
if (!isImageMimeType(params.mimeType)) return;
|
|
2538
|
-
const canonicalPayload = canonicalizeBase64(params.base64);
|
|
2539
|
-
if (!canonicalPayload) return;
|
|
2540
|
-
const sniffedMimeType = sniffInlineImageMime(Buffer.from(canonicalPayload.slice(0, IMAGE_SIGNATURE_PREFIX_BASE64_CHARS), "base64"));
|
|
2541
|
-
if (!sniffedMimeType) return;
|
|
2542
|
-
return {
|
|
2543
|
-
mimeType: sniffedMimeType,
|
|
2544
|
-
base64: canonicalPayload
|
|
2545
|
-
};
|
|
2546
|
-
}
|
|
2547
|
-
function parseInlineImageDataUrl(value) {
|
|
2548
|
-
if (!startsWithDataUrl(value)) return {
|
|
2549
|
-
metadata: [],
|
|
2550
|
-
payload: value
|
|
2551
|
-
};
|
|
2552
|
-
const commaIndex = value.indexOf(",");
|
|
2553
|
-
if (commaIndex < 0) return;
|
|
2554
|
-
return {
|
|
2555
|
-
metadata: value.slice(5, commaIndex).split(";").map((part) => part.trim()),
|
|
2556
|
-
payload: value.slice(commaIndex + 1)
|
|
2557
|
-
};
|
|
2558
|
-
}
|
|
2559
|
-
function metadataAllowsImageBase64(metadata) {
|
|
2560
|
-
const [mimeType, ...options] = metadata;
|
|
2561
|
-
return mimeType !== void 0 && isImageMimeType(mimeType) && options.some((part) => part.toLowerCase() === "base64");
|
|
2562
|
-
}
|
|
2563
|
-
function sanitizeInlineImageDataUrlWithAllowedMimes(imageUrl, allowedMimes) {
|
|
2564
|
-
const parsed = parseInlineImageDataUrl(imageUrl);
|
|
2565
|
-
if (!parsed) return;
|
|
2566
|
-
if (parsed.metadata.length === 0) return imageUrl;
|
|
2567
|
-
if (!metadataAllowsImageBase64(parsed.metadata)) return;
|
|
2568
|
-
const [mimeType] = parsed.metadata;
|
|
2569
|
-
const sanitized = sanitizeInlineImageBase64({
|
|
2570
|
-
mimeType: mimeType ?? "",
|
|
2571
|
-
base64: parsed.payload
|
|
2749
|
+
//#region packages/ai/src/transports/openai-responses-compact-client.ts
|
|
2750
|
+
async function postOpenAIResponsesCompaction(params) {
|
|
2751
|
+
const compactInput = typeof params.request.instructions === "string" && params.request.instructions.length > 0 ? [buildOpenAIResponsesCompactSystemMessage(params.model, params.request.instructions), ...params.request.input ?? []] : params.request.input;
|
|
2752
|
+
const response = await params.client.post("/responses/compact", {
|
|
2753
|
+
...buildOpenAISdkRequestOptions(params.model, params.options?.signal, { timeoutMs: params.options?.timeoutMs }),
|
|
2754
|
+
body: {
|
|
2755
|
+
model: params.request.model,
|
|
2756
|
+
input: compactInput
|
|
2757
|
+
}
|
|
2572
2758
|
});
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
//#endregion
|
|
2582
|
-
//#region packages/ai/src/transports/responses-image-payload-sanitizer.ts
|
|
2583
|
-
/**
|
|
2584
|
-
* Sanitizes OpenAI Responses payloads before transport. Invalid inline images
|
|
2585
|
-
* are replaced with text placeholders so the request remains valid and
|
|
2586
|
-
* auditable.
|
|
2587
|
-
*/
|
|
2588
|
-
const IMAGE_OMITTED_TEXT = "omitted image payload: invalid inline image data";
|
|
2589
|
-
function invalidSnakeImage() {
|
|
2759
|
+
const output = isRecord(response) && Array.isArray(response.output) ? response.output : [];
|
|
2760
|
+
const item = output.at(-1);
|
|
2761
|
+
const retainedItems = output.slice(0, -1);
|
|
2762
|
+
const retainedUserMessageCount = retainedItems.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user" && Array.isArray(candidate.content)).length;
|
|
2763
|
+
const inputUserMessageCount = Array.isArray(params.request.input) ? params.request.input.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user").length : 0;
|
|
2764
|
+
const retainedMessagePrefixSupported = supportsNativeOpenAIResponsesEndpoint(params.model);
|
|
2765
|
+
const usage = isRecord(response) && isRecord(response.usage) ? response.usage : void 0;
|
|
2766
|
+
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");
|
|
2590
2767
|
return {
|
|
2591
|
-
|
|
2592
|
-
|
|
2768
|
+
output,
|
|
2769
|
+
item,
|
|
2770
|
+
historyMode: retainedUserMessageCount > 0 ? "retained-users" : "compacted-prefix",
|
|
2771
|
+
usage,
|
|
2772
|
+
model: params.model,
|
|
2773
|
+
replayMetadata: buildOpenAIResponsesReasoningReplayMetadata(params.model, {
|
|
2774
|
+
authProfileId: params.options?.authProfileId,
|
|
2775
|
+
sessionId: params.options?.sessionId
|
|
2776
|
+
})
|
|
2593
2777
|
};
|
|
2594
2778
|
}
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
} : invalidSnakeImage();
|
|
2779
|
+
//#endregion
|
|
2780
|
+
//#region packages/ai/src/transports/openai-responses-compact-request.ts
|
|
2781
|
+
const COMPACT_REQUEST = Symbol("openaiResponsesCompactRequest");
|
|
2782
|
+
function claimResponsesCompactRequest(options) {
|
|
2783
|
+
const controller = options ? Reflect.get(options, COMPACT_REQUEST) : void 0;
|
|
2784
|
+
if (controller?.claimed === false) {
|
|
2785
|
+
controller.claimed = true;
|
|
2786
|
+
return controller;
|
|
2604
2787
|
}
|
|
2605
|
-
const next = {};
|
|
2606
|
-
for (const [key, child] of Object.entries(value)) next[key] = sanitizeValue(child);
|
|
2607
|
-
return next;
|
|
2608
2788
|
}
|
|
2609
|
-
/**
|
|
2610
|
-
function
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2789
|
+
/** Run a compact-endpoint request through the session's prepared stream stack. */
|
|
2790
|
+
async function requestPreparedOpenAIResponsesCompaction(streamFn, model, context, options) {
|
|
2791
|
+
const preparedOptions = { ...options };
|
|
2792
|
+
let resolveResult;
|
|
2793
|
+
let rejectResult;
|
|
2794
|
+
const result = new Promise((resolve, reject) => {
|
|
2795
|
+
resolveResult = resolve;
|
|
2796
|
+
rejectResult = reject;
|
|
2797
|
+
});
|
|
2798
|
+
const controller = {
|
|
2799
|
+
claimed: false,
|
|
2800
|
+
resolve: resolveResult,
|
|
2801
|
+
reject: rejectResult
|
|
2615
2802
|
};
|
|
2803
|
+
Reflect.set(preparedOptions, COMPACT_REQUEST, controller);
|
|
2804
|
+
const stream = await Promise.resolve(streamFn(model, context, preparedOptions));
|
|
2805
|
+
if (!controller.claimed) throw new Error("Prepared stream did not reach an OpenAI Responses transport");
|
|
2806
|
+
try {
|
|
2807
|
+
return await result;
|
|
2808
|
+
} finally {
|
|
2809
|
+
await stream.result().catch(() => void 0);
|
|
2810
|
+
}
|
|
2616
2811
|
}
|
|
2617
2812
|
//#endregion
|
|
2618
2813
|
//#region packages/ai/src/transports/openai-responses-client.ts
|
|
@@ -2648,47 +2843,16 @@ function resolveProviderTransportTurnState(model, params) {
|
|
|
2648
2843
|
}
|
|
2649
2844
|
});
|
|
2650
2845
|
}
|
|
2651
|
-
function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId) {
|
|
2846
|
+
function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId, fetchOverride) {
|
|
2652
2847
|
return new OpenAI({
|
|
2653
2848
|
apiKey,
|
|
2654
2849
|
baseURL: resolveOpenAIClientBaseUrl(model),
|
|
2655
2850
|
dangerouslyAllowBrowser: true,
|
|
2656
2851
|
defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId),
|
|
2657
|
-
fetch: buildGuardedModelFetch(model),
|
|
2852
|
+
fetch: fetchOverride ?? buildGuardedModelFetch(model),
|
|
2658
2853
|
...buildOpenAISdkClientOptions(model)
|
|
2659
2854
|
});
|
|
2660
2855
|
}
|
|
2661
|
-
async function postOpenAIResponsesCompaction(params) {
|
|
2662
|
-
const response = await params.client.post("/responses/compact", {
|
|
2663
|
-
...buildOpenAISdkRequestOptions(params.model, params.options?.signal, {
|
|
2664
|
-
timeoutMs: params.options?.timeoutMs,
|
|
2665
|
-
maxRetries: params.options?.maxRetries
|
|
2666
|
-
}),
|
|
2667
|
-
body: {
|
|
2668
|
-
model: params.request.model,
|
|
2669
|
-
input: params.request.input
|
|
2670
|
-
}
|
|
2671
|
-
});
|
|
2672
|
-
const output = isRecord(response) && Array.isArray(response.output) ? response.output : [];
|
|
2673
|
-
const item = output.at(-1);
|
|
2674
|
-
const retainedItems = output.slice(0, -1);
|
|
2675
|
-
const retainedMessagesAreValid = retainedItems.every((candidate) => isRecord(candidate) && candidate.type === "message" && (candidate.role === "user" || candidate.role === "developer" || candidate.role === "system") && Array.isArray(candidate.content));
|
|
2676
|
-
const retainedUserMessageCount = retainedItems.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user" && Array.isArray(candidate.content)).length;
|
|
2677
|
-
const inputUserMessageCount = Array.isArray(params.request.input) ? params.request.input.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user").length : 0;
|
|
2678
|
-
const retainedMessagePrefixSupported = supportsNativeOpenAIResponsesEndpoint(params.model);
|
|
2679
|
-
const usage = isRecord(response) && isRecord(response.usage) ? response.usage : void 0;
|
|
2680
|
-
if (!isRecord(response) || response.object !== "response.compaction" || !retainedMessagesAreValid || retainedItems.length > 0 && (!retainedMessagePrefixSupported || retainedUserMessageCount !== inputUserMessageCount) || !isRecord(item) || item.type !== "compaction" || typeof item.encrypted_content !== "string" || item.encrypted_content.length === 0 || !usage || typeof usage.input_tokens !== "number" || typeof usage.output_tokens !== "number") throw new Error("Responses compact endpoint did not return one trailing compaction item");
|
|
2681
|
-
return {
|
|
2682
|
-
item,
|
|
2683
|
-
historyMode: retainedUserMessageCount > 0 ? "retained-users" : "compacted-prefix",
|
|
2684
|
-
usage,
|
|
2685
|
-
model: params.model,
|
|
2686
|
-
replayMetadata: buildOpenAIResponsesReasoningReplayMetadata(params.model, {
|
|
2687
|
-
authProfileId: params.options?.authProfileId,
|
|
2688
|
-
sessionId: params.options?.sessionId
|
|
2689
|
-
})
|
|
2690
|
-
};
|
|
2691
|
-
}
|
|
2692
2856
|
function createResponsesTransportExecutor(config) {
|
|
2693
2857
|
return (model, context, options) => {
|
|
2694
2858
|
const responsesOptions = options;
|
|
@@ -2709,9 +2873,11 @@ function createResponsesTransportExecutor(config) {
|
|
|
2709
2873
|
});
|
|
2710
2874
|
const websocketSessionPolicy = websocketMode ? turnState?.websocket : void 0;
|
|
2711
2875
|
const websocketHeaders = websocketMode ? buildOpenAIClientHeaders(model, context, options?.headers, websocketSessionPolicy?.headers, options?.sessionId) : void 0;
|
|
2712
|
-
const client = config.createClient(model, context, apiKey, options?.headers, turnState?.headers, options?.sessionId);
|
|
2713
|
-
const
|
|
2714
|
-
|
|
2876
|
+
const client = config.createClient(model, context, apiKey, options?.headers, turnState?.headers, options?.sessionId, compactRequest ? createBoundedOpenAIResponsesCompactionFetch(buildGuardedModelFetch(model)) : void 0);
|
|
2877
|
+
const nativeAstra = model.id === "gpt-6-astra" && supportsNativeOpenAIResponsesEndpoint(model);
|
|
2878
|
+
const asyncToolExecutionEligible = nativeAstra && options?.asyncToolExecution === true && !responsesOptions?.openclawCodeModeToolSurface;
|
|
2879
|
+
const prepareRequest = async (request) => {
|
|
2880
|
+
let params = request;
|
|
2715
2881
|
const nextParams = await options?.onPayload?.(params, model);
|
|
2716
2882
|
if (nextParams !== void 0) params = nextParams;
|
|
2717
2883
|
if (!isOpenAICodexResponsesModel(model)) params = mergeTransportMetadata(params, turnState?.metadata);
|
|
@@ -2723,9 +2889,15 @@ function createResponsesTransportExecutor(config) {
|
|
|
2723
2889
|
enforceCodeModeResponsesToolSurface(params, visibleToolNames, allowedHostedToolTypes, codeModeToolSurfaceObserver.get(options));
|
|
2724
2890
|
assertCodeModeResponsesToolSurface(params, visibleToolNames, allowedHostedToolTypes);
|
|
2725
2891
|
}
|
|
2892
|
+
if (asyncToolExecutionEligible && params.model === "gpt-6-astra" && params.multi_agent?.enabled !== true && params.tools) params.tools = params.tools.map((tool) => tool.type === "function" ? {
|
|
2893
|
+
...tool,
|
|
2894
|
+
async: true
|
|
2895
|
+
} : tool);
|
|
2726
2896
|
return params;
|
|
2727
2897
|
};
|
|
2728
|
-
const
|
|
2898
|
+
const buildRequest = (replayMode, requestContext = context) => prepareRequest(config.buildRequest(model, requestContext, responsesOptions, turnState?.metadata, replayMode));
|
|
2899
|
+
let params = await buildRequest("checkpoint");
|
|
2900
|
+
const asyncTools = asyncToolExecutionEligible && params.model === "gpt-6-astra" && params.multi_agent?.enabled !== true;
|
|
2729
2901
|
if (compactRequest) {
|
|
2730
2902
|
const compacted = await postOpenAIResponsesCompaction({
|
|
2731
2903
|
client,
|
|
@@ -2749,13 +2921,16 @@ function createResponsesTransportExecutor(config) {
|
|
|
2749
2921
|
provider: model.provider,
|
|
2750
2922
|
api: model.api,
|
|
2751
2923
|
baseUrl: model.baseUrl
|
|
2752
|
-
}) && sessionId && params.store === true && !params.previous_response_id)
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2924
|
+
}) && sessionId && (params.store === true || supportsResponsesReasoningUpdate(params)) && !params.previous_response_id) {
|
|
2925
|
+
continuationClaim = claimOpenAIResponsesHttpContinuation({
|
|
2926
|
+
sessionId,
|
|
2927
|
+
apiKey,
|
|
2928
|
+
baseUrl: model.baseUrl,
|
|
2929
|
+
headers: buildOpenAIClientHeaders(model, context, options?.headers, turnState?.headers, sessionId),
|
|
2930
|
+
request: params
|
|
2931
|
+
});
|
|
2932
|
+
if (continuationClaim) params = continuationClaim.fullRequest;
|
|
2933
|
+
}
|
|
2759
2934
|
const observePrompt = createResponsesPromptEgressObserver(responsesOptions, context.systemPrompt);
|
|
2760
2935
|
const requestStartedAt = Date.now();
|
|
2761
2936
|
let started = false;
|
|
@@ -2772,14 +2947,13 @@ function createResponsesTransportExecutor(config) {
|
|
|
2772
2947
|
firstEventAbort = firstEvent;
|
|
2773
2948
|
const requestOptions = buildOpenAISdkRequestOptions(model, firstEvent.signal, {
|
|
2774
2949
|
stream: config.streamRequest,
|
|
2775
|
-
timeoutMs: options?.timeoutMs
|
|
2776
|
-
maxRetries: options?.maxRetries
|
|
2950
|
+
timeoutMs: options?.timeoutMs
|
|
2777
2951
|
});
|
|
2778
2952
|
const websocketSignal = combineWebSocketTimeoutSignal(firstEvent.signal, model, requestOptions?.timeout);
|
|
2779
2953
|
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)}`);
|
|
2780
2954
|
let continuationBaseline;
|
|
2781
2955
|
const createSseStream = async (initialRequest = continuationClaim?.request ?? params, initialAttemptKind = "initial", initialRejectedCompaction) => {
|
|
2782
|
-
const { stream: responseStream } = await
|
|
2956
|
+
const { stream: responseStream } = await createResponsesStreamWithEncryptedContentRetry({
|
|
2783
2957
|
client,
|
|
2784
2958
|
request: initialRequest,
|
|
2785
2959
|
requestOptions,
|
|
@@ -2825,9 +2999,15 @@ function createResponsesTransportExecutor(config) {
|
|
|
2825
2999
|
headers: websocketHeaders,
|
|
2826
3000
|
signal: websocketSignal,
|
|
2827
3001
|
callerSignal: options?.signal,
|
|
2828
|
-
degradeCooldownMs: websocketSessionPolicy?.degradeCooldownMs
|
|
3002
|
+
degradeCooldownMs: websocketSessionPolicy?.degradeCooldownMs,
|
|
3003
|
+
onActiveResponse: nativeAstra && params.model === "gpt-6-astra" ? options?.onActiveResponse : void 0,
|
|
3004
|
+
steeringInput: (messages) => projectResponsesSteeringInput(params, () => buildRequest("checkpoint", {
|
|
3005
|
+
...context,
|
|
3006
|
+
messages: [...context.messages, ...messages]
|
|
3007
|
+
}))
|
|
2829
3008
|
});
|
|
2830
3009
|
finishWebSocket = websocket.finish;
|
|
3010
|
+
recordResponsesInputReplay(output, websocket.inputReplay);
|
|
2831
3011
|
observePrompt?.(websocket.request, {
|
|
2832
3012
|
egress: "responses-websocket",
|
|
2833
3013
|
payloadVariant: "initial"
|
|
@@ -2869,7 +3049,8 @@ function createResponsesTransportExecutor(config) {
|
|
|
2869
3049
|
yield* await createSseStream();
|
|
2870
3050
|
}
|
|
2871
3051
|
} };
|
|
2872
|
-
} catch {
|
|
3052
|
+
} catch (error) {
|
|
3053
|
+
if (error instanceof OpenAIResponsesWebSocketPostDispatchError) throw error;
|
|
2873
3054
|
closeWebSocketForFallback("setup_failure");
|
|
2874
3055
|
responseStream = await createSseStream();
|
|
2875
3056
|
}
|
|
@@ -2884,7 +3065,8 @@ function createResponsesTransportExecutor(config) {
|
|
|
2884
3065
|
reasoningReplayMetadata: buildOpenAIResponsesReasoningReplayMetadata(model, {
|
|
2885
3066
|
authProfileId: responsesOptions?.authProfileId,
|
|
2886
3067
|
sessionId: options?.sessionId
|
|
2887
|
-
})
|
|
3068
|
+
}),
|
|
3069
|
+
asyncToolExecution: asyncTools
|
|
2888
3070
|
});
|
|
2889
3071
|
finishWebSocket?.();
|
|
2890
3072
|
if (options?.signal?.aborted) throw transportAbortError(options.signal);
|
|
@@ -2933,7 +3115,6 @@ function createOpenAIResponsesTransportStreamFn() {
|
|
|
2933
3115
|
httpContinuation: true,
|
|
2934
3116
|
createClient: createOpenAIResponsesClient,
|
|
2935
3117
|
buildRequest: buildOpenAIResponsesParams,
|
|
2936
|
-
createResponseStream: createResponsesStreamWithEncryptedContentRetry,
|
|
2937
3118
|
pricingOptions: (options, model) => ({
|
|
2938
3119
|
serviceTier: options?.serviceTier,
|
|
2939
3120
|
applyServiceTierPricing: (usage, serviceTier) => applyResponsesServiceTierPricing(usage, serviceTier, model)
|
|
@@ -2945,27 +3126,23 @@ function createAzureOpenAIResponsesTransportStreamFn() {
|
|
|
2945
3126
|
outputApi: "azure-openai-responses",
|
|
2946
3127
|
firstEventTimeoutMs: AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS,
|
|
2947
3128
|
createClient: createAzureOpenAIClient,
|
|
2948
|
-
buildRequest: (model, context, options, metadata, replayMode) => buildAzureOpenAIResponsesParams(model, context, options, resolveAzureDeploymentName(model), metadata, replayMode)
|
|
2949
|
-
createResponseStream: createResponsesStreamWithEncryptedContentRetry
|
|
3129
|
+
buildRequest: (model, context, options, metadata, replayMode) => buildAzureOpenAIResponsesParams(model, context, options, resolveAzureDeploymentName(model), metadata, replayMode)
|
|
2950
3130
|
});
|
|
2951
3131
|
}
|
|
2952
|
-
function normalizeAzureBaseUrl(baseUrl) {
|
|
2953
|
-
return baseUrl.replace(/\/+$/, "");
|
|
2954
|
-
}
|
|
2955
3132
|
function resolveAzureDeploymentName(model) {
|
|
2956
3133
|
return resolveAzureDeploymentNameFromMap({
|
|
2957
3134
|
modelId: model.id,
|
|
2958
3135
|
deploymentMap: process.env.AZURE_OPENAI_DEPLOYMENT_NAME_MAP
|
|
2959
3136
|
});
|
|
2960
3137
|
}
|
|
2961
|
-
function createAzureOpenAIClient(model, context, apiKey, optionHeaders, turnHeaders) {
|
|
2962
|
-
const baseURL =
|
|
3138
|
+
function createAzureOpenAIClient(model, context, apiKey, optionHeaders, turnHeaders, _sessionId, fetchOverride) {
|
|
3139
|
+
const baseURL = model.baseUrl.replace(/\/+$/, "");
|
|
2963
3140
|
const clientOptions = {
|
|
2964
3141
|
apiKey,
|
|
2965
3142
|
dangerouslyAllowBrowser: true,
|
|
2966
3143
|
defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders),
|
|
2967
3144
|
baseURL,
|
|
2968
|
-
fetch: buildGuardedModelFetch(model),
|
|
3145
|
+
fetch: fetchOverride ?? buildGuardedModelFetch(model),
|
|
2969
3146
|
...buildOpenAISdkClientOptions(model)
|
|
2970
3147
|
};
|
|
2971
3148
|
if (isOpenAICompatibleAzureResponsesBaseUrl(baseURL)) return new OpenAI(clientOptions);
|
|
@@ -3011,6 +3188,112 @@ const responsesTesting = {
|
|
|
3011
3188
|
if (process.env.VITEST || false) globalThis.openclawOpenAIResponsesTransportTestApi = responsesTesting;
|
|
3012
3189
|
//#endregion
|
|
3013
3190
|
//#region packages/ai/src/transports/provider-compaction-replay.ts
|
|
3191
|
+
function isAssistantReplayMessage(message) {
|
|
3192
|
+
return message.role === "assistant";
|
|
3193
|
+
}
|
|
3194
|
+
/** Resolve from prepared transport facts; never retain or return credential material. */
|
|
3195
|
+
function resolveCompactionReplayEligibility(model, options) {
|
|
3196
|
+
if (OPENAI_RESPONSES_APIS.has(model.api)) return true;
|
|
3197
|
+
return Boolean(options.apiKey?.trim()) && resolveAnthropicServerCompactionPlan(model, options.extraParams, options.apiKey).enabled;
|
|
3198
|
+
}
|
|
3199
|
+
function resolveCompactionSource(messages, model, identity) {
|
|
3200
|
+
if (identity.enabled === false) return;
|
|
3201
|
+
const assistants = messages.filter(isAssistantReplayMessage);
|
|
3202
|
+
const selected = (() => {
|
|
3203
|
+
if (OPENAI_RESPONSES_APIS.has(model.api)) {
|
|
3204
|
+
const responses = resolveNewestOpenAIResponsesCompactionReplay(assistants, model, identity);
|
|
3205
|
+
return responses ? {
|
|
3206
|
+
family: "responses",
|
|
3207
|
+
...responses
|
|
3208
|
+
} : void 0;
|
|
3209
|
+
}
|
|
3210
|
+
if (identity.enabled !== true) return;
|
|
3211
|
+
const anthropic = resolveNewestAnthropicCompaction(assistants, model, identity);
|
|
3212
|
+
return anthropic ? {
|
|
3213
|
+
family: "anthropic",
|
|
3214
|
+
...anthropic
|
|
3215
|
+
} : void 0;
|
|
3216
|
+
})();
|
|
3217
|
+
if (!selected) return;
|
|
3218
|
+
const owner = assistants.find((message) => message === selected.owner);
|
|
3219
|
+
return owner ? {
|
|
3220
|
+
...selected,
|
|
3221
|
+
owner
|
|
3222
|
+
} : void 0;
|
|
3223
|
+
}
|
|
3224
|
+
/** Manual recovery uses the durable client compactor, never a guessed retained-user prefix. */
|
|
3225
|
+
function requiresCompactionReplayRefresh(messages, model, identity) {
|
|
3226
|
+
const checkpoint = resolveCompactionSource(messages, model, identity);
|
|
3227
|
+
return checkpoint?.family === "responses" && checkpoint.mode === "refresh-required";
|
|
3228
|
+
}
|
|
3229
|
+
/** Carry a checkpoint immediately after reference-preserving history limiting, before repair. */
|
|
3230
|
+
function preserveCompactionReplayWindow(source, windowed, model, identity) {
|
|
3231
|
+
const checkpoint = resolveCompactionSource(source, model, identity);
|
|
3232
|
+
if (!checkpoint || windowed.some((message) => message === checkpoint.owner)) return windowed;
|
|
3233
|
+
const owner = checkpoint.owner;
|
|
3234
|
+
const replay = checkpoint.owner.providerReplay;
|
|
3235
|
+
const providerReplay = replay?.type === "openai-responses-retained-compaction" ? replay : {
|
|
3236
|
+
...replay,
|
|
3237
|
+
replayIndex: 0
|
|
3238
|
+
};
|
|
3239
|
+
const suffix = new Set(source.slice(source.indexOf(owner) + 1));
|
|
3240
|
+
return [{
|
|
3241
|
+
...owner,
|
|
3242
|
+
content: [],
|
|
3243
|
+
providerReplay
|
|
3244
|
+
}, ...windowed.filter((message) => suffix.has(message))];
|
|
3245
|
+
}
|
|
3246
|
+
function estimateResponsesWindow(checkpoint, estimate) {
|
|
3247
|
+
return checkpoint.output.reduce((tokens, entry) => {
|
|
3248
|
+
if (entry.type === "compaction") {
|
|
3249
|
+
const { encrypted_content, ...metadata } = entry;
|
|
3250
|
+
return tokens + estimate.text(encrypted_content) + estimate.json(metadata);
|
|
3251
|
+
}
|
|
3252
|
+
const { content, ...metadata } = entry;
|
|
3253
|
+
return tokens + estimate.json(metadata) + content.reduce((sum, block) => {
|
|
3254
|
+
if (block.type === "input_text") {
|
|
3255
|
+
const { text, ...fields } = block;
|
|
3256
|
+
return sum + estimate.text(text) + estimate.json(fields);
|
|
3257
|
+
}
|
|
3258
|
+
if (block.type === "input_image") {
|
|
3259
|
+
const { image_url: _imageUrl, ...fields } = block;
|
|
3260
|
+
return sum + estimate.image() + estimate.json(block.image_url?.startsWith("data:") ? fields : block);
|
|
3261
|
+
}
|
|
3262
|
+
return sum + estimate.json(block);
|
|
3263
|
+
}, 0);
|
|
3264
|
+
}, 0);
|
|
3265
|
+
}
|
|
3266
|
+
/** Estimate the canonical prefix and its tail once, independent of unbound usage snapshots. */
|
|
3267
|
+
function resolveCompactionReplayPressure(messages, model, identity, estimate) {
|
|
3268
|
+
const checkpoint = resolveCompactionSource(messages, model, identity);
|
|
3269
|
+
if (!checkpoint) return;
|
|
3270
|
+
if (checkpoint.family === "responses" && checkpoint.mode === "refresh-required") throw new CompactionReplayRefreshRequiredError();
|
|
3271
|
+
const ownerIndex = messages.findIndex((message) => message === checkpoint.owner);
|
|
3272
|
+
const owner = messages[ownerIndex];
|
|
3273
|
+
if (!owner) return;
|
|
3274
|
+
const prefixTokens = checkpoint.family === "anthropic" ? estimate.text(checkpoint.summary) : checkpoint.mode === "complete-window" ? estimateResponsesWindow(checkpoint, estimate) : estimate.text(checkpoint.item.encrypted_content);
|
|
3275
|
+
const { contextUsage: _staleContextUsage, ...usage } = checkpoint.owner.usage;
|
|
3276
|
+
const tail = [];
|
|
3277
|
+
for (const message of messages.slice(ownerIndex + 1)) {
|
|
3278
|
+
if (!isAssistantReplayMessage(message) || message.usage.contextUsage === void 0) {
|
|
3279
|
+
tail.push(message);
|
|
3280
|
+
continue;
|
|
3281
|
+
}
|
|
3282
|
+
const { contextUsage: _unboundContextUsage, ...billedUsage } = message.usage;
|
|
3283
|
+
tail.push({
|
|
3284
|
+
...message,
|
|
3285
|
+
usage: billedUsage
|
|
3286
|
+
});
|
|
3287
|
+
}
|
|
3288
|
+
return {
|
|
3289
|
+
messages: [{
|
|
3290
|
+
...owner,
|
|
3291
|
+
content: checkpoint.owner.content.slice(checkpoint.replayIndex),
|
|
3292
|
+
usage
|
|
3293
|
+
}, ...tail],
|
|
3294
|
+
prefixTokens
|
|
3295
|
+
};
|
|
3296
|
+
}
|
|
3014
3297
|
/** Whether provider replay state is a prefix-bound server compaction checkpoint. */
|
|
3015
3298
|
function isCompactionReplayCheckpoint(replay) {
|
|
3016
3299
|
const type = replay && typeof replay === "object" ? replay.type : void 0;
|
|
@@ -3306,4 +3589,4 @@ function prepareModelForSimpleCompletion(params) {
|
|
|
3306
3589
|
return applyProviderSimpleCompletionWrapper(apiRegistry, model, cfg);
|
|
3307
3590
|
}
|
|
3308
3591
|
//#endregion
|
|
3309
|
-
export { GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, applyAnthropicCacheControlToMessages, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, captureOpenAIResponsesCompaction, coerceTransportToolCallArguments, copyProviderAcceptanceObserver, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIProviderAcceptanceHook, createOpenAIResponseHook, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, filterCodeModePayloadTools, finalizeTerminalToolCallArguments, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, googleFlashSupportsMinimalThinking, hasOpenAICompatibleConversationTurn, isCodeModeModelVisibleToolName, isCompactionReplayCheckpoint, isOpenAICodexResponsesModel, isOpenAICompletionsThinkingEnabled, log, measureUtf8AppendBytes, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, notifyProviderHttpMetadata, notifyProviderHttpResponse, notifyProviderStreamOpened, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, parseOpenAICompletionsUsage, parseTerminalToolCallArguments, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, readOpenAICompletionsReasoningBatch, replaceCompactionReplayOwnerContent, requestPreparedOpenAIResponsesCompaction, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveAnthropicServerCompactionPlan, resolveCodeModeResponsesVisibleToolNames, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAIClientBaseUrl, resolveOpenAICompletionsCompat, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesCompactEndpointPlan, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIResponsesServerCompactionPlan, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompactionReplayCheckpoint, stripCompactionReplayCheckpointInPlace, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend, withProviderAcceptanceObserver, withProviderResponseHook };
|
|
3592
|
+
export { CompactionReplayRefreshRequiredError, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, applyAnthropicCacheControlToMessages, applyAnthropicContextManagementToRequest, 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, isAnthropicServerToolClearingEnabled, isCodeModeModelVisibleToolName, isCompactionReplayCheckpoint, isDirectAnthropicModel, isOpenAICodexResponsesModel, isOpenAICompletionsThinkingEnabled, log, logAnthropicContextEdits, measureUtf8AppendBytes, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, notifyProviderHttpMetadata, notifyProviderHttpResponse, notifyProviderStreamOpened, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, parseOpenAICompletionsUsage, parseTerminalToolCallArguments, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, preserveCompactionReplayWindow, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, readOpenAICompletionsReasoningBatch, replaceCompactionReplayOwnerContent, requestPreparedOpenAIResponsesCompaction, requiresCompactionReplayRefresh, resolveAnthropicContextManagementBetaHeader, 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 };
|