@openclaw/ai 2026.9.3 → 2026.9.5

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 (101) hide show
  1. package/README.md +1 -1
  2. package/dist/{anthropic-CZy5U0NY.mjs → anthropic-COtDvgtt.mjs} +16 -16
  3. package/dist/{anthropic-payload-policy-wuRCb6MH.d.mts → anthropic-payload-policy-5Erq1Nzy.d.mts} +3 -3
  4. package/dist/{anthropic-stream-reducer-B_yo_7pf.mjs → anthropic-stream-reducer-BvdYYWL8.mjs} +56 -47
  5. package/dist/{api-registry-CB1-1oQ2.d.mts → api-registry-Ba2Cv-ut.d.mts} +2 -2
  6. package/dist/{assistant-output-iqnlJCV2.mjs → assistant-output-BsEkB-vU.mjs} +1 -1
  7. package/dist/{azure-openai-responses-Crpa40QR.mjs → azure-openai-responses-YrgnD583.mjs} +6 -9
  8. package/dist/{base64-D-su8YVo.mjs → base64-BQOzsvUH.mjs} +4 -4
  9. package/dist/credential-redaction-BKv49aiv.d.mts +24 -0
  10. package/dist/{diagnostics-dV98PqIy.mjs → diagnostics-Dm4bisWG.mjs} +89 -2
  11. package/dist/diagnostics.d.mts +4 -23
  12. package/dist/diagnostics.mjs +3 -3
  13. package/dist/{event-stream-C1Z2piyk.d.mts → event-stream-CCoa-qSI.d.mts} +1 -1
  14. package/dist/event-stream-DmSCpi1T.d.mts +1 -0
  15. package/dist/event-stream.d.mts +2 -2
  16. package/dist/expect-lbe3Hgrh.mjs +8 -0
  17. package/dist/{google-BDPriaVe.mjs → google-BuhpRO9r.mjs} +7 -10
  18. package/dist/{google-messages-CVn9eFpF.mjs → google-messages-CyWnYlh0.mjs} +3 -4
  19. package/dist/{google-shared-BedY23XS.mjs → google-shared-BT5ZeNer.mjs} +13 -13
  20. package/dist/{google-vertex-DMz8XQCn.mjs → google-vertex-C7EplRvt.mjs} +5 -8
  21. package/dist/{host-CWuF-sS3.mjs → host-B4MeUNBc.mjs} +145 -12
  22. package/dist/{host-DK3wmS3e.d.mts → host-FZ1RA_qD.d.mts} +7 -3
  23. package/dist/{host-policy-CAopLRKA.mjs → host-policy-DUnXSx0I.mjs} +1 -1
  24. package/dist/{index-CQ6LTHw8.d.mts → index-DaF2QbwS.d.mts} +5 -10
  25. package/dist/index.d.mts +7 -8
  26. package/dist/index.mjs +5 -5
  27. package/dist/internal/anthropic.d.mts +6 -7
  28. package/dist/internal/anthropic.mjs +4 -4
  29. package/dist/internal/openai-completions-compat.d.mts +2 -0
  30. package/dist/internal/openai-completions-compat.mjs +2 -0
  31. package/dist/internal/openai-responses-payload-policy.d.mts +3 -3
  32. package/dist/internal/openai-responses-payload-policy.mjs +3 -2
  33. package/dist/internal/openai.d.mts +10 -53
  34. package/dist/internal/openai.mjs +11 -10
  35. package/dist/internal/runtime.d.mts +43 -10
  36. package/dist/internal/runtime.mjs +5 -11
  37. package/dist/internal/shared.d.mts +35 -5
  38. package/dist/internal/shared.mjs +4 -4
  39. package/dist/internal/tool-schema.d.mts +3 -3
  40. package/dist/internal/tool-schema.mjs +2 -2
  41. package/dist/{mistral--m-Jm6VZ.mjs → mistral-moA-mbwl.mjs} +9 -16
  42. package/dist/{openai-chatgpt-responses-nDZccFW-.mjs → openai-chatgpt-responses-DWID3EFO.mjs} +76 -33
  43. package/dist/{openai-completions-KuoZyx0d.mjs → openai-completions-DJ1Vm-CD.mjs} +12 -13
  44. package/dist/{openai-prompt-cache-BI0rkM-5.mjs → openai-completions-compat-CkwdxTZx.mjs} +5 -50
  45. package/dist/{openai-completions-compat-CXn3T1we.d.mts → openai-completions-compat-JE7gqxb9.d.mts} +4 -4
  46. package/dist/{openai-completions-stream-BQk3SkLD.mjs → openai-completions-stream-Bu98b0Hv.mjs} +128 -99
  47. package/dist/openai-prompt-cache-1wfaIszn.mjs +46 -0
  48. package/dist/{openai-prompt-cache-rrutvqxq.d.mts → openai-prompt-cache-CJ_xEevu.d.mts} +2 -2
  49. package/dist/{openai-provider-client-ha_WxTyj.mjs → openai-provider-client-DPo0Hmak.mjs} +2 -2
  50. package/dist/{openai-reasoning-effort-BK7FbcLT.mjs → openai-reasoning-effort-NlFZmfEu.mjs} +87 -19
  51. package/dist/{openai-responses-D99dOzKI.mjs → openai-responses-BejZzQCP.mjs} +9 -13
  52. package/dist/{openai-responses-compaction-window-D5jbzCi3.mjs → openai-responses-compaction-window-D6P5oZP5.mjs} +21 -140
  53. package/dist/openai-responses-contracts-DWrfMODE.mjs +81 -0
  54. package/dist/{openai-responses-contracts-B55afwRo.d.mts → openai-responses-contracts-Dflvrfa8.d.mts} +10 -39
  55. package/dist/{openai-responses-payload-policy-rLRPsSmB.d.mts → openai-responses-payload-policy-C7GsA1y0.d.mts} +5 -3
  56. package/dist/openai-responses-prompt-observer-internal-C15_-OwV.mjs +195 -0
  57. package/dist/{openai-responses-shared-ZyQEzS5i.mjs → openai-responses-shared-CwsziD_m.mjs} +390 -183
  58. package/dist/openai-responses-terminal-usage-Dl3J6zrf.d.mts +47 -0
  59. package/dist/{openai-tool-schema-CzjyYXun.mjs → openai-tool-schema-BO8rwyAD.mjs} +92 -68
  60. package/dist/{openai-transport-params-DNasp2fU.mjs → openai-transport-params-DQeuAvBl.mjs} +162 -51
  61. package/dist/positive-integer-DtjCkbue.mjs +8 -0
  62. package/dist/{provider-error-C6TbKiey.mjs → provider-error-DDqw9Qda.mjs} +140 -36
  63. package/dist/{provider-options-BXr9Ec83.d.mts → provider-options-DprLsWh9.d.mts} +9 -6
  64. package/dist/{provider-replay-context-BuSUaAk5.mjs → provider-replay-context-CnUSOwhr.mjs} +1 -1
  65. package/dist/{provider-transcript-transform-pPmUIwKt.mjs → provider-transcript-transform-BsRAhuWJ.mjs} +1 -1
  66. package/dist/provider-transport-turn-state-CkGToCD2.mjs +42 -0
  67. package/dist/{provider-types-CAV0Og3m.d.mts → provider-types-CAKRC7N5.d.mts} +3 -3
  68. package/dist/provider-types.d.mts +6 -7
  69. package/dist/providers.d.mts +2 -2
  70. package/dist/providers.mjs +10 -10
  71. package/dist/{reasoning-tag-text-partitioner-BQBi4B9d.mjs → reasoning-tag-text-partitioner-Dy9IO8Dc.mjs} +15 -14
  72. package/dist/{session-affinity-CCH7eYdB.mjs → session-affinity-Bcunsn4I.mjs} +5 -2
  73. package/dist/{simple-options-tcKOqnpF.mjs → simple-options-C6cFWj_f.mjs} +26 -5
  74. package/dist/{src-B2Q_6G8V.mjs → src-DeKjbE8I.mjs} +3 -6
  75. package/dist/{stream-first-event-timeout-2hfrquuz.mjs → stream-first-event-timeout-C9ZadkJW.mjs} +1 -1
  76. package/dist/{string-normalization-CmLIasuf.mjs → string-normalization-J9ZiLfGO.mjs} +13 -1
  77. package/dist/tool-schema-json-projection-CD9c_fK8.mjs +134 -0
  78. package/dist/{transport-stream-shared-DOxpGJ-H.d.mts → transport-stream-shared-BbUkFaHi.d.mts} +20 -36
  79. package/dist/{transport-stream-shared-Cu3ZPhNW.mjs → transport-stream-shared-D-6FQSHm.mjs} +223 -11
  80. package/dist/{transport-utils-CCooe-cr.mjs → transport-utils-1cyq5Y7x.mjs} +4 -7
  81. package/dist/transports.d.mts +51 -165
  82. package/dist/transports.mjs +172 -507
  83. package/dist/{types-Dy1q0CSu.d.mts → types-4_uVs5WH.d.mts} +49 -3
  84. package/dist/types-DkJfb4W3.d.mts +1 -0
  85. package/dist/types-LFWwv0cF.mjs +8 -0
  86. package/dist/types.d.mts +6 -7
  87. package/dist/types.mjs +4 -4
  88. package/dist/{validation-CaFUZN9B.d.mts → validation-Ctzu2DhF.d.mts} +1 -1
  89. package/dist/{validation-BDzVDnTs.mjs → validation-Dw7cb6BV.mjs} +1 -0
  90. package/dist/validation.d.mts +1 -1
  91. package/dist/validation.mjs +1 -1
  92. package/package.json +10 -5
  93. package/dist/diagnostics-DnPnOui6.d.mts +0 -29
  94. package/dist/event-stream-I_GlBsuZ.d.mts +0 -1
  95. package/dist/hash-CHgqbJmD.mjs +0 -16
  96. package/dist/json-parse-Dw_hnxsA.mjs +0 -146
  97. package/dist/openai-responses-prompt-observer-internal-tApyTLVu.mjs +0 -32
  98. package/dist/sanitize-unicode-Bb-v9meu.mjs +0 -83
  99. package/dist/tool-schema-json-projection-ClptDdAO.mjs +0 -82
  100. package/dist/types-BADKjDBI.d.mts +0 -1
  101. package/dist/types-BDdaOVi2.mjs +0 -6
