@openclaw/ai 2026.8.1-beta.2 → 2026.8.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 (87) hide show
  1. package/dist/{anthropic-B6dLpq5L.mjs → anthropic-Djj7L1rx.mjs} +49 -39
  2. package/dist/{anthropic-compaction-replay-8lJNKXOE.mjs → anthropic-compaction-replay-CY4tkD4V.mjs} +42 -44
  3. package/dist/{anthropic-payload-policy-CiEuQS72.d.mts → anthropic-payload-policy-i_5_inWe.d.mts} +4 -2
  4. package/dist/{api-registry-k3zTz0cV.d.mts → api-registry-C9-wZd_W.d.mts} +2 -1
  5. package/dist/{azure-openai-responses-mxIOtUnn.mjs → azure-openai-responses-Bj3czHNa.mjs} +4 -4
  6. package/dist/{number-coercion-H9qHik3g.mjs → base64-CEFBpSkN.mjs} +73 -1
  7. package/dist/diagnostics.d.mts +2 -3
  8. package/dist/diagnostics.mjs +1 -1
  9. package/dist/{env-api-keys-DrgeBuva.mjs → env-api-keys-bktO00EJ.mjs} +2 -15
  10. package/dist/event-stream-C988TSLe.d.mts +1 -0
  11. package/dist/{event-stream-BP6AWT8j.d.mts → event-stream-UhnxHuqt.d.mts} +1 -2
  12. package/dist/event-stream.d.mts +2 -1
  13. package/dist/{google-C7h2QzDX.mjs → google-0Ca6TYbw.mjs} +4 -4
  14. package/dist/{google-shared-B0Qr9OR7.mjs → google-shared-DVfL9COU.mjs} +22 -8
  15. package/dist/{google-vertex-Bhc3TjDl.mjs → google-vertex-5dAMxprN.mjs} +4 -4
  16. package/dist/{host-DTqNc7ad.mjs → host-D51fmkH6.mjs} +40 -33
  17. package/dist/{host-vWgMMhiJ.d.mts → host-DoPJJ1KD.d.mts} +7 -7
  18. package/dist/index-N3zr6__t.d.mts +105 -0
  19. package/dist/index.d.mts +9 -10
  20. package/dist/index.mjs +2 -3
  21. package/dist/internal/anthropic.d.mts +57 -49
  22. package/dist/internal/anthropic.mjs +5 -5
  23. package/dist/internal/openai-responses-payload-policy.d.mts +3 -3
  24. package/dist/internal/openai-responses-payload-policy.mjs +2 -3
  25. package/dist/internal/openai.d.mts +65 -63
  26. package/dist/internal/openai.mjs +10 -8
  27. package/dist/internal/retry-after.d.mts +2 -3
  28. package/dist/internal/runtime.d.mts +53 -40
  29. package/dist/internal/runtime.mjs +10 -9
  30. package/dist/internal/shared.d.mts +37 -23
  31. package/dist/internal/shared.mjs +4 -4
  32. package/dist/{json-parse-CDnesDM_.mjs → json-parse-BuAJEbdW.mjs} +18 -2
  33. package/dist/{headers-DdOQtGuU.mjs → llm-request-activity-BjtkplhG.mjs} +1 -9
  34. package/dist/{mistral-CEWoQI_g.mjs → mistral-BCnrI-kV.mjs} +64 -53
  35. package/dist/{openai-chatgpt-responses-CrPmqERt.mjs → openai-chatgpt-responses-CGBGWSqr.mjs} +45 -20
  36. package/dist/{openai-completions-BPnt4Sml.mjs → openai-completions-BaTuwID7.mjs} +63 -258
  37. package/dist/{openai-completions-compat-Dt3dcawL.d.mts → openai-completions-compat-DB7FFq7k.d.mts} +3 -3
  38. package/dist/openai-completions-stream-Bpns6uNc.mjs +1622 -0
  39. package/dist/{openai-responses-DhIKtOup.mjs → openai-responses-1GBcQujk.mjs} +8 -6
  40. package/dist/openai-responses-compaction-window-DwydGZI8.mjs +686 -0
  41. package/dist/{openai-responses-contracts-XpZJxrRG.d.mts → openai-responses-contracts-DgaR3t5T.d.mts} +14 -5
  42. package/dist/{openai-responses-payload-policy-BSs371VM.d.mts → openai-responses-payload-policy-rLRPsSmB.d.mts} +2 -0
  43. package/dist/{openai-responses-prompt-observer-internal-DgNTYnRY.mjs → openai-responses-prompt-observer-internal-_nhGTn2b.mjs} +3 -3
  44. package/dist/{openai-responses-shared-DXIt3iY5.mjs → openai-responses-shared-zPmKnhF5.mjs} +345 -1553
  45. package/dist/openai-stop-reason-Drnn_6Qj.mjs +28 -0
  46. package/dist/openai-tool-schema-Dgl4H2MU.mjs +1695 -0
  47. package/dist/{provider-error-BUwEnjXq.mjs → provider-error-jZP5NMTZ.mjs} +3 -82
  48. package/dist/{provider-options-B96RdNpH.d.mts → provider-options-HvA_slFa.d.mts} +23 -4
  49. package/dist/provider-transcript-transform-C01bQ5a3.mjs +32 -0
  50. package/dist/provider-types.d.mts +18 -17
  51. package/dist/providers.d.mts +5 -6
  52. package/dist/providers.mjs +9 -9
  53. package/dist/{reasoning-tag-text-partitioner-rnPwX2pg.mjs → reasoning-tag-text-partitioner-CwzKb0bA.mjs} +4 -1
  54. package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
  55. package/dist/{sanitize-unicode-BYqrYtC_.mjs → sanitize-unicode-DCkltN94.mjs} +1 -2
  56. package/dist/{simple-options-D58D5Kvw.mjs → simple-options-DKx86yX9.mjs} +42 -4
  57. package/dist/{anthropic-JsNA5KCu.mjs → src-Bu3FiFAG.mjs} +1 -1
  58. package/dist/{stream-first-event-timeout-MK28puvq.mjs → stream-first-event-timeout-DcNjoFQE.mjs} +1 -1
  59. package/dist/{streaming-byte-guard-BrbkbwUu.mjs → streaming-byte-guard-CC-HMn_u.mjs} +5 -6
  60. package/dist/string-normalization--fwJ4S2q.mjs +16 -0
  61. package/dist/{tool-schema-json-projection-q5d7QX5c.mjs → tool-schema-json-projection-qvTEs5Am.mjs} +17 -8
  62. package/dist/transport-stream-shared-CT5ycdzn.mjs +342 -0
  63. package/dist/transport-stream-shared-NjwWNaRY.d.mts +138 -0
  64. package/dist/{transport-utils-DJqkxbhC.mjs → transport-utils-BHx9z8Cl.mjs} +9 -9
  65. package/dist/transports.d.mts +140 -169
  66. package/dist/transports.mjs +269 -1262
  67. package/dist/types-DtGu2d3C.d.mts +1 -0
  68. package/dist/{types-BHNrPS1l.d.mts → types-h38Azne1.d.mts} +53 -17
  69. package/dist/types.d.mts +6 -5
  70. package/dist/types.mjs +1 -2
  71. package/dist/utf16-slice-qz3nsy87.mjs +84 -0
  72. package/dist/{validation-DT9SrFn3.d.mts → validation-C68lP2uy.d.mts} +1 -2
  73. package/dist/validation.d.mts +1 -1
  74. package/package.json +6 -6
  75. package/dist/anthropic-SrGtwsJu.d.mts +0 -100
  76. package/dist/index-BVVgDSdq.d.mts +0 -1
  77. package/dist/openai-responses-contracts-CyfIkQi5.mjs +0 -253
  78. package/dist/openai-responses-payload-policy-BDxV-W0c.mjs +0 -206
  79. package/dist/openai-stop-reason-BkFkqqK0.mjs +0 -563
  80. package/dist/openai-tool-projection-CY04OcvQ.mjs +0 -338
  81. package/dist/provider-transcript-transform-ePx-Bbfr.mjs +0 -155
  82. package/dist/record-coerce-DdXsgUd_.mjs +0 -23
  83. package/dist/src-D2H6yKkH.mjs +0 -2
  84. package/dist/stream-first-event-timeout-DvDeSucC.d.mts +0 -29
  85. package/dist/string-coerce-fsri9iCu.mjs +0 -34
  86. package/dist/types-BVVgDSdq.d.mts +0 -1
  87. package/dist/utf16-slice-CvGodqok.mjs +0 -29
