@openclaw/ai 2026.10.5 → 2026.10.10-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +11 -0
  2. package/dist/{anthropic-DIIiiz99.mjs → anthropic-D6spfBri.mjs} +16 -18
  3. package/dist/{anthropic-payload-policy-DGblkHL5.d.mts → anthropic-payload-policy-Cr8xjazC.d.mts} +6 -3
  4. package/dist/{anthropic-stream-reducer-DfMVFm-r.mjs → anthropic-stream-reducer-CzPXOaLM.mjs} +55 -227
  5. package/dist/anthropic-tool-projection-BdAS3rtJ.mjs +165 -0
  6. package/dist/anthropic-tool-projection-DKH-aEWU.d.mts +51 -0
  7. package/dist/{api-registry-BhXXYdRA.d.mts → api-registry-gDt0faai.d.mts} +2 -2
  8. package/dist/{assistant-output-BuhRpLeD.mjs → assistant-output-6iFA1nbC.mjs} +2 -2
  9. package/dist/{azure-openai-responses-DGQnXRMs.mjs → azure-openai-responses-0TqHwnlD.mjs} +8 -8
  10. package/dist/{cloudflare-5qSGvIUH.mjs → cloudflare-Dttf8jKq.mjs} +1 -1
  11. package/dist/{credential-redaction-BHxruEH6.d.mts → credential-redaction-XvsPf7Yi.d.mts} +1 -0
  12. package/dist/{diagnostics-tQasYct1.mjs → diagnostics-Cv7cW3pS.mjs} +3 -3
  13. package/dist/diagnostics.d.mts +6 -6
  14. package/dist/diagnostics.mjs +2 -2
  15. package/dist/{env-api-keys-CrxwdylR.mjs → env-api-keys-Xd8dm_aV.mjs} +10 -34
  16. package/dist/event-stream-CDpFza-M.d.mts +1 -0
  17. package/dist/{event-stream-BcqWLo_u.d.mts → event-stream-CzpE1g_o.d.mts} +1 -1
  18. package/dist/event-stream.d.mts +2 -2
  19. package/dist/{github-copilot-request-facts-DEE6gcB9.mjs → github-copilot-request-facts-F-EmvkpW.mjs} +1 -1
  20. package/dist/{google-interactions-zIz70M2e.mjs → google-interactions-DVQ7AaSF.mjs} +29 -50
  21. package/dist/{google-messages-CNbUJK5E.mjs → google-messages-DfpHVTaD.mjs} +15 -5
  22. package/dist/{google-provider-stream-Cn0XF1MG.mjs → google-provider-stream-DJ8ANfsS.mjs} +6 -6
  23. package/dist/{google-shared-BPnWP4tT.mjs → google-shared-VTcCJLW3.mjs} +21 -29
  24. package/dist/{google-vertex-XQ7OQtaM.mjs → google-vertex-Bkfizj7M.mjs} +3 -3
  25. package/dist/{google-BlbTC1Xp.mjs → google-zWpkDSeN.mjs} +4 -4
  26. package/dist/{host-Bf3NjYNj.mjs → host-B2gk-d1H.mjs} +5 -11
  27. package/dist/{host-CTDz7LXD.d.mts → host-jJOffdlW.d.mts} +4 -6
  28. package/dist/{host-policy-BzZluO6_.mjs → host-policy-mpqGhbeM.mjs} +1 -1
  29. package/dist/{index-BYDvopUB.d.mts → index-DSprYWaz.d.mts} +7 -5
  30. package/dist/index.d.mts +7 -7
  31. package/dist/index.mjs +6 -6
  32. package/dist/internal/anthropic.d.mts +7 -53
  33. package/dist/internal/anthropic.mjs +6 -5
  34. package/dist/internal/google-model-family.mjs +1 -1
  35. package/dist/internal/openai-completions-compat.d.mts +1 -1
  36. package/dist/internal/openai-completions-compat.mjs +1 -1
  37. package/dist/internal/openai-responses-payload-policy.d.mts +3 -3
  38. package/dist/internal/openai-responses-payload-policy.mjs +3 -3
  39. package/dist/internal/openai.d.mts +17 -26
  40. package/dist/internal/openai.mjs +10 -10
  41. package/dist/internal/retry-after.d.mts +1 -1
  42. package/dist/internal/retry-after.mjs +80 -55
  43. package/dist/internal/runtime.d.mts +9 -31
  44. package/dist/internal/runtime.mjs +10 -116
  45. package/dist/internal/shared.d.mts +9 -7
  46. package/dist/internal/shared.mjs +8 -6
  47. package/dist/internal/tool-schema.d.mts +83 -5
  48. package/dist/internal/tool-schema.mjs +4 -3
  49. package/dist/{mistral-dCDCR5ur.mjs → mistral-CATJrwne.mjs} +32 -35
  50. package/dist/model-request-body-BD5vy4rP.d.mts +17 -0
  51. package/dist/{number-coercion-C3hztWoY.mjs → number-coercion-37gmNkuA.mjs} +1 -1
  52. package/dist/{openai-chatgpt-responses-D8-q7cgy.mjs → openai-chatgpt-responses-CtdnpWwe.mjs} +95 -63
  53. package/dist/{openai-completions-CMN24pza.mjs → openai-completions-B6sET3oI.mjs} +10 -8
  54. package/dist/{openai-completions-compat-i-nLZxFy.d.mts → openai-completions-compat-1gsjP-KO.d.mts} +6 -3
  55. package/dist/{openai-completions-compat-CYX18uDk.mjs → openai-completions-compat-CFhQ3UVU.mjs} +7 -2
  56. package/dist/{openai-completions-transport-DuXQOxrH.mjs → openai-completions-transport-DviPEqw3.mjs} +369 -237
  57. package/dist/{openai-prompt-cache-r93BJhjm.mjs → openai-prompt-cache-DJ_P143P.mjs} +1 -1
  58. package/dist/{openai-prompt-cache-DIPMrMFy.d.mts → openai-prompt-cache-DgjD-UL5.d.mts} +2 -2
  59. package/dist/{openai-responses-BMxoJdTC.mjs → openai-responses-BXsJK-mD.mjs} +13 -15
  60. package/dist/{openai-responses-compaction-replay-B2FE4Nw8.d.mts → openai-responses-compaction-replay-Cvnl_nCq.d.mts} +5 -5
  61. package/dist/{openai-responses-contracts-DlKMMTxK.mjs → openai-responses-contracts-Bx-16mnf.mjs} +45 -6
  62. package/dist/{openai-responses-contracts-DKqMJ1Ct.d.mts → openai-responses-contracts-CQ4_AWjL.d.mts} +20 -8
  63. package/dist/{openai-responses-endpoint-CinGh4VZ.mjs → openai-responses-endpoint-D4v-eeYy.mjs} +55 -22
  64. package/dist/{openai-responses-payload-policy-C7GsA1y0.d.mts → openai-responses-payload-policy-BzM52TTH.d.mts} +9 -3
  65. package/dist/openai-responses-request-lifecycle-CTdAb2v1.mjs +246 -0
  66. package/dist/{openai-responses-shared-afo9-s16.mjs → openai-responses-shared-Bv_1NtH9.mjs} +284 -173
  67. package/dist/{openai-responses-terminal-usage-BygjiAdi.d.mts → openai-responses-terminal-usage-CpVjkqn-.d.mts} +2 -2
  68. package/dist/{openai-tool-schema-DDPXsvJP.mjs → openai-tool-schema-Buv0GXFb.mjs} +170 -237
  69. package/dist/overflow-DJHXTNBQ.mjs +117 -0
  70. package/dist/{positive-integer-CqWjqSi9.mjs → positive-integer-Bb4Evc7L.mjs} +1 -1
  71. package/dist/prompt-cache-stability-D_MeCQFI.mjs +32 -0
  72. package/dist/{provider-error-xumb1V3F.d.mts → provider-error-CnaWYTRY.d.mts} +1 -0
  73. package/dist/{provider-error-CF9GWCs2.mjs → provider-error-qtZD2inE.mjs} +75 -13
  74. package/dist/{provider-options-CVrXZBtA.d.mts → provider-options-DeYeaflL.d.mts} +52 -6
  75. package/dist/{transport-utils-34BQoXq3.mjs → provider-replay-context-J6CfU3m1.mjs} +28 -5
  76. package/dist/{provider-transport-turn-state-BYrELw8H.mjs → provider-transport-turn-state-Jxppzuc2.mjs} +5 -5
  77. package/dist/{provider-types-CHtRx0dI.d.mts → provider-types-ODq57rG_.d.mts} +3 -3
  78. package/dist/provider-types.d.mts +6 -6
  79. package/dist/providers.d.mts +2 -2
  80. package/dist/providers.mjs +11 -11
  81. package/dist/{reasoning-tag-text-partitioner-CpOy9-IQ.mjs → reasoning-tag-text-partitioner-DzlRubwU.mjs} +134 -47
  82. package/dist/{required-api-key-CFJvcFy_.mjs → required-api-key-D088S4Cd.mjs} +1 -1
  83. package/dist/{retry-after-CdCURCVg.d.mts → retry-after-sw-XX8aC.d.mts} +1 -1
  84. package/dist/sanitize-unicode-CRGuMONI.mjs +8 -0
  85. package/dist/sanitize-unicode-ZqVLLEKC.d.mts +27 -0
  86. package/dist/{session-resources-D1wgDQ8C.mjs → session-resources-vKvGIE3J.mjs} +1 -10
  87. package/dist/{simple-options-BAu4B54D.mjs → simple-options-BYgC6kse.mjs} +68 -79
  88. package/dist/{src-C44MKrW5.mjs → src-CyA0zJnt.mjs} +6 -2
  89. package/dist/{stream-Dd8DwRFL.mjs → stream-DLBirT0e.mjs} +8 -47
  90. package/dist/{stream-first-event-timeout-Dc42hKv6.mjs → stream-first-event-timeout-D_TfJHRJ.mjs} +1 -1
  91. package/dist/{string-coerce-CtgOVOSv.mjs → string-coerce-Cj8sqWHx.mjs} +26 -1
  92. package/dist/tool-schema-json-projection-B0hHDV7N.mjs +492 -0
  93. package/dist/{transport-stream-shared-BmpzDtdQ.d.mts → transport-stream-shared-8ru8eX4s.d.mts} +5 -5
  94. package/dist/{transport-stream-shared-CWGOuLcA.mjs → transport-stream-shared-CzQlAzJH.mjs} +27 -75
  95. package/dist/transports.d.mts +33 -28
  96. package/dist/transports.mjs +42 -48
  97. package/dist/{types-CQc6JNG4.mjs → types-BXd0kI8-.mjs} +1 -1
  98. package/dist/types-CBJthzJX.d.mts +1 -0
  99. package/dist/{types-Bd2T86VJ.d.mts → types-CVYzKrMl.d.mts} +20 -3
  100. package/dist/types.d.mts +6 -6
  101. package/dist/types.mjs +4 -4
  102. package/dist/{validation-ZX_sPVV0.mjs → validation-9FSkE8T-.mjs} +22 -3
  103. package/dist/{validation-DdGB1yy3.d.mts → validation-BQ5u20Ru.d.mts} +1 -1
  104. package/dist/validation.d.mts +1 -1
  105. package/dist/validation.mjs +1 -1
  106. package/package.json +3 -3
  107. package/dist/assistant-text-phase-mvdMcrY-.mjs +0 -50
  108. package/dist/event-stream-6UNs-AhN.d.mts +0 -1
  109. package/dist/expect-lbe3Hgrh.mjs +0 -8
  110. package/dist/json-schema-Bp07Qui3.mjs +0 -22
  111. package/dist/openai-responses-request-lifecycle-NSIJo9jY.mjs +0 -67
  112. package/dist/openai-tool-projection-793cE3QX.d.mts +0 -37
  113. package/dist/openai-tool-schema-a5ysBBga.d.mts +0 -32
  114. package/dist/rolldown-runtime-BhDjJH2R.mjs +0 -15
  115. package/dist/sanitize-unicode-CjDG6jJx.d.mts +0 -5
  116. package/dist/string-normalization-I3ux50s9.mjs +0 -28
  117. package/dist/text-signature-CUXnvk_c.mjs +0 -34
  118. package/dist/tool-schema-json-projection-B8sG1I9v.mjs +0 -180
  119. package/dist/types-Kdfw_04V.d.mts +0 -1
@@ -1,39 +1,40 @@
1
- import { _ as runtimeContextContentToText, f as hasRuntimeContextMarker, p as isRuntimeContextMessage } from "./types-CQc6JNG4.mjs";
1
+ import { t as createReasoningTagTextPartitioner } from "./reasoning-tag-text-partitioner-DzlRubwU.mjs";
2
+ import { _ as runtimeContextContentToText, f as hasRuntimeContextMarker, p as isRuntimeContextMessage } from "./types-BXd0kI8-.mjs";
3
+ import { t as appendAssistantMessageDiagnostic } from "./diagnostics-DzrF1h4J.mjs";
2
4
  import { r as appendAssistantThinking } from "./event-stream-X2gmsUWv.mjs";