@@ -1,26 +1,25 @@
1
+ import { t as appendAssistantMessageDiagnostic } from "./diagnostics-CPeq9F7y.mjs";
1
2
  import { r as appendAssistantThinking } from "./event-stream-D8PARQfL.mjs";
2
3
  import { a as normalizeOptionalString } from "./string-coerce-fsri9iCu.mjs";
3
- import { i as clampThinkingLevel, r as calculateCost } from "./sanitize-unicode-Bb-v9meu.mjs";
4
- import { a as describeToolResultMediaPlaceholder, c as extractToolResultText, d as isImageWithMediaPayload, n as getAiTransportHost } from "./host-CWuF-sS3.mjs";
5
4
  import { o as isRecord } from "./record-coerce-DwRYMj3t.mjs";
5
+ import { u as supportsOpenAITemperature } from "./openai-reasoning-effort-NlFZmfEu.mjs";
6
+ import { _ as isImageWithMediaPayload, d as describeToolResultMediaPlaceholder, j as calculateCost, m as extractToolResultText, n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-B4MeUNBc.mjs";
6
7
  import { t as truncateUtf16Safe } from "./utf16-slice-CvGodqok.mjs";
7
- import { i as stableStringify } from "./provider-error-C6TbKiey.mjs";
8
- import { a as resolveModelSseDebugMode, i as resolveModelPayloadDebugMode, r as emitModelTransportDebug } from "./diagnostics-dV98PqIy.mjs";
9
- import { r as asFiniteNumber } from "./base64-D-su8YVo.mjs";
10
- import { s as redactSensitiveText } from "./transport-utils-CCooe-cr.mjs";
11
- import { s as transformTransportMessages } from "./host-policy-CAopLRKA.mjs";
12
- import { d as stripSystemPromptCacheBoundary, m as sortPromptCacheToolsByName } from "./simple-options-tcKOqnpF.mjs";
13
- import { O as redactIdentifier, _ as createOpenAIProviderAcceptanceHook, b as log, f as projectOpenAITools, g as createModelStreamCooperativeScheduler, k as sha256Hex, u as resolveOpenAIStrictToolFlagWithDiagnostics } from "./openai-transport-params-DNasp2fU.mjs";
14
- import { _ as transportAbortError, c as finalizeTransportStream, g as sanitizeTransportPayloadText, h as sanitizeNonEmptyTransportPayloadText, m as parseTerminalToolCallArguments, o as failTransportStream, y as withProviderResponseHook } from "./transport-stream-shared-Cu3ZPhNW.mjs";
15
- import { t as shortHash } from "./hash-CHgqbJmD.mjs";
16
- import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-BuSUaAk5.mjs";
17
- import { r as parseStreamingJson, t as createToolArgumentPreviewSchedule } from "./json-parse-Dw_hnxsA.mjs";
8
+ import { o as stableStringify } from "./provider-error-DDqw9Qda.mjs";
9
+ import { a as resolveModelSseDebugMode, d as readResponsesReasoningTokens, f as resolveResponsesTerminalStopReason, i as resolveModelPayloadDebugMode, r as emitModelTransportDebug, u as mapResponsesTerminalUsage } from "./diagnostics-Dm4bisWG.mjs";
10
+ import { o as redactSensitiveText } from "./transport-utils-1cyq5Y7x.mjs";
11
+ import { s as transformTransportMessages } from "./host-policy-DUnXSx0I.mjs";
12
+ import { m as stripSystemPromptCacheBoundary, v as sortPromptCacheToolsByName } from "./simple-options-C6cFWj_f.mjs";
13
+ import { M as redactIdentifier, N as sha256Hex, b as createOpenAIProviderAcceptanceHook, d as prepareOpenAITools, h as resolveOpenAIRequestReasoning, u as resolveOpenAIStrictToolFlagWithDiagnostics, w as log, y as createModelStreamCooperativeScheduler } from "./openai-transport-params-DQeuAvBl.mjs";
14
+ import { E as parseStreamingJson, _ as sanitizeTransportPayloadText, b as withProviderResponseHook, g as sanitizeNonEmptyTransportPayloadText, h as parseTerminalToolCallArguments, k as shortHash, l as finalizeTransportStream, s as failTransportStream, t as IncompleteToolCallError, v as transportAbortError, w as createToolArgumentPreviewSchedule, x as parseJsonObjectPreservingUnsafeIntegers } from "./transport-stream-shared-D-6FQSHm.mjs";
15
+ import { n as providerReplayContextMatches, t as buildProviderReplayContext } from "./provider-replay-context-CnUSOwhr.mjs";
18
16
  import { t as notifyLlmRequestActivity } from "./llm-request-activity-BjtkplhG.mjs";
19
- import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-2hfrquuz.mjs";
20
- import { t as transformProviderMessages } from "./provider-transcript-transform-pPmUIwKt.mjs";
21
- import { a as resolveOpenAIModelReasoningEfforts, l as supportsOpenAITemperature, o as resolveOpenAIReasoningEffortForModel } from "./openai-reasoning-effort-BK7FbcLT.mjs";
22
- import { a as resolveOpenAIProjectedToolsStrictToolFlag, r as normalizeOpenAIStrictToolParameters } from "./openai-tool-schema-CzjyYXun.mjs";
23
- import { b as RESPONSE_FAILED_NO_DETAILS_MESSAGE, g as OPENAI_RESPONSES_RETAINED_COMPACTION_REPLAY_TYPE, h as OPENAI_RESPONSES_REASONING_REPLAY_META_KEY, m as OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY, n as isOpenAIResponsesCompactionOutput, p as OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE, r as readOpenAIResponsesCompactionWindow } from "./openai-responses-compaction-window-D5jbzCi3.mjs";
17
+ import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-C9ZadkJW.mjs";
18
+ import { t as transformProviderMessages } from "./provider-transcript-transform-BsRAhuWJ.mjs";
19
+ import { a as resolveOpenAIProjectedToolsStrictToolFlag, f as withPreparedToolSchemaNormalization, r as normalizeOpenAIStrictToolParameters } from "./openai-tool-schema-BO8rwyAD.mjs";
20
+ import { a as OPENAI_RESPONSES_COMPACTION_REPLAY_TYPE, c as OPENAI_RESPONSES_RETAINED_COMPACTION_REPLAY_TYPE, f as RESPONSE_FAILED_NO_DETAILS_MESSAGE, o as OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY, p as isPreviousResponseRejection, s as OPENAI_RESPONSES_REASONING_REPLAY_META_KEY } from "./openai-responses-contracts-DWrfMODE.mjs";
21
+ import { n as isOpenAIResponsesCompactionOutput, r as readOpenAIResponsesCompactionWindow } from "./openai-responses-compaction-window-D6P5oZP5.mjs";
22
+ import { n as registerSessionResourceCleanup } from "./session-resources-CkR4WWy1.mjs";
24
23
  import { createHash, randomUUID } from "node:crypto";
25
24
  //#region packages/ai/src/transports/openai-responses-replay.ts
26
25
  /** Resolves the assistant message id that can be replayed to OpenAI Responses. */
@@ -190,6 +189,199 @@ function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
190
189
  };