@@ -1,31 +1,27 @@
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";
10
- 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";
1
+ import { d as resolveClaudeSonnet5ModelIdentity, g as supportsClaudeNativeXhighEffort, p as supportsClaudeAdaptiveThinking, u as resolveClaudeOpus5ModelIdentity } from "./src-Bu3FiFAG.mjs";
2
+ import { c as normalizeLowercaseStringOrEmpty, o as isRecord, s as hasNonEmptyString } from "./utf16-slice-qz3nsy87.mjs";
3
+ import { r as calculateCost } from "./sanitize-unicode-DCkltN94.mjs";
4
+ import { S as usesClaudeStreamingRefusalContract, _ as prepareClaudeNoPrefillRequestContext, a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, f as ANTHROPIC_CLAUDE_CODE_BILLING_SYSTEM_BLOCK, g as mapAnthropicStopReason, h as defaultsClaudeAdaptiveThinking, m as applyClaudeRequestContract, n as getAiTransportHost, p as ANTHROPIC_CLAUDE_CODE_VERSION, r as resolveAiTransportHeaderSentinels, s as extractToolResultBlockText, v as requiresClaudeAdaptiveThinking, x as usesClaudeFable5MessagesContract, y as resolveAnthropicThinkingEffort } from "./host-D51fmkH6.mjs";
5
+ import { i as stableStringify } from "./provider-error-jZP5NMTZ.mjs";
6
+ import { n as toErrorObject, t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-_nhGTn2b.mjs";
7
+ import { a as asNonNegativeFiniteNumber } from "./base64-CEFBpSkN.mjs";
8
+ import { n as uniqueStrings } from "./string-normalization--fwJ4S2q.mjs";
9
+ import { A as applyAnthropicCacheControlToMessages, C as applyAnthropicFallbackBoundary, D as createAnthropicInlineImageBudget, E as applyAnthropicRefusal, F as resolveAnthropicServerCompactionPlan, I as isAnthropicOAuthApiKey, L as omitFoundryBearerCredentialHeaders, M as applyAnthropicPayloadPolicyToParams, N as resolveAnthropicEphemeralCacheControl, O as normalizeAnthropicInlineContent, P as resolveAnthropicPayloadPolicy, R as usesFoundryBearerAuth, T as resolveAnthropicFallbackServingModelCost, _ as toClaudeCodeToolName, a as suppressAnthropicCompaction, b as ANTHROPIC_SERVER_SIDE_FALLBACKS, f as normalizeAnthropicToolCallId, g as resolveOriginalAnthropicToolName, h as reconcileAnthropicToolChoice, i as resolveNewestAnthropicCompaction, j as applyAnthropicEphemeralCacheControlMarkers, k as resolveAnthropicImageMediaType, m as projectAnthropicTools, n as createCompactionCapture, o as applyAnthropicMessageDeltaUsage, p as normalizeAnthropicToolChoice, r as isAnthropicReplayRejection, s as applyAnthropicMessageStartUsage, t as buildAnthropicReplayPlan, v as ANTHROPIC_OMITTED_REASONING_TEXT, w as readAnthropicFallbackBoundary, x as ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, y as findActiveAnthropicToolTurnAssistantIndex } from "./anthropic-compaction-replay-CY4tkD4V.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 { a as codeModeToolSurfaceObserver, d as stripSystemPromptCacheBoundary, m as sortPromptCacheToolsByName, o as reasoningTagTextPolicy, t as adjustMaxTokensForThinking } from "./simple-options-DKx86yX9.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, i as isCodeModeModelVisibleToolName, l as readResponseTextSnippet, m as supportsModelTools, n as createAbortError$1, o as isGoogleGemini3ProModel, p as sha256Hex, r as estimateStringChars, t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, u as redactIdentifier } from "./transport-utils-BHx9z8Cl.mjs";
14
+ import { n as getEnvApiKey } from "./env-api-keys-bktO00EJ.mjs";
15
+ import { S as quoteUnsafeIntegerLiterals, _ as transportAbortError, a as createWritableTransportEventStream, b as parseJsonObjectPreservingUnsafeIntegers, c as finalizeTransportStream, d as notifyProviderHttpMetadata, f as notifyProviderHttpResponse, g as sanitizeTransportPayloadText, h as sanitizeNonEmptyTransportPayloadText, i as createEmptyTransportUsage, l as mergeTransportHeaders, m as parseTerminalToolCallArguments, n as coerceTransportToolCallArguments, o as failTransportStream, p as notifyProviderStreamOpened, r as copyProviderAcceptanceObserver, s as finalizeTerminalToolCallArguments, t as assignTransportErrorDetails, u as mergeTransportMetadata, v as withProviderAcceptanceObserver, x as parseJsonPreservingUnsafeIntegers, y as withProviderResponseHook } from "./transport-stream-shared-CT5ycdzn.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-Bpns6uNc.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 captureOpenAIResponsesCompaction, H as createOpenAIResponsesAssistantOutput, I as createResponsesStreamWithEncryptedContentRetry, J as resolveReplayableResponsesMessageId, K as resolveNewestOpenAIResponsesCompactionReplay, L as isInvalidEncryptedContentError, R as resolveAzureOpenAIApiVersion, S as summarizeResponsesPayload, U as CompactionReplayRefreshRequiredError, V as convertResponsesMessages, W as buildOpenAIResponsesReasoningReplayMetadata, X as resolveModelPayloadDebugMode, Y as emitModelTransportDebug, Z as resolveModelSseDebugMode, _ as safeDebugValue, b as summarizeOpenAITransportError, c as processResponsesStream, f as observeResponsesStream, g as normalizeResponsesFailedEvent, h as logResponsesFailedNoDetails, m as buildResponsesFailedNoDetailsObservation, n as applyResponsesServiceTierPricing, p as ResponsesStreamFailure, q as suppressOpenAIResponsesCompaction, v as stringifyRedactedEvent, x as summarizeResponsesFailedNoDetailsObservation, y as stringifyRedactedPayload, z as resolveNextResponsesEncryptedContentAttempt } from "./openai-responses-shared-zPmKnhF5.mjs";
22
+ import { A as readOpenAICompletionsReasoningBatch, C as createOpenAIProviderAcceptanceHook, D as measureUtf8AppendBytes, E as log, M as resolvePromptCacheKey, N as throwIfModelStreamAborted, O as parseOpenAICompletionsUsage, S as createModelStreamCooperativeScheduler, T as isOpenAICompletionsThinkingEnabled, b as reconcileOpenAIResponsesToolChoice, j as resolveOpenAIClientBaseUrl, k as readOpenAICompletionsContentDeltas, r as normalizeOpenAIStrictToolParameters, v as projectOpenAITools, w as createOpenAIResponseHook, x as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, y as reconcileOpenAICompletionsToolChoice } from "./openai-tool-schema-Dgl4H2MU.mjs";
23
+ import { i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-DcNjoFQE.mjs";
24
+ import { C as isOpenAIGpt54MiniModel, D as resolveOpenAIReasoningEffortForModel, E as normalizeOpenAIReasoningEffort, T as isOpenAIGpt56Model, _ as OpenAIResponsesWebSocketPostDispatchError, a as applyOpenAIResponsesPayloadPolicy, c as resolveOpenAIResponsesServerCompactionPlan, d as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS, f as OPENAI_RESPONSES_APIS, i as sanitizeResponsesImagePayload, l as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, n as isOpenAIResponsesCompactionOutput, o as resolveOpenAIResponsesCompactEndpointPlan, s as resolveOpenAIResponsesPayloadPolicy, t as createBoundedOpenAIResponsesCompactionFetch, v as OpenAIResponsesWebSocketPreDispatchError, w as isOpenAIGpt55Model, x as parseOpenAIResponsesWebSocketServerError, y as OpenAIResponsesWebSocketSafeRetryError } from "./openai-responses-compaction-window-DwydGZI8.mjs";
29
25
  import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
30
26
  import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
31
27
  import { randomUUID } from "node:crypto";
@@ -62,12 +58,9 @@ function resolveAnthropicMessagesMaxTokens(params) {
62
58
  const contextWindow = resolvePositiveAnthropicTokenLimit(params.modelContextWindow);
63
59
  return contextWindow === void 0 ? ANTHROPIC_MESSAGES_DEFAULT_MAX_TOKENS : Math.max(1, Math.min(ANTHROPIC_MESSAGES_DEFAULT_MAX_TOKENS, Math.floor(contextWindow / ANTHROPIC_MESSAGES_FALLBACK_CONTEXT_DIVISOR)));
64
60
  }
65
- function isAnthropicOAuthToken(apiKey) {
66
- return (resolveSecretSentinel(apiKey) ?? apiKey).includes("sk-ant-oat");
67
- }
68
61
  function isDirectAnthropicModel(model) {
69
62
  if (normalizeLowercaseStringOrEmpty(model.provider) !== "anthropic") return false;
70
- const endpointClass = resolveProviderEndpoint(model.baseUrl).endpointClass;
63
+ const endpointClass = resolveProviderEndpoint(model).endpointClass;
71
64
  return endpointClass === "default" || endpointClass === "anthropic-public";
72
65
  }
73
66
  function isKimiAnthropicProvider(provider) {
@@ -82,7 +75,7 @@ function useAnthropicServerSideFallback(model) {
82
75
  return (usesClaudeFable5MessagesContract(model) || resolveClaudeOpus5ModelIdentity(model) !== void 0) && isDirectAnthropicModel(model);
83
76
  }
84
77
  function supportsReasoningContentReplay(model) {
85
- return resolveProviderEndpoint(model.baseUrl).endpointClass === "xiaomi-native";
78
+ return resolveProviderEndpoint(model).endpointClass === "xiaomi-native";
86
79
  }
87
80
  function buildAnthropicBetaHeader(model, betaFeatures, params) {
88
81
  if (!isDirectAnthropicModel(model)) return;
@@ -304,7 +297,7 @@ function convertAnthropicTools(tools, isOAuthToken) {
304
297
  };
305
298
  }
306
299
  function parseAnthropicToolCallArguments(inputJson) {
307
- return parseJsonObjectPreservingUnsafeIntegers(inputJson) ?? parseStreamingJson(inputJson);
300
+ return coerceTransportToolCallArguments(parseJsonObjectPreservingUnsafeIntegers(inputJson) ?? parseStreamingJson(inputJson));
308
301
  }
309
302
  const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
310
303
  /** Resolve the effective Anthropic API base URL from model or environment. */
@@ -407,7 +400,7 @@ async function* parseAnthropicSseBody(body, signal) {
407
400
  }
408
401
  function createAnthropicMessagesClient(params) {
409
402
  const url = resolveAnthropicMessagesUrl(params.baseURL);
410
- return { messages: { async *stream(body, options) {
403
+ return { messages: { async stream(body, options) {
411
404
  const headers = mergeTransportHeaders({
412
405
  "content-type": "application/json",
413
406
  "anthropic-version": "2023-06-01",
@@ -420,12 +413,10 @@ function createAnthropicMessagesClient(params) {
420
413
  body: JSON.stringify(body),
421
414
  signal: options?.signal
422
415
  });
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);
416
+ return {
417
+ response,
418
+ stream: response.body ? parseAnthropicSseBody(response.body, options?.signal) : []
419
+ };
429
420
  } } };
430
421
  }
431
422
  function formatAnthropicMessagesHttpError(response, detail) {
@@ -486,7 +477,7 @@ function createAnthropicTransportClient(params) {
486
477
  }
487
478
  const betaFeatures = ["fine-grained-tool-streaming-2025-05-14"];
488
479
  if (needsInterleavedBeta) betaFeatures.push("interleaved-thinking-2025-05-14");
489
- if (isAnthropicOAuthToken(apiKey)) {
480
+ if (isAnthropicOAuthApiKey(apiKey)) {
490
481
  const betaHeader = buildAnthropicBetaHeader(model, betaFeatures, { oauth: true });
491
482
  return {
492
483
  client: createAnthropicMessagesClient({
@@ -536,7 +527,7 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
536
527
  baseUrl: model.baseUrl,
537
528
  cacheRetention: options?.cacheRetention,
538
529
  enableCacheControl: true
539
- });
530
+ }, model);
540
531
  const cacheBreakpointOptOutMessageIndexes = /* @__PURE__ */ new Set();
541
532
  const replayPlan = buildAnthropicReplayPlan(context.messages, model, {
542
533
  enabled: !isOAuthToken && options?.anthropicServerCompaction === true,
@@ -620,7 +611,7 @@ function resolveAnthropicTransportOptions(model, options, apiKey) {
620
611
  const reasoningModelMaxTokens = resolvePositiveAnthropicTokenLimit(model.maxTokens) ?? baseMaxTokens;
621
612
  const mandatoryAdaptiveThinking = requiresClaudeAdaptiveThinking(model);
622
613
  const reasoning = options?.reasoning === "off" && mandatoryAdaptiveThinking ? "low" : options?.reasoning;
623
- const resolved = {
614
+ const resolved = copyProviderAcceptanceObserver(options, {
624
615
  temperature: options?.temperature,
625
616
  stop: options?.stop,
626
617
  maxTokens: baseMaxTokens,
@@ -630,6 +621,7 @@ function resolveAnthropicTransportOptions(model, options, apiKey) {
630
621
  sessionId: options?.sessionId,
631
622
  headers: options?.headers,
632
623
  onPayload: options?.onPayload,
624
+ onResponse: options?.onResponse,
633
625
  maxRetryDelayMs: options?.maxRetryDelayMs,
634
626
  metadata: options?.metadata,
635
627
  interleavedThinking: options?.interleavedThinking,
@@ -638,7 +630,7 @@ function resolveAnthropicTransportOptions(model, options, apiKey) {
638
630
  reasoning,
639
631
  ...options?.anthropicServerCompaction === true ? { anthropicServerCompaction: true } : {},
640
632
  ...options?.authProfileId ? { authProfileId: options.authProfileId } : {}
641
- };
633
+ });
642
634
  if (reasoning === "off") {
643
635
  resolved.thinkingEnabled = false;
644
636
  return resolved;
@@ -700,12 +692,23 @@ function createAnthropicMessagesTransportStreamFn() {
700
692
  const nextParams = await transportOptions.onPayload?.(params, model);
701
693
  if (nextParams !== void 0) params = nextParams;
702
694
  applyClaudeRequestContract(params, model);
703
- const anthropicStream = client.messages.stream({
695
+ const { response, stream: anthropicStream } = await client.messages.stream({
704
696
  ...params,
705
697
  stream: true
706
698
  }, transportOptions.signal ? { signal: transportOptions.signal } : void 0);
699
+ await notifyProviderHttpResponse({
700
+ options: transportOptions,
701
+ response,
702
+ model
703
+ });
704
+ if (!response.ok) {
705
+ const detail = await readAnthropicMessagesErrorBodySnippet(response);
706
+ throw new Error(formatAnthropicMessagesHttpError(response, detail));
707
+ }
707
708
  const blocks = output.content;
708
709
  const blockIndexes = /* @__PURE__ */ new Map();
710
+ const toolArgumentPreviewSchedules = /* @__PURE__ */ new WeakMap();
711
+ const sealedToolCalls = [];
709
712
  const compactionCapture = createCompactionCapture(output, model, transportOptions);
710
713
  const pendingThinkingSignatures = /* @__PURE__ */ new Map();
711
714
  const allowReasoningContentReplay = supportsReasoningContentReplay(model);
@@ -740,6 +743,7 @@ function createAnthropicMessagesTransportStreamFn() {
740
743
  partial: output
741
744
  });
742
745
  }
746
+ if (contentIndex === void 0) return false;
743
747
  block.thinking += text;
744
748
  block.thinkingSignature = "reasoning_content";
745
749
  eventSink.push({
@@ -771,6 +775,7 @@ function createAnthropicMessagesTransportStreamFn() {
771
775
  partial: output
772
776
  });
773
777
  }
778
+ if (contentIndex === void 0) return false;
774
779
  block.text += text;
775
780
  eventSink.push({
776
781
  type: "text_delta",
@@ -833,6 +838,7 @@ function createAnthropicMessagesTransportStreamFn() {
833
838
  const fallbackBoundary = refusalBuffer ? readAnthropicFallbackBoundary(contentBlock) : null;
834
839
  if (fallbackBoundary) {
835
840
  refusalBuffer?.discard();
841
+ sealedToolCalls.length = 0;
836
842
  pendingTextEnds.length = 0;
837
843
  blockIndexes.clear();
838
844
  pendingThinkingSignatures.clear();
@@ -955,6 +961,7 @@ function createAnthropicMessagesTransportStreamFn() {
955
961
  };
956
962
  output.content.push(block);
957
963
  blockIndexes.set(index, output.content.length - 1);
964
+ toolArgumentPreviewSchedules.set(block, createToolArgumentPreviewSchedule());
958
965
  eventSink.push({
959
966
  type: "toolcall_start",
960
967
  contentIndex: output.content.length - 1,
@@ -975,7 +982,7 @@ function createAnthropicMessagesTransportStreamFn() {
975
982
  let appendedContent = false;
976
983
  if (!hasNativeAnthropicDelta && typeof delta?.content === "string" && delta.content.length > 0) {
977
984
  const text = sanitizeTransportPayloadText(delta.content);
978
- if (text.length > 0) if (block?.type === "text") {
985
+ if (text.length > 0) if (block?.type === "text" && index !== void 0) {
979
986
  block.text += text;
980
987
  eventSink.push({
981
988
  type: "text_delta",
@@ -1003,6 +1010,7 @@ function createAnthropicMessagesTransportStreamFn() {
1003
1010
  partial: output
1004
1011
  });
1005
1012
  }
1013
+ if (index === void 0) continue;
1006
1014
  if (block?.type === "text" && delta?.type === "text_delta" && typeof delta.text === "string") {
1007
1015
  block.text += delta.text;
1008
1016
  eventSink.push({
@@ -1026,7 +1034,7 @@ function createAnthropicMessagesTransportStreamFn() {
1026
1034
  if (block?.type === "toolCall" && delta?.type === "input_json_delta" && typeof delta.partial_json === "string") {
1027
1035
  const partialJson = `${block.partialJson ?? ""}${delta.partial_json}`;
1028
1036
  block.partialJson = partialJson;
1029
- block.arguments = parseAnthropicToolCallArguments(partialJson);
1037
+ if (toolArgumentPreviewSchedules.get(block)?.(partialJson.length)) block.arguments = parseAnthropicToolCallArguments(partialJson);
1030
1038
  eventSink.push({
1031
1039
  type: "toolcall_delta",
1032
1040
  contentIndex: index,
@@ -1080,12 +1088,9 @@ function createAnthropicMessagesTransportStreamFn() {
1080
1088
  continue;
1081
1089
  }
1082
1090
  if (block.type === "toolCall") {
1083
- delete block.partialJson;
1084
- eventSink.push({
1085
- type: "toolcall_end",
1086
- contentIndex: index,
1087
- toolCall: block,
1088
- partial: output
1091
+ sealedToolCalls.push({
1092
+ block,
1093
+ contentIndex: index
1089
1094
  });
1090
1095
  finishReasoningContentSidecars(event.index);
1091
1096
  }
@@ -1105,6 +1110,17 @@ function createAnthropicMessagesTransportStreamFn() {
1105
1110
  if (isDirectAnthropicModel(model) && !sawMessageStop) throw new Error("Anthropic stream ended before message_stop");
1106
1111
  if (transportOptions.signal?.aborted) throw transportAbortError(transportOptions.signal);
1107
1112
  if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
1113
+ if ([...blockIndexes.values()].some((index) => blocks[index]?.type === "toolCall")) throw new Error("Provider completed stream with an incomplete tool call");
1114
+ finalizeTerminalToolCallArguments(sealedToolCalls.map(({ block }) => block), (block) => block.partialJson && block.partialJson.length > 0 ? block.partialJson : block.arguments);
1115
+ for (const sealed of sealedToolCalls) {
1116
+ delete sealed.block.partialJson;
1117
+ eventSink.push({
1118
+ type: "toolcall_end",
1119
+ contentIndex: sealed.contentIndex,
1120
+ toolCall: sealed.block,
1121
+ partial: output
1122
+ });
1123
+ }
1108
1124
  refusalBuffer?.flush();
1109
1125
  if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
1110
1126
  flushPendingTextEnds();
@@ -1116,7 +1132,7 @@ function createAnthropicMessagesTransportStreamFn() {
1116
1132
  if (refusalBuffer) {
1117
1133
  refusalBuffer.discard();
1118
1134
  output.content = [];
1119
- }
1135
+ } else output.content = output.content.filter((block) => block.type !== "toolCall");
1120
1136
  if (usedCompactionReplay && isAnthropicReplayRejection(error)) suppressAnthropicCompaction(output, model, options);
1121
1137
  failTransportStream({
1122
1138
  stream,
@@ -1133,96 +1149,6 @@ function createAnthropicMessagesTransportStreamFn() {
1133
1149
  };
1134
1150
  }
1135
1151
  //#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
1152
  //#region packages/ai/src/transports/model-max-tokens-params.ts
1227
1153
  /**
1228
1154
  * Max-token parameter normalization across provider/native naming variants.
@@ -1521,202 +1447,10 @@ function applyCompletionsReplay(outgoingMessages, context, model, compat) {
1521
1447
  });
1522
1448
  }
1523
1449
  //#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
1450
  //#region packages/ai/src/transports/openai-completions-params.ts
1717
1451
  function isKnownOpenAICompletionsEndpoint(model) {
1718
1452
  if (!model.baseUrl.trim()) return true;
1719
- const endpointClass = resolveProviderEndpoint(model.baseUrl).endpointClass;
1453
+ const endpointClass = resolveProviderEndpoint(model).endpointClass;
1720
1454
  if (endpointClass === "openai-public" || endpointClass === "azure-openai") return true;
1721
1455
  try {
1722
1456
  return isAzureOpenAICompatibleHost(new URL(model.baseUrl).hostname.toLowerCase());
@@ -1724,7 +1458,7 @@ function isKnownOpenAICompletionsEndpoint(model) {
1724
1458
  return false;
1725
1459
  }
1726
1460
  }
1727
- function resolveOpenAICompletionsReasoningEffort$1(options) {
1461
+ function resolveOpenAICompletionsReasoningEffort(options) {
1728
1462
  return options?.reasoningEffort ?? options?.reasoning ?? "high";
1729
1463
  }
1730
1464
  function resolveOpenAICompletionsMaxTokens(model, options) {
@@ -1923,7 +1657,7 @@ function buildOpenAICompletionsParams(model, context, options) {
1923
1657
  if (clampedMaxTokens) if (compat.maxTokensField === "max_tokens") params.max_tokens = clampedMaxTokens;
1924
1658
  else params.max_completion_tokens = clampedMaxTokens;
1925
1659
  }
1926
- const completionsReasoningEffort = resolveOpenAICompletionsReasoningEffort$1(options);
1660
+ const completionsReasoningEffort = resolveOpenAICompletionsReasoningEffort(options);
1927
1661
  const resolvedCompletionsReasoningEffort = completionsReasoningEffort ? resolveOpenAIReasoningEffortForModel({
1928
1662
  model,
1929
1663
  effort: completionsReasoningEffort,
@@ -1949,713 +1683,6 @@ function buildOpenAICompletionsParams(model, context, options) {
1949
1683
  return params;
1950
1684
  }
1951
1685
  //#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
1686
  //#region packages/ai/src/transports/openai-completions-transport.ts
2660
1687
  function assertOpenAICompletionsPayloadHasConversationTurn(params, model) {
2661
1688
  const messages = params.messages;
@@ -2731,15 +1758,14 @@ function buildOpenAICompletionsClientConfig(model, context, optionHeaders) {
2731
1758
  }
2732
1759
  }
2733
1760
  return {
2734
- baseURL,
1761
+ baseURL: resolveOpenAIClientBaseUrl(model, baseURL),
2735
1762
  defaultHeaders: headers,
2736
1763
  defaultQuery: Object.keys(defaultQuery).length > 0 ? defaultQuery : void 0
2737
1764
  };
2738
1765
  }
2739
1766
  function createOpenAICompletionsTransportStreamFn() {
2740
1767
  return (model, context, options) => {
2741
- const eventStream = createAssistantMessageEventStream();
2742
- const stream = eventStream;
1768
+ const { eventStream, stream } = createWritableTransportEventStream();
2743
1769
  (async () => {
2744
1770
  const output = {
2745
1771
  role: "assistant",
@@ -2794,7 +1820,7 @@ function createOpenAICompletionsTransportStreamFn() {
2794
1820
  if (nextParams !== void 0) params = nextParams;
2795
1821
  if (options?.openclawCodeModeToolSurface === true) {
2796
1822
  const visibleToolNames = resolveCodeModeResponsesVisibleToolNames(context);
2797
- enforceCodeModeResponsesToolSurface(params, visibleToolNames);
1823
+ enforceCodeModeResponsesToolSurface(params, visibleToolNames, void 0, codeModeToolSurfaceObserver.get(options));
2798
1824
  assertCodeModeResponsesToolSurface(params, visibleToolNames);
2799
1825
  }
2800
1826
  if (getCompat(model).requiresNonEmptyUserOrAssistantMessage) assertOpenAICompletionsPayloadHasConversationTurn(params, model);
@@ -2808,7 +1834,7 @@ function createOpenAICompletionsTransportStreamFn() {
2808
1834
  stream: responseStream,
2809
1835
  signal: firstEventAbort.signal,
2810
1836
  abort: firstEventAbort.abort,
2811
- hook: createOpenAIResponseHook(options?.onResponse, response, model),
1837
+ hook: createOpenAIProviderAcceptanceHook(options, response, model),
2812
1838
  onReady: () => stream.push({
2813
1839
  type: "start",
2814
1840
  partial: output
@@ -2816,6 +1842,7 @@ function createOpenAICompletionsTransportStreamFn() {
2816
1842
  }), output, model, stream, {
2817
1843
  signal: options?.signal,
2818
1844
  emitReasoning,
1845
+ strictReasoningTags: reasoningTagTextPolicy.isStrict(options),
2819
1846
  firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options),
2820
1847
  abortFirstEventStream: firstEventAbort.abort,
2821
1848
  onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
@@ -2835,6 +1862,7 @@ function createOpenAICompletionsTransportStreamFn() {
2835
1862
  cleanup: () => {
2836
1863
  output.stopReason = options?.signal?.aborted ? "aborted" : "error";
2837
1864
  finalizeOpenAICompletionsToolCalls(output, { allowSilentToolCallPromotion: false });
1865
+ tagUnresolvedTextAsCommentary(output);
2838
1866
  }
2839
1867
  });
2840
1868
  } finally {
@@ -2889,7 +1917,7 @@ function jsonValuesEqual(left, right) {
2889
1917
  return stableStringify(JSON.parse(JSON.stringify(left))) === stableStringify(JSON.parse(JSON.stringify(right)));
2890
1918
  }
2891
1919
  function requestWithoutInput(request) {
2892
- const { input: _input, previous_response_id: _previousResponseId, ...rest } = request;
1920
+ const { input: _input, previous_response_id: _previousResponseId, instructions: _instructions, ...rest } = request;
2893
1921
  if (!isRecord(rest.metadata)) return rest;
2894
1922
  const metadata = Object.fromEntries(Object.entries(rest.metadata).filter(([key]) => key !== "openclaw_turn_id" && key !== "openclaw_turn_attempt"));
2895
1923
  return {
@@ -3080,18 +2108,27 @@ function sanitizeOpenAICodexResponsesParams(model, params) {
3080
2108
  stripOpenAICodexResponsesUnsupportedTextFields(params);
3081
2109
  return params;
3082
2110
  }
3083
- function buildOpenAICodexResponsesInstructions(context) {
2111
+ function buildOpenAIResponsesInstructionsText(context) {
3084
2112
  if (!context.systemPrompt) return;
3085
2113
  return sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt));
3086
2114
  }
3087
- function resolveOpenAICodexResponsesInstructions(model, context) {
3088
- const instructions = buildOpenAICodexResponsesInstructions(context);
2115
+ function resolveOpenAIResponsesInstructions(model, context, usesInstructionsField) {
2116
+ if (!usesInstructionsField) return;
2117
+ const instructions = buildOpenAIResponsesInstructionsText(context);
3089
2118
  if (instructions && instructions.trim().length > 0) return instructions;
3090
2119
  return usesNativeOpenAICodexResponsesBackend(model) ? OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS : void 0;
3091
2120
  }
3092
- function ensureOpenAICodexResponsesInput(messages, context) {
2121
+ function buildOpenAIResponsesCompactSystemMessage(model, instructions) {
2122
+ const compat = getCompat(model);
2123
+ const supportsDeveloperRole = typeof compat.supportsDeveloperRole === "boolean" ? compat.supportsDeveloperRole : void 0;
2124
+ return buildResponsesInputMessage(model.reasoning && supportsDeveloperRole !== false ? "developer" : "system", [{
2125
+ type: "input_text",
2126
+ text: instructions
2127
+ }]);
2128
+ }
2129
+ function ensureOpenAIResponsesNonEmptyInput(messages, context) {
3093
2130
  if (messages.length > 0 || !context.systemPrompt) return;
3094
- if (!buildOpenAICodexResponsesInstructions(context)) throw new Error("OpenAI Codex Responses requires non-empty input when only systemPrompt is provided.");
2131
+ if (!buildOpenAIResponsesInstructionsText(context)) throw new Error("OpenAI Responses requires non-empty input when only systemPrompt is provided.");
3095
2132
  messages.push(buildResponsesInputMessage("user", [{
3096
2133
  type: "input_text",
3097
2134
  text: " "
@@ -3105,16 +2142,12 @@ function resolveOpenAIResponsesTextFormat(responseFormat) {
3105
2142
  return responseFormat;
3106
2143
  }
3107
2144
  function convertOpenAIResponsesMessagesForRequest(model, context, options, replayMode) {
3108
- const isCodexResponses = isOpenAICodexResponsesModel(model);
3109
2145
  const isNativeCodexResponses = usesNativeOpenAICodexResponsesBackend(model);
3110
- const compat = getCompat(model);
3111
- const supportsDeveloperRole = typeof compat.supportsDeveloperRole === "boolean" ? compat.supportsDeveloperRole : void 0;
3112
2146
  const payloadPolicy = resolveOpenAIResponsesPayloadPolicy(model, { storeMode: "disable" });
3113
2147
  const policyAllowsReplayIds = payloadPolicy.explicitStore !== false && !payloadPolicy.shouldStripStore;
3114
2148
  const replayResponsesItemIds = !isNativeCodexResponses && (options?.replayResponsesItemIds ?? policyAllowsReplayIds);
3115
2149
  return convertResponsesMessages(model, context, OPENAI_RESPONSES_TOOL_CALL_PROVIDERS, {
3116
- includeSystemPrompt: !isCodexResponses,
3117
- supportsDeveloperRole,
2150
+ includeSystemPrompt: !payloadPolicy.usesInstructionsField,
3118
2151
  replayReasoningItems: true,
3119
2152
  replayResponsesItemIds,
3120
2153
  authProfileId: options?.authProfileId,
@@ -3123,19 +2156,19 @@ function convertOpenAIResponsesMessagesForRequest(model, context, options, repla
3123
2156
  });
3124
2157
  }
3125
2158
  function buildOpenAIResponsesParams(model, context, options, metadata, replayMode = "checkpoint") {
3126
- const isCodexResponses = isOpenAICodexResponsesModel(model);
3127
2159
  const payloadPolicy = resolveOpenAIResponsesPayloadPolicy(model, { storeMode: "disable" });
3128
2160
  const messages = convertOpenAIResponsesMessagesForRequest(model, context, options, replayMode);
3129
- if (isCodexResponses) ensureOpenAICodexResponsesInput(messages, context);
2161
+ ensureOpenAIResponsesNonEmptyInput(messages, context);
3130
2162
  const cacheRetention = resolveCacheRetention(options?.cacheRetention);
3131
2163
  const promptCacheKey = resolvePromptCacheKey(options, cacheRetention);
2164
+ const instructions = resolveOpenAIResponsesInstructions(model, context, payloadPolicy.usesInstructionsField);
3132
2165
  const params = {
3133
2166
  model: model.id,
3134
2167
  input: messages,
3135
2168
  stream: true,
3136
2169
  prompt_cache_key: promptCacheKey,
3137
2170
  prompt_cache_retention: getPromptCacheRetention(model.baseUrl, cacheRetention),
3138
- ...isCodexResponses ? { instructions: resolveOpenAICodexResponsesInstructions(model, context) } : {},
2171
+ ...instructions ? { instructions } : {},
3139
2172
  ...metadata ? { metadata } : {}
3140
2173
  };
3141
2174
  const effectiveMaxTokens = options?.maxTokens || model.maxTokens;
@@ -3405,9 +2438,8 @@ function createOpenAIResponsesWebSocketStream(params) {
3405
2438
  }
3406
2439
  const event = readServerEvent(next.value);
3407
2440
  if (!event) continue;
3408
- if (event.type === "response.failed") throw new OpenAIResponsesWebSocketResponseFailedError(event.response.output.length > 0);
3409
2441
  if (event.type === "response.completed") terminalResponse = event.response;
3410
- terminalReceived = event.type === "response.completed" || event.type === "response.incomplete";
2442
+ terminalReceived = event.type === "response.completed" || event.type === "response.incomplete" || event.type === "response.failed";
3411
2443
  yield event;
3412
2444
  if (terminalReceived) {
3413
2445
  degradedWebSocketConnections.delete(degradationKey);
@@ -3419,7 +2451,7 @@ function createOpenAIResponsesWebSocketStream(params) {
3419
2451
  const safeRetry = error instanceof OpenAIResponsesWebSocketSafeRetryError;
3420
2452
  if (!params.callerSignal?.aborted && !safeRetry) markDegraded();
3421
2453
  if (!requestDispatched && !params.signal?.aborted) throw new OpenAIResponsesWebSocketPreDispatchError(error);
3422
- if (!requestDispatched || params.callerSignal?.aborted || error instanceof OpenAIResponsesWebSocketResponseFailedError || safeRetry) throw error;
2454
+ if (!requestDispatched || params.callerSignal?.aborted || safeRetry) throw error;
3423
2455
  throw new OpenAIResponsesWebSocketPostDispatchError(error);
3424
2456
  } finally {
3425
2457
  await iterator.return?.().catch(() => void 0);
@@ -3441,149 +2473,6 @@ function closeOpenAIResponsesWebSocketSessions(sessionId) {
3441
2473
  }
3442
2474
  registerSessionResourceCleanup(closeOpenAIResponsesWebSocketSessions);
3443
2475
  //#endregion
3444
- //#region packages/media-core/src/inline-image-data-url.ts
3445
- /** Prefix used to distinguish inline data URLs from remote/local image references. */
3446
- const INLINE_IMAGE_DATA_URL_PREFIX = "data:";
3447
- const IMAGE_SIGNATURES = [
3448
- {
3449
- mime: "image/png",
3450
- matches: (buffer) => buffer.length >= 8 && buffer[0] === 137 && buffer[1] === 80 && buffer[2] === 78 && buffer[3] === 71 && buffer[4] === 13 && buffer[5] === 10 && buffer[6] === 26 && buffer[7] === 10
3451
- },
3452
- {
3453
- mime: "image/jpeg",
3454
- matches: (buffer) => buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255
3455
- },
3456
- {
3457
- mime: "image/webp",
3458
- matches: (buffer) => buffer.length >= 12 && buffer.subarray(0, 4).toString("ascii") === "RIFF" && buffer.subarray(8, 12).toString("ascii") === "WEBP"
3459
- },
3460
- {
3461
- mime: "image/gif",
3462
- matches: (buffer) => buffer.length >= 6 && (buffer.subarray(0, 6).toString("ascii") === "GIF87a" || buffer.subarray(0, 6).toString("ascii") === "GIF89a")
3463
- },
3464
- {
3465
- mime: "image/bmp",
3466
- matches: (buffer) => buffer.length >= 2 && buffer[0] === 66 && buffer[1] === 77
3467
- }
3468
- ];
3469
- const HEIC_BRANDS = /* @__PURE__ */ new Set([
3470
- "heic",
3471
- "heix",
3472
- "hevc",
3473
- "hevx",
3474
- "heis",
3475
- "heim",
3476
- "hevm",
3477
- "hevs"
3478
- ]);
3479
- const HEIF_BRANDS = /* @__PURE__ */ new Set(["mif1", "msf1"]);
3480
- const IMAGE_SIGNATURE_PREFIX_BASE64_CHARS = 128;
3481
- const INLINE_IMAGE_DATA_URL_MIMES = /* @__PURE__ */ new Set([
3482
- "image/png",
3483
- "image/jpeg",
3484
- "image/webp",
3485
- "image/gif"
3486
- ]);
3487
- function startsWithDataUrl(value) {
3488
- return value.slice(0, 5).toLowerCase() === INLINE_IMAGE_DATA_URL_PREFIX;
3489
- }
3490
- function sniffIsoBmffImageMime(buffer) {
3491
- if (buffer.length < 12 || buffer.subarray(4, 8).toString("ascii") !== "ftyp") return;
3492
- const brands = [buffer.subarray(8, 12).toString("ascii")];
3493
- for (let offset = 16; offset + 4 <= buffer.length; offset += 4) brands.push(buffer.subarray(offset, offset + 4).toString("ascii"));
3494
- if (brands.some((brand) => HEIC_BRANDS.has(brand))) return "image/heic";
3495
- if (brands.some((brand) => HEIF_BRANDS.has(brand))) return "image/heif";
3496
- }
3497
- /** Sniffs supported inline image formats from decoded bytes. */
3498
- function sniffInlineImageMime(buffer) {
3499
- return IMAGE_SIGNATURES.find((signature) => signature.matches(buffer))?.mime ?? sniffIsoBmffImageMime(buffer);
3500
- }
3501
- function isImageMimeType(value) {
3502
- return value.trim().toLowerCase().startsWith("image/");
3503
- }
3504
- /** Canonicalizes trusted inline image base64 and rejects malformed or non-image payloads. */
3505
- function sanitizeInlineImageBase64(params) {
3506
- if (!isImageMimeType(params.mimeType)) return;
3507
- const canonicalPayload = canonicalizeBase64(params.base64);
3508
- if (!canonicalPayload) return;
3509
- const sniffedMimeType = sniffInlineImageMime(Buffer.from(canonicalPayload.slice(0, IMAGE_SIGNATURE_PREFIX_BASE64_CHARS), "base64"));
3510
- if (!sniffedMimeType) return;
3511
- return {
3512
- mimeType: sniffedMimeType,
3513
- base64: canonicalPayload
3514
- };
3515
- }
3516
- function parseInlineImageDataUrl(value) {
3517
- if (!startsWithDataUrl(value)) return {
3518
- metadata: [],
3519
- payload: value
3520
- };
3521
- const commaIndex = value.indexOf(",");
3522
- if (commaIndex < 0) return;
3523
- return {
3524
- metadata: value.slice(5, commaIndex).split(";").map((part) => part.trim()),
3525
- payload: value.slice(commaIndex + 1)
3526
- };
3527
- }
3528
- function metadataAllowsImageBase64(metadata) {
3529
- const [mimeType, ...options] = metadata;
3530
- return mimeType !== void 0 && isImageMimeType(mimeType) && options.some((part) => part.toLowerCase() === "base64");
3531
- }
3532
- function sanitizeInlineImageDataUrlWithAllowedMimes(imageUrl, allowedMimes) {
3533
- const parsed = parseInlineImageDataUrl(imageUrl);
3534
- if (!parsed) return;
3535
- if (parsed.metadata.length === 0) return imageUrl;
3536
- if (!metadataAllowsImageBase64(parsed.metadata)) return;
3537
- const [mimeType] = parsed.metadata;
3538
- const sanitized = sanitizeInlineImageBase64({
3539
- mimeType: mimeType ?? "",
3540
- base64: parsed.payload
3541
- });
3542
- if (!sanitized) return;
3543
- if (allowedMimes && !allowedMimes.has(sanitized.mimeType)) return;
3544
- return `data:${sanitized.mimeType};base64,${sanitized.base64}`;
3545
- }
3546
- /** Canonicalizes provider-safe inline image data URLs and rejects unsupported formats. */
3547
- function sanitizeInlineImageDataUrl(imageUrl) {
3548
- return sanitizeInlineImageDataUrlWithAllowedMimes(imageUrl, INLINE_IMAGE_DATA_URL_MIMES);
3549
- }
3550
- //#endregion
3551
- //#region packages/ai/src/transports/responses-image-payload-sanitizer.ts
3552
- /**
3553
- * Sanitizes OpenAI Responses payloads before transport. Invalid inline images
3554
- * are replaced with text placeholders so the request remains valid and
3555
- * auditable.
3556
- */
3557
- const IMAGE_OMITTED_TEXT = "omitted image payload: invalid inline image data";
3558
- function invalidSnakeImage() {
3559
- return {
3560
- type: "input_text",
3561
- text: `[${IMAGE_OMITTED_TEXT}]`
3562
- };
3563
- }
3564
- function sanitizeValue(value) {
3565
- if (Array.isArray(value)) return value.map(sanitizeValue);
3566
- if (!isRecord(value)) return value;
3567
- if (value.type === "input_image" && typeof value.image_url === "string") {
3568
- const imageUrl = sanitizeInlineImageDataUrl(value.image_url);
3569
- return imageUrl ? {
3570
- ...value,
3571
- image_url: imageUrl
3572
- } : invalidSnakeImage();
3573
- }
3574
- const next = {};
3575
- for (const [key, child] of Object.entries(value)) next[key] = sanitizeValue(child);
3576
- return next;
3577
- }
3578
- /** Sanitize inline image fields inside a Responses API payload. */
3579
- function sanitizeResponsesImagePayload(params) {
3580
- if (!Array.isArray(params.input)) return params;
3581
- return {
3582
- ...params,
3583
- input: sanitizeValue(params.input)
3584
- };
3585
- }
3586
- //#endregion
3587
2476
  //#region packages/ai/src/transports/openai-responses-client.ts
3588
2477
  function resolveNativeOpenAIResponsesWebSocketMode(model, transport) {
3589
2478
  if (transport !== "websocket" && transport !== "websocket-cached" && transport !== "auto") return;
@@ -3617,17 +2506,18 @@ function resolveProviderTransportTurnState(model, params) {
3617
2506
  }
3618
2507
  });
3619
2508
  }
3620
- function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId) {
2509
+ function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId, fetchOverride) {
3621
2510
  return new OpenAI({
3622
2511
  apiKey,
3623
- baseURL: model.baseUrl,
2512
+ baseURL: resolveOpenAIClientBaseUrl(model),
3624
2513
  dangerouslyAllowBrowser: true,
3625
2514
  defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId),
3626
- fetch: buildGuardedModelFetch(model),
2515
+ fetch: fetchOverride ?? buildGuardedModelFetch(model),
3627
2516
  ...buildOpenAISdkClientOptions(model)
3628
2517
  });
3629
2518
  }
3630
2519
  async function postOpenAIResponsesCompaction(params) {
2520
+ const compactInput = typeof params.request.instructions === "string" && params.request.instructions.length > 0 ? [buildOpenAIResponsesCompactSystemMessage(params.model, params.request.instructions), ...params.request.input ?? []] : params.request.input;
3631
2521
  const response = await params.client.post("/responses/compact", {
3632
2522
  ...buildOpenAISdkRequestOptions(params.model, params.options?.signal, {
3633
2523
  timeoutMs: params.options?.timeoutMs,
@@ -3635,15 +2525,21 @@ async function postOpenAIResponsesCompaction(params) {
3635
2525
  }),
3636
2526
  body: {
3637
2527
  model: params.request.model,
3638
- input: params.request.input
2528
+ input: compactInput
3639
2529
  }
3640
2530
  });
3641
2531
  const output = isRecord(response) && Array.isArray(response.output) ? response.output : [];
3642
- const item = output[0];
2532
+ const item = output.at(-1);
2533
+ const retainedItems = output.slice(0, -1);
2534
+ const retainedUserMessageCount = retainedItems.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user" && Array.isArray(candidate.content)).length;
2535
+ const inputUserMessageCount = Array.isArray(params.request.input) ? params.request.input.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user").length : 0;
2536
+ const retainedMessagePrefixSupported = supportsNativeOpenAIResponsesEndpoint(params.model);
3643
2537
  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");
2538
+ if (!isRecord(response) || response.object !== "response.compaction" || !isOpenAIResponsesCompactionOutput(output, params.model) || retainedItems.length > 0 && (!retainedMessagePrefixSupported || retainedUserMessageCount !== inputUserMessageCount) || !isRecord(item) || item.type !== "compaction" || typeof item.encrypted_content !== "string" || item.encrypted_content.length === 0 || !usage || typeof usage.input_tokens !== "number" || typeof usage.output_tokens !== "number") throw new Error("Responses compact endpoint did not return one trailing compaction item");
3645
2539
  return {
2540
+ output,
3646
2541
  item,
2542
+ historyMode: retainedUserMessageCount > 0 ? "retained-users" : "compacted-prefix",
3647
2543
  usage,
3648
2544
  model: params.model,
3649
2545
  replayMetadata: buildOpenAIResponsesReasoningReplayMetadata(params.model, {
@@ -3656,8 +2552,7 @@ function createResponsesTransportExecutor(config) {
3656
2552
  return (model, context, options) => {
3657
2553
  const responsesOptions = options;
3658
2554
  const compactRequest = claimResponsesCompactRequest(responsesOptions);
3659
- const eventStream = createAssistantMessageEventStream();
3660
- const stream = eventStream;
2555
+ const { eventStream, stream } = createWritableTransportEventStream();
3661
2556
  (async () => {
3662
2557
  const output = createOpenAIResponsesAssistantOutput(model, config.outputApi);
3663
2558
  let firstEventAbort;
@@ -3673,7 +2568,7 @@ function createResponsesTransportExecutor(config) {
3673
2568
  });
3674
2569
  const websocketSessionPolicy = websocketMode ? turnState?.websocket : void 0;
3675
2570
  const websocketHeaders = websocketMode ? buildOpenAIClientHeaders(model, context, options?.headers, websocketSessionPolicy?.headers, options?.sessionId) : void 0;
3676
- const client = config.createClient(model, context, apiKey, options?.headers, turnState?.headers, options?.sessionId);
2571
+ const client = config.createClient(model, context, apiKey, options?.headers, turnState?.headers, options?.sessionId, compactRequest ? createBoundedOpenAIResponsesCompactionFetch(buildGuardedModelFetch(model)) : void 0);
3677
2572
  const buildRequest = async (replayMode) => {
3678
2573
  let params = config.buildRequest(model, context, responsesOptions, turnState?.metadata, replayMode);
3679
2574
  const nextParams = await options?.onPayload?.(params, model);
@@ -3684,7 +2579,7 @@ function createResponsesTransportExecutor(config) {
3684
2579
  if (options?.openclawCodeModeToolSurface === true) {
3685
2580
  const visibleToolNames = resolveCodeModeResponsesVisibleToolNames(context);
3686
2581
  const allowedHostedToolTypes = responsesOptions?.openclawCodeModeAllowedHostedToolTypes;
3687
- enforceCodeModeResponsesToolSurface(params, visibleToolNames, allowedHostedToolTypes);
2582
+ enforceCodeModeResponsesToolSurface(params, visibleToolNames, allowedHostedToolTypes, codeModeToolSurfaceObserver.get(options));
3688
2583
  assertCodeModeResponsesToolSurface(params, visibleToolNames, allowedHostedToolTypes);
3689
2584
  }
3690
2585
  return params;
@@ -3701,12 +2596,11 @@ function createResponsesTransportExecutor(config) {
3701
2596
  output.usage.output = compacted.usage.output_tokens;
3702
2597
  output.usage.totalTokens = compacted.usage.input_tokens + compacted.usage.output_tokens;
3703
2598
  compactRequest.resolve(compacted);
3704
- stream.push({
3705
- type: "done",
3706
- reason: output.stopReason,
3707
- message: output
2599
+ finalizeTransportStream({
2600
+ stream,
2601
+ output,
2602
+ signal: options?.signal
3708
2603
  });
3709
- stream.end();
3710
2604
  return;
3711
2605
  }
3712
2606
  const sessionId = options?.sessionId;
@@ -3744,7 +2638,7 @@ function createResponsesTransportExecutor(config) {
3744
2638
  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
2639
  let continuationBaseline;
3746
2640
  const createSseStream = async (initialRequest = continuationClaim?.request ?? params, initialAttemptKind = "initial", initialRejectedCompaction) => {
3747
- const { stream: rawResponseStream, response, attempt } = await config.createResponseStream({
2641
+ const { stream: responseStream } = await config.createResponseStream({
3748
2642
  client,
3749
2643
  request: initialRequest,
3750
2644
  requestOptions,
@@ -3753,19 +2647,23 @@ function createResponsesTransportExecutor(config) {
3753
2647
  initialAttemptKind,
3754
2648
  initialRejectedCompaction,
3755
2649
  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();
2650
+ onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, responsesOptions, checkpoint),
2651
+ canRetryStream: () => output.content.length === 0,
2652
+ wrapStream: ({ stream: rawResponseStream, response, attempt }) => {
2653
+ if (continuationClaim) continuationBaseline = attempt.request.previous_response_id ? params : attempt.request;
2654
+ return withProviderResponseHook({
2655
+ stream: observeResponsesStream(rawResponseStream, model, requestStartedAt),
2656
+ signal: firstEvent.signal,
2657
+ abort: firstEvent.abort,
2658
+ hook: createOpenAIProviderAcceptanceHook(options, response, model),
2659
+ onReady: () => {
2660
+ emitModelTransportDebug(log, `[responses] headers provider=${model.provider} api=${model.api} model=${model.id} transport=sse elapsedMs=${Date.now() - requestStartedAt}`);
2661
+ startStream();
2662
+ }
2663
+ });
3767
2664
  }
3768
2665
  });
2666
+ return responseStream;
3769
2667
  };
3770
2668
  let responseStream;
3771
2669
  let finishWebSocket;
@@ -3796,8 +2694,16 @@ function createResponsesTransportExecutor(config) {
3796
2694
  transport = "websocket";
3797
2695
  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
2696
  responseStream = { async *[Symbol.asyncIterator]() {
2697
+ let providerAccepted = false;
3799
2698
  try {
3800
2699
  for await (const event of websocket.stream) {
2700
+ if (!providerAccepted) {
2701
+ providerAccepted = true;
2702
+ await notifyProviderStreamOpened({
2703
+ options,
2704
+ cancelStream: () => websocket.finish({ keep: false })
2705
+ });
2706
+ }
3801
2707
  startStream();
3802
2708
  yield event;
3803
2709
  }
@@ -3848,33 +2754,30 @@ function createResponsesTransportExecutor(config) {
3848
2754
  throw error;
3849
2755
  }
3850
2756
  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
2757
+ finalizeTransportStream({
2758
+ stream,
2759
+ output,
2760
+ signal: options?.signal
3855
2761
  });
3856
- stream.end();
3857
2762
  } catch (error) {
3858
2763
  if (compactRequest) {
3859
2764
  compactRequest.reject(error);
3860
- Object.assign(output, projectProviderError(error, options?.signal));
3861
- stream.push({
3862
- type: "error",
3863
- reason: output.stopReason,
3864
- error: output
2765
+ failTransportStream({
2766
+ stream,
2767
+ output,
2768
+ signal: options?.signal,
2769
+ error
3865
2770
  });
3866
- stream.end();
3867
2771
  return;
3868
2772
  }
3869
2773
  if (error instanceof ResponsesStreamFailure && error.observation) logResponsesFailedNoDetails(error.observation);
3870
2774
  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
2775
+ failTransportStream({
2776
+ stream,
2777
+ output,
2778
+ signal: options?.signal,
2779
+ error
3876
2780
  });
3877
- stream.end();
3878
2781
  } finally {
3879
2782
  continuationClaim?.release();
3880
2783
  firstEventAbort?.dispose();
@@ -3905,23 +2808,20 @@ function createAzureOpenAIResponsesTransportStreamFn() {
3905
2808
  createResponseStream: createResponsesStreamWithEncryptedContentRetry
3906
2809
  });
3907
2810
  }
3908
- function normalizeAzureBaseUrl(baseUrl) {
3909
- return baseUrl.replace(/\/+$/, "");
3910
- }
3911
2811
  function resolveAzureDeploymentName(model) {
3912
2812
  return resolveAzureDeploymentNameFromMap({
3913
2813
  modelId: model.id,
3914
2814
  deploymentMap: process.env.AZURE_OPENAI_DEPLOYMENT_NAME_MAP
3915
2815
  });
3916
2816
  }
3917
- function createAzureOpenAIClient(model, context, apiKey, optionHeaders, turnHeaders) {
3918
- const baseURL = normalizeAzureBaseUrl(model.baseUrl);
2817
+ function createAzureOpenAIClient(model, context, apiKey, optionHeaders, turnHeaders, _sessionId, fetchOverride) {
2818
+ const baseURL = model.baseUrl.replace(/\/+$/, "");
3919
2819
  const clientOptions = {
3920
2820
  apiKey,
3921
2821
  dangerouslyAllowBrowser: true,
3922
2822
  defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders),
3923
2823
  baseURL,
3924
- fetch: buildGuardedModelFetch(model),
2824
+ fetch: fetchOverride ?? buildGuardedModelFetch(model),
3925
2825
  ...buildOpenAISdkClientOptions(model)
3926
2826
  };
3927
2827
  if (isOpenAICompatibleAzureResponsesBaseUrl(baseURL)) return new OpenAI(clientOptions);
@@ -3967,10 +2867,116 @@ const responsesTesting = {
3967
2867
  if (process.env.VITEST || false) globalThis.openclawOpenAIResponsesTransportTestApi = responsesTesting;
3968
2868
  //#endregion
3969
2869
  //#region packages/ai/src/transports/provider-compaction-replay.ts
2870
+ function isAssistantReplayMessage(message) {
2871
+ return message.role === "assistant";
2872
+ }
2873
+ /** Resolve from prepared transport facts; never retain or return credential material. */
2874
+ function resolveCompactionReplayEligibility(model, options) {
2875
+ if (OPENAI_RESPONSES_APIS.has(model.api)) return true;
2876
+ return Boolean(options.apiKey?.trim()) && resolveAnthropicServerCompactionPlan(model, options.extraParams, options.apiKey).enabled;
2877
+ }
2878
+ function resolveCompactionSource(messages, model, identity) {
2879
+ if (identity.enabled === false) return;
2880
+ const assistants = messages.filter(isAssistantReplayMessage);
2881
+ const selected = (() => {
2882
+ if (OPENAI_RESPONSES_APIS.has(model.api)) {
2883
+ const responses = resolveNewestOpenAIResponsesCompactionReplay(assistants, model, identity);
2884
+ return responses ? {
2885
+ family: "responses",
2886
+ ...responses
2887
+ } : void 0;
2888
+ }
2889
+ if (identity.enabled !== true) return;
2890
+ const anthropic = resolveNewestAnthropicCompaction(assistants, model, identity);
2891
+ return anthropic ? {
2892
+ family: "anthropic",
2893
+ ...anthropic
2894
+ } : void 0;
2895
+ })();
2896
+ if (!selected) return;
2897
+ const owner = assistants.find((message) => message === selected.owner);
2898
+ return owner ? {
2899
+ ...selected,
2900
+ owner
2901
+ } : void 0;
2902
+ }
2903
+ /** Manual recovery uses the durable client compactor, never a guessed retained-user prefix. */
2904
+ function requiresCompactionReplayRefresh(messages, model, identity) {
2905
+ const checkpoint = resolveCompactionSource(messages, model, identity);
2906
+ return checkpoint?.family === "responses" && checkpoint.mode === "refresh-required";
2907
+ }
2908
+ /** Carry a checkpoint immediately after reference-preserving history limiting, before repair. */
2909
+ function preserveCompactionReplayWindow(source, windowed, model, identity) {
2910
+ const checkpoint = resolveCompactionSource(source, model, identity);
2911
+ if (!checkpoint || windowed.some((message) => message === checkpoint.owner)) return windowed;
2912
+ const owner = checkpoint.owner;
2913
+ const replay = checkpoint.owner.providerReplay;
2914
+ const providerReplay = replay?.type === "openai-responses-retained-compaction" ? replay : {
2915
+ ...replay,
2916
+ replayIndex: 0
2917
+ };
2918
+ const suffix = new Set(source.slice(source.indexOf(owner) + 1));
2919
+ return [{
2920
+ ...owner,
2921
+ content: [],
2922
+ providerReplay
2923
+ }, ...windowed.filter((message) => suffix.has(message))];
2924
+ }
2925
+ function estimateResponsesWindow(checkpoint, estimate) {
2926
+ return checkpoint.output.reduce((tokens, entry) => {
2927
+ if (entry.type === "compaction") {
2928
+ const { encrypted_content, ...metadata } = entry;
2929
+ return tokens + estimate.text(encrypted_content) + estimate.json(metadata);
2930
+ }
2931
+ const { content, ...metadata } = entry;
2932
+ return tokens + estimate.json(metadata) + content.reduce((sum, block) => {
2933
+ if (block.type === "input_text") {
2934
+ const { text, ...fields } = block;
2935
+ return sum + estimate.text(text) + estimate.json(fields);
2936
+ }
2937
+ if (block.type === "input_image") {
2938
+ const { image_url: _imageUrl, ...fields } = block;
2939
+ return sum + estimate.image() + estimate.json(block.image_url?.startsWith("data:") ? fields : block);
2940
+ }
2941
+ return sum + estimate.json(block);
2942
+ }, 0);
2943
+ }, 0);
2944
+ }
2945
+ /** Estimate the canonical prefix and its tail once, independent of unbound usage snapshots. */
2946
+ function resolveCompactionReplayPressure(messages, model, identity, estimate) {
2947
+ const checkpoint = resolveCompactionSource(messages, model, identity);
2948
+ if (!checkpoint) return;
2949
+ if (checkpoint.family === "responses" && checkpoint.mode === "refresh-required") throw new CompactionReplayRefreshRequiredError();
2950
+ const ownerIndex = messages.findIndex((message) => message === checkpoint.owner);
2951
+ const owner = messages[ownerIndex];
2952
+ if (!owner) return;
2953
+ const prefixTokens = checkpoint.family === "anthropic" ? estimate.text(checkpoint.summary) : checkpoint.mode === "complete-window" ? estimateResponsesWindow(checkpoint, estimate) : estimate.text(checkpoint.item.encrypted_content);
2954
+ const { contextUsage: _staleContextUsage, ...usage } = checkpoint.owner.usage;
2955
+ const tail = [];
2956
+ for (const message of messages.slice(ownerIndex + 1)) {
2957
+ if (!isAssistantReplayMessage(message) || message.usage.contextUsage === void 0) {
2958
+ tail.push(message);
2959
+ continue;
2960
+ }
2961
+ const { contextUsage: _unboundContextUsage, ...billedUsage } = message.usage;
2962
+ tail.push({
2963
+ ...message,
2964
+ usage: billedUsage
2965
+ });
2966
+ }
2967
+ return {
2968
+ messages: [{
2969
+ ...owner,
2970
+ content: checkpoint.owner.content.slice(checkpoint.replayIndex),
2971
+ usage
2972
+ }, ...tail],
2973
+ prefixTokens
2974
+ };
2975
+ }
3970
2976
  /** Whether provider replay state is a prefix-bound server compaction checkpoint. */
3971
2977
  function isCompactionReplayCheckpoint(replay) {
3972
2978
  const type = replay && typeof replay === "object" ? replay.type : void 0;
3973
- return type === "anthropic-compaction" || type === "openai-responses-compaction";
2979
+ return type === "anthropic-compaction" || type === "openai-responses-compaction" || type === "openai-responses-retained-compaction";
3974
2980
  }
3975
2981
  /** Strip prefix-bound checkpoints after local history rewrites. */
3976
2982
  function stripCompactionReplayCheckpoint(message) {
@@ -3991,8 +2997,9 @@ function replaceCompactionReplayOwnerContent(message, content) {
3991
2997
  };
3992
2998
  const replay = message.providerReplay;
3993
2999
  if (!isCompactionReplayCheckpoint(replay)) return next;
3000
+ if (replay.type === "openai-responses-retained-compaction") return next;
3994
3001
  const replayIndex = replay.replayIndex ?? 0;
3995
- if (content.length === 0 || replayIndex > message.content.length) return stripCompactionReplayCheckpoint(next);
3002
+ if (content.length === 0 && message.content.length > 0 || replayIndex > message.content.length) return stripCompactionReplayCheckpoint(next);
3996
3003
  let sourceIndex = 0;
3997
3004
  let nextReplayIndex = 0;
3998
3005
  if (!content.every((block) => {
@@ -4261,4 +3268,4 @@ function prepareModelForSimpleCompletion(params) {
4261
3268
  return applyProviderSimpleCompletionWrapper(apiRegistry, model, cfg);
4262
3269
  }
4263
3270
  //#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 };
3271
+ export { CompactionReplayRefreshRequiredError, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, applyAnthropicCacheControlToMessages, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, captureOpenAIResponsesCompaction, coerceTransportToolCallArguments, copyProviderAcceptanceObserver, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIProviderAcceptanceHook, createOpenAIResponseHook, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, filterCodeModePayloadTools, finalizeTerminalToolCallArguments, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, googleFlashSupportsMinimalThinking, hasOpenAICompatibleConversationTurn, isCodeModeModelVisibleToolName, isCompactionReplayCheckpoint, isOpenAICodexResponsesModel, isOpenAICompletionsThinkingEnabled, log, measureUtf8AppendBytes, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, notifyProviderHttpMetadata, notifyProviderHttpResponse, notifyProviderStreamOpened, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, parseOpenAICompletionsUsage, parseTerminalToolCallArguments, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, preserveCompactionReplayWindow, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, readOpenAICompletionsReasoningBatch, replaceCompactionReplayOwnerContent, requestPreparedOpenAIResponsesCompaction, requiresCompactionReplayRefresh, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveAnthropicServerCompactionPlan, resolveCodeModeResponsesVisibleToolNames, resolveCompactionReplayEligibility, resolveCompactionReplayPressure, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAIClientBaseUrl, resolveOpenAICompletionsCompat, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesCompactEndpointPlan, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIResponsesServerCompactionPlan, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompactionReplayCheckpoint, stripCompactionReplayCheckpointInPlace, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend, withProviderAcceptanceObserver, withProviderResponseHook };