@openclaw/ai 2026.9.2 → 2026.9.4

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 (115) hide show
  1. package/README.md +3 -2
  2. package/dist/anthropic-C4Qu4H0Z.mjs +377 -0
  3. package/dist/{anthropic-payload-policy-d46X2pR0.d.mts → anthropic-payload-policy-BZ8umAbk.d.mts} +16 -6
  4. package/dist/{anthropic-compaction-replay-DB2FGLQc.mjs → anthropic-stream-reducer-CILWF7JD.mjs} +931 -184
  5. package/dist/{api-registry-DWtPjzyn.d.mts → api-registry-ByUwIR0e.d.mts} +2 -2
  6. package/dist/assistant-output-tLt4H-iQ.mjs +16 -0
  7. package/dist/assistant-text-phase-C20rxWwP.mjs +55 -0
  8. package/dist/{azure-openai-responses-C5bZRfAP.mjs → azure-openai-responses-BAlqlKKc.mjs} +5 -5
  9. package/dist/{base64-CEFBpSkN.mjs → base64-D-su8YVo.mjs} +1 -27
  10. package/dist/{diagnostics-DfFyKeX_.mjs → diagnostics-QuErwCIl.mjs} +96 -21
  11. package/dist/diagnostics.d.mts +3 -1
  12. package/dist/diagnostics.mjs +3 -3
  13. package/dist/{event-stream-BhT5T1Ay.d.mts → event-stream-Bt5Y4Pav.d.mts} +11 -3
  14. package/dist/event-stream-C3WGFsum.d.mts +1 -0
  15. package/dist/{event-stream-BgDvQeum.mjs → event-stream-D8PARQfL.mjs} +45 -1
  16. package/dist/event-stream.d.mts +2 -2
  17. package/dist/event-stream.mjs +1 -1
  18. package/dist/{github-copilot-headers-NCJtz9i0.mjs → github-copilot-headers-B37TB3rB.mjs} +3 -10
  19. package/dist/github-copilot-request-facts-BTEBMeOv.mjs +16 -0
  20. package/dist/{google-4qeuE8iX.mjs → google-DPBAOaOW.mjs} +10 -10
  21. package/dist/google-messages-6JkpHrhJ.mjs +448 -0
  22. package/dist/google-shared-BvBeW9aq.mjs +185 -0
  23. package/dist/{google-vertex-O9BcnB6X.mjs → google-vertex-k-TMCAYD.mjs} +7 -6
  24. package/dist/{host-DjzGmdZ2.d.mts → host-4atIX-2V.d.mts} +5 -3
  25. package/dist/{host-CEvLw30U.mjs → host-B8YfDGd4.mjs} +181 -41
  26. package/dist/host-policy-Zcg_cNz8.mjs +37 -0
  27. package/dist/{index-FnHM2FcI.d.mts → index-DdD3qerf.d.mts} +4 -4
  28. package/dist/index.d.mts +7 -7
  29. package/dist/index.mjs +7 -6
  30. package/dist/internal/anthropic.d.mts +7 -7
  31. package/dist/internal/anthropic.mjs +4 -4
  32. package/dist/internal/google-model-family.d.mts +5 -0
  33. package/dist/internal/google-model-family.mjs +15 -0
  34. package/dist/internal/openai-responses-payload-policy.d.mts +3 -3
  35. package/dist/internal/openai-responses-payload-policy.mjs +3 -2
  36. package/dist/internal/openai.d.mts +8 -103
  37. package/dist/internal/openai.mjs +9 -10
  38. package/dist/internal/retry-after.d.mts +2 -4
  39. package/dist/internal/retry-after.mjs +57 -8
  40. package/dist/internal/runtime.d.mts +43 -7
  41. package/dist/internal/runtime.mjs +6 -7
  42. package/dist/internal/shared.d.mts +43 -3
  43. package/dist/internal/shared.mjs +5 -4
  44. package/dist/internal/tool-schema.d.mts +63 -0
  45. package/dist/internal/tool-schema.mjs +3 -0
  46. package/dist/{mistral-Tb6oalqH.mjs → mistral-CxUZ1jUb.mjs} +10 -37
  47. package/dist/model-transport-url-DKocrEsb.d.mts +28 -0
  48. package/dist/{openai-chatgpt-responses-yUXjPNfu.mjs → openai-chatgpt-responses-CgO6kZfo.mjs} +50 -41
  49. package/dist/{openai-completions-compat-CpjYUArk.d.mts → openai-completions-compat-eHgh5UPE.d.mts} +26 -4
  50. package/dist/{openai-completions-stream-BsrBe3Gg.mjs → openai-completions-stream-Da2vvl-S.mjs} +654 -453
  51. package/dist/openai-completions-yJuk7eis.mjs +187 -0
  52. package/dist/openai-prompt-cache-B4eYo2-I.d.mts +16 -0
  53. package/dist/openai-prompt-cache-Bds-n_9Q.mjs +220 -0
  54. package/dist/openai-provider-client-S2gCrM2Z.mjs +24 -0
  55. package/dist/{openai-responses-CCL41ALM.mjs → openai-responses-DaYwH05E.mjs} +14 -29
  56. package/dist/{openai-responses-compaction-window-BMVHFOtq.mjs → openai-responses-compaction-window-CIhBAkkq.mjs} +6 -246
  57. package/dist/{openai-responses-contracts-rF5DDRNS.d.mts → openai-responses-contracts-BjBAqAg_.d.mts} +5 -38
  58. package/dist/openai-responses-contracts-DDOHA62Y.mjs +245 -0
  59. package/dist/{openai-responses-prompt-observer-internal-D0bhBfgL.mjs → openai-responses-prompt-observer-internal-f8J7wpsk.mjs} +3 -3
  60. package/dist/{openai-responses-shared-Bmma_3Qc.mjs → openai-responses-shared-B8RdBPCv.mjs} +47 -118
  61. package/dist/openai-tool-projection-793cE3QX.d.mts +37 -0
  62. package/dist/{openai-tool-schema-_pTAJqKF.mjs → openai-tool-schema-CzjyYXun.mjs} +38 -556
  63. package/dist/openai-tool-schema-ynZBgqW-.d.mts +38 -0
  64. package/dist/openai-transport-params-9aPuV5YY.mjs +675 -0
  65. package/dist/positive-integer-41zhOdcV.mjs +8 -0
  66. package/dist/{provider-error-9TraxGvt.mjs → provider-error-BA-v_tKd.mjs} +70 -11
  67. package/dist/{provider-options-Bcc_p-TU.d.mts → provider-options-Ceqv1OKk.d.mts} +4 -39
  68. package/dist/{provider-replay-context-BuSUaAk5.mjs → provider-replay-context-CJ_YvcEW.mjs} +1 -1
  69. package/dist/{provider-transcript-transform-BaMbI1hr.mjs → provider-transcript-transform-V5YzU9zh.mjs} +1 -1
  70. package/dist/provider-transport-turn-state-D5EXOFL2.mjs +42 -0
  71. package/dist/provider-types-CVjKjsuq.d.mts +29 -0
  72. package/dist/provider-types.d.mts +6 -31
  73. package/dist/providers.d.mts +2 -2
  74. package/dist/providers.mjs +11 -11
  75. package/dist/{reasoning-tag-text-partitioner-DLCNXki6.mjs → reasoning-tag-text-partitioner-BcR5pztD.mjs} +19 -19
  76. package/dist/record-coerce-DwRYMj3t.mjs +32 -0
  77. package/dist/retry-after-CdCURCVg.d.mts +15 -0
  78. package/dist/session-affinity-Bcunsn4I.mjs +23 -0
  79. package/dist/{simple-options-BjHCCh4v.mjs → simple-options-BQbb4yQL.mjs} +24 -5
  80. package/dist/src-DDmEryvj.mjs +2 -0
  81. package/dist/{stream-first-event-timeout-DcNjoFQE.mjs → stream-first-event-timeout-2hfrquuz.mjs} +1 -1
  82. package/dist/string-coerce-fsri9iCu.mjs +34 -0
  83. package/dist/{string-normalization--fwJ4S2q.mjs → string-normalization-CmLIasuf.mjs} +1 -1
  84. package/dist/{tool-schema-json-projection-mJhXDcyz.mjs → tool-schema-json-projection-ClptDdAO.mjs} +2 -38
  85. package/dist/{transport-stream-shared-xnaqxmbP.d.mts → transport-stream-shared-DNvmoWnv.d.mts} +20 -36
  86. package/dist/{transport-stream-shared-CZqMhfIw.mjs → transport-stream-shared-zHll9BxO.mjs} +225 -13
  87. package/dist/transport-utils-zrYjICLZ.mjs +118 -0
  88. package/dist/transports.d.mts +137 -193
  89. package/dist/transports.mjs +204 -1334
  90. package/dist/types-DlfwzH3T.d.mts +1 -0
  91. package/dist/types-LFWwv0cF.mjs +8 -0
  92. package/dist/{types-CJ1-Ht7A.d.mts → types-Ntv5z2g2.d.mts} +74 -57
  93. package/dist/types.d.mts +6 -6
  94. package/dist/types.mjs +6 -5
  95. package/dist/{src-2qBGKg8O.mjs → usage-cost-BNWbbXav.mjs} +0 -1
  96. package/dist/utf16-slice-CvGodqok.mjs +29 -0
  97. package/dist/{validation-AKZBDGQd.d.mts → validation-B0t_G2H6.d.mts} +1 -1
  98. package/dist/{validation-CJZtym2g.mjs → validation-BDzVDnTs.mjs} +9 -1
  99. package/dist/validation.d.mts +1 -1
  100. package/dist/validation.mjs +1 -1
  101. package/package.json +13 -3
  102. package/dist/anthropic-BDdqdVLK.mjs +0 -886
  103. package/dist/event-stream-zctLx0yr.d.mts +0 -1
  104. package/dist/google-shared-CWeG8RIl.mjs +0 -636
  105. package/dist/google-thinking-level-C-V3tecN.mjs +0 -9
  106. package/dist/hash-CHgqbJmD.mjs +0 -16
  107. package/dist/json-parse-BuAJEbdW.mjs +0 -146
  108. package/dist/openai-completions-BIUV3RDT.mjs +0 -403
  109. package/dist/openai-prompt-cache-CGnVB74a.mjs +0 -21
  110. package/dist/openai-prompt-cache-CNoIfHYC.d.mts +0 -16
  111. package/dist/sanitize-unicode-D6xUvZaS.mjs +0 -83
  112. package/dist/transport-utils-7il795_9.mjs +0 -138
  113. package/dist/types-3Lnm-QSJ.d.mts +0 -1
  114. package/dist/types-BDdaOVi2.mjs +0 -6
  115. package/dist/utf16-slice-qz3nsy87.mjs +0 -84
@@ -1,31 +1,34 @@
1
- import { _ as supportsClaudeAdaptiveThinking, b as supportsClaudeNativeXhighEffort, h as resolveClaudeSonnet5ModelIdentity, m as resolveClaudeOpus5ModelIdentity } from "./src-2qBGKg8O.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-D6xUvZaS.mjs";
4
- import { S as usesClaudeStreamingRefusalContract, _ as prepareClaudeNoPrefillRequestContext, a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, f as ANTHROPIC_CLAUDE_CODE_BILLING_SYSTEM_BLOCK, g as mapAnthropicStopReason, h as defaultsClaudeAdaptiveThinking, m as applyClaudeRequestContract, n as getAiTransportHost, p as ANTHROPIC_CLAUDE_CODE_VERSION, r as resolveAiTransportHeaderSentinels, s as extractToolResultBlockText, v as requiresClaudeAdaptiveThinking, x as usesClaudeFable5MessagesContract, y as resolveAnthropicThinkingEffort } from "./host-CEvLw30U.mjs";
5
- import { i as stableStringify } from "./provider-error-9TraxGvt.mjs";
6
- import { r as toErrorObject } from "./diagnostics-DfFyKeX_.mjs";
7
- import { a as asNonNegativeFiniteNumber } from "./base64-CEFBpSkN.mjs";
8
- import { n as uniqueStrings } from "./string-normalization--fwJ4S2q.mjs";
9
- import { r as resolveOpenAIResponsesCacheParams } from "./openai-prompt-cache-CGnVB74a.mjs";
10
- import { A as createAnthropicInlineImageBudget, B as resolveAnthropicContextManagementBetaHeader, C as ANTHROPIC_SERVER_SIDE_FALLBACKS, D as readAnthropicFallbackBoundary, E as applyAnthropicFallbackBoundary, F as applyAnthropicEphemeralCacheControlMarkers, G as omitFoundryBearerCredentialHeaders, H as resolveAnthropicPayloadPolicy, I as applyAnthropicPayloadPolicyToParams, K as usesFoundryBearerAuth, L as isAnthropicServerToolClearingEnabled, M as resolveAnthropicImageMediaType, N as applyAnthropicCacheControlToMessages, O as resolveAnthropicFallbackServingModelCost, P as applyAnthropicContextManagementToRequest, R as isDirectAnthropicModel, S as readAnthropicInputTransformations, U as resolveAnthropicServerCompactionPlan, V as resolveAnthropicEphemeralCacheControl, W as isAnthropicOAuthApiKey, _ as toClaudeCodeToolName, a as suppressAnthropicCompaction, b as findActiveAnthropicToolTurnAssistantIndex, f as normalizeAnthropicToolCallId, g as resolveOriginalAnthropicToolName, h as reconcileAnthropicToolChoice, i as resolveNewestAnthropicCompaction, j as normalizeAnthropicInlineContent, k as applyAnthropicRefusal, m as projectAnthropicTools, n as createCompactionCapture, o as applyAnthropicMessageDeltaUsage, p as normalizeAnthropicToolChoice, r as isAnthropicReplayRejection, s as applyAnthropicMessageStartUsage, t as buildAnthropicReplayPlan, v as ANTHROPIC_OMITTED_REASONING_TEXT, w as ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, x as logAnthropicThinkingDrops, y as applyAnthropicThinkingBindingControls, z as logAnthropicContextEdits } from "./anthropic-compaction-replay-DB2FGLQc.mjs";
1
+ import { _ as supportsClaudeAdaptiveThinking, h as resolveClaudeSonnet5ModelIdentity, m as resolveClaudeOpus5ModelIdentity } from "./usage-cost-BNWbbXav.mjs";
2
+ import { n as normalizeLowercaseStringOrEmpty, t as hasNonEmptyString } from "./string-coerce-fsri9iCu.mjs";
3
+ import { E as resolveAnthropicThinkingEffort, O as usesClaudeFable5MessagesContract, S as defaultsClaudeAdaptiveThinking, T as requiresClaudeAdaptiveThinking, b as ANTHROPIC_CLAUDE_CODE_VERSION, k as usesClaudeStreamingRefusalContract, n as getAiTransportHost, r as resolveAiTransportHeaderSentinels, w as prepareClaudeNoPrefillRequestContext, x as applyClaudeRequestContract } from "./host-B8YfDGd4.mjs";
4
+ import { o as isRecord } from "./record-coerce-DwRYMj3t.mjs";
5
+ import { i as stableStringify } from "./provider-error-BA-v_tKd.mjs";
6
+ import { a as isNativeOpenAIEndpoint, c as resolveOpenAIPromptCacheKeySupport, i as detectOpenAICompletionsCompat, l as usesNativeOpenAICodexResponsesBackend, o as isOpenAICodexResponsesModel, r as resolveOpenAIPromptCacheParams, s as resolveOpenAICompletionsCompat } from "./openai-prompt-cache-Bds-n_9Q.mjs";
7
+ import { a as resolveModelSseDebugMode, i as resolveModelPayloadDebugMode, n as formatModelTransportDebugUrl, r as emitModelTransportDebug, t as formatModelTransportDebugBaseUrl, u as toErrorObject } from "./diagnostics-QuErwCIl.mjs";
8
+ import { a as readResponseTextSnippet, i as isCodeModeModelVisibleToolName, n as createAbortError$1, s as resolveModelHeaderSentinels$1, t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE } from "./transport-utils-zrYjICLZ.mjs";
9
+ import { parseRetryAfterHeadersSeconds } from "./internal/retry-after.mjs";
10
+ import { i as resolveProviderEndpoint, r as resolveOpenAIStrictToolSetting, s as transformTransportMessages, t as buildGuardedModelFetch } from "./host-policy-Zcg_cNz8.mjs";
11
+ import { B as logAnthropicContextEdits, C as applyAnthropicThinkingBindingControls, D as ANTHROPIC_SERVER_SIDE_FALLBACKS, F as applyAnthropicPayloadPolicyToParams, G as resolveAnthropicServerCompactionPlan, H as resolveAnthropicContextManagementBetaHeader, I as applyAnthropicRequestCacheControl, J as usesFoundryBearerAuth, K as isAnthropicOAuthApiKey, L as buildAnthropicSystemBlocks, N as applyAnthropicContextManagementToRequest, O as ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, P as applyAnthropicEphemeralCacheControlMarkers, R as isAnthropicServerToolClearingEnabled, U as resolveAnthropicEphemeralCacheControl, V as resolveAnthropicCacheOptions, W as resolveAnthropicPayloadPolicy, d as convertAnthropicTools, f as buildAnthropicReplayPlan, g as normalizeAnthropicToolCallId, h as suppressAnthropicCompaction, l as buildAnthropicGenerationParams, m as resolveNewestAnthropicCompaction, p as isAnthropicReplayRejection, q as omitFoundryBearerCredentialHeaders, t as consumeAnthropicStream, u as convertAnthropicMessages, z as isDirectAnthropicModel } from "./anthropic-stream-reducer-CILWF7JD.mjs";
11
12
  import { t as resolveCacheRetention } from "./cache-retention-0x979a5V.mjs";
