@openclaw/ai 2026.8.1-beta.2 → 2026.9.1-beta.1

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