191
190
  }
192
191
  //#endregion
192
+ //#region packages/ai/src/transports/openai-responses-reasoning-update.ts
193
+ function isConfigurationUpdate(value) {
194
+ return isRecord(value) && value.type === "configuration_update" && isRecord(value.reasoning) && typeof value.reasoning.effort === "string";
195
+ }
196
+ function isResponsesReasoningUpdateCompatible(request) {
197
+ const mode = isRecord(request.reasoning) ? request.reasoning.mode : void 0;
198
+ return request.model === "gpt-6-astra" && (mode === void 0 || mode === "standard") && (!isRecord(request.multi_agent) || request.multi_agent.enabled !== true) && request.truncation !== "auto" && (!Array.isArray(request.context_management) || !request.context_management.some((item) => isRecord(item) && item.type === "compaction"));
199
+ }
200
+ function supportsResponsesReasoningUpdate(request) {
201
+ return isResponsesReasoningUpdateCompatible(request) && isRecord(request.reasoning) && typeof request.reasoning.effort === "string";
202
+ }
203
+ function canReferenceResponsesReasoningHistory(previous, request) {
204
+ return !previous.input?.some(isConfigurationUpdate) || isResponsesReasoningUpdateCompatible(request);
205
+ }
206
+ /** Rehydrate input controls only provisionally; continuation must validate the full prefix. */
207
+ function replayResponsesReasoningUpdates(previous, request, previousOutputLength, steering) {
208
+ if (steering !== "required-input" && (!supportsResponsesReasoningUpdate(previous) || !supportsResponsesReasoningUpdate(request)) || !Array.isArray(previous.input) || !Array.isArray(request.input) || request.input.some(isConfigurationUpdate)) return request;
209
+ const input = [...request.input];
210
+ let activeEffort = isRecord(previous.reasoning) ? previous.reasoning.effort : void 0;
211
+ for (const [index, item] of previous.input.entries()) if (isConfigurationUpdate(item)) {
212
+ input.splice(index, 0, item);
213
+ activeEffort = item.reasoning.effort;
214
+ }
215
+ if (steering === "required-input") return input.length === request.input.length ? request : {
216
+ ...request,
217
+ input
218
+ };
219
+ if (!isRecord(previous.reasoning) || !isRecord(request.reasoning) || typeof request.reasoning.effort !== "string") return request;
220
+ if (activeEffort !== request.reasoning.effort && steering !== "automatic") {
221
+ const baselineLength = previous.input.length + previousOutputLength;
222
+ const nextUser = input.findIndex((item, index) => index >= baselineLength && "role" in item && item.role === "user");
223
+ if (nextUser === -1) return request;
224
+ input.splice(nextUser, 0, {
225
+ type: "configuration_update",
226
+ reasoning: { effort: request.reasoning.effort }
227
+ });
228
+ }
229
+ if (input.length === request.input.length && activeEffort === request.reasoning.effort) return request;
230
+ return {
231
+ ...request,
232
+ reasoning: {
233
+ ...request.reasoning,
234
+ effort: previous.reasoning.effort
235
+ },
236
+ input
237
+ };
238
+ }
239
+ //#endregion
240
+ //#region packages/ai/src/transports/openai-responses-continuation.ts
241
+ const HTTP_CONTINUATION_IDLE_TTL_MS = 3e5;
242
+ const TURN_HEADERS = /* @__PURE__ */ new Set([
243
+ "traceparent",
244
+ "x-openclaw-turn-id",
245
+ "x-openclaw-turn-attempt"
246
+ ]);
247
+ function jsonValuesEqual(left, right) {
248
+ const leftJson = JSON.stringify(left);
249
+ const normalizedLeft = stableStringify(JSON.parse(leftJson));
250
+ const rightJson = JSON.stringify(right);
251
+ return leftJson === rightJson || normalizedLeft === stableStringify(JSON.parse(rightJson));
252
+ }
253
+ function requestWithoutInput(request) {
254
+ const { input: _input, previous_response_id: _previousResponseId, instructions: _instructions, tools: _tools, ...rest } = request;
255
+ if (!isRecord(rest.metadata)) return rest;
256
+ const metadata = Object.fromEntries(Object.entries(rest.metadata).filter(([key]) => key !== "openclaw_turn_id" && key !== "openclaw_turn_attempt"));
257
+ return {
258
+ ...rest,
259
+ metadata
260
+ };
261
+ }
262
+ function normalizeAssistantReplayInput(input, fromResponse = false) {
263
+ return input.map((item) => {
264
+ if (!isRecord(item)) return item;
265
+ if (item.type === "reasoning") return { type: "reasoning" };
266
+ if (item.type !== "function_call" && !(item.type === "message" && item.role === "assistant")) return item;
267
+ const { id: _id, status: _status, ...stableItem } = item;
268
+ if (fromResponse && item.type === "function_call") {
269
+ const args = parseJsonObjectPreservingUnsafeIntegers(stableItem.arguments);
270
+ stableItem.arguments = args ? JSON.stringify(args) : stableItem.arguments;
271
+ }
272
+ if (item.type === "message" && Array.isArray(stableItem.content)) stableItem.content = stableItem.content.map((part) => {
273
+ if (!isRecord(part) || part.type !== "output_text") return part;
274
+ const { annotations: _annotations, logprobs: _logprobs, ...stablePart } = part;
275
+ return stablePart;
276
+ });
277
+ return stableItem;
278
+ });
279
+ }
280
+ function responsesContinuationRequestFingerprint(request) {
281
+ const serialized = JSON.stringify(requestWithoutInput(request));
282
+ return sha256Hex(stableStringify(JSON.parse(serialized)));
283
+ }
284
+ function responsesContinuationPrefixFingerprint(input, output = []) {
285
+ const serialized = JSON.stringify([...normalizeAssistantReplayInput(input), ...normalizeAssistantReplayInput(output, true)]);
286
+ return sha256Hex(stableStringify(JSON.parse(serialized)));
287
+ }
288
+ function resolveResponsesContinuationRequest(continuation, request, steering) {
289
+ if (!continuation) return {
290
+ request,
291
+ continuationStatus: "no_previous_response"
292
+ };
293
+ if (request.previous_response_id) return {
294
+ request,
295
+ continuationStatus: "explicit_previous_response_id"
296
+ };
297
+ if (!canReferenceResponsesReasoningHistory(continuation.lastRequest, request)) return {
298
+ request,
299
+ continuationStatus: "request_changed"
300
+ };
301
+ const prepared = replayResponsesReasoningUpdates(continuation.lastRequest, request, continuation.lastResponseItems.length, steering);
302
+ if (steering !== "required-input" && !jsonValuesEqual(requestWithoutInput(prepared), requestWithoutInput(continuation.lastRequest))) return {
303
+ request,
304
+ continuationStatus: "request_changed"
305
+ };
306
+ const currentInput = prepared.input ?? [];
307
+ const previousInput = continuation.lastRequest.input ?? [];
308
+ const baselineLength = previousInput.length + continuation.lastResponseItems.length;
309
+ if (currentInput.length < baselineLength) return {
310
+ request,
311
+ continuationStatus: "history_shorter"
312
+ };
313
+ if (!jsonValuesEqual(normalizeAssistantReplayInput(currentInput.slice(0, previousInput.length)), normalizeAssistantReplayInput(previousInput)) || !jsonValuesEqual(normalizeAssistantReplayInput(currentInput.slice(previousInput.length, baselineLength)), normalizeAssistantReplayInput(continuation.lastResponseItems, true))) return {
314
+ request,
315
+ continuationStatus: "history_changed"
316
+ };
317
+ return {
318
+ request: {
319
+ ...prepared,
320
+ previous_response_id: continuation.lastResponseId,
321
+ input: currentInput.slice(baselineLength)
322
+ },
323
+ ...prepared !== request ? { fullRequest: prepared } : {},
324
+ continuationStatus: "continued"
325
+ };
326
+ }
327
+ const httpContinuationEntries = /* @__PURE__ */ new Map();
328
+ function deleteHttpContinuationIfOwned(key, entry) {
329
+ if (httpContinuationEntries.get(key) === entry) httpContinuationEntries.delete(key);
330
+ }
331
+ function connectionIdentity(params) {
332
+ const headers = Object.entries(resolveAiTransportHeaderSentinels(params.headers) ?? {}).map(([name, value]) => [name.toLowerCase(), value]).filter(([name]) => !TURN_HEADERS.has(name)).toSorted(([a], [b]) => a.localeCompare(b));
333
+ return sha256Hex(JSON.stringify([
334
+ getAiTransportHost().resolveSecretSentinel(params.apiKey),
335
+ params.baseUrl,
336
+ headers
337
+ ]));
338
+ }
339
+ function claimOpenAIResponsesHttpContinuation(params) {
340
+ const key = `${params.sessionId}\0${connectionIdentity(params)}`;
341
+ const previous = httpContinuationEntries.get(key);
342
+ if (previous?.kind === "claimed") return;
343
+ if (previous?.kind === "ready") clearTimeout(previous.idleTimer);
344
+ const claimed = {
345
+ kind: "claimed",
346
+ sessionId: params.sessionId
347
+ };
348
+ httpContinuationEntries.set(key, claimed);
349
+ try {
350
+ const request = previous?.kind === "ready" ? params.request : params.restoreRequest?.() ?? params.request;
351
+ const resolved = resolveResponsesContinuationRequest(previous?.kind === "ready" ? previous.state : void 0, request);
352
+ const fullRequest = resolved.fullRequest ?? request;
353
+ return {
354
+ request: params.request.store === false ? fullRequest : resolved.request,
355
+ fullRequest,
356
+ commit: (effectiveRequest, response) => {
357
+ if (httpContinuationEntries.get(key) !== claimed) return;
358
+ const ready = {
359
+ ...claimed,
360
+ kind: "ready",
361
+ state: {
362
+ lastRequest: effectiveRequest,
363
+ lastResponseId: response.id,
364
+ lastResponseItems: response.output
365
+ },
366
+ idleTimer: setTimeout(() => deleteHttpContinuationIfOwned(key, ready), HTTP_CONTINUATION_IDLE_TTL_MS)
367
+ };
368
+ ready.idleTimer.unref?.();
369
+ httpContinuationEntries.set(key, ready);
370
+ },
371
+ release: () => deleteHttpContinuationIfOwned(key, claimed)
372
+ };
373
+ } catch (error) {
374
+ deleteHttpContinuationIfOwned(key, claimed);
375
+ throw error;
376
+ }
377
+ }
378
+ registerSessionResourceCleanup((sessionId) => {
379
+ for (const [key, entry] of httpContinuationEntries) if (!sessionId || entry.sessionId === sessionId) {
380
+ if (entry.kind === "ready") clearTimeout(entry.idleTimer);
381
+ httpContinuationEntries.delete(key);
382
+ }
383
+ });
384
+ //#endregion
193
385
  //#region packages/ai/src/transports/openai-responses-input-replay.ts