12
- import { a as codeModeToolSurfaceObserver, d as stripSystemPromptCacheBoundary, m as sortPromptCacheToolsByName, o as reasoningTagTextPolicy, t as adjustMaxTokensForThinking } from "./simple-options-BjHCCh4v.mjs";
13
- import { a as resolveProviderEndpoint, c as transformTransportMessages, i as resolveOpenAIStrictToolSetting, n as buildGuardedModelFetch } from "./tool-schema-json-projection-mJhXDcyz.mjs";
14
- import { a as isGoogleGemini3FlashModel, c as parseRetryAfterSeconds, f as resolveModelHeaderSentinels$1, i as isCodeModeModelVisibleToolName, l as readResponseTextSnippet, m as supportsModelTools, n as createAbortError$1, o as isGoogleGemini3ProModel, p as sha256Hex, r as estimateStringChars, t as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, u as redactIdentifier } from "./transport-utils-7il795_9.mjs";
13
+ import { a as codeModeToolSurfaceObserver, m as stripSystemPromptCacheBoundary, o as reasoningTagTextPolicy, t as adjustMaxTokensForThinking, v as sortPromptCacheToolsByName } from "./simple-options-BQbb4yQL.mjs";
14
+ import { C as readOpenAICompletionsContentDeltas, D as throwIfModelStreamAborted, E as resolvePromptCacheKey, O as redactIdentifier, S as parseOpenAICompletionsUsage, T as resolveOpenAIClientBaseUrl, _ as createOpenAIProviderAcceptanceHook, a as enforceCodeModeResponsesToolSurface, b as log, c as readCodeModePayloadToolName, d as resolveOpenAIReasoningEffortMap, f as projectOpenAITools, g as createModelStreamCooperativeScheduler, h as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, i as buildOpenAISdkRequestOptions, k as sha256Hex, l as resolveCodeModeResponsesVisibleToolNames, m as reconcileOpenAIResponsesToolChoice, n as buildOpenAIClientHeaders, o as filterCodeModePayloadTools, r as buildOpenAISdkClientOptions, s as getCompat, t as assertCodeModeResponsesToolSurface, u as resolveOpenAIStrictToolFlagWithDiagnostics, v as createOpenAIResponseHook, w as readOpenAICompletionsReasoningBatch, x as measureUtf8AppendBytes, y as isOpenAICompletionsThinkingEnabled } from "./openai-transport-params-9aPuV5YY.mjs";
15
15
  import { n as getEnvApiKey } from "./env-api-keys-bktO00EJ.mjs";
16
- import { S as quoteUnsafeIntegerLiterals, _ as transportAbortError, a as createWritableTransportEventStream, b as parseJsonObjectPreservingUnsafeIntegers, c as finalizeTransportStream, d as notifyProviderHttpMetadata, f as notifyProviderHttpResponse, g as sanitizeTransportPayloadText, h as sanitizeNonEmptyTransportPayloadText, i as createEmptyTransportUsage, l as mergeTransportHeaders, m as parseTerminalToolCallArguments, n as coerceTransportToolCallArguments, o as failTransportStream, p as notifyProviderStreamOpened, r as copyProviderAcceptanceObserver, s as finalizeTerminalToolCallArguments, t as assignTransportErrorDetails, u as mergeTransportMetadata, v as withProviderAcceptanceObserver, x as parseJsonPreservingUnsafeIntegers, y as withProviderResponseHook } from "./transport-stream-shared-CZqMhfIw.mjs";
17
- import { C as createDeepSeekTextFilter, E as tagUnresolvedTextAsCommentary, S as shouldOmitOllamaCompatResponseFormat, T as tagPendingCommentaryText, _ as hasToolCallHistory, a as buildOpenAISdkClientOptions, b as resolveOpenAICompletionsCompat, c as filterCodeModePayloadTools, d as readCodeModePayloadToolName, f as resolveCodeModeResponsesVisibleToolNames, g as convertMessages, h as resolveOpenAIReasoningEffortMap, i as buildOpenAIClientHeaders, l as getCompat, m as usesNativeOpenAICodexResponsesBackend, n as shouldEmitOpenAICompletionsReasoning, o as buildOpenAISdkRequestOptions, p as resolveOpenAIStrictToolFlagWithDiagnostics, r as assertCodeModeResponsesToolSurface, s as enforceCodeModeResponsesToolSurface, t as processCompletionsStream, u as isOpenAICodexResponsesModel, v as finalizeOpenAICompletionsToolCalls, x as resolveOpenAICompletionsResponseFormat, y as detectOpenAICompletionsCompat } from "./openai-completions-stream-BsrBe3Gg.mjs";
16
+ import { C as quoteUnsafeIntegerLiterals, S as parseJsonPreservingUnsafeIntegers, _ as sanitizeTransportPayloadText, a as createEmptyTransportUsage, b as withProviderResponseHook, c as finalizeTerminalToolCallArguments, d as mergeTransportMetadata, f as notifyProviderHttpMetadata, g as sanitizeNonEmptyTransportPayloadText, h as parseTerminalToolCallArguments, i as copyProviderAcceptanceObserver, l as finalizeTransportStream, m as notifyProviderStreamOpened, n as assignTransportErrorDetails, o as createWritableTransportEventStream, p as notifyProviderHttpResponse, r as coerceTransportToolCallArguments, s as failTransportStream, t as IncompleteToolCallError, u as mergeTransportHeaders, v as transportAbortError, x as parseJsonObjectPreservingUnsafeIntegers, y as withProviderAcceptanceObserver } from "./transport-stream-shared-zHll9BxO.mjs";
18
17
  import { t as createDeferredEventBuffer } from "./deferred-event-buffer-DAvyP7qA.mjs";
19
- import { r as parseStreamingJson, t as createToolArgumentPreviewSchedule } from "./json-parse-BuAJEbdW.mjs";
20
- import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
21
- import { t as googleFlashSupportsMinimalThinking } from "./google-thinking-level-C-V3tecN.mjs";
22
- import { $ as resolveModelPayloadDebugMode, B as resolveNextResponsesEncryptedContentAttempt, C as summarizeResponsesPayload, G as responsesInputFingerprint, H as convertResponsesMessages, J as captureOpenAIResponsesCompaction, K as CompactionReplayRefreshRequiredError, L as createResponsesStreamWithEncryptedContentRetry, Q as emitModelTransportDebug, R as isInvalidEncryptedContentError, S as summarizeResponsesFailedNoDetailsObservation, U as createOpenAIResponsesAssistantOutput, V as buildResponsesInputMessage, W as recordResponsesInputReplay, X as suppressOpenAIResponsesCompaction, Y as resolveNewestOpenAIResponsesCompactionReplay, Z as resolveReplayableResponsesMessageId, _ as normalizeResponsesFailedEvent, b as stringifyRedactedPayload, et as resolveModelSseDebugMode, g as logResponsesFailedNoDetails, h as buildResponsesFailedNoDetailsObservation, l as processResponsesStream, m as ResponsesStreamFailure, n as applyResponsesServiceTierPricing, p as observeResponsesStream, q as buildOpenAIResponsesReasoningReplayMetadata, v as safeDebugValue, w as summarizeResponsesTools, x as summarizeOpenAITransportError, y as stringifyRedactedEvent, z as resolveAzureOpenAIApiVersion } from "./openai-responses-shared-Bmma_3Qc.mjs";
23
- import { A as readOpenAICompletionsReasoningBatch, C as createOpenAIProviderAcceptanceHook, D as measureUtf8AppendBytes, E as log, M as resolvePromptCacheKey, N as throwIfModelStreamAborted, O as parseOpenAICompletionsUsage, S as createModelStreamCooperativeScheduler, T as isOpenAICompletionsThinkingEnabled, b as reconcileOpenAIResponsesToolChoice, j as resolveOpenAIClientBaseUrl, k as readOpenAICompletionsContentDeltas, r as normalizeOpenAIStrictToolParameters, v as projectOpenAITools, w as createOpenAIResponseHook, x as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, y as reconcileOpenAICompletionsToolChoice } from "./openai-tool-schema-_pTAJqKF.mjs";
24
- import { i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-DcNjoFQE.mjs";
25
- import { C as isOpenAIGpt54MiniModel, E as normalizeOpenAIReasoningEffort, O as resolveOpenAIReasoningEffortForModel, T as isOpenAIGpt56Model, _ as OpenAIResponsesWebSocketPostDispatchError, a as applyOpenAIResponsesPayloadPolicy, c as resolveOpenAIResponsesServerCompactionPlan, d as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS, f as OPENAI_RESPONSES_APIS, i as sanitizeResponsesImagePayload, j as supportsOpenAITemperature, l as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, n as isOpenAIResponsesCompactionOutput, o as resolveOpenAIResponsesCompactEndpointPlan, s as resolveOpenAIResponsesPayloadPolicy, t as createBoundedOpenAIResponsesCompactionFetch, v as OpenAIResponsesWebSocketPreDispatchError, w as isOpenAIGpt55Model, x as parseOpenAIResponsesWebSocketServerError, y as OpenAIResponsesWebSocketSafeRetryError } from "./openai-responses-compaction-window-BMVHFOtq.mjs";
18
+ import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-CJ_YvcEW.mjs";
19
+ import { a as tagUnresolvedTextAsCommentary } from "./assistant-text-phase-C20rxWwP.mjs";
20
+ import { t as createAssistantOutput } from "./assistant-output-tLt4H-iQ.mjs";
21
+ import { n as resolveOpencodeSessionHeaders } from "./session-affinity-Bcunsn4I.mjs";
22
+ import { c as flattenCompletionMessagesToStringContent, d as canonicalizeMaxTokensParam, f as resolveMaxTokensParam, l as stripCompletionMessagesToRoleContent, n as shouldEmitOpenAICompletionsReasoning, o as isAzureOpenAICompatibleHost, p as createDeepSeekTextFilter, r as buildOpenAICompletionsParams, s as finalizeOpenAICompletionsToolCalls, t as processCompletionsStream, u as applyCompletionsAnthropicCacheControl } from "./openai-completions-stream-Da2vvl-S.mjs";
23
+ import { a as googleFlashSupportsMinimalThinking, i as consumeGoogleGenerateContentStream, n as projectGoogleMessages, r as requiresGoogleToolCallId, t as convertGoogleTools } from "./google-messages-6JkpHrhJ.mjs";
24
+ import { i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-2hfrquuz.mjs";
25
+ import { C as supportsOpenAITemperature, b as resolveOpenAIReasoningEffortForModel, d as OpenAIResponsesWebSocketSafeRetryError, i as OPENAI_RESPONSES_APIS, l as OpenAIResponsesWebSocketPostDispatchError, p as parseOpenAIResponsesWebSocketServerError, r as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS, t as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, u as OpenAIResponsesWebSocketPreDispatchError, v as normalizeOpenAIReasoningEffort } from "./openai-responses-contracts-DDOHA62Y.mjs";
26
+ import { r as resolveProviderTransportTurnState, t as filterProviderTurnHeadersForExplicitOpencodeSession } from "./provider-transport-turn-state-D5EXOFL2.mjs";
27
+ import { a as applyOpenAIResponsesPayloadPolicy, c as resolveOpenAIResponsesServerCompactionPlan, i as sanitizeResponsesImagePayload, n as isOpenAIResponsesCompactionOutput, o as resolveOpenAIResponsesCompactEndpointPlan, s as resolveOpenAIResponsesPayloadPolicy, t as createBoundedOpenAIResponsesCompactionFetch } from "./openai-responses-compaction-window-CIhBAkkq.mjs";
28
+ import { B as responsesInputFingerprint, F as resolveNextResponsesEncryptedContentAttempt, G as resolveNewestOpenAIResponsesCompactionReplay, H as buildOpenAIResponsesReasoningReplayMetadata, I as buildResponsesInputMessage, K as suppressOpenAIResponsesCompaction, L as convertResponsesMessages, M as createResponsesStreamWithEncryptedContentRetry, N as isInvalidEncryptedContentError, P as resolveAzureOpenAIApiVersion, R as createOpenAIResponsesAssistantOutput, U as captureOpenAIResponsesCompaction, V as CompactionReplayRefreshRequiredError, W as isOpenAIResponsesReplayContext, _ as safeDebugValue, c as convertProjectedResponsesTools, g as logResponsesFailedNoDetails, h as ResponsesStreamFailure, m as observeResponsesStream, n as applyResponsesServiceTierPricing, q as resolveReplayableResponsesMessageId, u as processResponsesStream, v as summarizeOpenAITransportError, y as summarizeResponsesPayload, z as recordResponsesInputReplay } from "./openai-responses-shared-B8RdBPCv.mjs";
26
29
  import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
27
30
  import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
28
- import { t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-D0bhBfgL.mjs";
31
+ import { t as createResponsesPromptEgressObserver } from "./openai-responses-prompt-observer-internal-f8J7wpsk.mjs";
29
32
  import { randomUUID } from "node:crypto";
30
33
  import OpenAI, { AzureOpenAI } from "openai";
31
34
  import { ResponsesWS } from "openai/resources/responses/ws.js";
@@ -78,221 +81,12 @@ function buildAnthropicBetaHeader(model, betaFeatures, params) {
78
81
  if (!isDirectAnthropicModel(model)) return;
79
82
  return params.oauth ? `claude-code-20250219,oauth-2025-04-20,${betaFeatures.join(",")}` : betaFeatures.join(",");
80
83
  }
81
- const NON_VISION_USER_IMAGE_PLACEHOLDER = "(image omitted: model does not support images)";
82
- async function convertContentBlocks(content, model, imageBudget) {
83
- const text = extractToolResultText(content);
84
- const mediaPlaceholder = describeToolResultMediaPlaceholder(content);
85
- if (!(model.input.includes("image") && content.some(isImageWithMediaPayload))) return sanitizeNonEmptyTransportPayloadText(text, mediaPlaceholder ?? "(no output)");
86
- const blocks = [];
87
- let hasTextBlock = false;
88
- for (const block of content) {
89
- if (!block || typeof block !== "object") continue;
90
- const record = block;
91
- const blockText = extractToolResultBlockText(block);
92
- if (blockText) {
93
- blocks.push({
94
- type: "text",
95
- text: sanitizeTransportPayloadText(blockText)
96
- });
97
- hasTextBlock = true;
98
- }
99
- if (!isImageWithMediaPayload(record)) continue;
100
- const [normalizedImage] = await normalizeAnthropicInlineContent([{
101
- type: "image",
102
- data: typeof record.data === "string" ? record.data : "",
103
- mimeType: typeof record.mimeType === "string" ? record.mimeType : "image/png"
104
- }], imageBudget);
105
- if (normalizedImage?.type !== "image") continue;
106
- blocks.push({
107
- type: "image",
108
- source: {
109
- type: "base64",
110
- media_type: resolveAnthropicImageMediaType(normalizedImage.mimeType),
111
- data: normalizedImage.data
112
- }
113
- });
114
- }
115
- if (!hasTextBlock) blocks.unshift({
116
- type: "text",
117
- text: mediaPlaceholder ?? "(see attached image)"
118
- });
119
- return blocks;
120
- }
121
- async function convertAnthropicMessages(messages, model, isOAuthToken, options) {
122
- const params = [];
123
- const imageBudget = createAnthropicInlineImageBudget();
124
- const allowReasoningContentReplay = options.allowReasoningContentReplay === true;
125
- const replayThinkingEnabled = options.replayThinkingEnabled !== false;
126
- const transformedMessages = transformTransportMessages(messages, model, normalizeAnthropicToolCallId);
127
- const activeToolTurnAssistantIndex = replayThinkingEnabled ? -1 : findActiveAnthropicToolTurnAssistantIndex(transformedMessages);
128
- for (let i = 0; i < transformedMessages.length; i += 1) {
129
- const msg = transformedMessages[i];
130
- if (!msg) continue;
131
- if (msg.role === "user") {
132
- if (typeof msg.content === "string") {
133
- if (msg.content.trim().length > 0) {
134
- const userParam = {
135
- role: "user",
136
- content: sanitizeTransportPayloadText(msg.content)
137
- };
138
- params.push(userParam);
139
- }
140
- continue;
141
- }
142
- const blocks = (model.input.includes("image") ? await normalizeAnthropicInlineContent(msg.content, imageBudget) : msg.content.map((item) => item.type === "image" ? {
143
- type: "text",
144
- text: NON_VISION_USER_IMAGE_PLACEHOLDER
145
- } : item)).map((item) => item.type === "text" ? {
146
- type: "text",
147
- text: sanitizeTransportPayloadText(item.text)
148
- } : {
149
- type: "image",
150
- source: {
151
- type: "base64",
152
- media_type: resolveAnthropicImageMediaType(item.mimeType),
153
- data: item.data
154
- }
155
- });
156
- let filteredBlocks = model.input.includes("image") ? blocks : blocks.filter((block) => block.type !== "image");
157
- filteredBlocks = filteredBlocks.filter((block) => block.type !== "text" || block.text.trim().length > 0);
158
- if (filteredBlocks.length === 0) continue;
159
- const userParam = {
160
- role: "user",
161
- content: filteredBlocks
162
- };
163
- params.push(userParam);
164
- continue;
165
- }
166
- if (msg.role === "assistant") {
167
- const blocks = i === 0 && options.compaction ? [options.compaction] : [];
168
- const reasoningContent = [];
169
- let omittedThinking = false;
170
- for (const block of msg.content) {
171
- if (block.type === "text") {
172
- if (block.text.trim().length > 0) blocks.push({
173
- type: "text",
174
- text: sanitizeTransportPayloadText(block.text)
175
- });
176
- continue;
177
- }
178
- if (block.type === "thinking") {
179
- const thinkingSignature = block.thinkingSignature?.trim();
180
- const isReasoningContent = thinkingSignature === "reasoning_content";
181
- if (!replayThinkingEnabled && i !== activeToolTurnAssistantIndex && !isReasoningContent) {
182
- omittedThinking = true;
183
- continue;
184
- }
185
- if (block.redacted) {
186
- blocks.push({
187
- type: "redacted_thinking",
188
- data: block.thinkingSignature
189
- });
190
- continue;
191
- }
192
- const hasNativeThinkingSignature = Boolean(thinkingSignature) && !isReasoningContent;
193
- if (block.thinking.trim().length === 0 && !hasNativeThinkingSignature) continue;
194
- if (!thinkingSignature) blocks.push({
195
- type: "text",
196
- text: sanitizeTransportPayloadText(block.thinking)
197
- });
198
- else {
199
- const thinking = thinkingSignature === "reasoning_content" ? sanitizeTransportPayloadText(block.thinking) : block.thinking;
200
- if (thinkingSignature === "reasoning_content") {
201
- if (allowReasoningContentReplay) {
202
- blocks.push({
203
- type: "thinking",
204
- thinking,
205
- signature: thinkingSignature
206
- });
207
- reasoningContent.push(thinking);
208
- }
209
- continue;
210
- }
211
- blocks.push({
212
- type: "thinking",
213
- thinking,
214
- signature: thinkingSignature
215
- });
216
- }
217
- continue;
218
- }
219
- if (block.type === "toolCall") blocks.push({
220
- type: "tool_use",
221
- id: block.id,
222
- name: isOAuthToken ? toClaudeCodeToolName(block.name) : block.name,
223
- input: coerceTransportToolCallArguments(block.arguments)
224
- });
225
- }
226
- if (blocks.length === 0 && omittedThinking) blocks.push({
227
- type: "text",
228
- text: ANTHROPIC_OMITTED_REASONING_TEXT
229
- });
230
- if (blocks.length > 0) {
231
- const assistantMsg = {
232
- role: "assistant",
233
- content: blocks
234
- };
235
- if (reasoningContent.length > 0) assistantMsg.reasoning_content = reasoningContent.join("\n");
236
- else if (allowReasoningContentReplay) blocks.unshift({
237
- type: "thinking",
238
- thinking: "",
239
- signature: "reasoning_content"
240
- });
241
- params.push(assistantMsg);
242
- }
243
- continue;
244
- }
245
- if (msg.role === "toolResult") {
246
- const toolResult = msg;
247
- const toolResults = [{
248
- type: "tool_result",
249
- tool_use_id: toolResult.toolCallId,
250
- content: await convertContentBlocks(toolResult.content, model, imageBudget),
251
- is_error: toolResult.isError
252
- }];
253
- let j = i + 1;
254
- while (j < transformedMessages.length) {
255
- const nextMsg = transformedMessages.at(j);
256
- if (nextMsg?.role !== "toolResult") break;
257
- toolResults.push({
258
- type: "tool_result",
259
- tool_use_id: nextMsg.toolCallId,
260
- content: await convertContentBlocks(nextMsg.content, model, imageBudget),
261
- is_error: nextMsg.isError
262
- });
263
- j += 1;
264
- }
265
- i = j - 1;
266
- params.push({
267
- role: "user",
268
- content: toolResults
269
- });
270
- }
271
- }
272
- return params;
273
- }
274
84
  function ensureNonEmptyAnthropicMessages(messages) {
275
85
  return messages.length > 0 ? messages : [{
276
86
  role: "user",
277
87
  content: EMPTY_ANTHROPIC_MESSAGES_FALLBACK_TEXT
278
88
  }];
279
89
  }
280
- function convertAnthropicTools(tools, isOAuthToken) {
281
- const projection = projectAnthropicTools(tools ?? [], (name) => isOAuthToken ? toClaudeCodeToolName(name) : name);
282
- const converted = [];
283
- for (const tool of projection.tools) converted.push({
284
- name: tool.wireName,
285
- description: tool.description,
286
- input_schema: tool.inputSchema
287
- });
288
- return {
289
- projection,
290
- tools: converted
291
- };
292
- }
293
- function parseAnthropicToolCallArguments(inputJson) {
294
- return coerceTransportToolCallArguments(parseJsonObjectPreservingUnsafeIntegers(inputJson) ?? parseStreamingJson(inputJson));
295
- }
296
90
  const DEFAULT_ANTHROPIC_BASE_URL = "https://api.anthropic.com";
297
91
  /** Resolve the effective Anthropic API base URL from model or environment. */
298
92
  function resolveAnthropicBaseUrl(baseUrl) {
@@ -323,7 +117,6 @@ function readAnthropicSseChunk(reader, signal) {
323
117
  if (settled) return;
324
118
  settled = true;
325
119
  signal.removeEventListener("abort", onAbort);
326
- reader.cancel(signal.reason).catch(() => void 0);
327
120
  reject(createAbortError(signal));
328
121
  };
329
122
  if (signal.aborted) {
@@ -388,7 +181,11 @@ async function* parseAnthropicSseBody(body, signal) {
388
181
  if (data && data !== "[DONE]") yield parseAnthropicSseEventData(data);
389
182
  }
390
183
  } finally {
391
- if (!completed) await reader.cancel(signal?.reason).catch(() => void 0);
184
+ if (!completed) {
185
+ const cancellation = reader.cancel(signal?.reason).catch(() => void 0);
186
+ if (signal?.aborted) getAiTransportHost().observePendingProviderWork?.(cancellation);
187
+ else await cancellation;
188
+ }
392
189
  reader.releaseLock();
393
190
  }
394
191
  }
@@ -415,7 +212,7 @@ function createAnthropicMessagesClient(params) {
415
212
  } } };
416
213
  }