3
5
  import { i as asOptionalRecord, o as isRecord, r as asOptionalObjectRecord } from "./record-coerce-CNDovvft.mjs";
4
- import { s as readNonEmptyStringPreservingWhitespace, t as hasNonEmptyString } from "./string-coerce-CtgOVOSv.mjs";
5
- import { n as asNonNegativeFiniteNumber, r as asPositiveFiniteNumber } from "./number-coercion-C3hztWoY.mjs";
6
- import { N as isImageWithMediaPayload, a as resolveAiTransportHeaderSentinels, r as getAiTransportHost } from "./host-Bf3NjYNj.mjs";
7
- import { M as resolveOpenAIThinkingApi, S as isOpenAIGpt6Model, _ as isResponsesServiceTierRejection, b as isOpenAIGpt55Model, d as OpenAIResponsesWebSocketSafeRetryError, g as responsesServiceTierObserver, k as supportsOpenAITemperature, l as OpenAIResponsesWebSocketPostDispatchError, m as parseOpenAIResponsesWebSocketServerError, r as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS, t as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, u as OpenAIResponsesWebSocketPreDispatchError, v as nextResponsesServiceTier, x as isOpenAIGpt56Model, y as isOpenAIGpt54MiniModel } from "./openai-responses-contracts-DlKMMTxK.mjs";
8
- import { r as uniqueStrings } from "./string-normalization-I3ux50s9.mjs";
9
- import { n as getSessionResourceOwnerId, r as registerSessionResourceCleanup } from "./session-resources-D1wgDQ8C.mjs";
10
- import { c as stableStringify, s as truncateUtf16Safe } from "./provider-error-CF9GWCs2.mjs";
11
- import { r as resolveOpenAIPromptCacheParams } from "./openai-prompt-cache-r93BJhjm.mjs";
12
- import { d as hasOnlyResponsesFunctionTools, i as emitModelTransportError, r as emitModelTransportDebug, t as formatModelTransportDebugBaseUrl } from "./diagnostics-tQasYct1.mjs";
13
- import { c as supportsModelTools, n as estimateStringChars } from "./transport-utils-34BQoXq3.mjs";
14
- import { c as resolveOpenAIResponsesTextFormat, i as resolveOpenAICompletionsCompat, l as shouldOmitOllamaCompatResponseFormat, n as isNativeOpenAIEndpoint, o as usesNativeOpenAICodexResponsesBackend, r as isOpenAICodexResponsesModel, s as resolveOpenAICompletionsResponseFormat, t as detectOpenAICompletionsCompat } from "./openai-completions-compat-CYX18uDk.mjs";
15
- import { i as resolveProviderEndpoint, t as buildGuardedModelFetch } from "./host-policy-BzZluO6_.mjs";
16
- import { i as resolveCacheRetention, r as buildCopilotDynamicHeaders } from "./cloudflare-5qSGvIUH.mjs";
17
- import { E as createToolArgumentPreviewSchedule, M as racePromiseWithAbortSignal, O as parseStreamingJson, P as sanitizeSurrogates, S as withProviderResponseHook, b as transportAbortError, c as failTransportStream, d as iterateModelStream, h as notifyProviderStreamOpened, l as finalizeTerminalToolCallArguments, s as createWritableTransportEventStream, u as finalizeTransportStream, v as sanitizeTransportPayloadText, y as throwIfModelStreamAborted } from "./transport-stream-shared-CWGOuLcA.mjs";
18
- import { C as stripSystemPromptCacheBoundary, D as sortPromptCacheToolsByName, S as splitSystemPromptRelocatableBoundary, d as describeToolResultMediaPlaceholder, l as codeModeToolSurfaceObserver, m as extractToolResultText, r as clampMaxTokensToModel, s as prepareModelRequestBody, u as reasoningTagTextPolicy, w as stripSystemPromptRelocatableBoundary, x as splitSystemPromptCacheBoundary } from "./simple-options-BAu4B54D.mjs";
19
- import { $ as replayResponsesReasoningUpdates, A as summarizeResponsesPayload, At as log, B as responsesInputFingerprint, C as readResponsesRecoveryEvent, Ct as toOpenAIResponsesToolChoice, D as logResponsesFailedNoDetails, Dt as createResponseModelTracker, E as ResponsesStreamFailure, Ft as resolveOpenAIClientBaseUrl, G as responsesContinuationRequestFingerprint, H as recordResponsesContinuationState, I as convertResponsesMessages, It as resolvePromptCacheKey, Lt as redactIdentifier, Mt as parseOpenAICompletionsUsage, Nt as readOpenAICompletionsContentDeltas, O as safeDebugValue, Ot as detachPartialSnapshot, P as buildResponsesInputMessage, Pt as readOpenAICompletionsReasoningBatch, Q as isConfigurationUpdate, R as readResponsesInputReplayState, Rt as sha256Hex, S as isInvalidEncryptedContentError, St as reconcileOpenAIResponsesToolChoice, T as resolveNextResponsesEncryptedContentAttempt, Tt as createOpenAIProviderAcceptanceHook, U as resolveResponsesContinuationRequest, V as claimOpenAIResponsesHttpContinuation, W as responsesContinuationPrefixFingerprint, _t as resolveOpenAISimpleReasoningEffort, a as prepareResponsesTools, at as suppressOpenAIResponsesCompaction, bt as projectOpenAITools, c as observeResponsesStream, ct as buildOpenAISdkClientOptions, et as supportsResponsesReasoningUpdate, ft as getCompat, gt as resolveOpenAIRequestReasoning, ht as resolveOpenAIStrictToolFlagWithDiagnostics, j as recordResponsesContextUsage, jt as measureUtf8AppendBytes, k as summarizeOpenAITransportError, kt as isOpenAICompletionsThinkingEnabled, lt as buildOpenAISdkRequestOptions, mt as resolveCodeModeResponsesVisibleToolNames, n as applyResponsesServiceTierPricing, nt as buildOpenAIResponsesReasoningReplayMetadata, ot as assertCodeModeResponsesToolSurface, s as processResponsesStream, st as buildOpenAIClientHeaders, ut as enforceCodeModeResponsesToolSurface, w as resolveAzureOpenAIApiVersion, wt as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, x as createResponsesStreamWithRecovery, xt as reconcileOpenAICompletionsToolChoice, yt as prepareOpenAITools, z as recordResponsesInputReplay } from "./openai-responses-shared-afo9-s16.mjs";
20
- import { n as getEnvApiKey } from "./env-api-keys-CrxwdylR.mjs";
21
- import { i as providerReplayContextMatches, n as buildProviderReplayContext, r as isProviderReplayContext } from "./text-signature-CUXnvk_c.mjs";
22
- import { n as transformProviderMessages, t as createAssistantOutput } from "./assistant-output-BuhRpLeD.mjs";
23
- import { a as tagUnresolvedTextAsCommentary, i as tagPendingCommentaryText, n as rememberPendingCommentaryTags, r as tagInterruptedTextPhases, t as clearPendingCommentaryText } from "./assistant-text-phase-mvdMcrY-.mjs";
6
+ import { c as readNonEmptyStringPreservingWhitespace, t as hasNonEmptyString } from "./string-coerce-Cj8sqWHx.mjs";
7
+ import { n as asNonNegativeFiniteNumber, r as asPositiveFiniteNumber } from "./number-coercion-37gmNkuA.mjs";
8
+ import { N as isImageWithMediaPayload, a as resolveAiTransportHeaderSentinels, r as getAiTransportHost } from "./host-B2gk-d1H.mjs";
9
+ import { A as supportsOpenAITemperature, C as isOpenAIGpt6Model, L as resolveOpenAIThinkingApi, M as uniqueStrings, S as isOpenAIGpt56Model, _ as responsesServiceTierObserver, b as isOpenAIGpt54MiniModel, d as OpenAIResponsesWebSocketSafeRetryError, h as parseOpenAIResponsesWebSocketServerError, l as OpenAIResponsesWebSocketPostDispatchError, r as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS, t as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, u as OpenAIResponsesWebSocketPreDispatchError, v as isResponsesServiceTierRejection, x as isOpenAIGpt55Model, y as nextResponsesServiceTier } from "./openai-responses-contracts-Bx-16mnf.mjs";
10
+ import { n as getSessionResourceOwnerId, r as registerSessionResourceCleanup } from "./session-resources-vKvGIE3J.mjs";
11
+ import { c as stableStringify, s as truncateUtf16Safe } from "./provider-error-qtZD2inE.mjs";
12
+ import { r as resolveOpenAIPromptCacheParams } from "./openai-prompt-cache-DJ_P143P.mjs";
13
+ import { d as hasOnlyResponsesFunctionTools, i as emitModelTransportError, r as emitModelTransportDebug, t as formatModelTransportDebugBaseUrl } from "./diagnostics-Cv7cW3pS.mjs";
14
+ import { a as estimateStringChars, d as supportsModelTools, n as isProviderReplayContext, r as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-J6CfU3m1.mjs";
15
+ import { c as resolveOpenAIResponsesTextFormat, i as resolveOpenAICompletionsCompat, l as shouldOmitOllamaCompatResponseFormat, n as isNativeOpenAIEndpoint, o as usesNativeOpenAICodexResponsesBackend, r as isOpenAICodexResponsesModel, s as resolveOpenAICompletionsResponseFormat, t as detectOpenAICompletionsCompat } from "./openai-completions-compat-CFhQ3UVU.mjs";
16
+ import { i as resolveProviderEndpoint, t as buildGuardedModelFetch } from "./host-policy-mpqGhbeM.mjs";
17
+ import { i as resolveCacheRetention, r as buildCopilotDynamicHeaders } from "./cloudflare-Dttf8jKq.mjs";
18
+ import { t as sanitizeSurrogates } from "./sanitize-unicode-CRGuMONI.mjs";
19
+ import { r as sortPromptCacheToolsByName } from "./prompt-cache-stability-D_MeCQFI.mjs";
20
+ import { C as splitSystemPromptRelocatableBoundary, S as splitSystemPromptCacheBoundary, T as stripSystemPromptRelocatableBoundary, f as extractToolResultText, g as reasoningTagTextPolicy, h as preparedRequestSuffix, l as describeToolResultMediaPlaceholder, m as codeModeToolSurfaceObserver, r as clampMaxTokensToModel, s as prepareModelRequestBody, w as stripSystemPromptCacheBoundary } from "./simple-options-BYgC6kse.mjs";
21
+ import { A as shortHash, E as createToolArgumentPreviewSchedule, M as racePromiseWithAbortSignal, O as parseStreamingJson, S as withProviderResponseHook, b as transportAbortError, c as failTransportStream, d as iterateModelStream, h as notifyProviderStreamOpened, l as finalizeTerminalToolCallArguments, s as createWritableTransportEventStream, u as finalizeTransportStream, v as sanitizeTransportPayloadText, y as throwIfModelStreamAborted } from "./transport-stream-shared-CzQlAzJH.mjs";
22
+ import { C as redactIdentifier, w as sha256Hex } from "./tool-schema-json-projection-B0hHDV7N.mjs";
23
+ import { n as getEnvApiKey } from "./env-api-keys-Xd8dm_aV.mjs";
24
+ import { n as transformProviderMessages, t as createAssistantOutput } from "./assistant-output-6iFA1nbC.mjs";
24
25
  import { t as notifyLlmRequestActivity } from "./llm-request-activity-CfMuh5cC.mjs";
25
26
  import { n as resolveOpencodeSessionHeaders } from "./session-affinity-DA4WHv1h.mjs";
26
27
  import { isGoogleGemini3ThinkingLevelModel } from "./internal/google-model-family.mjs";
27
28
  import "./types.mjs";
28
- import { i as createOpenAIProviderClient, n as resolveProviderSimpleCompletionHeaders, r as resolveProviderTransportTurnState, t as filterProviderTurnHeadersForExplicitOpencodeSession } from "./provider-transport-turn-state-BYrELw8H.mjs";
29
- import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-Dc42hKv6.mjs";
29
+ import { $ as isConfigurationUpdate, A as summarizeResponsesPayload, At as log, B as recordResponsesInputReplay, C as readResponsesRecoveryEvent, Ct as reconcileOpenAIResponsesToolChoice, D as logResponsesFailedNoDetails, E as ResponsesStreamFailure, Et as createOpenAIProviderAcceptanceHook, Ft as resolveOpenAIClientBaseUrl, G as responsesContinuationPrefixFingerprint, H as claimOpenAIResponsesHttpContinuation, I as convertResponsesMessages, It as resolvePromptCacheKey, K as responsesContinuationRequestFingerprint, Lt as withOpenAIErrorResponseHook, Mt as parseOpenAICompletionsUsage, Nt as readOpenAICompletionsContentDeltas, O as safeDebugValue, Ot as createResponseModelTracker, P as buildResponsesInputMessage, Pt as readOpenAICompletionsReasoningBatch, S as isInvalidEncryptedContentError, St as reconcileOpenAICompletionsToolChoice, T as resolveNextResponsesEncryptedContentAttempt, Tt as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, U as recordResponsesContinuationState, V as responsesInputFingerprint, W as resolveResponsesContinuationRequest, _t as resolveOpenAIRequestReasoning, a as prepareResponsesTools, bt as prepareOpenAITools, c as observeResponsesStream, ct as buildOpenAIClientHeaders, dt as enforceCodeModeResponsesToolSurface, et as replayResponsesReasoningUpdates, gt as resolveOpenAIStrictToolFlagWithDiagnostics, ht as resolveCodeModeResponsesVisibleToolNames, j as recordResponsesContextUsage, jt as measureUtf8AppendBytes, k as summarizeOpenAITransportError, kt as isOpenAICompletionsThinkingEnabled, lt as buildOpenAISdkClientOptions, n as applyResponsesServiceTierPricing, ot as suppressOpenAIResponsesCompaction, pt as getCompat, rt as buildOpenAIResponsesReasoningReplayMetadata, s as processResponsesStream, st as assertCodeModeResponsesToolSurface, tt as supportsResponsesReasoningUpdate, ut as buildOpenAISdkRequestOptions, vt as resolveOpenAISimpleReasoningEffort, w as resolveAzureOpenAIApiVersion, wt as toOpenAIResponsesToolChoice, x as createResponsesStreamWithRecovery, xt as projectOpenAITools, z as readResponsesInputReplayState } from "./openai-responses-shared-Bv_1NtH9.mjs";
30
+ import { i as createOpenAIProviderClient, n as resolveProviderSimpleCompletionHeaders, r as resolveProviderTransportTurnState, t as filterProviderTurnHeadersForExplicitOpencodeSession } from "./provider-transport-turn-state-Jxppzuc2.mjs";
31
+ import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-D_TfJHRJ.mjs";
30
32
  import { t as boundResponseBody } from "./streaming-byte-guard-DBXr1XYn.mjs";
31
- import { f as withPreparedToolSchemaNormalization, r as normalizeOpenAIStrictToolParameters } from "./openai-tool-schema-DDPXsvJP.mjs";
33
+ import { b as prepareOpenAIFunctionTool, f as normalizeToolSchema, p as withPreparedToolSchemaNormalization, r as normalizeOpenAIStrictToolParameters } from "./openai-tool-schema-Buv0GXFb.mjs";
32
34
  import { t as mapOpenAIStopReason } from "./openai-stop-reason-8s70vDXj.mjs";
33
- import { t as createReasoningTagTextPartitioner } from "./reasoning-tag-text-partitioner-CpOy9-IQ.mjs";
34
35
  import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-D0dvJMbZ.mjs";
35
- import { i as isOpenAIResponsesCompactionOutput, l as resolveOpenAIResponsesPayloadPolicy, n as supportsNativeOpenAIResponsesEndpoint, o as sanitizeResponsesImagePayload, r as createBoundedOpenAIResponsesCompactionFetch, s as applyOpenAIResponsesPayloadPolicy, t as isOfficialOpenAIResponsesBaseUrl } from "./openai-responses-endpoint-CinGh4VZ.mjs";
36
- import { n as withResponsesRequestAcceptance, r as createResponsesPromptEgressObserver, t as responsesRequestLifecycle } from "./openai-responses-request-lifecycle-NSIJo9jY.mjs";
36
+ import { a as isOpenAIResponsesCompactionOutput, c as applyOpenAIResponsesPayloadPolicy, d as resolveOpenAIResponsesPayloadPolicy, i as getOpenAIResponsesCompactionOutputError, n as supportsNativeOpenAIResponsesEndpoint, r as createBoundedOpenAIResponsesCompactionFetch, s as sanitizeResponsesImagePayload, t as isOfficialOpenAIResponsesBaseUrl } from "./openai-responses-endpoint-D4v-eeYy.mjs";
37
+ import { a as createResponsesV2CompactionCollector, i as createResponsesPromptEgressObserver, n as responsesRequestLifecycle, o as claimResponsesCompactRequest, r as withResponsesRequestAcceptance, t as independentResponsesRequest } from "./openai-responses-request-lifecycle-CTdAb2v1.mjs";
37
38
  import { randomUUID } from "node:crypto";
38
39
  import OpenAI, { AzureOpenAI } from "openai";
39
40
  import { ResponsesWS } from "openai/resources/responses/ws.js";
@@ -208,9 +209,21 @@ function applyCompletionsAnthropicCacheControl(payload, cacheControl = { type: "
208
209
  if (shapedPayloads.has(payload)) return;
209
210
  shapedPayloads.add(payload);
210
211
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
211
- const tools = Array.isArray(payload.tools) ? payload.tools.filter(isRecord) : [];
212
+ const tools = Array.isArray(payload.tools) ? payload.tools : [];
213
+ let lastToolIndex = -1;
214
+ for (let index = 0; index < tools.length; index++) {
215
+ const tool = tools[index];
216
+ if (isRecord(tool)) {
217
+ lastToolIndex = index;
218
+ if (Object.hasOwn(tool, "cache_control")) {
219
+ const unmarked = { ...tool };
220
+ delete unmarked.cache_control;
221
+ tools[index] = unmarked;
222
+ }
223
+ }
224
+ }
212
225
  const blocks = messages.filter(isRecord).flatMap((message) => Array.isArray(message.content) ? message.content.filter(isRecord) : []);
213
- for (const block of [...tools, ...blocks]) delete block.cache_control;
226
+ for (const block of blocks) delete block.cache_control;
214
227
  if (!cacheControl) return;
215
228
  const markText = (message, splitBoundary) => {
216
229
  if (typeof message.content === "string" && message.content) message.content = [{
@@ -238,8 +251,10 @@ function applyCompletionsAnthropicCacheControl(payload, cacheControl = { type: "
238
251
  }
239
252
  return false;
240
253
  };
241
- const lastTool = tools.at(-1);
242
- if (markTools && lastTool) lastTool.cache_control = cacheControl;
254
+ if (markTools && lastToolIndex >= 0) tools[lastToolIndex] = {
255
+ ...tools[lastToolIndex],
256
+ cache_control: cacheControl
257
+ };
243
258
  if (!markMessages) return;
244
259
  const system = messages.find((message) => isRecord(message) && (message.role === "system" || message.role === "developer"));
245
260
  if (isRecord(system)) markText(system, true);
@@ -452,12 +467,12 @@ function finalizeOpenAICompletionsToolCalls(output, options = {}) {
452
467
  output.errorMessage = "Provider returned an incomplete or malformed tool call";
453
468
  output.content = output.content.filter((candidate) => !isToolCall(candidate));
454
469
  };
455
- if (toolCalls.some((call) => typeof call.name !== "string" || call.name.trim().length === 0 || typeof call.partialArgs !== "string" || call.partialArgs.trim().length === 0)) {
470
+ if (toolCalls.some((call) => typeof call.name !== "string" || call.name.trim().length === 0 || typeof call.partialJson !== "string" || call.partialJson.trim().length === 0)) {
456
471
  rejectToolCalls();
457
472
  return;
458
473
  }
459
474
  try {
460
- finalizeTerminalToolCallArguments(toolCalls, (call) => call.partialArgs);
475
+ finalizeTerminalToolCallArguments(toolCalls, (call) => call.partialJson);
461
476
  } catch {
462
477
  rejectToolCalls();
463
478
  return;
@@ -465,12 +480,75 @@ function finalizeOpenAICompletionsToolCalls(output, options = {}) {
465
480
  for (let contentIndex = 0; contentIndex < output.content.length; contentIndex += 1) {
466
481
  const block = output.content[contentIndex];
467
482
  if (!block || !isToolCall(block)) continue;
468
- delete block.partialArgs;
483
+ delete block.partialJson;
469
484
  delete block.streamIndex;
470
485
  options.onConfirmedToolCall?.(block, contentIndex);
471
486
  }
472
487
  }
473
488
  //#endregion
489
+ //#region packages/ai/src/transports/openai-completions-context-budget-buffer.ts
490
+ const MAX_CONTEXT_BUDGET_BUFFER_CHUNKS = 8192;
491
+ const MAX_CONTEXT_BUDGET_BUFFER_BYTES = 4194304;
492
+ async function bufferContextLimitedCompletions(source, signal) {
493
+ const iterator = source[Symbol.asyncIterator]();
494
+ const chunks = [];
495
+ let bufferedBytes = 0;
496
+ let overflow;
497
+ let finished = false;
498
+ let failed = false;
499
+ let sourceError;
500
+ let finishReason;
501
+ try {
502
+ for (;;) {
503
+ const next = await iterator.next();
504
+ if (next.done) {
505
+ finished = true;
506
+ break;
507
+ }
508
+ const chunk = next.value;
509
+ const chunkBytes = Buffer.byteLength(JSON.stringify(chunk) ?? "", "utf8");
510
+ if (chunks.length >= MAX_CONTEXT_BUDGET_BUFFER_CHUNKS || bufferedBytes + chunkBytes > MAX_CONTEXT_BUDGET_BUFFER_BYTES) {
511
+ overflow = next;
512
+ break;
513
+ }
514
+ chunks.push(chunk);
515
+ bufferedBytes += chunkBytes;
516
+ const chunkFinishReason = chunk?.choices?.[0]?.finish_reason;
517
+ if (chunkFinishReason) finishReason = chunkFinishReason;
518
+ signal?.throwIfAborted();
519
+ }
520
+ } catch (error) {
521
+ failed = true;
522
+ sourceError = error;
523
+ iterator.return?.().catch(() => void 0);
524
+ }
525
+ return {
526
+ bounded: overflow === void 0,
527
+ failed,
528
+ finishReason,
529
+ stream: { async *[Symbol.asyncIterator]() {
530
+ try {
531
+ yield* chunks;
532
+ if (failed) throw sourceError;
533
+ if (overflow !== void 0) {
534
+ yield overflow.value;
535
+ for (;;) {
536
+ const next = await iterator.next();
537
+ if (next.done) {
538
+ finished = true;
539
+ return;
540
+ }
541
+ yield next.value;
542
+ }
543
+ }
544
+ } finally {
545
+ chunks.length = 0;
546
+ if (!finished && !failed) iterator.return?.().catch(() => void 0);
547
+ }
548
+ } }
549
+ };
550
+ }
551
+ //#endregion
474
552
  //#region packages/ai/src/transports/openai-completions-host.ts
475
553
  /**
476
554
  * Chat Completions accepts Azure AI Foundry hosts in addition to traditional
@@ -489,6 +567,7 @@ function hasToolCallHistory(messages) {
489
567
  /** Convert a normalized transcript to OpenAI Chat Completions messages. */
490
568
  function convertMessages(model, context, compat, options = {}) {
491
569
  const params = [];
570
+ const supportsTools = options.supportsTools !== false;
492
571
  const normalizeToolCallId = (id) => {
493
572
  if (id.includes("|")) return id.slice(0, id.indexOf("|")).replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 40);
494
573
  if (model.provider === "openai") return id.length > 40 ? truncateUtf16Safe(id, 40) : id;
@@ -566,7 +645,10 @@ function convertMessages(model, context, compat, options = {}) {
566
645
  msg.content.forEach((block) => {
567
646
  if (block.type === "text" && block.text.trim().length > 0) assistantTexts.push(sanitizeSurrogates(block.text));
568
647
  else if (block.type === "thinking" && block.thinking.trim().length > 0) nonEmptyThinkingBlocks.push(block);
569
- else if (block.type === "toolCall") toolCalls.push(block);
648
+ else if (block.type === "toolCall") {
649
+ if (supportsTools) toolCalls.push(block);
650
+ else assistantTexts.push(sanitizeSurrogates(`[tool call id=${block.id} name=${block.name}] ${JSON.stringify(block.arguments)}`));
651
+ }
570
652
  });
571
653
  if (nonEmptyThinkingBlocks.length > 0 && compat.requiresThinkingAsText) assistantMsg.content = [{
572
654
  type: "text",
@@ -618,13 +700,28 @@ function convertMessages(model, context, compat, options = {}) {
618
700
  const textResult = extractToolResultText(toolMsg.content);
619
701
  const mediaPlaceholder = describeToolResultMediaPlaceholder(toolMsg.content);
620
702
  const images = toolMsg.content.filter(isImageWithMediaPayload);
621
- const toolResultMsg = {
622
- role: "tool",
623
- content: textResult.trim() ? textResult : mediaPlaceholder ?? "(no output)",
624
- tool_call_id: toolMsg.toolCallId
625
- };
626
- if (compat.requiresToolResultName && toolMsg.toolName) toolResultMsg.name = toolMsg.toolName;
627
- params.push(toolResultMsg);
703
+ const content = textResult.trim() ? textResult : mediaPlaceholder ?? "(no output)";
704
+ if (supportsTools) {
705
+ const toolResultMsg = {
706
+ role: "tool",
707
+ content,
708
+ tool_call_id: preparedRequestSuffix.has(context) ? preparedRequestSuffix.toolCallId(context, toolMsg.toolCallId, normalizeToolCallId(toolMsg.toolCallId)) : toolMsg.toolCallId
709
+ };
710
+ if (compat.requiresToolResultName && toolMsg.toolName) toolResultMsg.name = toolMsg.toolName;
711
+ params.push(toolResultMsg);
712
+ } else {
713
+ const text = sanitizeSurrogates(`[tool result id=${toolMsg.toolCallId} name=${toolMsg.toolName}] ${content}`);
714
+ const previous = params.at(-1);
715
+ if (previous?.role !== "assistant") params.push({
716
+ role: "assistant",
717
+ content: text
718
+ });
719
+ else if (Array.isArray(previous.content)) previous.content.push({
720
+ type: "text",
721
+ text
722
+ });
723
+ else previous.content = previous.content ? `${previous.content}\n${text}` : text;
724
+ }
628
725
  if (images.length > 0 && model.input.includes("image")) {
629
726
  const boundedToolName = sanitizeSurrogates(truncateUtf16Safe(toolMsg.toolName ?? "", 64));
630
727
  imageContentParts.push({
@@ -640,7 +737,7 @@ function convertMessages(model, context, compat, options = {}) {
640
737
  }
641
738
  i = j - 1;
642
739
  if (imageContentParts.length > 0) {
643
- if (compat.requiresAssistantAfterToolResult) params.push({
740
+ if (supportsTools && compat.requiresAssistantAfterToolResult) params.push({
644
741
  role: "assistant",
645
742
  content: "I have processed the tool results."
646
743
  });
@@ -649,7 +746,7 @@ function convertMessages(model, context, compat, options = {}) {
649
746
  content: imageContentParts
650
747
  });
651
748
  lastRole = "user";
652
- } else lastRole = "toolResult";
749
+ } else lastRole = supportsTools ? "toolResult" : "assistant";
653
750
  continue;
654
751
  }
655
752
  lastRole = msg.role;
@@ -686,7 +783,7 @@ function applyCompletionsReasoningAndRouting(params, model, reasoning, compat, m
686
783
  const direct = mode === "direct";
687
784
  const nativeEffort = compat.thinkingFormat === "openrouter" ? void 0 : reasoning.effort;
688
785
  const enabled = reasoning.thinkingEnabled ?? false;
689
- if (model.reasoning) {
786
+ if (model.reasoning && (!compat.thinkingOffControlUndeclared || reasoning.thinkingEnabled !== void 0 || !reasoning.thinkingExplicit)) {
690
787
  let allowScalarEffort = true;
691
788
  if (direct && compat.thinkingFormat === "zai") {
692
789
  params.thinking = enabled ? {
@@ -698,9 +795,11 @@ function applyCompletionsReasoningAndRouting(params, model, reasoning, compat, m
698
795
  params.enable_thinking = enabled;
699
796
  allowScalarEffort = false;
700
797
  } else if (compat.thinkingFormat === "qwen-chat-template") {
798
+ const chatTemplateReasoningEffort = enabled && reasoning.thinkingExplicit && model.compat?.supportedReasoningEfforts?.length ? reasoning.effort : void 0;
701
799
  params.chat_template_kwargs = {
702
800
  enable_thinking: enabled,
703
- ...direct ? { preserve_thinking: true } : {}
801
+ ...direct ? { preserve_thinking: true } : {},
802
+ ...chatTemplateReasoningEffort ? { reasoning_effort: chatTemplateReasoningEffort } : {}
704
803
  };
705
804
  allowScalarEffort = false;
706
805
  } else if (compat.thinkingFormat === "together" || direct && compat.thinkingFormat === "deepseek") {
@@ -879,10 +978,6 @@ function resolveOpenAICompletionsMaxTokens(model, options) {
879
978
  clampToModelMaxTokens: false
880
979
  };
881
980
  }
882
- function resolveOpenAICompletionsModelMaxTokens(model) {
883
- const maxTokens = asPositiveFiniteNumber(model.maxTokens);
884
- return maxTokens === void 0 ? void 0 : Math.floor(maxTokens);
885
- }
886
981
  const OPENAI_COMPLETIONS_INPUT_TOKEN_SAFETY_MARGIN = 1.25;
887
982
  const OPENAI_COMPLETIONS_IMAGE_CHAR_ESTIMATE = 8e3;
888
983
  const MIN_USEFUL_OUTPUT_TOKENS = 16;
@@ -894,8 +989,7 @@ function estimateJsonChars(value, fallback) {
894
989
  }
895
990
  }
896
991
  function estimateOpenAICompletionsInputTokens(payload) {
897
- let adjustedChars = 0;
898
- adjustedChars += estimateOpenAICompletionsMessagesChars(payload.messages);
992
+ let adjustedChars = estimateOpenAICompletionsMessagesChars(payload.messages);
899
993
  if (payload.tools?.length) adjustedChars += estimateJsonChars(payload.tools, 1024);
900
994
  if (payload.response_format !== void 0) adjustedChars += estimateJsonChars(payload.response_format, 256);
901
995
  return Math.ceil(adjustedChars / 4 * OPENAI_COMPLETIONS_INPUT_TOKEN_SAFETY_MARGIN);
@@ -945,16 +1039,8 @@ function convertTools(tools, compat, model, mode) {
945
1039
  return {
946
1040
  projection,
947
1041
  tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
948
- const functionTool = {
949
- name: tool.name,
950
- description: tool.description,
951
- parameters: mode === "direct" ? tool.parameters : normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model.compat)
952
- };
953
- if (strict !== void 0) functionTool.strict = strict;
954
- return {
955
- type: "function",
956
- function: functionTool
957
- };
1042
+ const parameters = compat.requiresTypedUnionBranches ? normalizeToolSchema(tool.parameters, "moonshot") : tool.parameters;
1043
+ return prepareOpenAIFunctionTool(tool.name, tool.description, mode === "direct" ? parameters : normalizeOpenAIStrictToolParameters(parameters, strict === true, model.compat), strict).completions;
958
1044
  })
959
1045
  };
960
1046
  };
@@ -963,7 +1049,22 @@ function convertTools(tools, compat, model, mode) {
963
1049
  function buildOpenAICompletionsParams(model, context, options) {
964
1050
  return buildOpenAICompletionsRequest(model, context, options, { mode: "managed" });
965
1051
  }
1052
+ const contextOutputBudgets = /* @__PURE__ */ new WeakMap();
1053
+ function completionsInputHash(payload) {
1054
+ return shortHash(JSON.stringify([
1055
+ payload.messages,
1056
+ payload.tools,
1057
+ payload.response_format
1058
+ ]));
1059
+ }
1060
+ function resolveCompletionsContextOutputBudget(request, payload) {
1061
+ const budget = contextOutputBudgets.get(request);
1062
+ const limits = [payload.max_tokens, payload.max_completion_tokens].filter((value) => value !== void 0);
1063
+ if (!budget || payload.model !== budget.model || !Array.isArray(payload.messages) || payload.tools !== void 0 && !Array.isArray(payload.tools) || limits.length === 0 || limits.some((value) => value !== budget.cap) || completionsInputHash(payload) !== budget.inputHash) return;
1064
+ return budget.cap;
1065
+ }
966
1066
  function buildOpenAICompletionsRequest(model, context, options, policy) {
1067
+ let contextOutputCap;
967
1068
  const resolvedPolicy = policy.mode === "direct" ? policy : {
968
1069
  ...policy,
969
1070
  compat: getCompat(model)
@@ -981,8 +1082,10 @@ function buildOpenAICompletionsRequest(model, context, options, policy) {
981
1082
  "qwen"
982
1083
  ].includes(model.provider));
983
1084
  const cacheOptOutIndexes = /* @__PURE__ */ new Set();
1085
+ const supportsTools = policy.mode === "direct" || supportsModelTools(model);
984
1086
  const convertedMessages = convertMessages(model, context, compat, {
985
1087
  cacheOptOutIndexes,
1088
+ supportsTools,
986
1089
  preserveSystemPromptCacheBoundary: cacheControl !== void 0 && !managedCompat?.requiresStringContent
987
1090
  });
988
1091
  let messages = convertedMessages;
@@ -1015,7 +1118,7 @@ function buildOpenAICompletionsRequest(model, context, options, policy) {
1015
1118
  if (policy.mode === "managed" && options?.seed !== void 0) params.seed = options.seed;
1016
1119
  if (options?.stop !== void 0 && options.stop.length > 0) params.stop = options.stop;
1017
1120
  let directToolProjection;
1018
- if (policy.mode === "direct" || supportsModelTools(model)) {
1121
+ if (supportsTools) {
1019
1122
  if (context.tools) {
1020
1123
  const converted = convertTools(context.tools, compat, model, policy.mode);
1021
1124
  if (policy.mode === "direct") directToolProjection = converted.projection;
@@ -1044,7 +1147,11 @@ function buildOpenAICompletionsRequest(model, context, options, policy) {
1044
1147
  ...model,
1045
1148
  compat: model.compat ?? void 0
1046
1149
  }, simpleReasoning)) ?? (usesBinaryOpenRouterThinking ? void 0 : "high");
1047
- const reasoning = resolveOpenAIRequestReasoning(model, requestedEffort, compat.reasoningEffortForOff);
1150
+ const thinkingExplicit = options?.openclawThinkingExplicit ?? (options?.reasoningEffort !== void 0 || options?.reasoning !== void 0);
1151
+ const reasoning = {
1152
+ ...resolveOpenAIRequestReasoning(model, requestedEffort, compat.reasoningEffortForOff),
1153
+ thinkingExplicit
1154
+ };
1048
1155
  const { effort, thinkingEnabled } = reasoning;
1049
1156
  {
1050
1157
  const maxTokenBudget = policy.mode === "direct" ? {
@@ -1054,7 +1161,8 @@ function buildOpenAICompletionsRequest(model, context, options, policy) {
1054
1161
  const effectiveMaxTokens = maxTokenBudget.maxTokens;
1055
1162
  const effectiveContextTokens = asPositiveFiniteNumber(model.contextTokens) ?? asPositiveFiniteNumber(model.contextWindow);
1056
1163
  let clampedMaxTokens = effectiveMaxTokens;
1057
- const modelMaxTokens = resolveOpenAICompletionsModelMaxTokens(model);
1164
+ const modelOutputLimit = asPositiveFiniteNumber(model.maxTokens);
1165
+ const modelMaxTokens = modelOutputLimit === void 0 ? void 0 : Math.floor(modelOutputLimit);
1058
1166
  if (maxTokenBudget.clampToModelMaxTokens && clampedMaxTokens !== void 0 && modelMaxTokens !== void 0 && clampedMaxTokens > modelMaxTokens) {
1059
1167
  clampedMaxTokens = modelMaxTokens;
1060
1168
  if (policy.mode === "managed") emitModelTransportDebug(log, `[completions] clamp_max_tokens provider=${model.provider} api=${model.api} model=${model.id} requested=${effectiveMaxTokens} output=${clampedMaxTokens} modelMaxTokens=${modelMaxTokens}`);
@@ -1063,8 +1171,9 @@ function buildOpenAICompletionsRequest(model, context, options, policy) {
1063
1171
  const estimatedInputTokens = estimateOpenAICompletionsInputTokens(params);
1064
1172
  const remainingBudget = Math.max(0, effectiveContextTokens - estimatedInputTokens - 1);
1065
1173
  if (clampedMaxTokens > remainingBudget) {
1066
- if (remainingBudget < MIN_USEFUL_OUTPUT_TOKENS) throw Object.assign(/* @__PURE__ */ new Error(`Context window exceeded: estimated input ${estimatedInputTokens} leaves only ${remainingBudget} output tokens within the ${effectiveContextTokens}-token context.`), { code: "context_length_exceeded" });
1174
+ if (remainingBudget < (params.tools?.length && params.tool_choice !== "none" ? Math.max(MIN_USEFUL_OUTPUT_TOKENS, Math.min(2048, Math.ceil((modelMaxTokens ?? 0) / 8))) : MIN_USEFUL_OUTPUT_TOKENS)) throw Object.assign(/* @__PURE__ */ new Error(`Context window exceeded: estimated input ${estimatedInputTokens} leaves only ${remainingBudget} output tokens within the ${effectiveContextTokens}-token context.`), { code: "context_length_exceeded" });
1067
1175
  clampedMaxTokens = remainingBudget;
1176
+ contextOutputCap = remainingBudget;
1068
1177
  emitModelTransportDebug(log, `[completions] clamp_max_tokens provider=${model.provider} api=${model.api} model=${model.id} requested=${effectiveMaxTokens} output=${clampedMaxTokens} effectiveContext=${effectiveContextTokens} estimatedInput=${estimatedInputTokens}`);
1069
1178
  }
1070
1179
  }
@@ -1083,6 +1192,11 @@ function buildOpenAICompletionsRequest(model, context, options, policy) {
1083
1192
  if (isOpenAIGpt56Model(model)) params.reasoning_effort = "none";
1084
1193
  else if (isOpenAIGpt54MiniModel(model) || isOpenAIGpt55Model(model)) delete params.reasoning_effort;
1085
1194
  }
1195
+ if (contextOutputCap !== void 0) contextOutputBudgets.set(params, {
1196
+ model: params.model,
1197
+ cap: contextOutputCap,
1198
+ inputHash: completionsInputHash(params)
1199
+ });
1086
1200
  return params;
1087
1201
  }
1088
1202
  //#endregion
@@ -1219,7 +1333,7 @@ function parseDeepSeekDsmlToolCallBlock(body) {
1219
1333
  kind: "toolCall",
1220
1334
  name: invokeName,
1221
1335
  arguments: parsedArguments,
1222
- partialArgs: JSON.stringify(parsedArguments)
1336
+ partialJson: JSON.stringify(parsedArguments)
1223
1337
  });
1224
1338
  }
1225
1339
  return toolCalls;
@@ -1380,7 +1494,7 @@ function recoverGemmaCalls(text) {
1380
1494
  kind: "toolCall",
1381
1495
  name,
1382
1496
  arguments: argumentsValue,
1383
- partialArgs: JSON.stringify(argumentsValue)
1497
+ partialJson: JSON.stringify(argumentsValue)
1384
1498
  });
1385
1499
  } catch {
1386
1500
  return;
@@ -1438,6 +1552,38 @@ function extractToolCallThoughtSignature(toolCall) {
1438
1552
  const extra = tc.extra_content?.google;
1439
1553
  return readNonEmptyStringPreservingWhitespace(extra?.thought_signature) ?? readNonEmptyStringPreservingWhitespace(tc.function?.thought_signature) ?? readNonEmptyStringPreservingWhitespace(tc.thought_signature);
1440
1554
  }
1555
+ async function* observeOpenAICompletionsProgress(responseStream, signal) {
1556
+ const maxUsageTokens = {
1557
+ prompt: 0,
1558
+ completion: 0,
1559
+ total: 0,
1560
+ reasoning: 0
1561
+ };
1562
+ for await (const rawChunk of responseStream) {
1563
+ throwIfModelStreamAborted(signal);
1564
+ if (rawChunk && typeof rawChunk === "object") {
1565
+ const chunk = rawChunk;
1566
+ const choice = Array.isArray(chunk.choices) ? chunk.choices[0] : void 0;
1567
+ const usage = chunk.usage || choice?.usage;
1568
+ let hasUsageProgress = false;
1569
+ for (const [counter, reported] of [
1570
+ ["prompt", usage?.prompt_tokens],
1571
+ ["completion", usage?.completion_tokens],
1572
+ ["total", usage?.total_tokens],
1573
+ ["reasoning", usage?.completion_tokens_details?.reasoning_tokens]
1574
+ ]) {
1575
+ const tokens = asPositiveFiniteNumber(reported) ?? 0;
1576
+ if (tokens > maxUsageTokens[counter]) {
1577
+ maxUsageTokens[counter] = tokens;
1578
+ hasUsageProgress = true;
1579
+ }
1580
+ }
1581
+ const rawChoiceDelta = choice?.delta ?? choice?.message;
1582
+ notifyLlmRequestActivity(signal, Boolean(hasUsageProgress || choice?.finish_reason || rawChoiceDelta && (rawChoiceDelta.tool_calls?.length || hasOpenAICompletionsDeltaContent(rawChoiceDelta))));
1583
+ }
1584
+ yield rawChunk;
1585
+ }
1586
+ }
1441
1587
  async function processCompletionsStream(responseStream, output, model, stream, options) {
1442
1588
  const MAX_POST_TOOL_CALL_BUFFER_BYTES = 256e3;
1443
1589
  const directMode = options?.mode === "direct";
@@ -1454,17 +1600,14 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1454
1600
  let currentBlock = null;
1455
1601
  const directContent = { block: null };
1456
1602
  let currentTextSource;
1457
- let pendingInterruptedTextBlock = null;
1458
- let confirmedInterruptedTextBlock = null;
1603
+ let sawReasoning = false;
1459
1604
  let pendingPostToolCallDeltas = [];
1460
1605
  let pendingPostToolCallBytes = 0;
1461
1606
  const toolCallBlocksByIndex = /* @__PURE__ */ new Map();
1462
1607
  const toolCallBlocksById = /* @__PURE__ */ new Map();
1463
1608
  const encryptedReasoning = createOpenAIEncryptedToolCallReasoningTracker();
1464
1609
  const toolArgumentPreviewSchedules = /* @__PURE__ */ new WeakMap();
1465
- const provisionalCommentaryTags = directMode ? options.provisionalCommentaryTags : /* @__PURE__ */ new Map();
1466
1610
  const blockIndices = /* @__PURE__ */ new WeakMap();
1467
- let explicitVisibleTextBlocks;
1468
1611
  const normalizeToolCallDeltas = createOpenAICompletionsToolCallDeltaNormalizer();
1469
1612
  let finishReason;
1470
1613
  let sawNativeToolCallDelta = false;
@@ -1472,7 +1615,7 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1472
1615
  let chunkPushedEvent = false;
1473
1616
  const pushStreamEvent = (event) => {
1474
1617
  chunkPushedEvent = true;
1475
- stream.push(detachPartialSnapshot(event));
1618
+ stream.push(event);
1476
1619
  };
1477
1620
  const appendToolCallBlock = (block) => {
1478
1621
  output.content.push(block);
@@ -1506,7 +1649,6 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1506
1649
  text: ""
1507
1650
  };
1508
1651
  currentTextSource = delta.source;
1509
- if (delta.source === "reasoning_detail") (explicitVisibleTextBlocks ??= /* @__PURE__ */ new Set()).add(currentBlock);
1510
1652
  } else currentBlock = {
1511
1653
  type: "thinking",
1512
1654
  thinking: "",
@@ -1522,13 +1664,7 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1522
1664
  });
1523
1665
  }
1524
1666
  if (currentBlock.type === "thinking") appendAssistantThinking(currentBlock, delta.text);
1525
- else {
1526
- currentBlock.text += delta.text;
1527
- if (pendingInterruptedTextBlock && delta.text.trim()) {
1528
- confirmedInterruptedTextBlock = pendingInterruptedTextBlock;
1529
- pendingInterruptedTextBlock = null;
1530
- }
1531
- }
1667
+ else currentBlock.text += delta.text;
1532
1668
  const event = {
1533
1669
  contentIndex: blockIndex(),
1534
1670
  delta: delta.text
@@ -1580,20 +1716,19 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1580
1716
  currentBlock = null;
1581
1717
  flushPendingPostToolCallDeltas();
1582
1718
  }
1583
- rememberPendingCommentaryTags(provisionalCommentaryTags, tagPendingCommentaryText(output.content));
1584
1719
  const block = {
1585
1720
  type: "toolCall",
1586
1721
  id: `call_${randomUUID().replaceAll("-", "").slice(0, 24)}`,
1587
1722
  name: toolCall.name,
1588
1723
  arguments: toolCall.arguments,
1589
- partialArgs: toolCall.partialArgs
1724
+ partialJson: toolCall.partialJson
1590
1725
  };
1591
1726
  currentBlock = block;
1592
1727
  appendToolCallBlock(block);
1593
1728
  pushStreamEvent({
1594
1729
  type: "toolcall_delta",
1595
1730
  contentIndex: blockIndices.get(block) ?? -1,
1596
- delta: toolCall.partialArgs,
1731
+ delta: toolCall.partialJson,
1597
1732
  partial: output
1598
1733
  });
1599
1734
  };
@@ -1624,7 +1759,7 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1624
1759
  });
1625
1760
  };
1626
1761
  const flushReasoningTagTextPartitioner = (allowRecovery = true) => {
1627
- const recoverUnclosed = allowRecovery && output.stopReason !== "length" && output.stopReason !== "error" && output.stopReason !== "aborted";
1762
+ const recoverUnclosed = allowRecovery && !sawReasoning && output.stopReason !== "length" && output.stopReason !== "error" && output.stopReason !== "aborted";
1628
1763
  for (const delta of reasoningTagTextPartitioner.flush({ recoverUnclosed })) appendPartitionedVisibleDelta(delta);
1629
1764
  };
1630
1765
  const flushGemmaToolCallRecoverer = (allowRecovery = true) => {
@@ -1635,36 +1770,17 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1635
1770
  if (currentBlock?.type !== "text" && !reasoningTagTextPartitioner.hasPending()) return;
1636
1771
  flushReasoningTagTextPartitioner();
1637
1772
  if (currentBlock?.type !== "text") return;
1638
- if (currentTextSource !== "reasoning_detail" && currentBlock.text.trim()) pendingInterruptedTextBlock = currentBlock;
1639
1773
  currentBlock = null;
1640
1774
  if (directMode) directContent.block = null;
1641
1775
  currentTextSource = void 0;
1642
1776
  };
1643
- const beginReasoning = (hasFollowingVisibleText, forceStrict = false) => {
1644
- if (!output.openclawDelivery?.textPhaseRequiresTerminal) output.openclawDelivery = {
1645
- ...output.openclawDelivery,
1646
- textPhaseRequiresTerminal: true
1647
- };
1648
- if (forceStrict || reasoningTagTextPartitioner.hasPending()) reasoningTagTextPartitioner.markStrict();
1777
+ const beginReasoning = (hasFollowingVisibleText) => {
1778
+ sawReasoning = true;
1649
1779
  if (!hasFollowingVisibleText || !reasoningTagTextPartitioner.hasPendingSyntax()) sealTextBeforeReasoning();
1650
1780
  };
1651
- const guardedStream = withFirstStreamEventTimeout(responseStream, {
1652
- provider: model.provider,
1653
- api: model.api,
1654
- model: model.id,
1655
- timeoutMs: options?.firstEventTimeoutMs ?? 0,
1656
- stage: "completions",
1657
- abort: options?.abortFirstEventStream,
1658
- onTimeout: options?.onFirstEventTimeout,
1659
- hint: "The provider may be stalled while parsing the tool payload; retry with a smaller tool surface or enable OPENCLAW_DEBUG_MODEL_PAYLOAD=tools to inspect exposed tools."
1660
- });
1661
- const events = directMode ? guardedStream : iterateModelStream(guardedStream, options?.signal);
1662
- const maxUsageTokens = {
1663
- prompt: 0,
1664
- completion: 0,
1665
- total: 0,
1666
- reasoning: 0
1667
- };
1781
+ const events = directMode ? responseStream : iterateModelStream(responseStream, options?.signal);
1782
+ let maxReasoningTokens = 0;
1783
+ let providerProcessingMs;
1668
1784
  for await (const rawChunk of events) {
1669
1785
  throwIfModelStreamAborted(options?.signal);
1670
1786
  chunkPushedEvent = false;
@@ -1674,24 +1790,21 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1674
1790
  if (typeof chunk.model === "string" && chunk.model.length > 0 && chunk.model !== model.id) output.responseModel ||= chunk.model;
1675
1791
  const choice = Array.isArray(chunk.choices) ? chunk.choices[0] : void 0;
1676
1792
  const usage = chunk.usage || choice?.usage;
1677
- let hasUsageProgress = false;
1678
- let hasReasoningUsageActivity = false;
1679
- for (const [counter, reported] of [
1680
- ["prompt", usage?.prompt_tokens],
1681
- ["completion", usage?.completion_tokens],
1682
- ["total", usage?.total_tokens],
1683
- ["reasoning", usage?.completion_tokens_details?.reasoning_tokens]
1684
- ]) {
1685
- const tokens = asPositiveFiniteNumber(reported) ?? 0;
1686
- if (tokens > maxUsageTokens[counter]) {
1687
- maxUsageTokens[counter] = tokens;
1688
- hasUsageProgress = true;
1689
- hasReasoningUsageActivity ||= counter === "reasoning";
1690
- }
1793
+ if (chunk.timings !== void 0 && (choice?.finish_reason || Array.isArray(chunk.choices) && chunk.choices.length === 0 && chunk.usage)) {
1794
+ const promptMs = asNonNegativeFiniteNumber(chunk.timings?.prompt_ms);
1795
+ const predictedMs = asNonNegativeFiniteNumber(chunk.timings?.predicted_ms);
1796
+ providerProcessingMs = promptMs !== void 0 && predictedMs !== void 0 ? asNonNegativeFiniteNumber(promptMs + predictedMs) : void 0;
1797
+ }
1798
+ const reasoningTokens = asPositiveFiniteNumber(usage?.completion_tokens_details?.reasoning_tokens) ?? 0;
1799
+ const hasReasoningUsageActivity = reasoningTokens > maxReasoningTokens;
1800
+ maxReasoningTokens = Math.max(maxReasoningTokens, reasoningTokens);
1801
+ if (usage) {
1802
+ output.usage = parseOpenAICompletionsUsage(usage, model, { includeReasoningTokens: !directMode });
1803
+ const terminalUsage = Boolean(finishReason || choice?.finish_reason || chunk.choices?.length === 0);
1804
+ const completeCounts = [usage.prompt_tokens, usage.completion_tokens].every((value) => typeof value === "number" && Number.isFinite(value) && value >= 0);
1805
+ output.usage.usageReport = { state: terminalUsage && completeCounts ? "available" : "unavailable" };
1691
1806
  }
1692
- if (usage) output.usage = parseOpenAICompletionsUsage(usage, model, { includeReasoningTokens: !directMode });
1693
1807
  const rawChoiceDelta = choice?.delta ?? choice?.message;
1694
- notifyLlmRequestActivity(options?.signal, Boolean(hasUsageProgress || choice?.finish_reason || rawChoiceDelta && (rawChoiceDelta.tool_calls?.length || hasOpenAICompletionsDeltaContent(rawChoiceDelta))));
1695
1808
  if (!choice) {
1696
1809
  emitReasoningUsageActivity(hasReasoningUsageActivity);
1697
1810
  continue;
@@ -1716,15 +1829,12 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1716
1829
  const lastVisibleTextIndex = contentDeltas.findLastIndex((delta) => delta.kind === "text");
1717
1830
  const hasSameChunkVisibleText = reasoningBatch.hasVisibleText || lastVisibleTextIndex !== -1;
1718
1831
  if (hasReasoningThinking) {
1719
- beginReasoning(hasSameChunkVisibleText, true);
1832
+ beginReasoning(hasSameChunkVisibleText);
1720
1833
  appendReasoningDeltas(reasoningDeltas);
1721
1834
  }
1722
1835
  for (const [contentDeltaIndex, contentDelta] of contentDeltas.entries()) if (contentDelta.kind === "text") {
1723
1836
  const parts = gemmaToolCallRecoverer?.push(contentDelta.text) ?? [contentDelta];
1724
- for (const part of parts) {
1725
- const routedDeltas = hasReasoningThinking ? reasoningTagTextPartitioner.push(part.text) : reasoningTagTextPartitioner.pushVisible(part.text);
1726
- for (const routedDelta of routedDeltas) appendPartitionedVisibleDelta(routedDelta);
1727
- }
1837
+ for (const part of parts) for (const routedDelta of reasoningTagTextPartitioner.pushVisible(part.text)) appendPartitionedVisibleDelta(routedDelta);
1728
1838
  } else {
1729
1839
  beginReasoning(contentDeltaIndex < lastVisibleTextIndex);
1730
1840
  if (emitReasoning) {
@@ -1738,7 +1848,6 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1738
1848
  flushGemmaToolCallRecoverer(false);
1739
1849
  sawNativeToolCallDelta = true;
1740
1850
  flushReasoningTagTextPartitioner(false);
1741
- rememberPendingCommentaryTags(provisionalCommentaryTags, tagPendingCommentaryText(output.content));
1742
1851
  for (const toolCall of toolCallDeltas) {
1743
1852
  const streamIndex = typeof toolCall.index === "number" ? toolCall.index : void 0;
1744
1853
  let block = streamIndex !== void 0 ? toolCallBlocksByIndex.get(streamIndex) : void 0;
@@ -1756,7 +1865,7 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1756
1865
  id: toolCall.id || "",
1757
1866
  name: toolCall.function?.name || "",
1758
1867
  arguments: {},
1759
- partialArgs: "",
1868
+ partialJson: "",
1760
1869
  ...initialSig ? { thoughtSignature: initialSig } : {}
1761
1870
  };
1762
1871
  encryptedReasoning.rememberToolCall(block.id, block);
@@ -1777,8 +1886,8 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1777
1886
  if (deltaSig) block.thoughtSignature = deltaSig;
1778
1887
  const toolArgumentsDelta = toolCall.function?.arguments;
1779
1888
  if (toolArgumentsDelta) {
1780
- block.partialArgs += toolArgumentsDelta;
1781
- if (toolArgumentPreviewSchedules.get(block)?.(block.partialArgs.length)) block.arguments = parseStreamingJson(block.partialArgs);
1889
+ block.partialJson += toolArgumentsDelta;
1890
+ if (toolArgumentPreviewSchedules.get(block)?.(block.partialJson.length)) block.arguments = parseStreamingJson(block.partialJson);
1782
1891
  }
1783
1892
  if (toolArgumentsDelta || directMode) pushStreamEvent({
1784
1893
  type: "toolcall_delta",
@@ -1813,14 +1922,16 @@ async function processCompletionsStream(responseStream, output, model, stream, o
1813
1922
  });
1814
1923
  }
1815
1924
  });
1816
- if (confirmedInterruptedTextBlock && output.stopReason !== "toolUse" && output.stopReason !== "error" && output.stopReason !== "aborted") tagInterruptedTextPhases(output.content, confirmedInterruptedTextBlock, explicitVisibleTextBlocks);
1817
- if (output.stopReason !== "toolUse") clearPendingCommentaryText(provisionalCommentaryTags);
1818
- if (output.stopReason === "error" || output.stopReason === "aborted") tagUnresolvedTextAsCommentary(output);
1819
- if (output.stopReason === "toolUse") tagPendingCommentaryText(output.content);
1820
- if (!output.usage.contextUsage && !options?.signal?.aborted && output.stopReason !== "error" && output.stopReason !== "aborted") {
1925
+ output.usage.usageReport ??= { state: "unavailable" };
1926
+ if ((!output.usage.contextUsage || output.usage.usageReport.state === "unavailable") && !options?.signal?.aborted && output.stopReason !== "error" && output.stopReason !== "aborted") {
1821
1927
  output.usage.contextUsage = { state: "unavailable" };
1822
1928
  if (!compat.supportsUsageInStreaming) warnMissingStreamingUsage(openAIModel);
1823
1929
  }
1930
+ if (providerProcessingMs !== void 0) appendAssistantMessageDiagnostic(output, {
1931
+ type: "provider_timing",
1932
+ timestamp: Date.now(),
1933
+ details: { processingMs: providerProcessingMs }
1934
+ });
1824
1935
  }
1825
1936
  const MAX_MISSING_USAGE_HINT_KEYS = 256;
1826
1937
  const missingUsageHintKeys = /* @__PURE__ */ new Set();
@@ -1921,7 +2032,7 @@ function ensureOpenAIResponsesNonEmptyInput(messages, context) {
1921
2032
  text: " "
1922
2033
  }]));
1923
2034
  }
1924
- function buildOpenAIResponsesParams(model, context, options, metadata, replayMode = "checkpoint") {
2035
+ function buildOpenAIResponsesParams(model, context, options, metadata, replayMode = "checkpoint", retainUserProvenance = false) {
1925
2036
  const payloadPolicy = resolveOpenAIResponsesPayloadPolicy(model, { storeMode: "transport-default" });
1926
2037
  const policyAllowsReplayIds = payloadPolicy.explicitStore !== false && !payloadPolicy.shouldStripStore;
1927
2038
  const replayResponsesItemIds = !usesNativeOpenAICodexResponsesBackend(model) && (options?.replayResponsesItemIds ?? policyAllowsReplayIds);
@@ -1931,7 +2042,8 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
1931
2042
  replayResponsesItemIds,
1932
2043
  authProfileId: options?.authProfileId,
1933
2044
  sessionId: options?.sessionId,
1934
- replayMode
2045
+ replayMode,
2046
+ retainUserProvenance
1935
2047
  });
1936
2048
  ensureOpenAIResponsesNonEmptyInput(messages, context);
1937
2049
  const cacheRetention = resolveCacheRetention(options?.cacheRetention);
@@ -1993,26 +2105,31 @@ function buildOpenAIResponsesParams(model, context, options, metadata, replayMod
1993
2105
  //#endregion
1994
2106
  //#region packages/ai/src/transports/openai-responses-compact-client.ts
1995
2107
  async function postOpenAIResponsesCompaction(params) {
1996
- const compactInput = typeof params.request.instructions === "string" && params.request.instructions.length > 0 ? [buildOpenAIResponsesCompactSystemMessage(params.model, params.request.instructions), ...params.request.input ?? []] : params.request.input;
2108
+ const instructions = typeof params.request.instructions === "string" && params.request.instructions.length > 0 ? params.request.instructions : void 0;
2109
+ const body = instructions && !supportsNativeOpenAIResponsesEndpoint(params.model) ? {
2110
+ model: params.request.model,
2111
+ input: [buildOpenAIResponsesCompactSystemMessage(params.model, instructions), ...params.request.input ?? []]
2112
+ } : {
2113
+ model: params.request.model,
2114
+ input: params.request.input,
2115
+ ...instructions ? { instructions } : {}
2116
+ };
1997
2117
  const response = await params.client.post("/responses/compact", {
1998
2118
  ...buildOpenAISdkRequestOptions(params.model, params.options?.signal, { timeoutMs: params.options?.timeoutMs }),
1999
- body: {
2000
- model: params.request.model,
2001
- input: compactInput
2002
- }
2119
+ body
2003
2120
  });
2004
- const output = isRecord(response) && Array.isArray(response.output) ? response.output : [];
2005
- const item = output.at(-1);
2006
- const retainedItems = output.slice(0, -1);
2007
- const retainedUserMessageCount = retainedItems.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user" && Array.isArray(candidate.content)).length;
2008
- const inputUserMessageCount = Array.isArray(params.request.input) ? params.request.input.filter((candidate) => isRecord(candidate) && candidate.type === "message" && candidate.role === "user").length : 0;
2009
- const retainedMessagePrefixSupported = supportsNativeOpenAIResponsesEndpoint(params.model);
2010
- const usage = isRecord(response) && isRecord(response.usage) ? response.usage : void 0;
2011
- if (!isRecord(response) || response.object !== "response.compaction" || !isOpenAIResponsesCompactionOutput(output, params.model) || retainedItems.length > 0 && (!retainedMessagePrefixSupported || retainedUserMessageCount !== inputUserMessageCount) || !isRecord(item) || item.type !== "compaction" || typeof item.encrypted_content !== "string" || item.encrypted_content.length === 0 || !usage || typeof usage.input_tokens !== "number" || typeof usage.output_tokens !== "number") throw new Error("Responses compact endpoint did not return one trailing compaction item");
2121
+ if (!isRecord(response) || response.object !== "response.compaction") throw new Error("Responses compact endpoint must return a response.compaction object");
2122
+ const output = response.output;
2123
+ if (!isOpenAIResponsesCompactionOutput(output, params.model)) throw new Error(`Responses compact endpoint: ${getOpenAIResponsesCompactionOutputError(output, params.model)}`);
2124
+ const window = output;
2125
+ const item = window.at(-1);
2126
+ if (window.length > 1 && !supportsNativeOpenAIResponsesEndpoint(params.model)) throw new Error("Responses compact endpoint: retained messages require native OpenAI");
2127
+ const usage = isRecord(response.usage) ? response.usage : void 0;
2128
+ if (!usage || typeof usage.input_tokens !== "number" || typeof usage.output_tokens !== "number") throw new Error("Responses compact endpoint: usage must include input_tokens and output_tokens");
2012
2129
  return {
2013
- output,
2130
+ output: window,
2014
2131
  item,
2015
- historyMode: retainedUserMessageCount > 0 ? "retained-users" : "compacted-prefix",
2132
+ historyMode: window.length > 1 ? "retained-users" : "compacted-prefix",
2016
2133
  usage,
2017
2134
  model: params.model,
2018
2135
  replayMetadata: buildOpenAIResponsesReasoningReplayMetadata(params.model, {
@@ -2022,39 +2139,6 @@ async function postOpenAIResponsesCompaction(params) {
2022
2139
  };
2023
2140
  }
2024
2141
  //#endregion
2025
- //#region packages/ai/src/transports/openai-responses-compact-request.ts
2026
- const COMPACT_REQUEST = Symbol("openaiResponsesCompactRequest");
2027
- function claimResponsesCompactRequest(options) {
2028
- const controller = options ? Reflect.get(options, COMPACT_REQUEST) : void 0;
2029
- if (controller?.claimed === false) {
2030
- controller.claimed = true;
2031
- return controller;
2032
- }
2033
- }
2034
- /** Run a compact-endpoint request through the session's prepared stream stack. */
2035
- async function requestPreparedOpenAIResponsesCompaction(streamFn, model, context, options) {
2036
- const preparedOptions = { ...options };
2037
- let resolveResult;
2038
- let rejectResult;
2039
- const result = new Promise((resolve, reject) => {
2040
- resolveResult = resolve;
2041
- rejectResult = reject;
2042
- });
2043
- const controller = {
2044
- claimed: false,
2045
- resolve: resolveResult,
2046
- reject: rejectResult
2047
- };
2048
- Reflect.set(preparedOptions, COMPACT_REQUEST, controller);
2049
- const stream = await Promise.resolve(streamFn(model, context, preparedOptions));
2050
- if (!controller.claimed) throw new Error("Prepared stream did not reach an OpenAI Responses transport");
2051
- try {
2052
- return await result;
2053
- } finally {
2054
- await stream.result().catch(() => void 0);
2055
- }
2056
- }
2057
- //#endregion
2058
2142
  //#region packages/ai/src/transports/openai-responses-reasoning-state.ts
2059
2143
  /** Save only admitted settings and hashes, never another copy of the conversation. */
2060
2144
  function recordResponsesReasoningState(message, model, identity, request, output) {
@@ -2315,6 +2399,16 @@ function createRecoverableResponsesWebSocketStream(params) {
2315
2399
  const SESSION_WEBSOCKET_CACHE_TTL_MS = 3e5;
2316
2400
  const SESSION_WEBSOCKET_MAX_AGE_MS = 33e5;
2317
2401
  const WEBSOCKET_OPEN_STATE = 1;
2402
+ function resolveNativeOpenAIResponsesWebSocketMode(model, transport) {
2403
+ if (transport !== "websocket" && transport !== "websocket-cached" && transport !== "auto") return;
2404
+ if (getAiTransportHost().requiresManagedTransport(model)) return;
2405
+ return supportsNativeOpenAIResponsesEndpoint(model) ? transport : void 0;
2406
+ }
2407
+ function combineWebSocketTimeoutSignal(signal, model, timeoutMs) {
2408
+ const resolvedTimeoutMs = timeoutMs !== void 0 && Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : getAiTransportHost().resolveModelRequestTimeoutMs(model);
2409
+ if (resolvedTimeoutMs === void 0 || !Number.isFinite(resolvedTimeoutMs)) return signal;
2410
+ return AbortSignal.any([signal, AbortSignal.timeout(Math.max(1, resolvedTimeoutMs))]);
2411
+ }
2318
2412
  const websocketSessionCache = /* @__PURE__ */ new Map();
2319
2413
  const degradedWebSocketConnections = /* @__PURE__ */ new Map();
2320
2414
  function closeWebSocketSilently(socket, reason = "done") {
@@ -2676,16 +2770,6 @@ function closeOpenAIResponsesWebSocketSessions(sessionId, owner) {
2676
2770
  registerSessionResourceCleanup(closeOpenAIResponsesWebSocketSessions);
2677
2771
  //#endregion
2678
2772
  //#region packages/ai/src/transports/openai-responses-client.ts
2679
- function resolveNativeOpenAIResponsesWebSocketMode(model, transport) {
2680
- if (transport !== "websocket" && transport !== "websocket-cached" && transport !== "auto") return;
2681
- if (getAiTransportHost().requiresManagedTransport(model)) return;
2682
- return supportsNativeOpenAIResponsesEndpoint(model) ? transport : void 0;
2683
- }
2684
- function combineWebSocketTimeoutSignal(signal, model, timeoutMs) {
2685
- const resolvedTimeoutMs = timeoutMs !== void 0 && Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : getAiTransportHost().resolveModelRequestTimeoutMs(model);
2686
- if (resolvedTimeoutMs === void 0 || !Number.isFinite(resolvedTimeoutMs)) return signal;
2687
- return AbortSignal.any([signal, AbortSignal.timeout(Math.max(1, resolvedTimeoutMs))]);
2688
- }
2689
2773
  function createOpenAIResponsesClient(model, apiKey, defaultHeaders, fetchOverride) {
2690
2774
  return new OpenAI({
2691
2775
  apiKey,
@@ -2699,7 +2783,9 @@ function createOpenAIResponsesClient(model, apiKey, defaultHeaders, fetchOverrid
2699
2783
  function createResponsesTransportExecutor(config) {
2700
2784
  return (model, context, options) => {
2701
2785
  const responsesOptions = options;
2786
+ const independent = independentResponsesRequest.has(options);
2702
2787
  const compactRequest = claimResponsesCompactRequest(responsesOptions);
2788
+ const v2Compaction = compactRequest?.mode === "v2" ? createResponsesV2CompactionCollector(compactRequest.replayBudget) : void 0;
2703
2789
  const { eventStream, stream } = createWritableTransportEventStream();
2704
2790
  (async () => {
2705
2791
  const output = createAssistantOutput(model, config.outputApi);
@@ -2707,9 +2793,10 @@ function createResponsesTransportExecutor(config) {
2707
2793
  let continuationClaim;
2708
2794
  const requestLifecycle = responsesRequestLifecycle.get(options);
2709
2795
  try {
2796
+ if (compactRequest && requestLifecycle) throw new Error("Provider review continuation cannot replace its reviewed input with compaction");
2710
2797
  const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
2711
- const websocketMode = resolveNativeOpenAIResponsesWebSocketMode(model, responsesOptions?.transport);
2712
- const encodeBody = prepareModelRequestBody(websocketMode || compactRequest ? void 0 : options);
2798
+ const websocketMode = independent ? void 0 : resolveNativeOpenAIResponsesWebSocketMode(model, responsesOptions?.transport);
2799
+ const encodeBody = prepareModelRequestBody(websocketMode || compactRequest?.mode === "endpoint" ? void 0 : options);
2713
2800
  const turnState = resolveProviderTransportTurnState(model, {
2714
2801
  sessionId: options?.sessionId,
2715
2802
  turnId: randomUUID(),
@@ -2721,21 +2808,26 @@ function createResponsesTransportExecutor(config) {
2721
2808
  const websocketTurnHeaders = filterProviderTurnHeadersForExplicitOpencodeSession(model, options, websocketSessionPolicy?.headers);
2722
2809
  const websocketHeaders = websocketMode ? buildOpenAIClientHeaders(model, context, options?.headers, websocketTurnHeaders, options?.sessionId, options?.cacheRetention) : void 0;
2723
2810
  const httpHeaders = buildOpenAIClientHeaders(model, context, options?.headers, httpTurnHeaders, options?.sessionId, options?.cacheRetention);
2724
- const fetchOverride = createResponsesRequestFetch(model, {
2725
- compact: Boolean(compactRequest),
2811
+ const fetchOverride = withOpenAIErrorResponseHook(createResponsesRequestFetch(model, {
2812
+ compact: compactRequest?.mode === "endpoint",
2726
2813
  stream: config.streamRequest,
2727
2814
  lifecycle: requestLifecycle,
2728
2815
  onSseComment: () => notifyLlmRequestActivity(options?.signal, false)
2729
- });
2816
+ }) ?? buildGuardedModelFetch(model), options?.onResponse, model);
2730
2817
  const client = config.createClient(model, apiKey, httpHeaders, fetchOverride);
2731
2818
  const nativeAstra = model.id === "gpt-6-astra" && supportsNativeOpenAIResponsesEndpoint(model);
2732
2819
  const asyncToolExecutionEligible = nativeAstra && options?.asyncToolExecution === true && !responsesOptions?.openclawCodeModeToolSurface;
2733
2820
  const prepareRequest = async (request) => {
2734
2821
  let params = request;
2822
+ const preserveUsers = v2Compaction?.preserveUsers(request.input ?? []);
2735
2823
  const nextParams = await options?.onPayload?.(params, model);
2736
2824
  if (nextParams !== void 0) params = nextParams;
2825
+ if (preserveUsers) params = {
2826
+ ...params,
2827
+ input: preserveUsers(params.input ?? [])
2828
+ };
2737
2829
  params = sanitizeOpenAICodexResponsesParams(model, params);
2738
- params = sanitizeResponsesImagePayload(params);
2830
+ params = v2Compaction ? v2Compaction.sanitizeImages(params) : sanitizeResponsesImagePayload(params);
2739
2831
  if (responsesOptions?.openclawCodeModeToolSurface === true) {
2740
2832
  const visibleToolNames = resolveCodeModeResponsesVisibleToolNames(context);
2741
2833
  const allowedHostedToolTypes = responsesOptions?.openclawCodeModeAllowedHostedToolTypes;
@@ -2749,12 +2841,16 @@ function createResponsesTransportExecutor(config) {
2749
2841
  async: true
2750
2842
  } : tool);
2751
2843
  }
2844
+ if (v2Compaction) {
2845
+ params.input = [...params.input ?? [], { type: "compaction_trigger" }];
2846
+ v2Compaction.assertReplayFits(params.input, model);
2847
+ }
2752
2848
  return params;
2753
2849
  };
2754
- const buildRequest = (replayMode, requestContext = context) => prepareRequest(config.buildRequest(model, requestContext, responsesOptions, turnState?.metadata, replayMode));
2850
+ const buildRequest = (replayMode, requestContext = context) => prepareRequest(config.buildRequest(model, requestContext, responsesOptions, turnState?.metadata, replayMode, Boolean(v2Compaction)));
2755
2851
  let params = await buildRequest("checkpoint");
2756
- const asyncTools = asyncToolExecutionEligible && params.model === "gpt-6-astra" && params.multi_agent?.enabled !== true;
2757
- if (compactRequest) {
2852
+ const asyncTools = !compactRequest && asyncToolExecutionEligible && params.model === "gpt-6-astra" && params.multi_agent?.enabled !== true;
2853
+ if (compactRequest?.mode === "endpoint") {
2758
2854
  const compacted = await postOpenAIResponsesCompaction({
2759
2855
  client,
2760
2856
  model,
@@ -2764,6 +2860,7 @@ function createResponsesTransportExecutor(config) {
2764
2860
  output.usage.input = compacted.usage.input_tokens;
2765
2861
  output.usage.output = compacted.usage.output_tokens;
2766
2862
  output.usage.totalTokens = compacted.usage.input_tokens + compacted.usage.output_tokens;
2863
+ output.usage.usageReport = { state: "available" };
2767
2864
  compactRequest.resolve(compacted);
2768
2865
  finalizeTransportStream({
2769
2866
  stream,
@@ -2773,16 +2870,17 @@ function createResponsesTransportExecutor(config) {
2773
2870
  return;
2774
2871
  }
2775
2872
  const sessionId = options?.sessionId;
2776
- if (config.httpContinuation && !websocketMode && !getAiTransportHost().requiresManagedTransport(model) && (supportsNativeOpenAIResponsesEndpoint(model) || resolveOpenAIResponsesPayloadPolicy(model).explicitContinuationOptIn) && sessionId && (params.store === true || supportsResponsesReasoningUpdate(params)) && !params.previous_response_id) {
2873
+ if (config.httpContinuation && !compactRequest && !independent && !websocketMode && !getAiTransportHost().requiresManagedTransport(model) && (supportsNativeOpenAIResponsesEndpoint(model) || resolveOpenAIResponsesPayloadPolicy(model).explicitContinuationOptIn) && sessionId && (params.store === true || supportsResponsesReasoningUpdate(params)) && !params.previous_response_id) {
2874
+ const restoreRequest = () => restoreResponsesReasoningState(context, model, responsesOptions, params);
2777
2875
  continuationClaim = claimOpenAIResponsesHttpContinuation({
2778
2876
  sessionId,
2779
2877
  apiKey,
2780
2878
  baseUrl: model.baseUrl,
2781
2879
  headers: httpHeaders,
2782
2880
  request: params,
2783
- restoreRequest: () => restoreResponsesReasoningState(context, model, responsesOptions, params)
2881
+ restoreRequest
2784
2882
  });
2785
- if (continuationClaim) params = continuationClaim.fullRequest;
2883
+ params = continuationClaim?.fullRequest ?? restoreRequest();
2786
2884
  }
2787
2885
  const observePrompt = createResponsesPromptEgressObserver(responsesOptions, context.systemPrompt);
2788
2886
  const requestStartedAt = Date.now();
@@ -2830,7 +2928,7 @@ function createResponsesTransportExecutor(config) {
2830
2928
  continuationBaseline = attempt.request.previous_response_id ? params : attempt.request;
2831
2929
  const trackedResponseStream = responseModelTracker.track(response, rawResponseStream);
2832
2930
  return withProviderResponseHook({
2833
- stream: observeResponsesStream(trackedResponseStream, model, requestStartedAt),
2931
+ stream: observeResponsesStream(v2Compaction ? v2Compaction.observe(trackedResponseStream) : trackedResponseStream, model, requestStartedAt, attempt.request),
2834
2932
  signal: firstEvent.signal,
2835
2933
  abort: firstEvent.abort,
2836
2934
  hook: createOpenAIProviderAcceptanceHook(options, response, model),
@@ -2865,7 +2963,7 @@ function createResponsesTransportExecutor(config) {
2865
2963
  signal: websocketSignal,
2866
2964
  callerSignal: options?.signal,
2867
2965
  degradeCooldownMs: websocketSessionPolicy?.degradeCooldownMs,
2868
- onActiveResponse: nativeAstra && params.model === "gpt-6-astra" ? options?.onActiveResponse : void 0,
2966
+ onActiveResponse: !compactRequest && nativeAstra && params.model === "gpt-6-astra" ? options?.onActiveResponse : void 0,
2869
2967
  steeringInput: (messages) => {
2870
2968
  contextUsageEligible = false;
2871
2969
  return projectResponsesSteeringInput(params, () => buildRequest("checkpoint", {
@@ -2886,7 +2984,7 @@ function createResponsesTransportExecutor(config) {
2886
2984
  transport = "websocket";
2887
2985
  emitModelTransportDebug(log, `[responses] websocket_selected provider=${model.provider} api=${model.api} model=${model.id} mode=${websocketMode} reused=${websocket.reusedConnection} continuation=${websocket.continuationStatus === "continued"} continuationStatus=${websocket.continuationStatus} sessionIdHash=${redactIdentifier(options?.sessionId)} headersHash=${redactIdentifier(JSON.stringify(Object.entries(websocketHeaders ?? {}).toSorted(([a], [b]) => a.localeCompare(b))))}`);
2888
2986
  responseStream = createRecoverableResponsesWebSocketStream({
2889
- trackedWebSocketStream: responseModelTracker.track(void 0, websocket.stream),
2987
+ trackedWebSocketStream: observeResponsesStream(v2Compaction ? v2Compaction.observe(responseModelTracker.track(void 0, websocket.stream)) : responseModelTracker.track(void 0, websocket.stream), model, requestStartedAt, websocket.request, "websocket"),
2890
2988
  websocket,
2891
2989
  websocketSignal,
2892
2990
  options,
@@ -2912,7 +3010,7 @@ function createResponsesTransportExecutor(config) {
2912
3010
  canRetryIdentityConflict: () => hasOnlyResponsesFunctionTools(transport === "websocket" ? websocketBaseline : continuationBaseline),
2913
3011
  ...config.pricingOptions?.(responsesOptions, model),
2914
3012
  resolveServiceTier: (responseTier, originalTier) => responseTier ?? (requestedTier === "priority" || requestedTier === "default" ? requestedTier : originalTier),
2915
- onServiceTier: (responseTier) => responsesServiceTierObserver.observe(options, requestedTier, responseTier),
3013
+ onServiceTier: (tier, response) => responsesServiceTierObserver.observe(options, requestedTier, tier, response),
2916
3014
  firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options) ?? config.firstEventTimeoutMs,
2917
3015
  abortFirstEventStream: firstEvent.abort,
2918
3016
  onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
@@ -2927,7 +3025,25 @@ function createResponsesTransportExecutor(config) {
2927
3025
  finishWebSocket?.();
2928
3026
  if (options?.signal?.aborted) throw transportAbortError(options.signal);
2929
3027
  if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
2930
- const admitted = transport === "websocket" ? websocketBaseline : continuationBaseline;
3028
+ const admitted = !independent && (transport === "websocket" ? websocketBaseline : continuationBaseline);
3029
+ if (v2Compaction && compactRequest) {
3030
+ const compacted = v2Compaction.finish({
3031
+ terminal,
3032
+ input: params.input ?? [],
3033
+ model,
3034
+ options: responsesOptions
3035
+ });
3036
+ compactRequest.resolve({
3037
+ ...compacted,
3038
+ modelUsage: output.usage
3039
+ });
3040
+ finalizeTransportStream({
3041
+ stream,
3042
+ output,
3043
+ signal: options?.signal
3044
+ });
3045
+ return;
3046
+ }
2931
3047
  if (terminal && admitted && supportsNativeOpenAIResponsesEndpoint(model)) recordResponsesReasoningState(output, model, responsesOptions, admitted, terminal.output);
2932
3048
  if (continuationClaim && continuationBaseline && terminal) continuationClaim.commit(continuationBaseline, terminal, dispatchedPreviousResponseId);
2933
3049
  if (terminal && admitted && contextUsageEligible) recordResponsesContextUsage(output, model, responsesOptions, admitted, terminal.output, "transport");
@@ -3159,7 +3275,7 @@ function streamOpenAICompletionsRequest(model, context, options, mode) {
3159
3275
  const { eventStream, stream } = createWritableTransportEventStream();
3160
3276
  (async () => {
3161
3277
  const output = createAssistantOutput(model);
3162
- const provisionalCommentaryTags = /* @__PURE__ */ new Map();
3278
+ let discardCandidate = false;
3163
3279
  let firstEventAbort;
3164
3280
  try {
3165
3281
  const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
@@ -3171,10 +3287,11 @@ function streamOpenAICompletionsRequest(model, context, options, mode) {
3171
3287
  cacheRetention
3172
3288
  } : { mode };
3173
3289
  const { client, sawStreamDONE } = policy.mode === "direct" ? {
3174
- client: createDirectCompletionsClient(model, context, apiKey, resolveProviderSimpleCompletionHeaders(model, options), cacheRetention === "none" ? void 0 : options?.sessionId, policy.compat),
3290
+ client: createDirectCompletionsClient(model, context, apiKey, options, cacheRetention === "none" ? void 0 : options?.sessionId, policy.compat),
3175
3291
  sawStreamDONE: void 0
3176
3292
  } : createManagedCompletionsClient(model, context, options, apiKey, cacheRetention);
3177
- let params = buildOpenAICompletionsRequest(model, context, options, policy);
3293
+ const builtParams = buildOpenAICompletionsRequest(model, context, options, policy);
3294
+ let params = builtParams;
3178
3295
  const encodeBody = prepareModelRequestBody(options);
3179
3296
  const nextParams = await options?.onPayload?.(params, model);
3180
3297
  if (nextParams !== void 0) params = nextParams;
@@ -3186,6 +3303,7 @@ function streamOpenAICompletionsRequest(model, context, options, mode) {
3186
3303
  }
3187
3304
  if (getCompat(model).requiresNonEmptyUserOrAssistantMessage) assertOpenAICompletionsPayloadHasConversationTurn(params, model);
3188
3305
  }
3306
+ const contextOutputBudget = resolveCompletionsContextOutputBudget(builtParams, params);
3189
3307
  const emitReasoning = mode === "direct" ? directEmitReasoning : shouldEmitOpenAICompletionsReasoning(model, options);
3190
3308
  firstEventAbort = createFirstStreamEventAbortController(options?.signal);
3191
3309
  const requestOptions = mode === "direct" ? {
@@ -3215,27 +3333,42 @@ function streamOpenAICompletionsRequest(model, context, options, mode) {
3215
3333
  signal: firstEventAbort.signal,
3216
3334
  abort: firstEventAbort.abort,
3217
3335
  hook: createOpenAIProviderAcceptanceHook(options, response, model),
3218
- onReady: () => stream.push({
3219
- type: "start",
3220
- partial: output
3221
- })
3336
+ onReady: () => {
3337
+ if (contextOutputBudget === void 0) stream.push({
3338
+ type: "start",
3339
+ partial: output
3340
+ });
3341
+ }
3342
+ });
3343
+ const providerStream = observeOpenAICompletionsProgress(withFirstStreamEventTimeout(hookedResponseStream, {
3344
+ provider: model.provider,
3345
+ api: model.api,
3346
+ model: model.id,
3347
+ timeoutMs: getFirstStreamEventTimeoutMs(options) ?? 0,
3348
+ stage: "completions",
3349
+ abort: firstEventAbort.abort,
3350
+ onTimeout: getFirstStreamEventTimeoutHandler(options),
3351
+ hint: "The provider may be stalled while parsing the tool payload; retry with a smaller tool surface or enable OPENCLAW_DEBUG_MODEL_PAYLOAD=tools to inspect exposed tools."
3352
+ }), options?.signal);
3353
+ const buffered = contextOutputBudget === void 0 ? void 0 : await bufferContextLimitedCompletions(providerStream, options?.signal);
3354
+ discardCandidate = Boolean(buffered?.bounded && (buffered.failed || buffered.finishReason === "length"));
3355
+ if (buffered && !discardCandidate) stream.push({
3356
+ type: "start",
3357
+ partial: output
3222
3358
  });
3223
3359
  const directEvents = mode === "direct" ? createDirectCompletionsEventStream(output, stream) : void 0;
3224
3360
  try {
3225
- await processCompletionsStream(hookedResponseStream, output, model, directEvents?.stream ?? stream, {
3361
+ await processCompletionsStream(buffered?.stream ?? providerStream, output, model, discardCandidate ? { push() {} } : directEvents?.stream ?? stream, {
3226
3362
  ...directEvents ? {
3227
3363
  mode: "direct",
3228
- beforeContentBlock: directEvents.beforeContentBlock,
3229
- provisionalCommentaryTags
3364
+ beforeContentBlock: directEvents.beforeContentBlock
3230
3365
  } : { mode: "managed" },
3231
- signal: options?.signal,
3366
+ signal: discardCandidate ? void 0 : options?.signal,
3232
3367
  emitReasoning,
3233
3368
  strictReasoningTags: reasoningTagTextPolicy.isStrict(options),
3234
- firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options),
3235
- abortFirstEventStream: firstEventAbort.abort,
3236
- onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
3237
3369
  sawStreamDONE
3238
3370
  });
3371
+ if (discardCandidate) throw new Error(`Context length exceeded: automatic output budget of ${contextOutputBudget} tokens exhausted before completion.`);
3239
3372
  if (directEvents) {
3240
3373
  if (options?.signal?.aborted) throw transportAbortError(options.signal);
3241
3374
  if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage || (output.stopReason === "aborted" ? "Request was aborted" : "Provider returned an invalid tool call"));
@@ -3251,6 +3384,7 @@ function streamOpenAICompletionsRequest(model, context, options, mode) {
3251
3384
  signal: options?.signal
3252
3385
  });
3253
3386
  } catch (error) {
3387
+ if (discardCandidate) output.content = [];
3254
3388
  failTransportStream({
3255
3389
  stream,
3256
3390
  output,
@@ -3258,11 +3392,9 @@ function streamOpenAICompletionsRequest(model, context, options, mode) {
3258
3392
  error,
3259
3393
  cleanup: () => {
3260
3394
  finalizeOpenAICompletionsToolCalls(output, { allowSilentToolCallPromotion: false });
3261
- clearPendingCommentaryText(provisionalCommentaryTags);
3262
- tagUnresolvedTextAsCommentary(output);
3263
3395
  if (mode === "direct") for (const block of output.content) {
3264
3396
  delete block.index;
3265
- delete block.partialArgs;
3397
+ if (block.type === "toolCall") delete block.partialJson;
3266
3398
  delete block.streamIndex;
3267
3399
  }
3268
3400
  }
@@ -3273,7 +3405,7 @@ function streamOpenAICompletionsRequest(model, context, options, mode) {
3273
3405
  })();
3274
3406
  return eventStream;
3275
3407
  }
3276
- function createDirectCompletionsClient(model, context, apiKey, optionsHeaders, sessionId, compat) {
3408
+ function createDirectCompletionsClient(model, context, apiKey, options, sessionId, compat) {
3277
3409
  if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
3278
3410
  const headers = { ...model.headers };
3279
3411
  if (model.provider === "github-copilot") Object.assign(headers, buildCopilotDynamicHeaders(context.messages));
@@ -3285,7 +3417,7 @@ function createDirectCompletionsClient(model, context, apiKey, optionsHeaders, s
3285
3417
  headers["x-session-affinity"] = sessionId;
3286
3418
  }
3287
3419
  }
3288
- return createOpenAIProviderClient(model, apiKey, headers, optionsHeaders);
3420
+ return createOpenAIProviderClient(model, apiKey, headers, resolveProviderSimpleCompletionHeaders(model, options), options?.onResponse);
3289
3421
  }
3290
3422
  function createManagedCompletionsClient(model, context, options, apiKey, cacheRetention) {
3291
3423
  const turnState = resolveProviderTransportTurnState(model, {
@@ -3297,7 +3429,7 @@ function createManagedCompletionsClient(model, context, options, apiKey, cacheRe
3297
3429
  const optionHeaders = resolveOpencodeSessionHeaders(model, options);
3298
3430
  const turnHeaders = filterProviderTurnHeadersForExplicitOpencodeSession(model, options, turnState?.headers);
3299
3431
  const doneDetector = createSseDoneDetector();
3300
- const baseFetch = buildGuardedModelFetch(model, void 0, { onSseComment: () => notifyLlmRequestActivity(options?.signal, false) });
3432
+ const baseFetch = withOpenAIErrorResponseHook(buildGuardedModelFetch(model, void 0, { onSseComment: () => notifyLlmRequestActivity(options?.signal, false) }), options?.onResponse, model);
3301
3433
  const doneDetectingFetch = async (url, init) => {
3302
3434
  const response = await baseFetch(url, init);
3303
3435
  if (!response.body || !response.ok) return response;
@@ -3331,4 +3463,4 @@ function createManagedCompletionsClient(model, context, options, apiKey, cacheRe
3331
3463
  };
3332
3464
  }
3333
3465
  //#endregion
3334
- export { requestPreparedOpenAIResponsesCompaction as a, convertMessages as c, applyCompletionsAnthropicCacheControl as d, hasOpenAICompatibleConversationTurn as f, createDeepSeekTextFilter as h, createOpenAIResponsesTransportStreamFn as i, flattenCompletionMessagesToStringContent as l, resolveMaxTokensParam as m, streamOpenAICompletionsRequest as n, hasResponsesWebSearchTool as o, canonicalizeMaxTokensParam as p, createAzureOpenAIResponsesTransportStreamFn as r, buildOpenAICompletionsParams as s, createOpenAICompletionsTransportStreamFn as t, stripCompletionMessagesToRoleContent as u };
3466
+ export { hasResponsesWebSearchTool as a, flattenCompletionMessagesToStringContent as c, hasOpenAICompatibleConversationTurn as d, canonicalizeMaxTokensParam as f, createOpenAIResponsesTransportStreamFn as i, stripCompletionMessagesToRoleContent as l, createDeepSeekTextFilter as m, streamOpenAICompletionsRequest as n, buildOpenAICompletionsParams as o, resolveMaxTokensParam as p, createAzureOpenAIResponsesTransportStreamFn as r, convertMessages as s, createOpenAICompletionsTransportStreamFn as t, applyCompletionsAnthropicCacheControl as u };