194
386
  function recordResponsesInputReplay(message, replay) {
195
387
  if (replay) Object.assign(message, { openclawResponsesInputReplay: replay });
@@ -608,6 +800,83 @@ function convertProviderResponsesMessages(model, context, allowedToolCallProvide
608
800
  return convertResponsesMessagesWithStyle(model, context, allowedToolCallProviders, options, "provider");
609
801
  }
610
802
  //#endregion
803
+ //#region packages/ai/src/transports/openai-responses-context-usage.ts
804
+ const TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set([
805
+ "openai",
806
+ "opencode",
807
+ "azure-openai-responses",
808
+ "github-copilot"
809
+ ]);
810
+ function inputReplay(message) {
811
+ const value = "openclawResponsesInputReplay" in message ? message.openclawResponsesInputReplay : void 0;
812
+ return isRecord(value) ? value : void 0;
813
+ }
814
+ function contextFingerprint(input, output = []) {
815
+ const reasoning = [...input, ...output].flatMap((item) => {
816
+ if (!isRecord(item) || item.type !== "reasoning") return [];
817
+ const { id: _id, status: _status, ...content } = item;
818
+ return [content];
819
+ });
820
+ return sha256Hex(stableStringify({
821
+ prefix: responsesContinuationPrefixFingerprint(input, output),
822
+ reasoning
823
+ }));
824
+ }
825
+ /** Bind measured usage to the admitted replay prefix, without copying its content. */
826
+ function recordResponsesContextUsage(message, model, identity, request, output, projection) {
827
+ const usage = message.usage.contextUsage;
828
+ if (usage?.state !== "available" || !Number.isSafeInteger(usage.totalTokens) || usage.totalTokens <= 0 || message.stopReason === "error" || message.stopReason === "aborted" || message.providerReplay || request.previous_response_id || !Array.isArray(request.input) || !request.input.some((item) => isRecord(item) && item.type === "compaction") || !Array.isArray(output) || output.some((item) => isRecord(item) && item.type === "compaction")) return;
829
+ const replayOutput = (projection === "transport" ? convertResponsesMessages$1 : convertProviderResponsesMessages)(model, { messages: [message] }, TOOL_CALL_PROVIDERS, {
830
+ ...identity,
831
+ includeSystemPrompt: false
832
+ }).filter((item) => item.type !== "function_call_output");
833
+ const firstInput = request.input[0];
834
+ const contextUsage = {
835
+ ...buildProviderReplayContext(model, identity),
836
+ projection,
837
+ includeSystemPrompt: request.instructions === void 0 && firstInput?.type === "message" && (firstInput.role === "developer" || firstInput.role === "system"),
838
+ prefixHash: contextFingerprint(request.input, replayOutput),
839
+ prefixLength: request.input.length + replayOutput.length,
840
+ promptTokens: usage.promptTokens,
841
+ totalTokens: usage.totalTokens
842
+ };
843
+ Object.assign(message, { openclawResponsesInputReplay: {
844
+ ...inputReplay(message),
845
+ contextUsage
846
+ } });
847
+ }
848
+ /** Only matching provider input may replace the conservative local pressure estimate. */
849
+ function resolveResponsesContextUsageBoundary(messages, model, identity, systemPrompt) {
850
+ for (let index = messages.length - 1; index >= 0; index -= 1) {
851
+ const message = messages[index];
852
+ if (!message || !isAssistant(message)) continue;
853
+ const state = inputReplay(message)?.contextUsage;
854
+ const usage = message.usage.contextUsage;
855
+ if (!isRecord(state) || usage?.state !== "available") continue;
856
+ const { projection, prefixHash, prefixLength, promptTokens, totalTokens, includeSystemPrompt } = state;
857
+ if (!isOpenAIResponsesReplayContext(state) || !providerReplayContextMatches(state, buildProviderReplayContext(model, identity)) || message.provider !== model.provider || message.api !== model.api || message.model !== model.id || projection !== "transport" && projection !== "provider" || typeof prefixHash !== "string" || typeof prefixLength !== "number" || !Number.isSafeInteger(prefixLength) || prefixLength <= 0 || promptTokens !== usage.promptTokens || totalTokens !== usage.totalTokens || !Number.isSafeInteger(usage.totalTokens) || usage.totalTokens <= 0) return;
858
+ const input = (projection === "transport" ? convertResponsesMessages$1 : convertProviderResponsesMessages)(model, {
859
+ messages: messages.filter(isProviderMessage),
860
+ systemPrompt
861
+ }, TOOL_CALL_PROVIDERS, {
862
+ ...identity,
863
+ includeSystemPrompt: includeSystemPrompt === true
864
+ });
865
+ if (input.length < prefixLength || contextFingerprint(input.slice(0, prefixLength)) !== prefixHash) return;
866
+ return {
867
+ index,
868
+ totalTokens: usage.totalTokens,
869
+ suffix: input.slice(prefixLength)
870
+ };
871
+ }
872
+ }
873
+ function isAssistant(message) {
874
+ return message.role === "assistant";
875
+ }
876
+ function isProviderMessage(message) {
877
+ return message.role === "user" || message.role === "assistant" || message.role === "toolResult";
878
+ }
879
+ //#endregion
611
880
  //#region packages/ai/src/transports/openai-responses-replay-internal.ts
612
881
  function isAsyncIterable(value) {
613
882
  return (typeof value === "object" && value !== null || typeof value === "function") && Symbol.asyncIterator in value;
@@ -694,7 +963,7 @@ async function createResponsesStreamWithEncryptedContentRetry(params) {
694
963
  };
695
964
  } catch (error) {
696
965
  let nextAttempt = await resolveNextResponsesEncryptedContentAttempt(attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest });
697
- if (!nextAttempt && attempt.request.previous_response_id && error && typeof error === "object" && typeof error.status === "number" && error.code === "previous_response_not_found") {
966
+ if (!nextAttempt && attempt.request.previous_response_id && error && typeof error === "object" && typeof error.status === "number" && isPreviousResponseRejection(error)) {
698
967
  const request = { ...params.buildFullHistoryRequest ? await params.buildFullHistoryRequest() : attempt.request };
699
968
  delete request.previous_response_id;
700
969
  nextAttempt = {
@@ -714,43 +983,40 @@ async function createResponsesStreamWithEncryptedContentRetry(params) {
714
983
  request: params.request,
715
984
  ...params.initialRejectedCompaction ? { rejectedCompaction: params.initialRejectedCompaction } : {}
716
985
  });
717
- return {
718
- ...result,
719
- stream: { async *[Symbol.asyncIterator]() {
720
- let current = result;
721
- for (;;) {
722
- let rejectedEvent;
723
- try {
724
- for await (const event of params.wrapStream?.(current) ?? current.stream) {
725
- if (isRecord(event)) {
726
- const failure = event.type === "response.failed" && isRecord(event.response) ? event.response.error : event.type === "error" ? event.error ?? event : void 0;
727
- if (isRecord(failure) && params.canRetryStream?.() === true && isInvalidEncryptedContentError(failure)) {
728
- rejectedEvent = event;
729
- const message = typeof failure.message === "string" ? failure.message : "";
730
- throw Object.assign(new Error(message), {
731
- code: failure.code,
732
- status: failure.status
733
- });
734
- }
986
+ return { stream: { async *[Symbol.asyncIterator]() {
987
+ let current = result;
988
+ for (;;) {
989
+ let rejectedEvent;
990
+ try {
991
+ for await (const event of params.wrapStream?.(current) ?? current.stream) {
992
+ if (isRecord(event)) {
993
+ const failure = event.type === "response.failed" && isRecord(event.response) ? event.response.error : event.type === "error" ? event.error ?? event : void 0;
994
+ if (isRecord(failure) && params.canRetryStream?.() === true && isInvalidEncryptedContentError(failure)) {
995
+ rejectedEvent = event;
996
+ const message = typeof failure.message === "string" ? failure.message : "";
997
+ throw Object.assign(new Error(message), {
998
+ code: failure.code,
999
+ status: failure.status
1000
+ });
735
1001
  }
736
- yield event;
737
1002
  }
738
- return;
739
- } catch (error) {
740
- const nextAttempt = params.canRetryStream?.() === true && !params.requestOptions?.signal?.aborted ? await resolveNextResponsesEncryptedContentAttempt(current.attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest }) : void 0;
741
- if (!nextAttempt) {
742
- if (rejectedEvent !== void 0) {
743
- yield rejectedEvent;
744
- return;
745
- }
746
- throw error;
1003
+ yield event;
1004
+ }
1005
+ return;
1006
+ } catch (error) {
1007
+ const nextAttempt = params.canRetryStream?.() === true && !params.requestOptions?.signal?.aborted ? await resolveNextResponsesEncryptedContentAttempt(current.attempt, error, { buildFullHistoryRequest: params.buildFullHistoryRequest }) : void 0;
1008
+ if (!nextAttempt) {
1009
+ if (rejectedEvent !== void 0) {
1010
+ yield rejectedEvent;
1011
+ return;
747
1012
  }
748
- log.warn(`[responses] retrying streamed encrypted content provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
749
- current = await send(nextAttempt);
1013
+ throw error;
750
1014
  }
1015
+ log.warn(`[responses] retrying streamed encrypted content provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
1016
+ current = await send(nextAttempt);
751
1017
  }
752
- } }
753
- };
1018
+ }
1019
+ } } };
754
1020
  }
755
1021
  function resolveAzureOpenAIApiVersion(env = process.env) {
756
1022
  return env.AZURE_OPENAI_API_VERSION?.trim() || "preview";
@@ -1291,86 +1557,6 @@ function createResponsesOutputSlotTracker() {
1291
1557
  };
1292
1558
  }
1293
1559
  //#endregion
1294
- //#region packages/ai/src/providers/openai-responses-terminal-usage.ts
1295
- /**
1296
- * Canonical mapping for terminal OpenAI Responses events.
1297
- *
1298
- * `response.completed`, `response.incomplete`, and `response.failed` are terminal and can carry
1299
- * usage, so every Responses path finalizes through the helpers here. Keeping one owner prevents
1300
- * package and managed transports from drifting on token buckets, service-tier pricing, or future
1301
- * terminal-event semantics.
1302
- */
1303
- function readReportedCount(value) {
1304
- return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
1305
- }
1306
- function readCount(value) {
1307
- return readReportedCount(value) ?? 0;
1308
- }
1309
- /**
1310
- * Split a terminal usage payload into the priced buckets.
1311
- *
1312
- * OpenAI includes cache reads and writes in `input_tokens`, so both are subtracted out of the
1313
- * billable input bucket. `total_tokens` comes from the payload, but never below the sum of the
1314
- * split buckets: proxies routinely omit it (reporting 0 would understate the turn), and a payload
1315
- * whose `cached_tokens` exceeds `input_tokens` clamps the input bucket, leaving the reported total
1316
- * short of what the buckets actually price.
1317
- */
1318
- function mapResponsesTerminalUsage(usage) {
1319
- if (!usage) return;
1320
- const cacheRead = readCount(usage.input_tokens_details?.cached_tokens);
1321
- const cacheWrite = readCount(usage.input_tokens_details?.cache_write_tokens);
1322
- const input = Math.max(0, readCount(usage.input_tokens) - cacheRead - cacheWrite);
1323
- const output = readCount(usage.output_tokens);
1324
- const bucketTotal = input + output + cacheRead + cacheWrite;
1325
- const totalTokens = Math.max(bucketTotal, readCount(usage.total_tokens));
1326
- const reportedInput = readReportedCount(usage.input_tokens);
1327
- const reportedOutput = readReportedCount(usage.output_tokens);
1328
- const reportedTotal = readReportedCount(usage.total_tokens);
1329
- return {
1330
- input,
1331
- output,
1332
- cacheRead,
1333
- cacheWrite,
1334
- contextUsage: reportedInput !== void 0 && (reportedOutput !== void 0 || reportedTotal !== void 0 && reportedTotal >= reportedInput) && cacheRead + cacheWrite <= reportedInput ? {
1335
- state: "available",
1336
- promptTokens: reportedInput,
1337
- totalTokens: Math.max(totalTokens, reportedInput + (reportedOutput ?? 0))
1338
- } : { state: "unavailable" },
1339
- totalTokens
1340
- };
1341
- }
1342
- /** Reasoning tokens are reported by the agent path only; the package path does not track them. */
1343
- function readResponsesReasoningTokens(usage) {
1344
- return asFiniteNumber(usage?.output_tokens_details?.reasoning_tokens);
1345
- }
1346
- function mapResponsesTerminalStopReason(status) {
1347
- if (!status) return "stop";
1348
- switch (status) {
1349
- case "completed": return "stop";
1350
- case "incomplete": return "length";
1351
- case "failed":
1352
- case "cancelled": return "error";
1353
- case "in_progress":
1354
- case "queued": return "stop";
1355
- default: throw new Error(`Unhandled stop reason: ${String(status)}`);
1356
- }
1357
- }
1358
- /**
1359
- * Resolve the terminal stop reason, including the two overrides every Responses path shares: a
1360
- * content-filtered turn is a provider error rather than a truncated answer, and a turn that
1361
- * produced tool calls reports `toolUse` instead of a plain stop.
1362
- */
1363
- function resolveResponsesTerminalStopReason(params) {
1364
- const status = params.status ?? (params.terminalEventType === "response.incomplete" ? "incomplete" : void 0);
1365
- if (status === "incomplete" && params.incompleteReason === "content_filter") return {
1366
- stopReason: "error",
1367
- errorMessage: "Provider incomplete_reason: content_filter"
1368
- };
1369
- const stopReason = mapResponsesTerminalStopReason(status);
1370
- if (stopReason === "stop" && params.hasToolCall) return { stopReason: "toolUse" };
1371
- return { stopReason };
1372
- }
1373
- //#endregion
1374
1560
  //#region packages/ai/src/transports/openai-responses-stream-terminal-internal.ts
1375
1561
  function splitToolCallId(id) {
1376
1562
  const separator = id.indexOf("|");
@@ -1387,7 +1573,7 @@ function resolveResponsesToolCallId(item, fallbackId) {
1387
1573
  return resolvedItemId ? `${generated}|${resolvedItemId}` : generated;
1388
1574
  }
1389
1575
  function resolveCompletedResponsesToolCall(item, streamed) {
1390
- if (item.status && item.status !== "completed") throw new Error("Responses stream completed with an incomplete terminal tool call");
1576
+ if (item.status && item.status !== "completed") throw new IncompleteToolCallError("Responses stream completed with an incomplete terminal tool call");
1391
1577
  const streamedName = streamed?.name?.trim() || void 0;
1392
1578
  const completedName = typeof item.name === "string" ? item.name.trim() || void 0 : void 0;
1393
1579
  if (streamedName && completedName && streamedName !== completedName) throw new Error(`Responses stream changed tool-call function name from ${streamedName} to ${completedName}`);
@@ -1564,7 +1750,7 @@ function createResponsesTerminalController(params) {
1564
1750
  };
1565
1751
  const finalizeTerminalFacts = (response, responseId = response.id) => {
1566
1752
  output.responseId = responseId || output.responseId;
1567
- output.responseModel = response.model?.trim() || void 0;
1753
+ output.responseModel = options?.resolveResponseModel ? options.resolveResponseModel()?.trim() || void 0 : response.model?.trim() || void 0;
1568
1754
  const usage = mapResponsesTerminalUsage(response.usage);
1569
1755
  const reasoningTokens = readResponsesReasoningTokens(response.usage);
1570
1756
  if (usage) output.usage = {
@@ -1595,6 +1781,17 @@ function createResponsesTerminalController(params) {
1595
1781
  });
1596
1782
  output.stopReason = terminal.stopReason;
1597
1783
  output.errorMessage = terminal.errorMessage;
1784
+ if (terminalEventType === "response.completed" && typeof response.end_turn === "boolean") output.endTurn = response.end_turn;
1785
+ const incompleteReason = response.incomplete_details?.reason;
1786
+ appendAssistantMessageDiagnostic(output, {
1787
+ type: "openai_responses_terminal",
1788
+ timestamp: Date.now(),
1789
+ details: {
1790
+ eventType: terminalEventType,
1791
+ ...terminalEventType === "response.incomplete" ? { incompleteReason: incompleteReason === "max_output_tokens" || incompleteReason === "max_messages" || incompleteReason === "content_filter" || incompleteReason === "steered" ? incompleteReason : "unknown" } : {},
1792
+ endTurn: typeof response.end_turn === "boolean" ? response.end_turn : response.end_turn === void 0 ? "absent" : "invalid"
1793
+ }
1794
+ });
1598
1795
  };
1599
1796
  return {
1600
1797
  finalizeResponse,
@@ -1810,6 +2007,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
1810
2007
  block: toolCallBlock,
1811
2008
  contentIndex,
1812
2009
  argumentStreamReliable: true,
2010
+ argumentsStreamed: false,
1813
2011
  previewSchedule: createToolArgumentPreviewSchedule(),
1814
2012
  ...readResponsesToolCallItemIdentity(item)
1815
2013
  };
@@ -1903,6 +2101,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
1903
2101
  const toolCall = streamingToolCalls.resolve(event);
1904
2102
  if (toolCall) {
1905
2103
  toolCall.block.partialJson += event.delta;
2104
+ toolCall.argumentsStreamed = true;
1906
2105
  if (toolCall.previewSchedule(toolCall.block.partialJson.length)) toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
1907
2106
  stream.push({
1908
2107
  type: "toolcall_delta",
@@ -1920,6 +2119,7 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
1920
2119
  toolCall.block.partialJson = doneArguments;
1921
2120
  toolCall.block.arguments = parseStreamingJson(toolCall.block.partialJson);
1922
2121
  toolCall.argumentStreamReliable = true;
2122
+ toolCall.argumentsStreamed = true;
1923
2123
  }
1924
2124
  if (doneArguments?.startsWith(previousPartialJson)) {
1925
2125
  const delta = doneArguments.slice(previousPartialJson.length);
@@ -2015,9 +2215,11 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2015
2215
  if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
2016
2216
  const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
2017
2217
  if (streamingToolCall && !streamingToolCall.argumentStreamReliable && !completedArguments) continue;
2218
+ const streamedArguments = streamingToolCall?.block.partialJson || "";
2219
+ const preferredArguments = streamingToolCall?.argumentStreamReliable && streamingToolCall?.argumentsStreamed && streamedArguments.length > 0 && completedArguments !== void 0 && streamedArguments !== completedArguments && parseJsonObjectPreservingUnsafeIntegers(streamedArguments) !== null ? streamedArguments : completedArguments || streamedArguments;
2018
2220
  const validated = resolveCompletedResponsesToolCall(item, {
2019
2221
  name: streamingToolCall?.block.name,
2020
- arguments: completedArguments || streamingToolCall?.block.partialJson || ""
2222
+ arguments: preferredArguments
2021
2223
  });
2022
2224
  finalizeToolCall(item, readResponsesOutputIndex(event), streamingToolCall, validated);
2023
2225
  }
@@ -2027,7 +2229,10 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2027
2229
  if (output.errorMessage) throw new Error(output.errorMessage);
2028
2230
  resolveCompletedResponsesToolCall(incompleteToolCall);
2029
2231
  }
2030
- if (event.type === "response.incomplete" && streamingToolCalls.hasActive()) throw new Error(output.errorMessage ?? "Responses stream completed with unresolved tool calls");
2232
+ if (event.type === "response.incomplete" && streamingToolCalls.hasActive()) {
2233
+ if (output.errorMessage) throw new Error(output.errorMessage);
2234
+ throw new IncompleteToolCallError("Responses stream completed with unresolved tool calls");
2235
+ }
2031
2236
  if (event.type === "response.completed" || output.stopReason === "length") {
2032
2237
  const items = event.response.output ?? [];
2033
2238
  const completeToolCall = event.type === "response.completed" ? prepareTerminalToolCalls(items) : void 0;
@@ -2055,23 +2260,33 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
2055
2260
  //#region packages/ai/src/providers/openai-responses-tools.ts
2056
2261
  /** Projects direct provider descriptors before resolving their strict policy. */
2057
2262
  function convertResponsesToolPayload(tools, options) {
2058
- return convertProjectedResponsesTools(projectOpenAITools(tools), resolveResponsesStrictToolSetting(options), options?.model);
2059
- }
2060
- /** Uses caller-prepared facts without rereading descriptors or resolving host policy again. */
2061
- function convertProjectedResponsesTools(projection, strictSetting, model) {
2062
- const strict = model ? resolveOpenAIStrictToolFlagWithDiagnostics(projection, strictSetting, {
2063
- transport: "responses",
2064
- model
2065
- }) : resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
2066
- return sortPromptCacheToolsByName(projection.tools).map((tool) => {
2067
- const result = {
2068
- type: "function",
2069
- name: tool.name,
2070
- description: tool.description,
2071
- parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model?.compat)
2072
- };
2073
- if (strict !== void 0) result.strict = strict;
2074
- return result;
2263
+ return convertPreparedResponsesTools(prepareOpenAITools(tools), resolveResponsesStrictToolSetting(options), options?.model);
2264
+ }
2265
+ /** The transport has already resolved policy before descriptor projection. */
2266
+ function prepareResponsesTools(tools, strictSetting, model) {
2267
+ const prepared = prepareOpenAITools(tools);
2268
+ return {
2269
+ projection: prepared.projection,
2270
+ tools: convertPreparedResponsesTools(prepared, strictSetting, model)
2271
+ };
2272
+ }
2273
+ function convertPreparedResponsesTools(prepared, strictSetting, model) {
2274
+ const { projection, schemas } = prepared;
2275
+ return withPreparedToolSchemaNormalization(schemas, () => {
2276
+ const strict = model ? resolveOpenAIStrictToolFlagWithDiagnostics(projection, strictSetting, {
2277
+ transport: "responses",
2278
+ model
2279
+ }) : resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
2280
+ return sortPromptCacheToolsByName(projection.tools).map((tool) => {
2281
+ const result = {
2282
+ type: "function",
2283
+ name: tool.name,
2284
+ description: tool.description,
2285
+ parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model?.compat)
2286
+ };
2287
+ if (strict !== void 0) result.strict = strict;
2288
+ return result;
2289
+ });
2075
2290
  });
2076
2291
  }
2077
2292
  function resolveResponsesStrictToolSetting(options) {
@@ -2099,19 +2314,6 @@ function applyResponsesServiceTierPricing(usage, serviceTier, model) {
2099
2314
  usage.cost.cacheWrite *= multiplier;
2100
2315
  usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
2101
2316
  }
2102
- function resolveResponsesReasoningEffort(model, reasoning) {
2103
- if (!reasoning) return;
2104
- const clampedReasoning = model.reasoning && model.thinkingLevelMap?.[reasoning] === void 0 && resolveOpenAIModelReasoningEfforts(model)?.includes(reasoning) ? reasoning : clampThinkingLevel(model, reasoning);
2105
- return clampedReasoning === "off" ? void 0 : clampedReasoning;
2106
- }
2107
- function resolveResponsesRequestReasoningEffort(model, reasoning) {
2108
- const mapped = model.thinkingLevelMap?.[reasoning === "none" ? "off" : reasoning];
2109
- if (mapped !== void 0) return mapped ?? void 0;
2110
- return resolveOpenAIModelReasoningEfforts(model) === void 0 ? reasoning === "off" ? "none" : reasoning : resolveOpenAIReasoningEffortForModel({
2111
- model,
2112
- effort: reasoning
2113
- });
2114
- }
2115
2317
  function applyCommonResponsesParams(params, model, context, options, config) {
2116
2318
  if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
2117
2319
  if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
@@ -2121,10 +2323,10 @@ function applyCommonResponsesParams(params, model, context, options, config) {
2121
2323
  }
2122
2324
  if (!model.reasoning) return;
2123
2325
  const requestedEffort = options?.reasoningEffort ?? (options?.reasoningSummary ? "medium" : config?.setDefaultReasoningOff ?? true ? "off" : void 0);
2124
- const effort = requestedEffort === void 0 ? void 0 : resolveResponsesRequestReasoningEffort(model, requestedEffort);
2326
+ const effort = requestedEffort === void 0 ? void 0 : resolveOpenAIRequestReasoning(model, requestedEffort).effort;
2125
2327
  if (effort === void 0) return;
2126
2328
  params.reasoning = { effort };
2127
- if (options?.reasoningEffort || options?.reasoningSummary) {
2329
+ if (effort !== "none" && (options?.reasoningEffort || options?.reasoningSummary)) {
2128
2330
  params.reasoning.summary = options?.reasoningSummary || "auto";
2129
2331
  params.include = ["reasoning.encrypted_content"];
2130
2332
  }
@@ -2158,6 +2360,7 @@ async function runResponsesStreamLifecycle(params) {
2158
2360
  const firstEvent = createFirstStreamEventAbortController(options?.signal);
2159
2361
  firstEventAbort = firstEvent;
2160
2362
  let started = false;
2363
+ let admittedRequest;
2161
2364
  const { stream: hookedOpenAIStream } = await createResponsesStreamWithEncryptedContentRetry({
2162
2365
  client,
2163
2366
  request: requestParams,
@@ -2169,25 +2372,28 @@ async function runResponsesStreamLifecycle(params) {
2169
2372
  buildFullHistoryRequest: () => buildRequest("full-history"),
2170
2373
  onCompactionRejected: (checkpoint) => suppressOpenAIResponsesCompaction(output, model, options, checkpoint),
2171
2374
  canRetryStream: () => output.content.length === 0,
2172
- wrapStream: ({ stream: openaiStream, response }) => withProviderResponseHook({
2173
- stream: openaiStream,
2174
- signal: firstEvent.signal,
2175
- abort: firstEvent.abort,
2176
- hook: createOpenAIProviderAcceptanceHook(options, response, model),
2177
- onReady: () => {
2178
- if (!started) {
2179
- started = true;
2180
- stream.push({
2181
- type: "start",
2182
- partial: output
2183
- });
2375
+ wrapStream: ({ stream: openaiStream, response, attempt }) => {
2376
+ admittedRequest = attempt.kind === "initial" ? attempt.request : void 0;
2377
+ return withProviderResponseHook({
2378
+ stream: openaiStream,
2379
+ signal: firstEvent.signal,
2380
+ abort: firstEvent.abort,
2381
+ hook: createOpenAIProviderAcceptanceHook(options, response, model),
2382
+ onReady: () => {
2383
+ if (!started) {
2384
+ started = true;
2385
+ stream.push({
2386
+ type: "start",
2387
+ partial: output
2388
+ });
2389
+ }
2184
2390
  }
2185
- }
2186
- })
2391
+ });
2392
+ }
2187
2393
  });
2188
2394
  const firstEventTimeoutMs = getFirstStreamEventTimeoutMs(options);
2189
2395
  const onFirstEventTimeout = getFirstStreamEventTimeoutHandler(options);
2190
- await processResponsesStream(hookedOpenAIStream, output, stream, model, {
2396
+ const terminal = await processResponsesStream(hookedOpenAIStream, output, stream, model, {
2191
2397
  ...params.processStreamOptions || firstEventTimeoutMs !== void 0 || onFirstEventTimeout !== void 0 ? {
2192
2398
  ...params.processStreamOptions,
2193
2399
  firstEventTimeoutMs: params.processStreamOptions?.firstEventTimeoutMs ?? firstEventTimeoutMs,
@@ -2200,6 +2406,7 @@ async function runResponsesStreamLifecycle(params) {
2200
2406
  authProfileId: options?.authProfileId
2201
2407
  })
2202
2408
  });
2409
+ if (terminal && admittedRequest && !options?.signal?.aborted) recordResponsesContextUsage(output, model, options, admittedRequest, terminal.output, "provider");
2203
2410
  finalizeTransportStream({
2204
2411
  stream,
2205
2412
  output,
@@ -2218,4 +2425,4 @@ async function runResponsesStreamLifecycle(params) {
2218
2425
  }
2219
2426
  }
2220
2427
  //#endregion
2221
- export { resolveReplayableResponsesMessageId as $, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as A, resolveAzureOpenAIApiVersion as B, summarizeResponsesFailedNoDetailsObservation as C, readResponsesToolCallItemIdentity as D, createResponsesToolCallTracker as E, isResponsesTextDeltaEventType as F, recordResponsesInputReplay as G, buildResponsesInputMessage as H, resolveResponsesMessageSnapshotCollapse as I, buildOpenAIResponsesReasoningReplayMetadata as J, responsesInputFingerprint as K, commitResponsesEncryptedContentAttempt as L, isAzureResponsesTextDeltaEvent as M, isAzureResponsesTextDeltaEventType as N, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as O, isResponsesTextContentPartType as P, suppressOpenAIResponsesCompaction as Q, createResponsesStreamWithEncryptedContentRetry as R, summarizeOpenAITransportError as S, summarizeResponsesTools as T, convertResponsesMessages$1 as U, resolveNextResponsesEncryptedContentAttempt as V, createOpenAIResponsesAssistantOutput as W, isOpenAIResponsesReplayContext as X, captureOpenAIResponsesCompaction as Y, resolveNewestOpenAIResponsesCompactionReplay as Z, logResponsesFailedNoDetails as _, resolveResponsesReasoningEffort as a, stringifyRedactedEvent as b, convertProjectedResponsesTools as c, mapResponsesTerminalUsage as d, readResponsesReasoningTokens as f, buildResponsesFailedNoDetailsObservation as g, ResponsesStreamFailure as h, createResponsesAssistantOutput as i, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as j, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as k, convertResponsesToolPayload as l, observeResponsesStream as m, applyResponsesServiceTierPricing as n, resolveResponsesRequestReasoningEffort as o, resolveResponsesTerminalStopReason as p, CompactionReplayRefreshRequiredError as q, convertResponsesMessages as r, runResponsesStreamLifecycle as s, applyCommonResponsesParams as t, processResponsesStream as u, normalizeResponsesFailedEvent as v, summarizeResponsesPayload as w, stringifyRedactedPayload as x, safeDebugValue as y, isInvalidEncryptedContentError as z };
2428
+ export { resolveNextResponsesEncryptedContentAttempt as A, responsesContinuationPrefixFingerprint as B, isResponsesTextContentPartType as C, createResponsesStreamWithEncryptedContentRetry as D, commitResponsesEncryptedContentAttempt as E, createOpenAIResponsesAssistantOutput as F, CompactionReplayRefreshRequiredError as G, isConfigurationUpdate as H, recordResponsesInputReplay as I, isOpenAIResponsesReplayContext as J, buildOpenAIResponsesReasoningReplayMetadata as K, responsesInputFingerprint as L, resolveResponsesContextUsageBoundary as M, buildResponsesInputMessage as N, isInvalidEncryptedContentError as O, convertResponsesMessages$1 as P, claimOpenAIResponsesHttpContinuation as R, isAzureResponsesTextDeltaEventType as S, resolveResponsesMessageSnapshotCollapse as T, replayResponsesReasoningUpdates as U, responsesContinuationRequestFingerprint as V, supportsResponsesReasoningUpdate as W, suppressOpenAIResponsesCompaction as X, resolveNewestOpenAIResponsesCompactionReplay as Y, resolveReplayableResponsesMessageId as Z, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as _, runResponsesStreamLifecycle as a, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as b, processResponsesStream as c, logResponsesFailedNoDetails as d, safeDebugValue as f, readResponsesToolCallItemIdentity as g, createResponsesToolCallTracker as h, createResponsesAssistantOutput as i, recordResponsesContextUsage as j, resolveAzureOpenAIApiVersion as k, observeResponsesStream as l, summarizeResponsesPayload as m, applyResponsesServiceTierPricing as n, convertResponsesToolPayload as o, summarizeOpenAITransportError as p, captureOpenAIResponsesCompaction as q, convertResponsesMessages as r, prepareResponsesTools as s, applyCommonResponsesParams as t, ResponsesStreamFailure as u, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as v, isResponsesTextDeltaEventType as w, isAzureResponsesTextDeltaEvent as x, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as y, resolveResponsesContinuationRequest as z };