417
214
  function formatAnthropicMessagesHttpError(response, detail) {
418
- const retryAfterSeconds = parseRetryAfterSeconds(response.headers);
215
+ const retryAfterSeconds = parseRetryAfterHeadersSeconds(response.headers);
419
216
  const retryAfterSuffix = Number.isFinite(retryAfterSeconds) ? `; Retry-After: ${Math.ceil(retryAfterSeconds ?? 0)} seconds` : "";
420
217
  return `HTTP ${response.status}: ${detail || "Anthropic Messages request failed"}${retryAfterSuffix}`;
421
218
  }
@@ -434,6 +231,7 @@ async function readAnthropicMessagesErrorBodySnippet(response) {
434
231
  }
435
232
  function createAnthropicTransportClient(params) {
436
233
  const { model, context, apiKey, options } = params;
234
+ const optionHeaders = resolveOpencodeSessionHeaders(model, options);
437
235
  const needsInterleavedBeta = (options?.interleavedThinking ?? true) && !supportsClaudeAdaptiveThinking(model);
438
236
  const fetch = isKimiAnthropicProvider(model.provider) && options?.thinkingEnabled === true ? buildGuardedModelFetch(model, void 0, { sanitizeSse: false }) : buildGuardedModelFetch(model);
439
237
  if (model.provider === "github-copilot") {
@@ -447,7 +245,7 @@ function createAnthropicTransportClient(params) {
447
245
  accept: "application/json",
448
246
  "anthropic-dangerous-direct-browser-access": "true",
449
247
  ...betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}
450
- }, model.headers, getAiTransportHost().buildCopilotDynamicHeaders(context.messages), options?.headers),
248
+ }, model.headers, getAiTransportHost().buildCopilotDynamicHeaders(context.messages), optionHeaders),
451
249
  fetch
452
250
  }),
453
251
  isOAuthToken: false
@@ -464,7 +262,7 @@ function createAnthropicTransportClient(params) {
464
262
  accept: "application/json",
465
263
  "anthropic-dangerous-direct-browser-access": "true",
466
264
  ...betaFeatures.length > 0 ? { "anthropic-beta": betaFeatures.join(",") } : {}
467
- }, omitFoundryBearerCredentialHeaders(model.headers), options?.headers),
265
+ }, omitFoundryBearerCredentialHeaders(model.headers), optionHeaders),
468
266
  fetch
469
267
  }),
470
268
  isOAuthToken: false
@@ -485,7 +283,7 @@ function createAnthropicTransportClient(params) {
485
283
  ...betaHeader ? { "anthropic-beta": betaHeader } : {},
486
284
  "user-agent": `claude-cli/${ANTHROPIC_CLAUDE_CODE_VERSION}`,
487
285
  "x-app": "cli"
488
- }, model.headers, options?.headers),
286
+ }, model.headers, optionHeaders),
489
287
  fetch
490
288
  }),
491
289
  isOAuthToken: true
@@ -497,7 +295,7 @@ function createAnthropicTransportClient(params) {
497
295
  accept: "application/json",
498
296
  "anthropic-dangerous-direct-browser-access": "true",
499
297
  ...betaHeader ? { "anthropic-beta": betaHeader } : {}
500
- }, model.headers, options?.headers);
298
+ }, model.headers, optionHeaders);
501
299
  return {
502
300
  client: createAnthropicMessagesClient({
503
301
  apiKey,
@@ -510,30 +308,26 @@ function createAnthropicTransportClient(params) {
510
308
  };
511
309
  }
512
310
  async function buildAnthropicParams(model, context, isOAuthToken, options) {
513
- const mandatoryAdaptiveThinking = requiresClaudeAdaptiveThinking(model);
514
- const replayThinkingEnabled = mandatoryAdaptiveThinking || options?.thinkingEnabled === true;
311
+ const replayThinkingEnabled = requiresClaudeAdaptiveThinking(model) || options?.thinkingEnabled === true;
515
312
  const maxTokens = resolveAnthropicMessagesMaxTokens({
516
313
  modelContextWindow: model.contextWindow,
517
314
  modelMaxTokens: model.maxTokens,
518
315
  requestedMaxTokens: options?.maxTokens
519
316
  });
520
317
  if (maxTokens === void 0) throw new Error(`Anthropic Messages transport requires a positive maxTokens value for ${model.provider}/${model.id}`);
521
- const payloadPolicy = resolveAnthropicPayloadPolicy({
522
- provider: model.provider,
523
- api: model.api,
524
- baseUrl: model.baseUrl,
525
- cacheRetention: options?.cacheRetention,
526
- enableCacheControl: true
527
- }, model);
318
+ const { cacheControl, supportsCacheControlOnTools } = resolveAnthropicCacheOptions(model, options?.cacheRetention);
528
319
  const replayPlan = buildAnthropicReplayPlan(context.messages, model, {
529
320
  enabled: !isOAuthToken && options?.anthropicServerCompaction === true,
530
321
  authProfileId: options?.authProfileId,
531
322
  sessionId: options?.sessionId
532
323
  });
533
- const messages = await convertAnthropicMessages(replayPlan.messages, model, isOAuthToken, {
324
+ const cacheBreakpointOptOutMessageIndexes = /* @__PURE__ */ new Set();
325
+ const messages = await convertAnthropicMessages(transformTransportMessages(replayPlan.messages, model, normalizeAnthropicToolCallId), model, isOAuthToken, {
326
+ profile: "transport",
534
327
  allowReasoningContentReplay: supportsReasoningContentReplay(model),
535
328
  compaction: replayPlan.compaction,
536
- replayThinkingEnabled
329
+ replayThinkingEnabled,
330
+ cacheBreakpointOptOutMessageIndexes
537
331
  });
538
332
  const params = {
539
333
  model: resolveAnthropicRequestModelId(model),
@@ -542,54 +336,18 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
542
336
  stream: true
543
337
  };
544
338
  if (!isOAuthToken && useAnthropicServerSideFallback(model)) params.fallbacks = ANTHROPIC_SERVER_SIDE_FALLBACKS;
545
- if (isOAuthToken) params.system = [
546
- {
547
- type: "text",
548
- text: ANTHROPIC_CLAUDE_CODE_BILLING_SYSTEM_BLOCK
549
- },
550
- {
551
- type: "text",
552
- text: "You are Claude Code, Anthropic's official CLI for Claude."
553
- },
554
- ...context.systemPrompt ? [{
555
- type: "text",
556
- text: sanitizeTransportPayloadText(context.systemPrompt)
557
- }] : []
558
- ];
559
- else if (context.systemPrompt) params.system = [{
560
- type: "text",
561
- text: sanitizeTransportPayloadText(context.systemPrompt)
562
- }];
563
- if (options?.temperature !== void 0 && !options.thinkingEnabled && !supportsClaudeNativeXhighEffort(model)) params.temperature = options.temperature;
564
- if (options?.stop !== void 0 && options.stop.length > 0) params.stop_sequences = options.stop;
565
- let toolProjection;
566
- if (context.tools) {
567
- const convertedTools = convertAnthropicTools(context.tools, isOAuthToken);
568
- toolProjection = convertedTools.projection;
569
- if (convertedTools.tools.length > 0) params.tools = convertedTools.tools;
570
- }
571
- if (mandatoryAdaptiveThinking || model.reasoning || supportsClaudeAdaptiveThinking(model)) {
572
- if (mandatoryAdaptiveThinking || options?.thinkingEnabled) {
573
- if (supportsClaudeAdaptiveThinking(model)) {
574
- params.thinking = {
575
- type: "adaptive",
576
- display: options?.thinkingDisplay ?? "summarized"
577
- };
578
- const effort = options?.effort ?? (mandatoryAdaptiveThinking ? "high" : void 0);
579
- if (effort) params.output_config = { effort };
580
- } else params.thinking = {
581
- type: "enabled",
582
- budget_tokens: options?.thinkingBudgetTokens ?? 1024
583
- };
584
- } else if (options?.thinkingEnabled === false) params.thinking = { type: "disabled" };
585
- }
586
- if (options?.metadata && typeof options.metadata.user_id === "string") params.metadata = { user_id: options.metadata.user_id };
587
- if (options?.toolChoice) {
588
- const normalizedToolChoice = normalizeAnthropicToolChoice(replayThinkingEnabled, options.toolChoice);
589
- const projectedToolChoice = toolProjection ? reconcileAnthropicToolChoice(normalizedToolChoice, toolProjection) : normalizedToolChoice;
590
- if (projectedToolChoice) params.tool_choice = projectedToolChoice;
591
- }
592
- applyAnthropicPayloadPolicyToParams(params, payloadPolicy, /* @__PURE__ */ new Set());
339
+ const system = buildAnthropicSystemBlocks(context.systemPrompt, isOAuthToken, cacheControl);
340
+ if (system) params.system = system;
341
+ const convertedTools = context.tools ? convertAnthropicTools(context.tools, isOAuthToken) : void 0;
342
+ const toolProjection = convertedTools?.projection;
343
+ Object.assign(params, buildAnthropicGenerationParams({
344
+ model,
345
+ options,
346
+ tools: convertedTools?.tools,
347
+ toolProjection,
348
+ profile: "transport"
349
+ }));
350
+ applyAnthropicRequestCacheControl(params, cacheControl, supportsCacheControlOnTools, cacheBreakpointOptOutMessageIndexes);
593
351
  return {
594
352
  params,
595
353
  toolProjection,
@@ -657,22 +415,9 @@ function createAnthropicMessagesTransportStreamFn() {
657
415
  const options = rawOptions;
658
416
  const { eventStream, stream } = createWritableTransportEventStream();
659
417
  (async () => {
660
- const output = {
661
- role: "assistant",
662
- content: [],
663
- api: "anthropic-messages",
664
- provider: model.provider,
665
- model: model.id,
666
- usage: createEmptyTransportUsage(),
667
- stopReason: "stop",
668
- timestamp: Date.now()
669
- };
418
+ const output = createAssistantOutput(model, "anthropic-messages");
670
419
  const refusalBuffer = usesClaudeStreamingRefusalContract(model) ? createDeferredEventBuffer(stream) : void 0;
671
- const eventSink = refusalBuffer ?? stream;
672
- let costModel = model;
673
- let messageStartPromptUsage;
674
420
  let usedCompactionReplay = false;
675
- let inputTransformations;
676
421
  try {
677
422
  const apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? "";
678
423
  if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
@@ -693,7 +438,7 @@ function createAnthropicMessagesTransportStreamFn() {
693
438
  if (nextParams !== void 0) params = nextParams;
694
439
  applyClaudeRequestContract(params, model);
695
440
  const betaHeader = resolveAnthropicContextManagementBetaHeader(params, directApiKeyBetaHeader);
696
- const bindingHeaders = applyAnthropicThinkingBindingControls(params, betaHeader) ?? (betaHeader !== void 0 ? { "anthropic-beta": betaHeader } : void 0);
441
+ const bindingHeaders = applyAnthropicThinkingBindingControls(params, betaHeader) ?? (betaHeader ? { "anthropic-beta": betaHeader } : void 0);
697
442
  const { response, stream: anthropicStream } = await client.messages.stream({
698
443
  ...params,
699
444
  stream: true
@@ -710,432 +455,17 @@ function createAnthropicMessagesTransportStreamFn() {
710
455
  const detail = await readAnthropicMessagesErrorBodySnippet(response);
711
456
  throw new Error(formatAnthropicMessagesHttpError(response, detail));
712
457
  }
713
- const blocks = output.content;
714
- const blockIndexes = /* @__PURE__ */ new Map();
715
- const toolArgumentPreviewSchedules = /* @__PURE__ */ new WeakMap();
716
- const sealedToolCalls = [];
717
- const compactionCapture = createCompactionCapture(output, model, transportOptions);
718
- const pendingThinkingSignatures = /* @__PURE__ */ new Map();
719
- const allowReasoningContentReplay = supportsReasoningContentReplay(model);
720
- const reasoningContentThinkingBlocks = /* @__PURE__ */ new Map();
721
- const reasoningContentTextBlocks = /* @__PURE__ */ new Map();
722
- let sawMessageStop = false;
723
- const pendingTextEnds = [];
724
- const flushPendingTextEnds = () => {
725
- for (const event of pendingTextEnds) eventSink.push(event);
726
- pendingTextEnds.length = 0;
727
- };
728
- const eventIndexKey = (eventIndex) => typeof eventIndex === "number" ? eventIndex : -1;
729
- const appendReasoningContentThinkingDelta = (eventIndex, rawText) => {
730
- if (typeof rawText !== "string") return false;
731
- const text = sanitizeTransportPayloadText(rawText);
732
- if (text.length === 0) return false;
733
- const key = eventIndexKey(eventIndex);
734
- let contentIndex = reasoningContentThinkingBlocks.get(key);
735
- let block = contentIndex === void 0 ? void 0 : output.content[contentIndex];
736
- if (!block || block.type !== "thinking") {
737
- block = {
738
- type: "thinking",
739
- thinking: "",
740
- thinkingSignature: "reasoning_content"
741
- };
742
- output.content.push(block);
743
- contentIndex = output.content.length - 1;
744
- reasoningContentThinkingBlocks.set(key, contentIndex);
745
- eventSink.push({
746
- type: "thinking_start",
747
- contentIndex,
748
- partial: output
749
- });
750
- }
751
- if (contentIndex === void 0) return false;
752
- block.thinking += text;
753
- block.thinkingSignature = "reasoning_content";
754
- eventSink.push({
755
- type: "thinking_delta",
756
- contentIndex,
757
- delta: text,
758
- partial: output
759
- });
760
- return true;
761
- };
762
- const appendReasoningContentTextDelta = (eventIndex, rawText) => {
763
- if (typeof rawText !== "string") return false;
764
- const text = sanitizeTransportPayloadText(rawText);
765
- if (text.length === 0) return false;
766
- const key = eventIndexKey(eventIndex);
767
- let contentIndex = reasoningContentTextBlocks.get(key);
768
- let block = contentIndex === void 0 ? void 0 : output.content[contentIndex];
769
- if (!block || block.type !== "text") {
770
- block = {
771
- type: "text",
772
- text: ""
773
- };
774
- output.content.push(block);
775
- contentIndex = output.content.length - 1;
776
- reasoningContentTextBlocks.set(key, contentIndex);
777
- eventSink.push({
778
- type: "text_start",
779
- contentIndex,
780
- partial: output
781
- });
782
- }
783
- if (contentIndex === void 0) return false;
784
- block.text += text;
785
- eventSink.push({
786
- type: "text_delta",
787
- contentIndex,
788
- delta: text,
789
- partial: output
790
- });
791
- return true;
792
- };
793
- const finishReasoningContentSidecars = (eventIndex) => {
794
- const key = eventIndexKey(eventIndex);
795
- const thinkingContentIndex = reasoningContentThinkingBlocks.get(key);
796
- if (thinkingContentIndex !== void 0) {
797
- reasoningContentThinkingBlocks.delete(key);
798
- const block = output.content[thinkingContentIndex];
799
- if (block?.type === "thinking") eventSink.push({
800
- type: "thinking_end",
801
- contentIndex: thinkingContentIndex,
802
- content: block.thinking,
803
- partial: output
804
- });
805
- }
806
- const textContentIndex = reasoningContentTextBlocks.get(key);
807
- if (textContentIndex === void 0) return;
808
- reasoningContentTextBlocks.delete(key);
809
- const block = output.content[textContentIndex];
810
- if (block?.type === "text") eventSink.push({
811
- type: "text_end",
812
- contentIndex: textContentIndex,
813
- content: block.text,
814
- partial: output
815
- });
816
- };
817
- for await (const event of anthropicStream) {
818
- inputTransformations = readAnthropicInputTransformations(event) ?? inputTransformations;
819
- notifyLlmRequestActivity(transportOptions.signal);
820
- if (event.type === "error") {
821
- const error = event.error;
822
- throw new Error(error?.message || "Anthropic Messages stream failed");
823
- }
824
- if (event.type === "message_start") {
825
- const message = event.message;
826
- const usage = message?.usage ?? {};
827
- output.responseId = typeof message?.id === "string" ? message.id : void 0;
828
- output.responseModel = typeof message?.model === "string" ? message.model : void 0;
829
- messageStartPromptUsage = applyAnthropicMessageStartUsage(output.usage, usage);
830
- calculateCost(costModel, output.usage);
831
- eventSink.push({
832
- type: "start",
833
- partial: output
834
- });
835
- continue;
836
- }
837
- if (event.type === "message_stop") {
838
- sawMessageStop = true;
839
- continue;
840
- }
841
- if (event.type === "content_block_start") {
842
- const contentBlock = event.content_block;
843
- const index = typeof event.index === "number" ? event.index : -1;
844
- if (transportOptions.anthropicServerCompaction === true && compactionCapture.begin(index, contentBlock, output.content.length)) continue;
845
- const fallbackBoundary = refusalBuffer ? readAnthropicFallbackBoundary(contentBlock) : null;
846
- if (fallbackBoundary) {
847
- refusalBuffer?.discard();
848
- sealedToolCalls.length = 0;
849
- pendingTextEnds.length = 0;
850
- blockIndexes.clear();
851
- pendingThinkingSignatures.clear();
852
- applyAnthropicFallbackBoundary({
853
- output,
854
- boundary: fallbackBoundary,
855
- provider: model.provider
856
- });
857
- costModel = {
858
- ...model,
859
- cost: resolveAnthropicFallbackServingModelCost({
860
- requestedModelId: model.id,
861
- servingModelId: fallbackBoundary.toModel,
862
- requestedCost: model.cost
863
- })
864
- };
865
- calculateCost(costModel, output.usage);
866
- eventSink.push({
867
- type: "start",
868
- partial: output
869
- });
870
- for (const [i, block] of output.content.entries()) {
871
- if (block.type !== "text") continue;
872
- delete block.index;
873
- eventSink.push({
874
- type: "text_start",
875
- contentIndex: i,
876
- partial: output
877
- });
878
- if (block.text) eventSink.push({
879
- type: "text_delta",
880
- contentIndex: i,
881
- delta: block.text,
882
- partial: output
883
- });
884
- pendingTextEnds.push({
885
- type: "text_end",
886
- contentIndex: i,
887
- content: block.text,
888
- partial: output
889
- });
890
- }
891
- continue;
892
- }
893
- pendingThinkingSignatures.delete(index);
894
- if (contentBlock?.type === "text") {
895
- const text = typeof contentBlock.text === "string" ? sanitizeTransportPayloadText(contentBlock.text) : "";
896
- const block = {
897
- type: "text",
898
- text,
899
- index
900
- };
901
- output.content.push(block);
902
- const contentIndex = output.content.length - 1;
903
- blockIndexes.set(index, contentIndex);
904
- eventSink.push({
905
- type: "text_start",
906
- contentIndex,
907
- partial: output
908
- });
909
- if (text.length > 0) eventSink.push({
910
- type: "text_delta",
911
- contentIndex,
912
- delta: text,
913
- partial: output
914
- });
915
- continue;
916
- }
917
- if (contentBlock?.type === "thinking") {
918
- const thinking = typeof contentBlock.thinking === "string" ? contentBlock.thinking : "";
919
- const block = {
920
- type: "thinking",
921
- thinking,
922
- thinkingSignature: typeof contentBlock.signature === "string" ? contentBlock.signature : "",
923
- index
924
- };
925
- output.content.push(block);
926
- const contentIndex = output.content.length - 1;
927
- blockIndexes.set(index, contentIndex);
928
- eventSink.push({
929
- type: "thinking_start",
930
- contentIndex,
931
- partial: output
932
- });
933
- if (thinking.length > 0) eventSink.push({
934
- type: "thinking_delta",
935
- contentIndex,
936
- delta: thinking,
937
- partial: output
938
- });
939
- continue;
940
- }
941
- if (contentBlock?.type === "redacted_thinking") {
942
- const block = {
943
- type: "thinking",
944
- thinking: "[Reasoning redacted]",
945
- thinkingSignature: typeof contentBlock.data === "string" ? contentBlock.data : "",
946
- redacted: true,
947
- index
948
- };
949
- output.content.push(block);
950
- blockIndexes.set(index, output.content.length - 1);
951
- eventSink.push({
952
- type: "thinking_start",
953
- contentIndex: output.content.length - 1,
954
- partial: output
955
- });
956
- continue;
957
- }
958
- if (contentBlock?.type === "tool_use") {
959
- tagPendingCommentaryText(output.content);
960
- flushPendingTextEnds();
961
- const block = {
962
- type: "toolCall",
963
- id: typeof contentBlock.id === "string" ? contentBlock.id : "",
964
- name: typeof contentBlock.name === "string" ? isOAuthToken ? resolveOriginalAnthropicToolName(contentBlock.name, toolProjection) : contentBlock.name : "",
965
- arguments: contentBlock.input && typeof contentBlock.input === "object" ? contentBlock.input : {},
966
- partialJson: "",
967
- index
968
- };
969
- output.content.push(block);
970
- blockIndexes.set(index, output.content.length - 1);
971
- toolArgumentPreviewSchedules.set(block, createToolArgumentPreviewSchedule());
972
- eventSink.push({
973
- type: "toolcall_start",
974
- contentIndex: output.content.length - 1,
975
- partial: output
976
- });
977
- }
978
- continue;
979
- }
980
- if (event.type === "content_block_delta") {
981
- const delta = event.delta;
982
- const eventIndex = typeof event.index === "number" ? event.index : void 0;
983
- if (eventIndex !== void 0 && compactionCapture.delta(eventIndex, delta)) continue;
984
- let index = eventIndex === void 0 ? void 0 : blockIndexes.get(eventIndex);
985
- let block = index === void 0 ? void 0 : blocks[index];
986
- if (allowReasoningContentReplay) {
987
- const appendedThinking = appendReasoningContentThinkingDelta(event.index, delta?.reasoning_content);
988
- const hasNativeAnthropicDelta = delta?.type === "text_delta" && typeof delta.text === "string" || delta?.type === "thinking_delta" && typeof delta.thinking === "string" || delta?.type === "input_json_delta" && typeof delta.partial_json === "string" || delta?.type === "signature_delta" && typeof delta.signature === "string";
989
- let appendedContent = false;
990
- if (!hasNativeAnthropicDelta && typeof delta?.content === "string" && delta.content.length > 0) {
991
- const text = sanitizeTransportPayloadText(delta.content);
992
- if (text.length > 0) {
993
- if (block?.type === "text" && index !== void 0) {
994
- block.text += text;
995
- eventSink.push({
996
- type: "text_delta",
997
- contentIndex: index,
998
- delta: text,
999
- partial: output
1000
- });
1001
- appendedContent = true;
1002
- } else appendedContent = appendReasoningContentTextDelta(event.index, text);
1003
- }
1004
- }
1005
- if ((appendedThinking || appendedContent) && !hasNativeAnthropicDelta) continue;
1006
- }
1007
- if (!block && delta?.type === "text_delta" && typeof delta.text === "string") {
1008
- block = {
1009
- type: "text",
1010
- text: "",
1011
- index: typeof event.index === "number" ? event.index : blocks.length
1012
- };
1013
- output.content.push(block);
1014
- index = output.content.length - 1;
1015
- if (typeof event.index === "number") blockIndexes.set(event.index, index);
1016
- eventSink.push({
1017
- type: "text_start",
1018
- contentIndex: index,
1019
- partial: output
1020
- });
1021
- }
1022
- if (index === void 0) continue;
1023
- if (block?.type === "text" && delta?.type === "text_delta" && typeof delta.text === "string") {
1024
- block.text += delta.text;
1025
- eventSink.push({
1026
- type: "text_delta",
1027
- contentIndex: index,
1028
- delta: delta.text,
1029
- partial: output
1030
- });
1031
- continue;
1032
- }
1033
- if (block?.type === "thinking" && delta?.type === "thinking_delta" && typeof delta.thinking === "string") {
1034
- block.thinking += delta.thinking;
1035
- eventSink.push({
1036
- type: "thinking_delta",
1037
- contentIndex: index,
1038
- delta: delta.thinking,
1039
- partial: output
1040
- });
1041
- continue;
1042
- }
1043
- if (block?.type === "toolCall" && delta?.type === "input_json_delta" && typeof delta.partial_json === "string") {
1044
- const partialJson = `${block.partialJson ?? ""}${delta.partial_json}`;
1045
- block.partialJson = partialJson;
1046
- if (toolArgumentPreviewSchedules.get(block)?.(partialJson.length)) block.arguments = parseAnthropicToolCallArguments(partialJson);
1047
- eventSink.push({
1048
- type: "toolcall_delta",
1049
- contentIndex: index,
1050
- delta: delta.partial_json,
1051
- partial: output
1052
- });
1053
- continue;
1054
- }
1055
- if (block?.type === "thinking" && delta?.type === "signature_delta" && typeof delta.signature === "string") {
1056
- const signatureIndex = eventIndexKey(event.index);
1057
- const pendingSignature = pendingThinkingSignatures.get(signatureIndex);
1058
- if (pendingSignature === void 0) {
1059
- block.thinkingSignature = "";
1060
- pendingThinkingSignatures.set(signatureIndex, delta.signature);
1061
- } else pendingThinkingSignatures.set(signatureIndex, pendingSignature + delta.signature);
1062
- }
1063
- continue;
1064
- }
1065
- if (event.type === "content_block_stop") {
1066
- const eventIndex = typeof event.index === "number" ? event.index : void 0;
1067
- if (eventIndex !== void 0 && compactionCapture.complete(eventIndex)) continue;
1068
- const pendingSignature = eventIndex === void 0 ? void 0 : pendingThinkingSignatures.get(eventIndex);
1069
- if (eventIndex !== void 0) pendingThinkingSignatures.delete(eventIndex);
1070
- const index = eventIndex === void 0 ? void 0 : blockIndexes.get(eventIndex);
1071
- const block = index === void 0 ? void 0 : blocks[index];
1072
- if (eventIndex === void 0 || index === void 0 || !block) {
1073
- finishReasoningContentSidecars(event.index);
1074
- continue;
1075
- }
1076
- blockIndexes.delete(eventIndex);
1077
- delete block.index;
1078
- if (block.type === "text") {
1079
- pendingTextEnds.push({
1080
- type: "text_end",
1081
- contentIndex: index,
1082
- content: block.text,
1083
- partial: output
1084
- });
1085
- finishReasoningContentSidecars(event.index);
1086
- continue;
1087
- }
1088
- if (block.type === "thinking") {
1089
- if (pendingSignature !== void 0) block.thinkingSignature = pendingSignature;
1090
- eventSink.push({
1091
- type: "thinking_end",
1092
- contentIndex: index,
1093
- content: block.thinking,
1094
- partial: output
1095
- });
1096
- finishReasoningContentSidecars(event.index);
1097
- continue;
1098
- }
1099
- if (block.type === "toolCall") {
1100
- sealedToolCalls.push({
1101
- block,
1102
- contentIndex: index
1103
- });
1104
- finishReasoningContentSidecars(event.index);
1105
- }
1106
- continue;
1107
- }
1108
- if (event.type === "message_delta") {
1109
- logAnthropicContextEdits(event);
1110
- const delta = event.delta;
1111
- const usage = event.usage;
1112
- if (delta?.stop_reason) {
1113
- if (delta.stop_reason === "refusal") applyAnthropicRefusal(output, delta.stop_details, model.provider);
1114
- else output.stopReason = mapAnthropicStopReason(delta.stop_reason);
1115
- }
1116
- applyAnthropicMessageDeltaUsage(output.usage, usage, messageStartPromptUsage);
1117
- calculateCost(costModel, output.usage);
1118
- if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
1119
- flushPendingTextEnds();
1120
- }
1121
- }
1122
- if (isDirectAnthropicModel(model) && !sawMessageStop) throw new Error("Anthropic stream ended before message_stop");
1123
- if (transportOptions.signal?.aborted) throw transportAbortError(transportOptions.signal);
1124
- if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
1125
- if ([...blockIndexes.values()].some((index) => blocks[index]?.type === "toolCall")) throw new Error("Provider completed stream with an incomplete tool call");
1126
- finalizeTerminalToolCallArguments(sealedToolCalls.map(({ block }) => block), (block) => block.partialJson && block.partialJson.length > 0 ? block.partialJson : block.arguments);
1127
- for (const sealed of sealedToolCalls) {
1128
- delete sealed.block.partialJson;
1129
- eventSink.push({
1130
- type: "toolcall_end",
1131
- contentIndex: sealed.contentIndex,
1132
- toolCall: sealed.block,
1133
- partial: output
1134
- });
1135
- }
1136
- refusalBuffer?.flush();
1137
- if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
1138
- flushPendingTextEnds();
458
+ await consumeAnthropicStream({
459
+ events: anthropicStream,
460
+ model,
461
+ options: transportOptions,
462
+ output,
463
+ stream,
464
+ refusalBuffer,
465
+ isOAuthToken,
466
+ toolProjection,
467
+ profile: "transport"
468
+ });
1139
469
  finalizeTransportStream({
1140
470
  stream,
1141
471
  output
@@ -1155,71 +485,12 @@ function createAnthropicMessagesTransportStreamFn() {
1155
485
  for (const block of output.content) delete block.index;
1156
486
  }
1157
487
  });
1158
- } finally {
1159
- logAnthropicThinkingDrops(inputTransformations);
1160
488
  }
1161
489
  })();
1162
490
  return eventStream;
1163
491
  };
1164
492
  }
1165
493
  //#endregion
1166
- //#region packages/ai/src/transports/model-max-tokens-params.ts
1167
- /**
1168
- * Max-token parameter normalization across provider/native naming variants.
1169
- * Callers canonicalize aliases before dispatch so payloads cannot carry
1170
- * conflicting limits.
1171
- */
1172
- const MAX_TOKENS_PARAM_KEYS = [
1173
- "maxTokens",
1174
- "max_completion_tokens",
1175
- "max_tokens"
1176
- ];
1177
- /** Resolve the first supported max-token parameter present in a params object. */
1178
- function resolveMaxTokensParam(params) {
1179
- if (!params) return;
1180
- for (const key of MAX_TOKENS_PARAM_KEYS) {
1181
- const resolved = asNonNegativeFiniteNumber(params[key]);
1182
- if (resolved !== void 0) return resolved;
1183
- }
1184
- }
1185
- /**
1186
- * Canonicalize merged params to `maxTokens`, preserving source precedence from
1187
- * left to right across the provided source objects.
1188
- */
1189
- function canonicalizeMaxTokensParam(params) {
1190
- let resolved;
1191
- for (const source of params.sources) {
1192
- const sourceValue = resolveMaxTokensParam(source);
1193
- if (sourceValue !== void 0) resolved = sourceValue;
1194
- }
1195
- if (resolved === void 0) return;
1196
- for (const key of MAX_TOKENS_PARAM_KEYS) delete params.merged[key];
1197
- params.merged.maxTokens = resolved;
1198
- }
1199
- //#endregion
1200
- //#region packages/ai/src/transports/model-transport-url.ts
1201
- /**
1202
- * Debug formatting helpers for model transport endpoints.
1203
- * Keeps logs useful without exposing credentials, request params, or fragments.
1204
- */
1205
- /** Return a sanitized URL suitable for logs and diagnostics. */
1206
- function formatModelTransportDebugUrl(rawUrl) {
1207
- try {
1208
- const parsed = new URL(rawUrl);
1209
- parsed.username = "";
1210
- parsed.password = "";
1211
- parsed.search = "";
1212
- parsed.hash = "";
1213
- return parsed.toString();
1214
- } catch {
1215
- return "<invalid-url>";
1216
- }
1217
- }
1218
- /** Format a configured base URL for debug output, or the implicit default. */
1219
- function formatModelTransportDebugBaseUrl(rawUrl) {
1220
- return rawUrl ? formatModelTransportDebugUrl(rawUrl) : "default";
1221
- }
1222
- //#endregion
1223
494
  //#region packages/ai/src/transports/openai-compatible-conversation-turn.ts
1224
495
  /**
1225
496
  * OpenAI-compatible conversation turn detector.
@@ -1256,450 +527,6 @@ function hasOpenAICompatibleConversationTurn(messages) {
1256
527
  });
1257
528
  }
1258
529
  //#endregion
1259
- //#region packages/ai/src/transports/openai-completions-string-content.ts
1260
- /**
1261
- * OpenAI Chat Completions compatibility helpers. Some providers only accept
1262
- * role/content messages with plain string content instead of text block arrays.
1263
- */
1264
- function flattenStringOnlyCompletionContent(content) {
1265
- if (!Array.isArray(content)) return content;
1266
- const textParts = [];
1267
- for (const item of content) {
1268
- if (!item || typeof item !== "object" || item.type !== "text" || typeof item.text !== "string") return content;
1269
- textParts.push(item.text);
1270
- }
1271
- return textParts.join("\n");
1272
- }
1273
- /** Flatten string-only text block content arrays into newline-joined strings. */
1274
- function flattenCompletionMessagesToStringContent(messages) {
1275
- return messages.map((message) => {
1276
- if (!message || typeof message !== "object") return message;
1277
- const content = message.content;
1278
- const flattenedContent = flattenStringOnlyCompletionContent(content);
1279
- if (flattenedContent === content) return message;
1280
- return {
1281
- ...message,
1282
- content: flattenedContent
1283
- };
1284
- });
1285
- }
1286
- /** Strip completion messages to role/content fields for strict providers. */
1287
- function stripCompletionMessagesToRoleContent(messages) {
1288
- return messages.map((message) => {
1289
- if (!message || typeof message !== "object" || Array.isArray(message)) return message;
1290
- const record = message;
1291
- const stripped = {};
1292
- if (Object.hasOwn(record, "role")) stripped.role = record.role;
1293
- if (Object.hasOwn(record, "content")) stripped.content = record.content;
1294
- return stripped;
1295
- });
1296
- }
1297
- //#endregion
1298
- //#region packages/ai/src/transports/openai-completions-host.ts
1299
- /**
1300
- * Chat Completions accepts Azure AI Foundry hosts in addition to traditional
1301
- * Azure OpenAI hosts. Do not replace this with isTraditionalAzureOpenAIHost,
1302
- * which intentionally excludes the .services.ai.azure.com Foundry suffix.
1303
- */
1304
- function isAzureOpenAICompatibleHost(hostname) {
1305
- return hostname.endsWith(".openai.azure.com") || hostname.endsWith(".services.ai.azure.com") || hostname.endsWith(".cognitiveservices.azure.com");
1306
- }
1307
- //#endregion
1308
- //#region packages/ai/src/transports/openai-completions-replay.ts
1309
- function isGoogleOpenAICompatModel(model) {
1310
- const endpointClass = detectOpenAICompletionsCompat(model).capabilities.endpointClass;
1311
- return model.provider === "google" || endpointClass === "google-generative-ai" || endpointClass === "google-vertex";
1312
- }
1313
- function requiresGoogleCompatToolCallThoughtSignature(model) {
1314
- return isGoogleGemini3ProModel(model.id) || isGoogleGemini3FlashModel(model.id);
1315
- }
1316
- const GOOGLE_COMPAT_THOUGHT_SIGNATURE_ELLIPSIS_RE = /[\u2026]|\.\.\./;
1317
- const GOOGLE_COMPAT_THOUGHT_SIGNATURE_BASE64_RE = /^[A-Za-z0-9+/=]+$/;
1318
- function hasGoogleCompatThoughtSignatureTruncationFootprint(value) {
1319
- return GOOGLE_COMPAT_THOUGHT_SIGNATURE_ELLIPSIS_RE.test(value) || GOOGLE_COMPAT_THOUGHT_SIGNATURE_BASE64_RE.test(value) && value.length % 4 !== 0;
1320
- }
1321
- function injectToolCallThoughtSignatures(outgoingMessages, context, model) {
1322
- if (!isGoogleOpenAICompatModel(model)) return;
1323
- const sigById = /* @__PURE__ */ new Map();
1324
- const fallbackSig = requiresGoogleCompatToolCallThoughtSignature(model) ? GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP : void 0;
1325
- for (const msg of context.messages ?? []) {
1326
- if (msg.role !== "assistant") continue;
1327
- const source = msg;
1328
- if (!Array.isArray(source.content)) continue;
1329
- for (const block of source.content) {
1330
- if (block.type !== "toolCall") continue;
1331
- const id = block.id;
1332
- const sig = block.thoughtSignature;
1333
- if (typeof id === "string" && typeof sig === "string" && sig.length > 0) {
1334
- const isSameRoute = source.api === model.api && source.provider === model.provider && source.model === model.id;
1335
- if (!isSameRoute && !fallbackSig) continue;
1336
- sigById.set(id, isSameRoute ? sig : fallbackSig ?? sig);
1337
- }
1338
- }
1339
- }
1340
- if (sigById.size === 0 && !fallbackSig) return;
1341
- for (const message of outgoingMessages) {
1342
- const toolCalls = message.tool_calls;
1343
- if (!Array.isArray(toolCalls)) continue;
1344
- for (const toolCall of toolCalls) {
1345
- const id = toolCall.id;
1346
- if (typeof id !== "string") continue;
1347
- let sig = sigById.get(id) ?? fallbackSig;
1348
- if (typeof sig === "string" && sig.length > 0) {
1349
- if (hasGoogleCompatThoughtSignatureTruncationFootprint(sig.trim())) sig = fallbackSig;
1350
- }
1351
- if (typeof sig !== "string" || sig.length === 0) continue;
1352
- const extra = toolCall.extra_content && typeof toolCall.extra_content === "object" ? toolCall.extra_content : {};
1353
- toolCall.extra_content = extra;
1354
- const google = extra.google && typeof extra.google === "object" ? extra.google : {};
1355
- extra.google = google;
1356
- google.thought_signature = sig;
1357
- }
1358
- }
1359
- }
1360
- const COMPLETIONS_REASONING_REPLAY_FIELDS = [
1361
- "reasoning_details",
1362
- "reasoning_content",
1363
- "reasoning",
1364
- "reasoning_text"
1365
- ];
1366
- function stripCompletionsReasoningReplayFields(record) {
1367
- for (const field of COMPLETIONS_REASONING_REPLAY_FIELDS) if (field in record) delete record[field];
1368
- }
1369
- function sanitizeOpenRouterReasoningReplayFields(record) {
1370
- const reasoningDetails = record.reasoning_details;
1371
- if (typeof reasoningDetails === "string") {
1372
- if (reasoningDetails.length > 0 && typeof record.reasoning !== "string") record.reasoning = reasoningDetails;
1373
- delete record.reasoning_details;
1374
- } else if (reasoningDetails !== void 0 && !Array.isArray(reasoningDetails)) delete record.reasoning_details;
1375
- if ("reasoning" in record && (typeof record.reasoning !== "string" || record.reasoning === "")) delete record.reasoning;
1376
- if ("reasoning_content" in record && (typeof record.reasoning_content !== "string" || record.reasoning_content === "")) delete record.reasoning_content;
1377
- const reasoningText = record.reasoning_text;
1378
- if (typeof reasoningText === "string" && reasoningText.length > 0 && typeof record.reasoning !== "string" && typeof record.reasoning_content !== "string") record.reasoning = reasoningText;
1379
- if ("reasoning_text" in record) delete record.reasoning_text;
1380
- }
1381
- function sanitizeReasoningContentReplayFields(record) {
1382
- if ("reasoning_content" in record && typeof record.reasoning_content !== "string") delete record.reasoning_content;
1383
- delete record.reasoning_details;
1384
- delete record.reasoning;
1385
- delete record.reasoning_text;
1386
- }
1387
- const REASONING_CONTENT_REPLAY_MODEL_IDS = /* @__PURE__ */ new Set([
1388
- "deepseek-v4-flash",
1389
- "deepseek-v4-pro",
1390
- "kimi-for-coding",
1391
- "kimi-k2.5",
1392
- "kimi-k2.6",
1393
- "kimi-k2.7-code",
1394
- "kimi-k2.7-code-highspeed",
1395
- "kimi-k3",
1396
- "kimi-k2-thinking",
1397
- "kimi-k2-thinking-turbo",
1398
- "mimo-v2-pro",
1399
- "mimo-v2-omni",
1400
- "mimo-v2.5",
1401
- "mimo-v2.5-pro",
1402
- "mimo-v2.6-pro"
1403
- ]);
1404
- const REASONING_CONTENT_REPLAY_TIER_SUFFIXES = [
1405
- "-free",
1406
- "-paid",
1407
- "-trial"
1408
- ];
1409
- function stripReasoningContentReplayTierSuffix(modelId) {
1410
- for (const suffix of REASONING_CONTENT_REPLAY_TIER_SUFFIXES) if (modelId.length > suffix.length && modelId.endsWith(suffix)) return modelId.slice(0, -suffix.length);
1411
- return modelId;
1412
- }
1413
- function getReasoningContentReplayModelIdCandidates(modelId) {
1414
- if (typeof modelId !== "string") return [];
1415
- const normalized = modelId.trim().toLowerCase();
1416
- if (!normalized) return [];
1417
- const parts = normalized.split("/").filter(Boolean);
1418
- const finalPart = parts[parts.length - 1] ?? normalized;
1419
- const candidates = [finalPart];
1420
- const colonParts = finalPart.split(":").filter(Boolean);
1421
- if (colonParts.length > 1) candidates.push(colonParts[0] ?? "", colonParts[colonParts.length - 1] ?? "");
1422
- const baseCount = candidates.length;
1423
- for (let index = 0; index < baseCount; index += 1) {
1424
- const candidate = candidates[index];
1425
- if (typeof candidate !== "string") continue;
1426
- const stripped = stripReasoningContentReplayTierSuffix(candidate);
1427
- if (stripped !== candidate) candidates.push(stripped);
1428
- }
1429
- return uniqueStrings(candidates.filter(Boolean));
1430
- }
1431
- function shouldPreserveReasoningContentReplay(model, compat) {
1432
- if (compat.requiresReasoningContentOnAssistantMessages || compat.thinkingFormat === "deepseek" || compat.thinkingFormat === "zai" || shouldTrustReasoningContentReplayMetadata(model)) return true;
1433
- return getReasoningContentReplayModelIdCandidates(model.id).some((modelId) => REASONING_CONTENT_REPLAY_MODEL_IDS.has(modelId));
1434
- }
1435
- function shouldPreserveOpenRouterReasoningReplay(model) {
1436
- if (model.provider !== "openrouter") return true;
1437
- const normalizedModelId = model.id.trim().toLowerCase();
1438
- return !(normalizedModelId.startsWith("anthropic/") || normalizedModelId.startsWith("x-ai/"));
1439
- }
1440
- function shouldTrustReasoningContentReplayMetadata(model) {
1441
- if (!model.reasoning) return false;
1442
- if (model.provider.trim().toLowerCase() === "openai") return false;
1443
- return shouldPreserveOpenRouterReasoningReplay(model);
1444
- }
1445
- function sanitizeCompletionsReasoningReplayFields(messages, options) {
1446
- if (!Array.isArray(messages)) return;
1447
- for (const msg of messages) {
1448
- if (!msg || typeof msg !== "object") continue;
1449
- const record = msg;
1450
- if (record.role !== "assistant") continue;
1451
- if (options.preserveOpenRouterReasoning) sanitizeOpenRouterReasoningReplayFields(record);
1452
- else if (options.preserveReasoningContent) sanitizeReasoningContentReplayFields(record);
1453
- else stripCompletionsReasoningReplayFields(record);
1454
- }
1455
- }
1456
- function applyCompletionsReplay(outgoingMessages, context, model, compat) {
1457
- injectToolCallThoughtSignatures(outgoingMessages, context, model);
1458
- sanitizeCompletionsReasoningReplayFields(outgoingMessages, {
1459
- preserveOpenRouterReasoning: compat.thinkingFormat === "openrouter" && shouldPreserveOpenRouterReasoningReplay(model),
1460
- preserveReasoningContent: shouldPreserveReasoningContentReplay(model, compat)
1461
- });
1462
- }
1463
- //#endregion
1464
- //#region packages/ai/src/transports/openai-completions-params.ts
1465
- function isKnownOpenAICompletionsEndpoint(model) {
1466
- if (!model.baseUrl.trim()) return true;
1467
- const endpointClass = resolveProviderEndpoint(model).endpointClass;
1468
- if (endpointClass === "openai-public" || endpointClass === "azure-openai") return true;
1469
- try {
1470
- return isAzureOpenAICompatibleHost(new URL(model.baseUrl).hostname.toLowerCase());
1471
- } catch {
1472
- return false;
1473
- }
1474
- }
1475
- function resolveOpenAICompletionsReasoningEffort(options) {
1476
- return options?.reasoningEffort ?? options?.reasoning ?? "high";
1477
- }
1478
- function resolveOpenAICompletionsMaxTokens(model, options) {
1479
- if (options?.maxTokens) return {
1480
- maxTokens: options.maxTokens,
1481
- clampToModelMaxTokens: true
1482
- };
1483
- const paramsMaxTokens = resolveMaxTokensParam(model.params);
1484
- if (paramsMaxTokens) return {
1485
- maxTokens: paramsMaxTokens,
1486
- clampToModelMaxTokens: false
1487
- };
1488
- return {
1489
- maxTokens: model.maxTokens,
1490
- clampToModelMaxTokens: false
1491
- };
1492
- }
1493
- function resolveOpenAICompletionsModelMaxTokens(model) {
1494
- return typeof model.maxTokens === "number" && Number.isFinite(model.maxTokens) && model.maxTokens > 0 ? Math.floor(model.maxTokens) : void 0;
1495
- }
1496
- const OPENAI_COMPLETIONS_INPUT_TOKEN_SAFETY_MARGIN = 1.25;
1497
- const OPENAI_COMPLETIONS_IMAGE_CHAR_ESTIMATE = 8e3;
1498
- function estimateOpenAICompletionsInputTokens(payload) {
1499
- let adjustedChars = 0;
1500
- adjustedChars += estimateOpenAICompletionsMessagesChars(payload.messages);
1501
- if (Array.isArray(payload.tools) && payload.tools.length > 0) try {
1502
- adjustedChars += estimateStringChars(JSON.stringify(payload.tools));
1503
- } catch {
1504
- adjustedChars += 1024;
1505
- }
1506
- if (payload.response_format !== void 0) try {
1507
- adjustedChars += estimateStringChars(JSON.stringify(payload.response_format));
1508
- } catch {
1509
- adjustedChars += 256;
1510
- }
1511
- return Math.ceil(adjustedChars / 4 * OPENAI_COMPLETIONS_INPUT_TOKEN_SAFETY_MARGIN);
1512
- }
1513
- function estimateOpenAICompletionsMessagesChars(messages) {
1514
- if (!Array.isArray(messages)) return 0;
1515
- let adjustedChars = 0;
1516
- for (const message of messages) {
1517
- if (!message || typeof message !== "object") continue;
1518
- const record = message;
1519
- adjustedChars += estimateOpenAICompletionsContentChars(record.content);
1520
- for (const field of COMPLETIONS_REASONING_REPLAY_FIELDS) adjustedChars += estimateOpenAICompletionsContentChars(record[field]);
1521
- if (record.tool_calls !== void 0) try {
1522
- adjustedChars += estimateStringChars(JSON.stringify(record.tool_calls));
1523
- } catch {
1524
- adjustedChars += 256;
1525
- }
1526
- }
1527
- return adjustedChars;
1528
- }
1529
- function estimateOpenAICompletionsContentChars(value) {
1530
- if (typeof value === "string") return estimateStringChars(value);
1531
- if (!Array.isArray(value)) return 0;
1532
- let adjustedChars = 0;
1533
- for (const block of value) {
1534
- if (!block || typeof block !== "object") continue;
1535
- const record = block;
1536
- if (record.type === "image_url" || record.type === "input_image") {
1537
- adjustedChars += OPENAI_COMPLETIONS_IMAGE_CHAR_ESTIMATE;
1538
- continue;
1539
- }
1540
- const text = record.text;
1541
- if (typeof text === "string") {
1542
- adjustedChars += estimateStringChars(text);
1543
- continue;
1544
- }
1545
- try {
1546
- adjustedChars += estimateStringChars(JSON.stringify(block));
1547
- } catch {
1548
- adjustedChars += 256;
1549
- }
1550
- }
1551
- return adjustedChars;
1552
- }
1553
- function resolveOpenAICompletionsEffectiveContextTokens(model) {
1554
- const contextTokens = model.contextTokens;
1555
- if (typeof contextTokens === "number" && Number.isFinite(contextTokens) && contextTokens > 0) return contextTokens;
1556
- return typeof model.contextWindow === "number" && Number.isFinite(model.contextWindow) && model.contextWindow > 0 ? model.contextWindow : void 0;
1557
- }
1558
- function isQwenOpenAICompletionsThinkingFormat(format) {
1559
- return format === "qwen" || format === "qwen-chat-template";
1560
- }
1561
- function setQwenChatTemplateThinking(params, enabled) {
1562
- const existing = params.chat_template_kwargs;
1563
- params.chat_template_kwargs = existing && typeof existing === "object" && !Array.isArray(existing) ? {
1564
- ...existing,
1565
- enable_thinking: enabled
1566
- } : { enable_thinking: enabled };
1567
- }
1568
- function applyQwenOpenAICompletionsThinkingParams(params) {
1569
- if (!params.modelReasoning || !isQwenOpenAICompletionsThinkingFormat(params.compatThinkingFormat)) return false;
1570
- const enabled = isOpenAICompletionsThinkingEnabled(params.requestedEffort);
1571
- if (params.compatThinkingFormat === "qwen-chat-template") setQwenChatTemplateThinking(params.payload, enabled);
1572
- else params.payload.enable_thinking = enabled;
1573
- return true;
1574
- }
1575
- function applyTogetherOpenAICompletionsThinkingParams(params) {
1576
- if (!params.modelReasoning || params.compatThinkingFormat !== "together") return;
1577
- params.payload.reasoning = { enabled: isOpenAICompletionsThinkingEnabled(params.requestedEffort) };
1578
- }
1579
- function convertTools(tools, compat, model) {
1580
- const projection = projectOpenAITools(tools);
1581
- const strict = resolveOpenAIStrictToolFlagWithDiagnostics(projection, resolveOpenAIStrictToolSetting(model, {
1582
- transport: "stream",
1583
- supportsStrictMode: compat?.supportsStrictMode
1584
- }), {
1585
- transport: "completions",
1586
- model
1587
- });
1588
- return {
1589
- projection,
1590
- tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
1591
- const functionTool = {
1592
- name: tool.name,
1593
- description: tool.description,
1594
- parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model.compat)
1595
- };
1596
- if (strict !== void 0) functionTool.strict = strict;
1597
- return {
1598
- type: "function",
1599
- function: functionTool
1600
- };
1601
- })
1602
- };
1603
- }
1604
- function buildOpenAICompletionsParams(model, context, options) {
1605
- const compat = getCompat(model);
1606
- const compatDetection = detectOpenAICompletionsCompat(model);
1607
- const completionsContext = context.systemPrompt ? {
1608
- ...context,
1609
- systemPrompt: stripSystemPromptCacheBoundary(context.systemPrompt)
1610
- } : context;
1611
- let messages = convertMessages(model, completionsContext, compat);
1612
- applyCompletionsReplay(messages, context, model, compat);
1613
- if (compat.strictMessageKeys) messages = stripCompletionMessagesToRoleContent(messages);
1614
- const cacheRetention = resolveCacheRetention(options?.cacheRetention);
1615
- const promptCacheKey = resolvePromptCacheKey(options, cacheRetention);
1616
- const params = {
1617
- model: model.id,
1618
- messages: compat.requiresStringContent ? flattenCompletionMessagesToStringContent(messages) : messages,
1619
- stream: true
1620
- };
1621
- if (compat.supportsUsageInStreaming) params.stream_options = { include_usage: true };
1622
- if (compat.supportsStore) params.store = false;
1623
- if (compat.supportsPromptCacheKey && promptCacheKey) {
1624
- params.prompt_cache_key = promptCacheKey;
1625
- if (cacheRetention === "long" && compat.supportsLongCacheRetention) params.prompt_cache_retention = "24h";
1626
- }
1627
- if (options?.temperature !== void 0) params.temperature = options.temperature;
1628
- if (options?.topP !== void 0) params.top_p = options.topP;
1629
- const responseFormat = resolveOpenAICompletionsResponseFormat(shouldOmitOllamaCompatResponseFormat({
1630
- provider: model.provider,
1631
- baseUrl: model.baseUrl,
1632
- hasTools: () => Boolean(context.tools?.length)
1633
- }) ? void 0 : options?.responseFormat, compat.supportsJsonSchemaResponseFormat);
1634
- if (responseFormat !== void 0) params.response_format = responseFormat;
1635
- if (options?.frequencyPenalty !== void 0) params.frequency_penalty = options.frequencyPenalty;
1636
- if (options?.presencePenalty !== void 0) params.presence_penalty = options.presencePenalty;
1637
- if (options?.seed !== void 0) params.seed = options.seed;
1638
- if (options?.stop !== void 0 && options.stop.length > 0) params.stop = options.stop;
1639
- if (supportsModelTools(model)) {
1640
- if (context.tools) {
1641
- const converted = convertTools(context.tools, compat, model);
1642
- if (converted.tools.length > 0 || converted.projection.inputToolCount === 0 && converted.projection.diagnostics.length === 0) params.tools = converted.tools;
1643
- else if (hasToolCallHistory(context.messages)) params.tools = [];
1644
- if (options?.toolChoice) {
1645
- const toolChoice = reconcileOpenAICompletionsToolChoice(options.toolChoice, converted.projection);
1646
- if (toolChoice !== void 0) params.tool_choice = toolChoice;
1647
- } else if (compatDetection.capabilities.usesExplicitProxyLikeEndpoint && Array.isArray(params.tools) && params.tools.length > 0) params.tool_choice = "auto";
1648
- } else if (hasToolCallHistory(context.messages)) params.tools = [];
1649
- if (compatDetection.capabilities.usesExplicitProxyLikeEndpoint && Array.isArray(params.tools) && params.tools.length === 0) {
1650
- delete params.tools;
1651
- delete params.tool_choice;
1652
- }
1653
- }
1654
- {
1655
- const maxTokenBudget = resolveOpenAICompletionsMaxTokens(model, options);
1656
- const effectiveMaxTokens = maxTokenBudget.maxTokens;
1657
- const effectiveContextTokens = resolveOpenAICompletionsEffectiveContextTokens(model);
1658
- let clampedMaxTokens = effectiveMaxTokens;
1659
- const modelMaxTokens = resolveOpenAICompletionsModelMaxTokens(model);
1660
- if (maxTokenBudget.clampToModelMaxTokens && clampedMaxTokens !== void 0 && modelMaxTokens !== void 0 && clampedMaxTokens > modelMaxTokens) {
1661
- clampedMaxTokens = modelMaxTokens;
1662
- emitModelTransportDebug(log, `[completions] clamp_max_tokens provider=${model.provider} api=${model.api} model=${model.id} requested=${effectiveMaxTokens} output=${clampedMaxTokens} modelMaxTokens=${modelMaxTokens}`);
1663
- }
1664
- if (compatDetection.capabilities.usesExplicitProxyLikeEndpoint && clampedMaxTokens !== void 0 && effectiveContextTokens !== void 0) {
1665
- const estimatedInputTokens = estimateOpenAICompletionsInputTokens(params);
1666
- const remainingBudget = Math.max(1, effectiveContextTokens - estimatedInputTokens - 1);
1667
- if (clampedMaxTokens > remainingBudget) {
1668
- clampedMaxTokens = remainingBudget;
1669
- emitModelTransportDebug(log, `[completions] clamp_max_tokens provider=${model.provider} api=${model.api} model=${model.id} requested=${effectiveMaxTokens} output=${clampedMaxTokens} effectiveContext=${effectiveContextTokens} estimatedInput=${estimatedInputTokens}`);
1670
- }
1671
- }
1672
- if (clampedMaxTokens) {
1673
- if (compat.maxTokensField === "max_tokens") params.max_tokens = clampedMaxTokens;
1674
- else params.max_completion_tokens = clampedMaxTokens;
1675
- }
1676
- }
1677
- const completionsReasoningEffort = resolveOpenAICompletionsReasoningEffort(options);
1678
- const resolvedCompletionsReasoningEffort = completionsReasoningEffort ? resolveOpenAIReasoningEffortForModel({
1679
- model,
1680
- effort: completionsReasoningEffort,
1681
- fallbackMap: compat.reasoningEffortMap
1682
- }) : void 0;
1683
- const omitChatCompletionsToolReasoningEffort = Array.isArray(params.tools) && params.tools.length > 0 && (isOpenAIGpt54MiniModel(model) || isOpenAIGpt55Model(model) && isKnownOpenAICompletionsEndpoint(model));
1684
- const disableChatCompletionsToolReasoning = Array.isArray(params.tools) && params.tools.length > 0 && isOpenAIGpt56Model(model) && isKnownOpenAICompletionsEndpoint(model);
1685
- const handledQwenThinkingFormat = applyQwenOpenAICompletionsThinkingParams({
1686
- compatThinkingFormat: compat.thinkingFormat,
1687
- modelReasoning: model.reasoning,
1688
- payload: params,
1689
- requestedEffort: completionsReasoningEffort
1690
- });
1691
- applyTogetherOpenAICompletionsThinkingParams({
1692
- compatThinkingFormat: compat.thinkingFormat,
1693
- modelReasoning: model.reasoning,
1694
- payload: params,
1695
- requestedEffort: completionsReasoningEffort
1696
- });
1697
- if (disableChatCompletionsToolReasoning) params.reasoning_effort = "none";
1698
- else if (compat.thinkingFormat === "openrouter" && model.reasoning && resolvedCompletionsReasoningEffort) params.reasoning = { effort: resolvedCompletionsReasoningEffort };
1699
- else if (resolvedCompletionsReasoningEffort && model.reasoning && compat.supportsReasoningEffort && !handledQwenThinkingFormat && !omitChatCompletionsToolReasoningEffort) params.reasoning_effort = resolvedCompletionsReasoningEffort;
1700
- return params;
1701
- }
1702
- //#endregion
1703
530
  //#region packages/ai/src/transports/openai-completions-transport.ts
1704
531
  function assertOpenAICompletionsPayloadHasConversationTurn(params, model) {
1705
532
  const messages = params.messages;
@@ -1810,6 +637,14 @@ function createOpenAICompletionsTransportStreamFn() {
1810
637
  let firstEventAbort;
1811
638
  try {
1812
639
  const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
640
+ const turnState = resolveProviderTransportTurnState(model, {
641
+ sessionId: options?.sessionId,
642
+ turnId: randomUUID(),
643
+ attempt: 1,
644
+ transport: "stream"
645
+ });
646
+ const optionHeaders = resolveOpencodeSessionHeaders(model, options);
647
+ const turnHeaders = filterProviderTurnHeadersForExplicitOpencodeSession(model, options, turnState?.headers);
1813
648
  const doneDetector = createSseDoneDetector();
1814
649
  const baseFetch = buildGuardedModelFetch(model);
1815
650
  const doneDetectingFetch = async (url, init) => {
@@ -1831,7 +666,10 @@ function createOpenAICompletionsTransportStreamFn() {
1831
666
  statusText: response.statusText
1832
667
  });
1833
668
  };
1834
- const client = createOpenAICompletionsClient(model, context, apiKey, options?.headers, { fetch: doneDetectingFetch });
669
+ const client = createOpenAICompletionsClient(model, context, apiKey, {
670
+ ...turnHeaders,
671
+ ...optionHeaders
672
+ }, { fetch: doneDetectingFetch });
1835
673
  let params = buildOpenAICompletionsParams(model, context, options);
1836
674
  const nextParams = await options?.onPayload?.(params, model);
1837
675
  if (nextParams !== void 0) params = nextParams;
@@ -1895,26 +733,6 @@ const OPENAI_RESPONSES_TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set([
1895
733
  "azure-openai-responses",
1896
734
  "github-copilot"
1897
735
  ]);
1898
- function convertResponsesTools(tools, model, options) {
1899
- const projection = projectOpenAITools(tools);
1900
- const strict = resolveOpenAIStrictToolFlagWithDiagnostics(projection, options?.strict, {
1901
- transport: "responses",
1902
- model
1903
- });
1904
- return {
1905
- projection,
1906
- tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
1907
- const result = {
1908
- type: "function",
1909
- name: tool.name,
1910
- description: tool.description,
1911
- parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model.compat)
1912
- };
1913
- if (strict !== void 0) result.strict = strict;
1914
- return result;
1915
- })
1916
- };
1917
- }
1918
736
  function resolveOpenAIReasoningEffort(options) {
1919
737
  return normalizeOpenAIReasoningEffort(options?.reasoningEffort ?? options?.reasoning ?? "high");
1920
738
  }
@@ -1947,6 +765,7 @@ const OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS = [
1947
765
  "max_output_tokens",
1948
766
  "metadata",
1949
767
  "prompt_cache_retention",
768
+ "prompt_cache_options",
1950
769
  "service_tier",
1951
770
  "temperature",
1952
771
  "top_p"
@@ -1962,6 +781,7 @@ function stripOpenAICodexResponsesUnsupportedTextFields(params) {
1962
781
  function sanitizeOpenAICodexResponsesParams(model, params) {
1963
782
  if (!usesNativeOpenAICodexResponsesBackend(model)) return params;
1964
783
  for (const key of OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS) delete params[key];
784
+ Object.assign(params, { store: false });
1965
785
  stripOpenAICodexResponsesUnsupportedTextFields(params);
1966
786
  return params;
1967
787
  }
@@ -2018,14 +838,15 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
2018
838
  const messages = convertOpenAIResponsesMessagesForRequest(model, context, options, replayMode);
2019
839
  ensureOpenAIResponsesNonEmptyInput(messages, context);
2020
840
  const cacheRetention = resolveCacheRetention(options?.cacheRetention);
2021
- const promptCacheKey = resolvePromptCacheKey(options, cacheRetention);
841
+ const compat = getCompat(model);
842
+ const promptCacheKey = compat.supportsPromptCacheKey ? resolvePromptCacheKey(options, cacheRetention) : void 0;
2022
843
  const instructions = resolveOpenAIResponsesInstructions(model, context, payloadPolicy.usesInstructionsField);
2023
844
  const params = {
2024
845
  model: model.id,
2025
846
  input: messages,
2026
847
  stream: true,
2027
848
  prompt_cache_key: promptCacheKey,
2028
- ...resolveOpenAIResponsesCacheParams(model, cacheRetention, model.baseUrl?.includes("api.openai.com")),
849
+ ...resolveOpenAIPromptCacheParams(model, cacheRetention, compat),
2029
850
  ...instructions ? { instructions } : {},
2030
851
  ...metadata ? { metadata } : {}
2031
852
  };
@@ -2039,10 +860,13 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
2039
860
  };
2040
861
  if (options?.serviceTier !== void 0 && payloadPolicy.allowsServiceTier) params.service_tier = options.serviceTier;
2041
862
  if (context.tools) {
2042
- const converted = convertResponsesTools(context.tools, model, { strict: resolveOpenAIStrictToolSetting(model, { transport: "stream" }) });
2043
- if (converted.tools.length > 0 || converted.projection.inputToolCount === 0 && converted.projection.diagnostics.length === 0) params.tools = converted.tools;
863
+ const tools = context.tools;
864
+ const strict = resolveOpenAIStrictToolSetting(model, { transport: "stream" });
865
+ const projection = projectOpenAITools(tools);
866
+ const converted = convertProjectedResponsesTools(projection, strict, model);
867
+ if (converted.length > 0 || projection.inputToolCount === 0 && projection.diagnostics.length === 0) params.tools = converted;
2044
868
  if (options?.toolChoice) {
2045
- const toolChoice = reconcileOpenAIResponsesToolChoice(options.toolChoice, converted.projection);
869
+ const toolChoice = reconcileOpenAIResponsesToolChoice(options.toolChoice, projection);
2046
870
  if (toolChoice !== void 0) params.tool_choice = toolChoice;
2047
871
  }
2048
872
  }
@@ -2165,6 +989,14 @@ function normalizeAssistantReplayInput(input, fromResponse = false) {
2165
989
  return stableItem;
2166
990
  });
2167
991
  }
992
+ function responsesContinuationRequestFingerprint(request) {
993
+ const serialized = JSON.stringify(requestWithoutInput(request));
994
+ return sha256Hex(stableStringify(JSON.parse(serialized)));
995
+ }
996
+ function responsesContinuationPrefixFingerprint(input, output = []) {
997
+ const serialized = JSON.stringify([...normalizeAssistantReplayInput(input), ...normalizeAssistantReplayInput(output, true)]);
998
+ return sha256Hex(stableStringify(JSON.parse(serialized)));
999
+ }
2168
1000
  function resolveResponsesContinuationRequest(continuation, request, steering) {
2169
1001
  if (!continuation) return {
2170
1002
  request,
@@ -2227,8 +1059,9 @@ function claimOpenAIResponsesHttpContinuation(params) {
2227
1059
  };
2228
1060
  httpContinuationEntries.set(key, claimed);
2229
1061
  try {
2230
- const resolved = resolveResponsesContinuationRequest(previous?.kind === "ready" ? previous.state : void 0, params.request);
2231
- const fullRequest = resolved.fullRequest ?? params.request;
1062
+ const request = previous?.kind === "ready" ? params.request : params.restoreRequest?.() ?? params.request;
1063
+ const resolved = resolveResponsesContinuationRequest(previous?.kind === "ready" ? previous.state : void 0, request);
1064
+ const fullRequest = resolved.fullRequest ?? request;
2232
1065
  return {
2233
1066
  request: params.request.store === false ? fullRequest : resolved.request,
2234
1067
  fullRequest,
@@ -2532,7 +1365,7 @@ function readServerEvent(message) {
2532
1365
  }
2533
1366
  function createOpenAIResponsesWebSocketStream(params) {
2534
1367
  const connection = prepareWebSocketConnection(params.client, params.headers);
2535
- const fullRequest = sanitizeWebSocketRequest(params.request);
1368
+ let fullRequest = sanitizeWebSocketRequest(params.request);
2536
1369
  const requestModel = typeof fullRequest.model === "string" ? fullRequest.model : "";
2537
1370
  const degradationKey = `${params.sessionId ?? ""}\0${connection.identity}\0${requestModel}`;
2538
1371
  const degraded = degradedWebSocketConnections.get(degradationKey);
@@ -2561,10 +1394,13 @@ function createOpenAIResponsesWebSocketStream(params) {
2561
1394
  if (continuation && lease.entry) {
2562
1395
  lease.entry.continuation = void 0;
2563
1396
  prepared = resolveResponsesContinuationRequest(continuation, fullRequest, steeringMode);
2564
- } else prepared = {
2565
- request: fullRequest,
2566
- continuationStatus: lease.entry ? "no_previous_response" : "socket_not_cached"
2567
- };
1397
+ } else {
1398
+ fullRequest = params.restoreRequest?.(fullRequest) ?? fullRequest;
1399
+ prepared = {
1400
+ request: fullRequest,
1401
+ continuationStatus: lease.entry ? "no_previous_response" : "socket_not_cached"
1402
+ };
1403
+ }
2568
1404
  } catch (error) {
2569
1405
  lease.iterator.return?.().catch(() => void 0);
2570
1406
  lease.release({ keep: false });
@@ -2731,6 +1567,7 @@ function createOpenAIResponsesWebSocketStream(params) {
2731
1567
  }
2732
1568
  } },
2733
1569
  request: prepared.request,
1570
+ fullRequest: prepared.fullRequest ?? fullRequest,
2734
1571
  reusedConnection: lease.reusedConnection,
2735
1572
  continuationStatus: prepared.continuationStatus,
2736
1573
  inputReplay,
@@ -2810,6 +1647,59 @@ async function requestPreparedOpenAIResponsesCompaction(streamFn, model, context
2810
1647
  }
2811
1648
  }
2812
1649
  //#endregion
1650
+ //#region packages/ai/src/transports/openai-responses-reasoning-state.ts
1651
+ function inputReplay(message) {
1652
+ const value = "openclawResponsesInputReplay" in message ? message.openclawResponsesInputReplay : void 0;
1653
+ return isRecord(value) ? value : void 0;
1654
+ }
1655
+ /** Save only admitted settings and hashes, never another copy of the conversation. */
1656
+ function recordResponsesReasoningState(message, model, identity, request, output) {
1657
+ if (!supportsResponsesReasoningUpdate(request) || !isRecord(request.reasoning) || !request.input || request.previous_response_id || message.providerReplay || output.some((item) => isRecord(item) && item.type === "compaction")) return;
1658
+ const reasoning = {
1659
+ ...buildProviderReplayContext(model, identity),
1660
+ effort: request.reasoning.effort,
1661
+ controls: request.input.flatMap((item, index) => isConfigurationUpdate(item) ? [{
1662
+ index,
1663
+ item
1664
+ }] : []),
1665
+ inputLength: request.input.length,
1666
+ outputLength: output.length,
1667
+ prefixHash: responsesContinuationPrefixFingerprint(request.input, output),
1668
+ requestHash: responsesContinuationRequestFingerprint(request)
1669
+ };
1670
+ Object.assign(message, { openclawResponsesInputReplay: {
1671
+ ...inputReplay(message),
1672
+ reasoning
1673
+ } });
1674
+ }
1675
+ /** A cold transport can replay controls, but cannot resurrect a server response handle. */
1676
+ function restoreResponsesReasoningState(context, model, identity, request) {
1677
+ const latest = context.messages.findLast((message) => message.role === "assistant");
1678
+ const state = latest ? inputReplay(latest)?.reasoning : void 0;
1679
+ if (!isRecord(state)) return request;
1680
+ const { effort, inputLength, outputLength, controls, prefixHash, requestHash } = state;
1681
+ if (!isOpenAIResponsesReplayContext(state) || !providerReplayContextMatches(state, buildProviderReplayContext(model, identity)) || latest?.providerReplay || !supportsResponsesReasoningUpdate(request) || !isRecord(request.reasoning) || !request.input || request.previous_response_id || request.input.some(isConfigurationUpdate) || typeof effort !== "string" || typeof inputLength !== "number" || !Number.isSafeInteger(inputLength) || inputLength < 0 || typeof outputLength !== "number" || !Number.isSafeInteger(outputLength) || outputLength < 0 || !Array.isArray(controls) || controls.length > inputLength || inputLength + outputLength > request.input.length + controls.length) return request;
1682
+ const previousInput = request.input.slice(0, inputLength - controls.length);
1683
+ let lastIndex = -1;
1684
+ for (const control of controls) {
1685
+ if (!isRecord(control) || typeof control.index !== "number" || !Number.isSafeInteger(control.index) || control.index <= lastIndex || control.index > previousInput.length || !isConfigurationUpdate(control.item)) return request;
1686
+ previousInput.splice(control.index, 0, control.item);
1687
+ lastIndex = control.index;
1688
+ }
1689
+ const previous = {
1690
+ ...request,
1691
+ reasoning: {
1692
+ ...request.reasoning,
1693
+ effort
1694
+ },
1695
+ input: previousInput
1696
+ };
1697
+ if (responsesContinuationRequestFingerprint(previous) !== requestHash) return request;
1698
+ const prepared = replayResponsesReasoningUpdates(previous, request, outputLength);
1699
+ if (responsesContinuationPrefixFingerprint((prepared.input ?? []).slice(0, inputLength + outputLength)) !== prefixHash) return request;
1700
+ return prepared;
1701
+ }
1702
+ //#endregion
2813
1703
  //#region packages/ai/src/transports/openai-responses-client.ts
2814
1704
  function resolveNativeOpenAIResponsesWebSocketMode(model, transport) {
2815
1705
  if (transport !== "websocket" && transport !== "websocket-cached" && transport !== "auto") return;
@@ -2825,30 +1715,12 @@ function combineWebSocketTimeoutSignal(signal, model, timeoutMs) {
2825
1715
  if (resolvedTimeoutMs === void 0 || !Number.isFinite(resolvedTimeoutMs)) return signal;
2826
1716
  return AbortSignal.any([signal, AbortSignal.timeout(Math.max(1, resolvedTimeoutMs))]);
2827
1717
  }
2828
- function resolveProviderTransportTurnState(model, params) {
2829
- const normalizedProvider = model.provider.trim().toLowerCase();
2830
- const allowRuntimePluginLoad = normalizedProvider === "openai" || normalizedProvider === "azure-openai" || normalizedProvider === "azure-openai-responses";
2831
- return getAiTransportHost().plugin.resolveTransportTurnState({
2832
- provider: model.provider,
2833
- modelId: model.id,
2834
- allowRuntimePluginLoad,
2835
- context: {
2836
- provider: model.provider,
2837
- modelId: model.id,
2838
- model,
2839
- sessionId: params.sessionId,
2840
- turnId: params.turnId,
2841
- attempt: params.attempt,
2842
- transport: params.transport
2843
- }
2844
- });
2845
- }
2846
- function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId, fetchOverride) {
1718
+ function createOpenAIResponsesClient(model, apiKey, defaultHeaders, fetchOverride) {
2847
1719
  return new OpenAI({
2848
1720
  apiKey,
2849
1721
  baseURL: resolveOpenAIClientBaseUrl(model),
2850
1722
  dangerouslyAllowBrowser: true,
2851
- defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId),
1723
+ defaultHeaders,
2852
1724
  fetch: fetchOverride ?? buildGuardedModelFetch(model),
2853
1725
  ...buildOpenAISdkClientOptions(model)
2854
1726
  });
@@ -2872,8 +1744,11 @@ function createResponsesTransportExecutor(config) {
2872
1744
  transport: websocketMode ? "websocket" : "stream"
2873
1745
  });
2874
1746
  const websocketSessionPolicy = websocketMode ? turnState?.websocket : void 0;
2875
- const websocketHeaders = websocketMode ? buildOpenAIClientHeaders(model, context, options?.headers, websocketSessionPolicy?.headers, options?.sessionId) : void 0;
2876
- const client = config.createClient(model, context, apiKey, options?.headers, turnState?.headers, options?.sessionId, compactRequest ? createBoundedOpenAIResponsesCompactionFetch(buildGuardedModelFetch(model)) : void 0);
1747
+ const httpTurnHeaders = filterProviderTurnHeadersForExplicitOpencodeSession(model, options, turnState?.headers);
1748
+ const websocketTurnHeaders = filterProviderTurnHeadersForExplicitOpencodeSession(model, options, websocketSessionPolicy?.headers);
1749
+ const websocketHeaders = websocketMode ? buildOpenAIClientHeaders(model, context, options?.headers, websocketTurnHeaders, options?.sessionId, options?.cacheRetention) : void 0;
1750
+ const httpHeaders = buildOpenAIClientHeaders(model, context, options?.headers, httpTurnHeaders, options?.sessionId, options?.cacheRetention);
1751
+ const client = config.createClient(model, apiKey, httpHeaders, compactRequest ? createBoundedOpenAIResponsesCompactionFetch(buildGuardedModelFetch(model)) : void 0);
2877
1752
  const nativeAstra = model.id === "gpt-6-astra" && supportsNativeOpenAIResponsesEndpoint(model);
2878
1753
  const asyncToolExecutionEligible = nativeAstra && options?.asyncToolExecution === true && !responsesOptions?.openclawCodeModeToolSurface;
2879
1754
  const prepareRequest = async (request) => {
@@ -2926,8 +1801,9 @@ function createResponsesTransportExecutor(config) {
2926
1801
  sessionId,
2927
1802
  apiKey,
2928
1803
  baseUrl: model.baseUrl,
2929
- headers: buildOpenAIClientHeaders(model, context, options?.headers, turnState?.headers, sessionId),
2930
- request: params
1804
+ headers: httpHeaders,
1805
+ request: params,
1806
+ restoreRequest: () => restoreResponsesReasoningState(context, model, responsesOptions, params)
2931
1807
  });
2932
1808
  if (continuationClaim) params = continuationClaim.fullRequest;
2933
1809
  }
@@ -2965,7 +1841,7 @@ function createResponsesTransportExecutor(config) {
2965
1841
  onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, responsesOptions, checkpoint),
2966
1842
  canRetryStream: () => output.content.length === 0,
2967
1843
  wrapStream: ({ stream: rawResponseStream, response, attempt }) => {
2968
- if (continuationClaim) continuationBaseline = attempt.request.previous_response_id ? params : attempt.request;
1844
+ continuationBaseline = attempt.request.previous_response_id ? params : attempt.request;
2969
1845
  return withProviderResponseHook({
2970
1846
  stream: observeResponsesStream(rawResponseStream, model, requestStartedAt),
2971
1847
  signal: firstEvent.signal,
@@ -2981,6 +1857,7 @@ function createResponsesTransportExecutor(config) {
2981
1857
  return responseStream;
2982
1858
  };
2983
1859
  let responseStream;
1860
+ let websocketBaseline;
2984
1861
  let finishWebSocket;
2985
1862
  let transport = "sse";
2986
1863
  const logWebSocketFallback = (reason) => emitModelTransportDebug(log, `[responses] websocket_fallback provider=${model.provider} api=${model.api} model=${model.id} reason=${reason}`);
@@ -2994,6 +1871,7 @@ function createResponsesTransportExecutor(config) {
2994
1871
  const websocket = createOpenAIResponsesWebSocketStream({
2995
1872
  client,
2996
1873
  request: params,
1874
+ restoreRequest: (request) => restoreResponsesReasoningState(context, model, responsesOptions, request),
2997
1875
  mode: websocketMode,
2998
1876
  sessionId: options?.sessionId,
2999
1877
  headers: websocketHeaders,
@@ -3007,6 +1885,7 @@ function createResponsesTransportExecutor(config) {
3007
1885
  }))
3008
1886
  });
3009
1887
  finishWebSocket = websocket.finish;
1888
+ websocketBaseline = websocket.fullRequest;
3010
1889
  recordResponsesInputReplay(output, websocket.inputReplay);
3011
1890
  observePrompt?.(websocket.request, {
3012
1891
  egress: "responses-websocket",
@@ -3071,6 +1950,8 @@ function createResponsesTransportExecutor(config) {
3071
1950
  finishWebSocket?.();
3072
1951
  if (options?.signal?.aborted) throw transportAbortError(options.signal);
3073
1952
  if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
1953
+ const admitted = transport === "websocket" ? websocketBaseline : continuationBaseline;
1954
+ if (terminal && admitted && supportsNativeOpenAIResponsesEndpoint(model)) recordResponsesReasoningState(output, model, responsesOptions, admitted, terminal.output);
3074
1955
  if (continuationClaim && continuationBaseline && terminal) continuationClaim.commit(continuationBaseline, terminal);
3075
1956
  } catch (error) {
3076
1957
  finishWebSocket?.({ keep: false });
@@ -3135,12 +2016,12 @@ function resolveAzureDeploymentName(model) {
3135
2016
  deploymentMap: process.env.AZURE_OPENAI_DEPLOYMENT_NAME_MAP
3136
2017
  });
3137
2018
  }
3138
- function createAzureOpenAIClient(model, context, apiKey, optionHeaders, turnHeaders, _sessionId, fetchOverride) {
2019
+ function createAzureOpenAIClient(model, apiKey, defaultHeaders, fetchOverride) {
3139
2020
  const baseURL = model.baseUrl.replace(/\/+$/, "");
3140
2021
  const clientOptions = {
3141
2022
  apiKey,
3142
2023
  dangerouslyAllowBrowser: true,
3143
- defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders),
2024
+ defaultHeaders,
3144
2025
  baseURL,
3145
2026
  fetch: fetchOverride ?? buildGuardedModelFetch(model),
3146
2027
  ...buildOpenAISdkClientOptions(model)
@@ -3158,35 +2039,6 @@ function buildAzureOpenAIResponsesParams(model, context, options, deploymentName
3158
2039
  return params;
3159
2040
  }
3160
2041
  //#endregion
3161
- //#region packages/ai/src/transports/openai-responses-transport.ts
3162
- /** OpenAI Responses transport facade. */
3163
- const responsesTesting = {
3164
- getCompat,
3165
- assertCodeModeResponsesToolSurface,
3166
- buildOpenAIResponsesParams,
3167
- buildOpenAIClientHeaders,
3168
- buildOpenAISdkClientOptions,
3169
- buildOpenAISdkRequestOptions,
3170
- createAzureOpenAIClient,
3171
- createOpenAIResponsesClient,
3172
- enforceCodeModeResponsesToolSurface,
3173
- sanitizeOpenAICodexResponsesParams,
3174
- processResponsesStream,
3175
- formatModelTransportDebugBaseUrl,
3176
- buildResponsesFailedNoDetailsObservation,
3177
- buildOpenAIResponsesReasoningReplayMetadata,
3178
- isInvalidEncryptedContentError,
3179
- normalizeResponsesFailedEvent,
3180
- createResponsesStreamWithEncryptedContentRetry,
3181
- resolveAzureOpenAIApiVersion,
3182
- summarizeResponsesFailedNoDetailsObservation,
3183
- summarizeResponsesPayload,
3184
- summarizeResponsesTools,
3185
- stringifyRedactedEvent,
3186
- stringifyRedactedPayload
3187
- };
3188
- if (process.env.VITEST || false) globalThis.openclawOpenAIResponsesTransportTestApi = responsesTesting;
3189
- //#endregion
3190
2042
  //#region packages/ai/src/transports/provider-compaction-replay.ts
3191
2043
  function isAssistantReplayMessage(message) {
3192
2044
  return message.role === "assistant";
@@ -3353,7 +2205,7 @@ const SIMPLE_TRANSPORT_API_ALIAS = {
3353
2205
  "google-generative-ai": "openclaw-google-generative-ai-transport"
3354
2206
  };
3355
2207
  function createProviderOwnedGoogleTransportStreamFn(model, ctx) {
3356
- return getAiTransportHost().plugin.resolveProviderStream({
2208
+ const streamFn = getAiTransportHost().plugin.resolveProviderStream({
3357
2209
  provider: model.provider,
3358
2210
  config: ctx?.cfg,
3359
2211
  workspaceDir: ctx?.workspaceDir,
@@ -3380,6 +2232,10 @@ function createProviderOwnedGoogleTransportStreamFn(model, ctx) {
3380
2232
  model
3381
2233
  }
3382
2234
  }) ?? void 0;
2235
+ return streamFn ? (requestModel, context, options) => streamFn(requestModel, context, {
2236
+ ...options,
2237
+ headers: resolveOpencodeSessionHeaders(requestModel, options)
2238
+ }) : void 0;
3383
2239
  }
3384
2240
  function createSupportedTransportStreamFn(model, ctx) {
3385
2241
  switch (model.api) {
@@ -3438,6 +2294,18 @@ function buildTransportAwareSimpleStreamFn(model, ctx) {
3438
2294
  }
3439
2295
  //#endregion
3440
2296
  //#region packages/ai/src/transports/simple-completion-transport.ts
2297
+ /**
2298
+ * Simple completion transport preparation.
2299
+ *
2300
+ * Registers provider-specific stream functions and rewrites models that need OpenClaw-managed transport semantics.
2301
+ */
2302
+ /** Standalone completions have no durable session, but may require routing identity. */
2303
+ function prepareHeadersForSimpleCompletion(model, options) {
2304
+ return resolveOpencodeSessionHeaders(model, {
2305
+ ...options,
2306
+ sessionId: options?.sessionId || randomUUID()
2307
+ });
2308
+ }
3441
2309
  const PROVIDER_SIMPLE_COMPLETION_API_PREFIX = "openclaw-provider-simple:";
3442
2310
  const PROVIDER_STREAM_API_PREFIX = "openclaw-provider-stream:";
3443
2311
  const INVALID_CODEX_BASE_URL_MESSAGE = "OpenAI Codex Responses baseUrl must not include query parameters or fragments";
@@ -3564,7 +2432,9 @@ function prepareProviderStreamModel(params) {
3564
2432
  const streamFn = providerStreamFn ? wrapPluginProviderStream(providerStreamFn) : transportFallback && params.model.api === "google-generative-ai" ? wrapPluginProviderStream(transportFallback) : transportFallback;
3565
2433
  if (!streamFn) return;
3566
2434
  const api = params.apiRegistry.getApiProvider(params.model.api) ? resolveProviderStreamApi(params.model) : params.model.api;
3567
- if (!registerCustomApi(params.apiRegistry, api, streamFn)) return;
2435
+ const sourceApi = params.model.api;
2436
+ const sourceStreamFn = (runtimeModel, context, options) => streamFn(projectModel(runtimeModel, { api: sourceApi }), context, options);
2437
+ if (!registerCustomApi(params.apiRegistry, api, sourceStreamFn)) return;
3568
2438
  return api === params.model.api ? params.model : projectModel(params.model, { api });
3569
2439
  }
3570
2440
  function prepareModelForSimpleCompletion(params) {
@@ -3589,4 +2459,4 @@ function prepareModelForSimpleCompletion(params) {
3589
2459
  return applyProviderSimpleCompletionWrapper(apiRegistry, model, cfg);
3590
2460
  }
3591
2461
  //#endregion
3592
- export { CompactionReplayRefreshRequiredError, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, applyAnthropicCacheControlToMessages, applyAnthropicContextManagementToRequest, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, captureOpenAIResponsesCompaction, coerceTransportToolCallArguments, copyProviderAcceptanceObserver, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIProviderAcceptanceHook, createOpenAIResponseHook, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, filterCodeModePayloadTools, finalizeTerminalToolCallArguments, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, googleFlashSupportsMinimalThinking, hasOpenAICompatibleConversationTurn, isAnthropicServerToolClearingEnabled, isCodeModeModelVisibleToolName, isCompactionReplayCheckpoint, isDirectAnthropicModel, isOpenAICodexResponsesModel, isOpenAICompletionsThinkingEnabled, log, logAnthropicContextEdits, measureUtf8AppendBytes, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, notifyProviderHttpMetadata, notifyProviderHttpResponse, notifyProviderStreamOpened, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, parseOpenAICompletionsUsage, parseTerminalToolCallArguments, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, preserveCompactionReplayWindow, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, readOpenAICompletionsReasoningBatch, replaceCompactionReplayOwnerContent, requestPreparedOpenAIResponsesCompaction, requiresCompactionReplayRefresh, resolveAnthropicContextManagementBetaHeader, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveAnthropicServerCompactionPlan, resolveCodeModeResponsesVisibleToolNames, resolveCompactionReplayEligibility, resolveCompactionReplayPressure, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAIClientBaseUrl, resolveOpenAICompletionsCompat, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesCompactEndpointPlan, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIResponsesServerCompactionPlan, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompactionReplayCheckpoint, stripCompactionReplayCheckpointInPlace, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend, withProviderAcceptanceObserver, withProviderResponseHook };
2462
+ export { CompactionReplayRefreshRequiredError, GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, IncompleteToolCallError, MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, applyAnthropicContextManagementToRequest, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyAnthropicRequestCacheControl, applyCompletionsAnthropicCacheControl, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildAnthropicSystemBlocks, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, captureOpenAIResponsesCompaction, coerceTransportToolCallArguments, consumeGoogleGenerateContentStream, convertGoogleTools, copyProviderAcceptanceObserver, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIProviderAcceptanceHook, createOpenAIResponseHook, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, filterCodeModePayloadTools, finalizeTerminalToolCallArguments, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, googleFlashSupportsMinimalThinking, hasOpenAICompatibleConversationTurn, isAnthropicServerToolClearingEnabled, isCodeModeModelVisibleToolName, isCompactionReplayCheckpoint, isDirectAnthropicModel, isNativeOpenAIEndpoint, isOpenAICodexResponsesModel, isOpenAICompletionsThinkingEnabled, log, logAnthropicContextEdits, measureUtf8AppendBytes, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, notifyProviderHttpMetadata, notifyProviderHttpResponse, notifyProviderStreamOpened, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, parseOpenAICompletionsUsage, parseTerminalToolCallArguments, prepareHeadersForSimpleCompletion, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, preserveCompactionReplayWindow, projectGoogleMessages, quoteUnsafeIntegerLiterals, readCodeModePayloadToolName, readOpenAICompletionsContentDeltas, readOpenAICompletionsReasoningBatch, replaceCompactionReplayOwnerContent, requestPreparedOpenAIResponsesCompaction, requiresCompactionReplayRefresh, requiresGoogleToolCallId, resolveAnthropicCacheOptions, resolveAnthropicContextManagementBetaHeader, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveAnthropicServerCompactionPlan, resolveCodeModeResponsesVisibleToolNames, resolveCompactionReplayEligibility, resolveCompactionReplayPressure, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAIClientBaseUrl, resolveOpenAICompletionsCompat, resolveOpenAIPromptCacheKeySupport, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesCompactEndpointPlan, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIResponsesServerCompactionPlan, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompactionReplayCheckpoint, stripCompactionReplayCheckpointInPlace, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend, withProviderAcceptanceObserver, withProviderResponseHook };