@openclaw/ai 2026.7.2-beta.4 → 2026.7.2-beta.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 (55) hide show
  1. package/dist/{anthropic-CrUDIBpM.mjs → anthropic-CQVj3le6.mjs} +53 -19
  2. package/dist/{anthropic-BoTnz8cv.d.mts → anthropic-SrGtwsJu.d.mts} +27 -1
  3. package/dist/{api-registry-BMphkFf1.d.mts → api-registry-DlMgPR39.d.mts} +1 -1
  4. package/dist/{azure-openai-responses-CbrpVeEv.mjs → azure-openai-responses-DIYgsqFM.mjs} +3 -4
  5. package/dist/error-coercion-DgxlWC0n.mjs +15 -0
  6. package/dist/{event-stream-Douf9dob.d.mts → event-stream-YjaPW20U.d.mts} +1 -1
  7. package/dist/event-stream.d.mts +1 -1
  8. package/dist/{tool-schema-json-projection-BwNu3nDi.mjs → github-copilot-headers-BCoBNmL7.mjs} +48 -1
  9. package/dist/{google-Cs62KA7t.mjs → google-f-A8xrae.mjs} +2 -2
  10. package/dist/{google-shared-CMLI-tCZ.mjs → google-shared-J6qvYINH.mjs} +5 -4
  11. package/dist/{google-vertex-B4SD3U0f.mjs → google-vertex-D3yMVXIY.mjs} +2 -2
  12. package/dist/{host-WvWBo4h8.d.mts → host-B9GUmcra.d.mts} +2 -2
  13. package/dist/index.d.mts +7 -7
  14. package/dist/index.mjs +2 -2
  15. package/dist/internal/anthropic.d.mts +15 -11
  16. package/dist/internal/anthropic.mjs +4 -4
  17. package/dist/internal/openai.d.mts +2 -1
  18. package/dist/internal/openai.mjs +4 -6
  19. package/dist/internal/runtime.d.mts +8 -32
  20. package/dist/internal/runtime.mjs +2 -3
  21. package/dist/internal/shared.d.mts +13 -8
  22. package/dist/internal/shared.mjs +2 -2
  23. package/dist/{mistral-D5Ps7Led.mjs → mistral-CKV-TOQj.mjs} +4 -3
  24. package/dist/number-coercion-DvG7SNMg.mjs +129 -0
  25. package/dist/{openai-CoGicoDt.d.mts → openai-BPor_3WI.d.mts} +35 -9
  26. package/dist/{openai-responses-shared-CzCurmY1.mjs → openai-D3PD6PE-.mjs} +1771 -745
  27. package/dist/{openai-chatgpt-responses-h0o5yV8Y.mjs → openai-chatgpt-responses-CedIj0hk.mjs} +19 -20
  28. package/dist/{openai-completions-exO8NFQf.mjs → openai-completions-CiSutyu0.mjs} +366 -227
  29. package/dist/openai-prompt-cache-2uo_1OR1.d.mts +7 -0
  30. package/dist/openai-prompt-cache-mZTCdRPo.mjs +12 -0
  31. package/dist/prompt-cache-stability-Cwcjv_fx.d.mts +13 -0
  32. package/dist/{provider-error-C4VvV_3t.mjs → provider-error-apVOZI6G.mjs} +8 -2
  33. package/dist/providers.d.mts +3 -2
  34. package/dist/providers.mjs +10 -9
  35. package/dist/{system-prompt-cache-boundary-CbHeV4_l.mjs → shared-CdjNZd35.mjs} +117 -9
  36. package/dist/{src-CXno1H5g.mjs → src-QkygScBs.mjs} +23 -4
  37. package/dist/stream-first-event-timeout-C3OgBjIk.mjs +12294 -0
  38. package/dist/stream-first-event-timeout-DvDeSucC.d.mts +29 -0
  39. package/dist/transport-stream-shared-BbMELSI4.mjs +297 -0
  40. package/dist/transports.d.mts +105 -102
  41. package/dist/transports.mjs +334 -1966
  42. package/dist/{types-AFwwWium.d.mts → types-bzp5k29J.d.mts} +7 -0
  43. package/dist/types.d.mts +5 -5
  44. package/dist/types.mjs +2 -2
  45. package/dist/{validation-sxvxC8J-.d.mts → validation-B-j7cOYp.d.mts} +1 -1
  46. package/dist/validation.d.mts +1 -1
  47. package/package.json +1 -2
  48. package/dist/azure-openai-responses-client-compat-C7K7QfUE.mjs +0 -62
  49. package/dist/github-copilot-headers-BsH5cqGj.mjs +0 -48
  50. package/dist/model-utils-1GiZ2_rr.mjs +0 -64
  51. package/dist/openai-responses-BHpmtUKo.mjs +0 -136
  52. package/dist/openai-tool-projection-ITOU9bG1.mjs +0 -200
  53. package/dist/reasoning-tag-text-partitioner-BlVe67g6.mjs +0 -400
  54. package/dist/stream-first-event-timeout-DP4xEyBY.mjs +0 -150
  55. package/npm-shrinkwrap.json +0 -638
@@ -1,52 +1,22 @@
1
1
  import { n as getEnvApiKey } from "./env-api-keys-DrgeBuva.mjs";
2
- import { c as resolveClaudeNativeThinkingLevelMap, d as supportsClaudeNativeMaxEffort, f as supportsClaudeNativeXhighEffort, l as resolveClaudeSonnet5ModelIdentity, u as supportsClaudeAdaptiveThinking } from "./src-CXno1H5g.mjs";
2
+ import { d as resolveClaudeSonnet5ModelIdentity, g as supportsClaudeNativeXhighEffort, h as supportsClaudeNativeMaxEffort, l as resolveClaudeNativeThinkingLevelMap, p as supportsClaudeAdaptiveThinking, u as resolveClaudeOpus5ModelIdentity } from "./src-QkygScBs.mjs";
3
3
  import { r as createAssistantMessageEventStream } from "./event-stream-D8n2uFee.mjs";
4
4
  import { n as getAiTransportHost, r as resolveAiTransportHeaderSentinels } from "./host-XYGZcgO8.mjs";
5
- import { C as isImageWithMediaPayload, T as isRecord, _ as normalizeOptionalString, a as stripSystemPromptCacheBoundary, b as extractToolResultBlockText, d as prepareClaudeSonnet5RequestContext, f as requiresClaudeAdaptiveThinking, g as normalizeLowercaseStringOrEmpty, h as usesClaudeStreamingRefusalContract, i as splitSystemPromptCacheBoundary, l as applyClaudeRequestContract, m as usesClaudeFable5MessagesContract, u as defaultsClaudeAdaptiveThinking, v as readStringValue, w as truncateUtf16Safe, x as extractToolResultText, y as describeToolResultMediaPlaceholder } from "./system-prompt-cache-boundary-CbHeV4_l.mjs";
6
- import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
7
- import "./internal/shared.mjs";
8
- import { C as normalizeAnthropicInlineContent, S as createAnthropicInlineImageBudget, T as canonicalizeBase64, _ as buildAnthropicServerSideFallbacks, a as readAnthropicPromptUsageSnapshot, b as omitFoundryBearerCredentialHeaders, c as projectAnthropicTools, d as ANTHROPIC_OMITTED_REASONING_TEXT, f as findActiveAnthropicToolTurnAssistantIndex, g as applyAnthropicFallbackBoundary, h as CLAUDE_FABLE_5_FALLBACK_MODEL_COST, l as reconcileAnthropicToolChoice, o as readAnthropicUsageTokenCount, p as ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, s as readLastAnthropicIterationUsage, u as resolveOriginalAnthropicToolName, v as readAnthropicFallbackBoundary, w as resolveAnthropicImageMediaType, x as usesFoundryBearerAuth, y as applyAnthropicRefusal } from "./anthropic-CrUDIBpM.mjs";
9
- import { n as calculateCost, r as clampThinkingLevel, t as applyProviderReportedUsageCost } from "./model-utils-1GiZ2_rr.mjs";
5
+ import { n as clampOpenAIPromptCacheKey } from "./openai-prompt-cache-mZTCdRPo.mjs";
6
+ import { C as extractToolResultBlockText, E as isImageWithMediaPayload, O as isRecord, S as describeToolResultMediaPlaceholder, _ as usesClaudeStreamingRefusalContract, a as splitSystemPromptCacheBoundary, d as applyClaudeRequestContract, f as defaultsClaudeAdaptiveThinking, g as usesClaudeFable5MessagesContract, l as sortPromptCacheToolsByName, m as requiresClaudeAdaptiveThinking, o as stripSystemPromptCacheBoundary, p as prepareClaudeNoPrefillRequestContext, v as hasNonEmptyString, w as extractToolResultText, x as readStringValue, y as normalizeLowercaseStringOrEmpty } from "./shared-CdjNZd35.mjs";
7
+ import { C as transformTransportMessages, S as resolveProviderRequestPolicyConfig, _ as buildGuardedModelFetch, a as projectOpenAITools, b as resolveProviderEndpoint, c as mapOpenAIStopReason, d as resolveOpenAICompletionsCompat, f as resolveOpenAICompletionsResponseFormat, g as tagPendingCommentaryText, h as rememberPendingCommentaryTags, l as resolveOpenAIReasoningEffortMap, m as clearPendingCommentaryText, o as reconcileOpenAICompletionsToolChoice, p as shouldOmitOllamaCompatResponseFormat, s as reconcileOpenAIResponsesToolChoice, t as convertMessages, u as detectOpenAICompletionsCompat, v as resolveModelRequestTimeoutMs, x as resolveProviderRequestCapabilities, y as resolveOpenAIStrictToolSetting } from "./openai-completions-CiSutyu0.mjs";
8
+ import { t as toErrorObject } from "./error-coercion-DgxlWC0n.mjs";
9
+ import { C as normalizeAnthropicInlineContent, S as createAnthropicInlineImageBudget, T as canonicalizeBase64, _ as readAnthropicFallbackBoundary, a as readAnthropicPromptUsageSnapshot, b as omitFoundryBearerCredentialHeaders, c as projectAnthropicTools, d as ANTHROPIC_OMITTED_REASONING_TEXT, f as findActiveAnthropicToolTurnAssistantIndex, g as applyAnthropicFallbackBoundary, l as reconcileAnthropicToolChoice, m as ANTHROPIC_SERVER_SIDE_FALLBACK_BETA, o as readAnthropicUsageTokenCount, p as ANTHROPIC_SERVER_SIDE_FALLBACKS, s as readLastAnthropicIterationUsage, u as resolveOriginalAnthropicToolName, v as resolveAnthropicFallbackServingModelCost, w as resolveAnthropicImageMediaType, x as usesFoundryBearerAuth, y as applyAnthropicRefusal } from "./anthropic-CQVj3le6.mjs";
10
+ import { a as parseStrictPositiveInteger, c as calculateCost, l as clampThinkingLevel, s as applyProviderReportedUsageCost } from "./number-coercion-DvG7SNMg.mjs";
11
+ import { C as resolveSecretSentinel, S as resolveModelHeaderSentinels$1, T as supportsModelTools, _ as isGoogleGemini3ProModel, a as failTransportStream, c as mergeTransportMetadata, d as transportAbortError, f as MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE, g as isGoogleGemini3FlashModel, h as isCodeModeModelVisibleToolName, i as createWritableTransportEventStream, l as sanitizeNonEmptyTransportPayloadText, m as estimateStringChars, n as coerceTransportToolCallArguments, o as finalizeTransportStream, p as createAbortError$1, r as createEmptyTransportUsage, s as mergeTransportHeaders, t as assignTransportErrorDetails, u as sanitizeTransportPayloadText, v as parseRetryAfterSeconds, w as sha256Hex, y as readResponseTextSnippet } from "./transport-stream-shared-BbMELSI4.mjs";
10
12
  import { r as createDeferredEventBuffer, t as notifyLlmRequestActivity } from "./llm-request-activity-CehVkZP-.mjs";
11
13
  import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
12
14
  import "./internal/anthropic.mjs";
13
- import { t as createReasoningTagTextPartitioner } from "./reasoning-tag-text-partitioner-BlVe67g6.mjs";
14
- import { a as withFirstStreamEventTimeout, c as parseStrictFiniteNumber, i as getFirstStreamEventTimeoutMs, l as parseStrictNonNegativeInteger, o as asFiniteNumberInRange, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController, u as parseStrictPositiveInteger } from "./stream-first-event-timeout-DP4xEyBY.mjs";
15
+ import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, o as createReasoningTagTextPartitioner, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-C3OgBjIk.mjs";
15
16
  import "./internal/runtime.mjs";
16
- import { a as mapOpenAIStopReason, c as rememberPendingCommentaryTags, l as tagPendingCommentaryText, o as resolveOpenAIReasoningEffortMap, s as clearPendingCommentaryText, t as convertMessages } from "./openai-completions-exO8NFQf.mjs";
17
- import { parseRetryAfterHttpDateMs } from "./internal/retry-after.mjs";
18
- import { A as isOpenAIGpt54MiniModel, D as isResponsesTextContentPartType, G as uniqueStrings, I as supportsOpenAIReasoningEffort, M as isOpenAIGpt56Model, N as normalizeOpenAIReasoningEffort, O as isResponsesTextDeltaEventType, P as resolveOpenAIReasoningEffortForModel, _ as readResponsesToolCallItemIdentity, b as resolveResponsesTerminalStopReason, d as normalizeOpenAIStrictToolParameters, g as createResponsesToolCallTracker, j as isOpenAIGpt55Model, k as resolveResponsesMessageSnapshotCollapse, l as findOpenAIStrictToolProjectionDiagnostics, p as resolveOpenAIProjectedToolsStrictToolFlag, v as mapResponsesTerminalUsage, y as readResponsesReasoningTokens } from "./openai-responses-shared-CzCurmY1.mjs";
19
- import { i as resolveAzureDeploymentNameFromMap, t as isOpenAICompatibleAzureResponsesBaseUrl } from "./azure-openai-responses-client-compat-C7K7QfUE.mjs";
20
- import { a as clampOpenAIPromptCacheKey, n as reconcileOpenAICompletionsToolChoice, r as reconcileOpenAIResponsesToolChoice, t as projectOpenAITools } from "./openai-tool-projection-ITOU9bG1.mjs";
21
- import "./internal/openai.mjs";
22
- import { createHash, randomUUID } from "node:crypto";
17
+ import { A as resolveAzureOpenAIApiVersion, At as emitModelTransportDebug, B as stringifyRedactedPayload, C as observeResponsesStream, D as createResponsesStreamWithEncryptedContentRetry, E as convertResponsesMessages, F as buildResponsesFailedNoDetailsObservation, G as GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, H as summarizeResponsesFailedNoDetailsObservation, I as logResponsesFailedNoDetails, J as resolveCacheRetention, K as createModelStreamCooperativeScheduler, L as normalizeResponsesFailedEvent, M as tagOpenAIResponsesReasoningReplayItem, Mt as resolveModelSseDebugMode, N as resolveReplayableResponsesMessageId, O as isInvalidEncryptedContentError, P as applyServiceTierPricing, Q as OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS, R as safeDebugValue, T as buildResponsesInputMessage, U as summarizeResponsesPayload, V as summarizeOpenAITransportError, W as summarizeResponsesTools, X as throwIfModelStreamAborted, Y as resolvePromptCacheKey, Z as AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS, d as findOpenAIStrictToolProjectionDiagnostics, dt as isOpenAIGpt55Model, ft as isOpenAIGpt56Model, gt as supportsOpenAIReasoningEffort, h as resolveOpenAIProjectedToolsStrictToolFlag, j as stripResponsesRequestEncryptedContent, jt as resolveModelPayloadDebugMode, k as prepareOpenAIResponsesReasoningItemForReplay, kt as uniqueStrings, mt as resolveOpenAIReasoningEffortForModel, p as normalizeOpenAIStrictToolParameters, pt as normalizeOpenAIReasoningEffort, q as log, ut as isOpenAIGpt54MiniModel, v as ResponsesStreamFailure, vt as isOpenAICompatibleAzureResponsesBaseUrl, w as buildOpenAIResponsesReasoningReplayMetadata, xt as resolveAzureDeploymentNameFromMap, y as processResponsesStream, z as stringifyRedactedEvent } from "./openai-D3PD6PE-.mjs";
18
+ import { randomUUID } from "node:crypto";
23
19
  import OpenAI, { AzureOpenAI } from "openai";
24
- //#region packages/ai/src/transports/host-policy.ts
25
- function buildGuardedModelFetch(model, timeoutMs, options) {
26
- const host = getAiTransportHost();
27
- if (options !== void 0) return host.buildModelFetch(model, timeoutMs, options) ?? globalThis.fetch;
28
- if (timeoutMs !== void 0) return host.buildModelFetch(model, timeoutMs) ?? globalThis.fetch;
29
- return host.buildModelFetch(model) ?? globalThis.fetch;
30
- }
31
- function resolveProviderEndpoint(baseUrl) {
32
- return { endpointClass: getAiTransportHost().resolveProviderEndpointClass(baseUrl) };
33
- }
34
- function resolveProviderRequestCapabilities(input) {
35
- return getAiTransportHost().resolveProviderRequestCapabilities(input);
36
- }
37
- function resolveProviderRequestPolicyConfig(input) {
38
- return { headers: getAiTransportHost().resolveProviderRequestHeaders(input) };
39
- }
40
- function resolveModelRequestTimeoutMs(model, timeoutMs) {
41
- return timeoutMs ?? getAiTransportHost().resolveModelRequestTimeoutMs(model);
42
- }
43
- function resolveOpenAIStrictToolSetting(model, options) {
44
- return getAiTransportHost().resolveOpenAIStrictToolSetting(model, options);
45
- }
46
- function transformTransportMessages(messages, model, normalizeToolCallId, options) {
47
- return getAiTransportHost().transformTransportMessages(messages, model, normalizeToolCallId, options);
48
- }
49
- //#endregion
50
20
  //#region packages/ai/src/transports/anthropic-payload-policy.ts
51
21
  /**
52
22
  * Anthropic-family request payload policy helpers.
@@ -219,20 +189,6 @@ function applyAnthropicEphemeralCacheControlMarkers(payloadObj, cacheControl = {
219
189
  }
220
190
  }
221
191
  //#endregion
222
- //#region packages/normalization-core/src/error-coercion.ts
223
- /**
224
- * Normalizes an unknown thrown value into an Error. Non-Error objects become
225
- * the `cause` and have their enumerable fields copied so structured details
226
- * (codes, statuses) survive the coercion.
227
- */
228
- function toErrorObject(value, fallbackMessage) {
229
- if (value instanceof Error) return value;
230
- if (typeof value === "string") return new Error(value);
231
- const error = new Error(fallbackMessage, { cause: value });
232
- if (typeof value === "object" && value !== null || typeof value === "function") Object.assign(error, value);
233
- return error;
234
- }
235
- //#endregion
236
192
  //#region packages/ai/src/transports/json-unsafe-integers.ts
237
193
  /**
238
194
  * JSON parsing helpers that preserve integer literals larger than
@@ -330,270 +286,6 @@ function parseJsonObjectPreservingUnsafeIntegers(value) {
330
286
  return null;
331
287
  }
332
288
  //#endregion
333
- //#region packages/ai/src/transports/transport-utils.ts
334
- const MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE = "OpenClaw transport error: malformed_streaming_fragment";
335
- const NON_LATIN_RE = /[\u2E80-\u9FFF\uA000-\uA4FF\uAC00-\uD7AF\uF900-\uFAFF\uFF01-\uFF60\uFFE0-\uFFE6\u{20000}-\u{2FA1F}]/gu;
336
- const CJK_SURROGATE_HIGH_RE = /[\uD840-\uD87E][\uDC00-\uDFFF]/g;
337
- function sha256Hex(value) {
338
- return createHash("sha256").update(value).digest("hex");
339
- }
340
- function sha256HexPrefix(value, length) {
341
- return sha256Hex(value).slice(0, length);
342
- }
343
- function redactIdentifier(value, opts) {
344
- const trimmed = normalizeOptionalString(value);
345
- if (!trimmed) return "-";
346
- return `sha256:${sha256HexPrefix(trimmed, Number.isFinite(opts?.len) ? Math.max(1, Math.floor(opts?.len ?? 12)) : 12)}`;
347
- }
348
- function redactSensitiveText(text, _options) {
349
- return getAiTransportHost().redactToolPayloadText(text);
350
- }
351
- function resolveSecretSentinel(value) {
352
- return getAiTransportHost().resolveSecretSentinel(value);
353
- }
354
- function resolveModelHeaderSentinels$1(model) {
355
- if (!model.headers) return model;
356
- let headers;
357
- for (const [name, value] of Object.entries(model.headers)) {
358
- const resolved = resolveSecretSentinel(value);
359
- if (resolved !== value) {
360
- headers ??= { ...model.headers };
361
- headers[name] = resolved;
362
- }
363
- }
364
- return headers ? {
365
- ...model,
366
- headers
367
- } : model;
368
- }
369
- function createAbortError$1(message, options) {
370
- const error = new Error(message, options);
371
- error.name = "AbortError";
372
- return error;
373
- }
374
- function estimateStringChars(text) {
375
- if (!text) return 0;
376
- const nonLatinCount = (text.match(NON_LATIN_RE) ?? []).length;
377
- return (nonLatinCount === 0 ? text.length : text.length - (text.match(CJK_SURROGATE_HIGH_RE) ?? []).length) + nonLatinCount * 3;
378
- }
379
- function supportsModelTools(model) {
380
- return (model.compat && typeof model.compat === "object" ? model.compat : void 0)?.supportsTools !== false;
381
- }
382
- function isCodeModeModelVisibleToolName(name) {
383
- return name === "exec" || name === "wait" || name === "computer" || name === "image";
384
- }
385
- function isGoogleGemini3Model(modelId, family) {
386
- const normalized = modelId.trim().toLowerCase();
387
- const suffix = family === "pro" ? "pro" : "flash";
388
- return new RegExp(`(?:^|/)gemini-(?:3(?:\\.\\d+)?-${suffix}|${suffix}${family === "flash" ? "(?:-lite)?" : ""}-latest)(?:-|$)`).test(normalized);
389
- }
390
- function isGoogleGemini3ProModel(modelId) {
391
- return isGoogleGemini3Model(modelId, "pro");
392
- }
393
- function isGoogleGemini3FlashModel(modelId) {
394
- return isGoogleGemini3Model(modelId, "flash");
395
- }
396
- function parseRetryAfterSeconds(headers) {
397
- const retryAfterMs = headers.get("retry-after-ms");
398
- if (retryAfterMs) {
399
- const trimmed = retryAfterMs.trim();
400
- if (/^\d+(?:\.\d+)?$/.test(trimmed)) {
401
- const milliseconds = asFiniteNumberInRange(parseStrictFiniteNumber(trimmed), {
402
- min: 0,
403
- max: Number.MAX_SAFE_INTEGER
404
- });
405
- return milliseconds === void 0 ? Number.POSITIVE_INFINITY : milliseconds / 1e3;
406
- }
407
- }
408
- const retryAfter = headers.get("retry-after")?.trim();
409
- if (!retryAfter) return;
410
- if (/^\d+$/.test(retryAfter)) return parseStrictNonNegativeInteger(retryAfter) ?? Number.POSITIVE_INFINITY;
411
- const retryAt = parseRetryAfterHttpDateMs(retryAfter);
412
- return retryAt === void 0 ? void 0 : Math.max(0, (retryAt - Date.now()) / 1e3);
413
- }
414
- async function readChunkWithIdleTimeout(reader, timeoutMs, onIdleTimeout) {
415
- let timer;
416
- try {
417
- return await Promise.race([reader.read(), new Promise((_resolve, reject) => {
418
- timer = setTimeout(() => reject(onIdleTimeout?.({ chunkTimeoutMs: timeoutMs }) ?? /* @__PURE__ */ new Error("Read timed out")), timeoutMs);
419
- })]);
420
- } finally {
421
- if (timer) clearTimeout(timer);
422
- }
423
- }
424
- async function readResponseTextSnippet(response, options) {
425
- const maxBytes = options?.maxBytes ?? 8 * 1024;
426
- const maxChars = options?.maxChars ?? 200;
427
- const reader = response.body?.getReader();
428
- if (!reader) return;
429
- const chunks = [];
430
- let bytes = 0;
431
- let truncated = false;
432
- try {
433
- while (bytes < maxBytes) {
434
- const result = options?.chunkTimeoutMs ? await readChunkWithIdleTimeout(reader, options.chunkTimeoutMs, options.onIdleTimeout) : await reader.read();
435
- if (result.done) break;
436
- if (!result.value?.length) continue;
437
- const remaining = maxBytes - bytes;
438
- chunks.push(result.value.subarray(0, remaining));
439
- bytes += Math.min(result.value.length, remaining);
440
- if (result.value.length >= remaining) {
441
- truncated = true;
442
- await reader.cancel().catch(() => void 0);
443
- break;
444
- }
445
- }
446
- } catch (error) {
447
- await reader.cancel(error).catch(() => void 0);
448
- throw error;
449
- } finally {
450
- reader.releaseLock();
451
- }
452
- const merged = new Uint8Array(bytes);
453
- let offset = 0;
454
- for (const chunk of chunks) {
455
- merged.set(chunk, offset);
456
- offset += chunk.length;
457
- }
458
- const collapsed = new TextDecoder().decode(merged).replace(/\s+/g, " ").trim();
459
- if (!collapsed) return;
460
- if (collapsed.length > maxChars) return `${truncateUtf16Safe(collapsed, maxChars)}…`;
461
- return truncated ? `${collapsed}…` : collapsed;
462
- }
463
- //#endregion
464
- //#region packages/ai/src/transports/transport-stream-shared.ts
465
- const EMPTY_TOOL_RESULT_TEXT = "(no output)";
466
- function sanitizeTransportPayloadText(text) {
467
- if (typeof text !== "string") return "";
468
- return sanitizeSurrogates(text);
469
- }
470
- function sanitizeNonEmptyTransportPayloadText(text, fallback = EMPTY_TOOL_RESULT_TEXT) {
471
- const sanitized = sanitizeTransportPayloadText(text);
472
- return sanitized.trim().length > 0 ? sanitized : fallback;
473
- }
474
- function coerceTransportToolCallArguments(argumentsValue) {
475
- if (argumentsValue && typeof argumentsValue === "object" && !Array.isArray(argumentsValue)) return argumentsValue;
476
- if (typeof argumentsValue === "string") try {
477
- const parsed = JSON.parse(argumentsValue);
478
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
479
- } catch {}
480
- return {};
481
- }
482
- function mergeTransportHeaders(...headerSources) {
483
- const merged = {};
484
- for (const headers of headerSources) if (headers) Object.assign(merged, headers);
485
- return Object.keys(merged).length > 0 ? merged : void 0;
486
- }
487
- function mergeTransportMetadata(payload, metadata) {
488
- if (!metadata || Object.keys(metadata).length === 0) return payload;
489
- const existingMetadata = payload.metadata && typeof payload.metadata === "object" && !Array.isArray(payload.metadata) ? payload.metadata : void 0;
490
- return {
491
- ...payload,
492
- metadata: {
493
- ...existingMetadata,
494
- ...metadata
495
- }
496
- };
497
- }
498
- function createEmptyTransportUsage() {
499
- return {
500
- input: 0,
501
- output: 0,
502
- cacheRead: 0,
503
- cacheWrite: 0,
504
- totalTokens: 0,
505
- cost: {
506
- input: 0,
507
- output: 0,
508
- cacheRead: 0,
509
- cacheWrite: 0,
510
- total: 0
511
- }
512
- };
513
- }
514
- function createWritableTransportEventStream() {
515
- const eventStream = createAssistantMessageEventStream();
516
- return {
517
- eventStream,
518
- stream: eventStream
519
- };
520
- }
521
- function finalizeTransportStream(params) {
522
- const { stream, output, signal } = params;
523
- if (signal?.aborted) throw new Error("Request was aborted");
524
- if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
525
- stream.push({
526
- type: "done",
527
- reason: output.stopReason,
528
- message: output
529
- });
530
- stream.end();
531
- }
532
- function readStringLikeProperty(value, key) {
533
- if (!value || typeof value !== "object") return;
534
- const raw = value[key];
535
- if (typeof raw === "string") return raw.trim() || void 0;
536
- if (typeof raw === "number" && Number.isFinite(raw)) return String(raw);
537
- }
538
- function readObjectProperty(value, key) {
539
- if (!value || typeof value !== "object") return;
540
- const raw = value[key];
541
- return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : void 0;
542
- }
543
- function stringifyErrorBody(value) {
544
- if (typeof value === "string") return value;
545
- if (value === void 0 || value === null) return;
546
- try {
547
- return JSON.stringify(value);
548
- } catch {
549
- return;
550
- }
551
- }
552
- function stringifyTransportErrorMessage(value) {
553
- if (value instanceof Error) return value.message;
554
- const encoded = stringifyErrorBody(value);
555
- if (encoded !== void 0) return encoded;
556
- try {
557
- return String(value);
558
- } catch {
559
- return;
560
- }
561
- }
562
- function normalizeTransportErrorBody(value) {
563
- const text = stringifyErrorBody(value);
564
- if (!text?.trim()) return;
565
- const redacted = redactSensitiveText(text);
566
- return redacted.length > 500 ? `${truncateUtf16Safe(redacted, 499)}…` : redacted;
567
- }
568
- function extractTransportErrorDetails(error) {
569
- const errorObject = error && typeof error === "object" ? error : void 0;
570
- const nestedError = readObjectProperty(errorObject, "error");
571
- const errorCode = readStringLikeProperty(errorObject, "errorCode") ?? readStringLikeProperty(errorObject, "code") ?? readStringLikeProperty(nestedError, "code");
572
- const errorType = readStringLikeProperty(errorObject, "errorType") ?? readStringLikeProperty(errorObject, "type") ?? readStringLikeProperty(nestedError, "type");
573
- const errorBody = normalizeTransportErrorBody(readStringLikeProperty(errorObject, "errorBody")) ?? normalizeTransportErrorBody(readStringLikeProperty(errorObject, "body")) ?? normalizeTransportErrorBody(readObjectProperty(errorObject, "body")) ?? normalizeTransportErrorBody(nestedError);
574
- return {
575
- ...errorCode ? { errorCode } : {},
576
- ...errorType ? { errorType } : {},
577
- ...errorBody ? { errorBody } : {}
578
- };
579
- }
580
- function assignTransportErrorDetails(output, error, signal) {
581
- output.stopReason = signal?.aborted ? "aborted" : "error";
582
- output.errorMessage = stringifyTransportErrorMessage(error);
583
- Object.assign(output, extractTransportErrorDetails(error));
584
- }
585
- function failTransportStream(params) {
586
- const { stream, output, signal, error, cleanup } = params;
587
- cleanup?.();
588
- assignTransportErrorDetails(output, error, signal);
589
- stream.push({
590
- type: "error",
591
- reason: output.stopReason,
592
- error: output
593
- });
594
- stream.end();
595
- }
596
- //#endregion
597
289
  //#region packages/ai/src/transports/anthropic-transport-stream.ts
598
290
  /**
599
291
  * Native Anthropic Messages streaming transport.
@@ -712,7 +404,7 @@ function isKimiAnthropicProvider(provider) {
712
404
  * identity) requests are excluded until the beta is verified there.
713
405
  */
714
406
  function useAnthropicServerSideFallback(model) {
715
- return usesClaudeFable5MessagesContract(model) && isDirectAnthropicModel(model);
407
+ return (usesClaudeFable5MessagesContract(model) || resolveClaudeOpus5ModelIdentity(model) !== void 0) && isDirectAnthropicModel(model);
716
408
  }
717
409
  function supportsReasoningContentReplay(model) {
718
410
  return resolveProviderEndpoint(model.baseUrl).endpointClass === "xiaomi-native";
@@ -1200,7 +892,7 @@ async function buildAnthropicParams(model, context, isOAuthToken, options) {
1200
892
  max_tokens: maxTokens,
1201
893
  stream: true
1202
894
  };
1203
- if (!isOAuthToken && useAnthropicServerSideFallback(model)) params.fallbacks = buildAnthropicServerSideFallbacks();
895
+ if (!isOAuthToken && useAnthropicServerSideFallback(model)) params.fallbacks = ANTHROPIC_SERVER_SIDE_FALLBACKS;
1204
896
  if (isOAuthToken) params.system = [
1205
897
  {
1206
898
  type: "text",
@@ -1258,7 +950,7 @@ function resolveAnthropicTransportOptions(model, options, apiKey) {
1258
950
  modelContextWindow: model.contextWindow,
1259
951
  modelMaxTokens: model.maxTokens,
1260
952
  requestedMaxTokens: options?.maxTokens,
1261
- useModelDefault: resolveClaudeSonnet5ModelIdentity(model) !== void 0
953
+ useModelDefault: resolveClaudeSonnet5ModelIdentity(model) !== void 0 || resolveClaudeOpus5ModelIdentity(model) !== void 0
1262
954
  });
1263
955
  if (baseMaxTokens === void 0) throw new Error(`Anthropic Messages transport requires a positive maxTokens value for ${model.provider}/${model.id}`);
1264
956
  const reasoningModelMaxTokens = resolvePositiveAnthropicTokenLimit(model.maxTokens) ?? baseMaxTokens;
@@ -1332,7 +1024,7 @@ function createAnthropicMessagesTransportStreamFn() {
1332
1024
  const apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? "";
1333
1025
  if (!apiKey) throw new Error(`No API key for provider: ${model.provider}`);
1334
1026
  const transportOptions = resolveAnthropicTransportOptions(model, options, apiKey);
1335
- const requestContext = prepareClaudeSonnet5RequestContext(model, context);
1027
+ const requestContext = prepareClaudeNoPrefillRequestContext(model, context);
1336
1028
  const { client, isOAuthToken } = createAnthropicTransportClient({
1337
1029
  model,
1338
1030
  context: requestContext,
@@ -1502,7 +1194,11 @@ function createAnthropicMessagesTransportStreamFn() {
1502
1194
  });
1503
1195
  costModel = {
1504
1196
  ...model,
1505
- cost: CLAUDE_FABLE_5_FALLBACK_MODEL_COST
1197
+ cost: resolveAnthropicFallbackServingModelCost({
1198
+ requestedModelId: model.id,
1199
+ servingModelId: fallbackBoundary.toModel,
1200
+ requestedCost: model.cost
1201
+ })
1506
1202
  };
1507
1203
  calculateCost(costModel, output.usage);
1508
1204
  eventSink.push({
@@ -1779,7 +1475,7 @@ function createAnthropicMessagesTransportStreamFn() {
1779
1475
  }
1780
1476
  }
1781
1477
  if (refusalBuffer && !sawMessageStop) throw new Error("Anthropic stream ended before message_stop");
1782
- if (transportOptions.signal?.aborted) throw new Error("Request was aborted");
1478
+ if (transportOptions.signal?.aborted) throw transportAbortError(transportOptions.signal);
1783
1479
  if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
1784
1480
  refusalBuffer?.flush();
1785
1481
  if (output.stopReason === "toolUse" || output.content.some((block) => block.type === "toolCall")) tagPendingCommentaryText(output.content);
@@ -1936,44 +1632,6 @@ function canonicalizeMaxTokensParam(params) {
1936
1632
  params.merged.maxTokens = resolved;
1937
1633
  }
1938
1634
  //#endregion
1939
- //#region packages/ai/src/transports/model-transport-debug.ts
1940
- function normalizeEnv(value) {
1941
- return typeof value === "string" ? value.trim().toLowerCase() : "";
1942
- }
1943
- function isTruthyEnv(value) {
1944
- const normalized = normalizeEnv(value);
1945
- return normalized.length > 0 && normalized !== "0" && normalized !== "false" && normalized !== "off" && normalized !== "no";
1946
- }
1947
- /** Resolves model payload debug verbosity from `OPENCLAW_DEBUG_MODEL_PAYLOAD`. */
1948
- function resolveModelPayloadDebugMode(env = process.env) {
1949
- const normalized = normalizeEnv(env.OPENCLAW_DEBUG_MODEL_PAYLOAD);
1950
- if (normalized === "tools" || normalized === "full-redacted") return normalized;
1951
- if (normalized === "summary") return "summary";
1952
- return "off";
1953
- }
1954
- /** Resolves SSE stream debug verbosity from `OPENCLAW_DEBUG_SSE`. */
1955
- function resolveModelSseDebugMode(env = process.env) {
1956
- const normalized = normalizeEnv(env.OPENCLAW_DEBUG_SSE);
1957
- if (normalized === "peek") return "peek";
1958
- if (normalized === "events" || isTruthyEnv(normalized)) return "events";
1959
- return "off";
1960
- }
1961
- /** Returns whether any model transport debug channel is enabled. */
1962
- function isModelTransportDebugEnabled(env = process.env) {
1963
- return isTruthyEnv(env.OPENCLAW_DEBUG_MODEL_TRANSPORT) || resolveModelPayloadDebugMode(env) !== "off" || resolveModelSseDebugMode(env) !== "off" || isTruthyEnv(env.OPENCLAW_DEBUG_CODE_MODE);
1964
- }
1965
- function isModelFetchMetadataMessage(message) {
1966
- return message.startsWith("[model-fetch]");
1967
- }
1968
- /** Emits model-fetch metadata at info level by default; other diagnostics require debug env. */
1969
- function emitModelTransportDebug(log, message) {
1970
- if (isModelFetchMetadataMessage(message) || isModelTransportDebugEnabled()) {
1971
- log.info(message);
1972
- return;
1973
- }
1974
- log.debug(message);
1975
- }
1976
- //#endregion
1977
1635
  //#region packages/ai/src/transports/model-transport-url.ts
1978
1636
  /**
1979
1637
  * Debug formatting helpers for model transport endpoints.
@@ -2004,9 +1662,6 @@ function formatModelTransportDebugBaseUrl(rawUrl) {
2004
1662
  * Some providers reject requests without a non-empty user/assistant turn; this
2005
1663
  * helper checks the loose message payload shape before transport submission.
2006
1664
  */
2007
- function hasNonEmptyString(value) {
2008
- return typeof value === "string" && value.trim().length > 0;
2009
- }
2010
1665
  function hasNonEmptyContentPart(part) {
2011
1666
  if (!part || typeof part !== "object") return false;
2012
1667
  const record = part;
@@ -2036,62 +1691,6 @@ function hasOpenAICompatibleConversationTurn(messages) {
2036
1691
  });
2037
1692
  }
2038
1693
  //#endregion
2039
- //#region packages/ai/src/transports/openai-completions-compat.ts
2040
- function isDefaultRouteProvider(provider, ...ids) {
2041
- return provider !== void 0 && ids.includes(provider);
2042
- }
2043
- /** Resolves default request flags for an OpenAI-compatible completions endpoint. */
2044
- function resolveOpenAICompletionsCompatDefaults(input) {
2045
- const { provider, endpointClass, knownProviderFamily, supportsNativeStreamingUsageCompat = false, supportsOpenAICompletionsStreamingUsageCompat = false, usesExplicitProxyLikeEndpoint = false } = input;
2046
- const isDefaultRoute = endpointClass === "default";
2047
- const usesConfiguredNonOpenAIEndpoint = endpointClass !== "default" && endpointClass !== "openai-public";
2048
- const isMoonshotLike = knownProviderFamily === "moonshot" || knownProviderFamily === "modelstudio" || endpointClass === "moonshot-native" || endpointClass === "modelstudio-native";
2049
- const isModelStudioLike = knownProviderFamily === "modelstudio" || endpointClass === "modelstudio-native" || isDefaultRoute && isDefaultRouteProvider(provider, "dashscope", "modelstudio", "qwen");
2050
- const isZai = endpointClass === "zai-native" || isDefaultRoute && isDefaultRouteProvider(input.provider, "zai");
2051
- const isDeepSeek = endpointClass === "deepseek-native" || isDefaultRoute && isDefaultRouteProvider(input.provider, "deepseek");
2052
- const isTogether = knownProviderFamily === "together" || isDefaultRoute && isDefaultRouteProvider(input.provider, "together");
2053
- const isXiaomi = endpointClass === "xiaomi-native" || isDefaultRoute && isDefaultRouteProvider(input.provider, "xiaomi");
2054
- const isNonStandard = endpointClass === "cerebras-native" || endpointClass === "chutes-native" || endpointClass === "deepseek-native" || endpointClass === "mistral-public" || endpointClass === "opencode-native" || endpointClass === "xai-native" || isXiaomi || isZai || isDefaultRoute && isDefaultRouteProvider(input.provider, "cerebras", "chutes", "deepseek", "opencode", "xai");
2055
- const isOpenRouterLike = input.provider === "openrouter" || endpointClass === "openrouter";
2056
- const isLocalEndpoint = endpointClass === "local";
2057
- const usesMaxTokens = endpointClass === "chutes-native" || endpointClass === "mistral-public" || knownProviderFamily === "mistral" || isZai || isTogether || isDefaultRoute && isDefaultRouteProvider(provider, "chutes");
2058
- return {
2059
- supportsStore: !isNonStandard && knownProviderFamily !== "mistral" && !usesExplicitProxyLikeEndpoint,
2060
- supportsDeveloperRole: !isNonStandard && !isMoonshotLike && !usesConfiguredNonOpenAIEndpoint,
2061
- supportsReasoningEffort: !isZai && !isTogether && knownProviderFamily !== "mistral" && endpointClass !== "xai-native" && !usesExplicitProxyLikeEndpoint,
2062
- supportsUsageInStreaming: supportsOpenAICompletionsStreamingUsageCompat || !isNonStandard && (isLocalEndpoint || !usesConfiguredNonOpenAIEndpoint || supportsNativeStreamingUsageCompat),
2063
- maxTokensField: usesMaxTokens ? "max_tokens" : "max_completion_tokens",
2064
- thinkingFormat: isDeepSeek || isXiaomi ? "deepseek" : isZai ? "zai" : isTogether ? "together" : isOpenRouterLike ? "openrouter" : "openai",
2065
- visibleReasoningDetailTypes: isOpenRouterLike ? ["response.output_text", "response.text"] : [],
2066
- supportsStrictMode: !isZai && !usesConfiguredNonOpenAIEndpoint,
2067
- requiresReasoningContentOnAssistantMessages: isDeepSeek || isXiaomi,
2068
- requiresNonEmptyUserOrAssistantMessage: isModelStudioLike
2069
- };
2070
- }
2071
- function resolveOpenAICompletionsCompatDefaultsFromCapabilities(input) {
2072
- return resolveOpenAICompletionsCompatDefaults(input);
2073
- }
2074
- /** Detects endpoint capabilities and defaults for an OpenAI-completions model. */
2075
- function detectOpenAICompletionsCompat(model, resolveCapabilities = resolveProviderRequestCapabilities) {
2076
- const capabilities = resolveCapabilities({
2077
- provider: model.provider,
2078
- api: "openai-completions",
2079
- baseUrl: model.baseUrl,
2080
- capability: "llm",
2081
- transport: "stream",
2082
- modelId: model.id,
2083
- compat: model.compat && typeof model.compat === "object" ? model.compat : void 0
2084
- });
2085
- return {
2086
- capabilities,
2087
- defaults: resolveOpenAICompletionsCompatDefaultsFromCapabilities({
2088
- provider: model.provider,
2089
- ...capabilities
2090
- })
2091
- };
2092
- }
2093
- if (process.env.VITEST || false) globalThis[Symbol.for("openclaw.openAICompletionsCompatTestApi")] = { resolveOpenAICompletionsCompatDefaults };
2094
- //#endregion
2095
1694
  //#region packages/ai/src/transports/openai-completions-string-content.ts
2096
1695
  /**
2097
1696
  * OpenAI Chat Completions compatibility helpers. Some providers only accept
@@ -2135,7 +1734,7 @@ function stripCompletionMessagesToRoleContent(messages) {
2135
1734
  const MAX_OPENAI_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS = 256;
2136
1735
  const OPENAI_CODEX_RESPONSES_PROVIDERS = /* @__PURE__ */ new Set(["openai"]);
2137
1736
  const loggedOpenAIStrictToolDowngradeDiagnosticKeys = /* @__PURE__ */ new Set();
2138
- function readToolPayloadField$1(record, field) {
1737
+ function readToolPayloadField(record, field) {
2139
1738
  try {
2140
1739
  return record[field];
2141
1740
  } catch {
@@ -2144,11 +1743,11 @@ function readToolPayloadField$1(record, field) {
2144
1743
  }
2145
1744
  function transportPayloadToolName(tool) {
2146
1745
  if (!isRecord(tool)) return;
2147
- const name = readToolPayloadField$1(tool, "name");
1746
+ const name = readToolPayloadField(tool, "name");
2148
1747
  if (typeof name === "string") return name;
2149
- const fn = readToolPayloadField$1(tool, "function");
1748
+ const fn = readToolPayloadField(tool, "function");
2150
1749
  if (!isRecord(fn)) return;
2151
- const fnName = readToolPayloadField$1(fn, "name");
1750
+ const fnName = readToolPayloadField(fn, "name");
2152
1751
  return typeof fnName === "string" ? fnName : void 0;
2153
1752
  }
2154
1753
  function enforceCodeModeResponsesToolSurface(payload) {
@@ -2248,7 +1847,7 @@ function buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, se
2248
1847
  callerHeaders: Object.keys(callerHeaders).length > 0 ? callerHeaders : void 0,
2249
1848
  precedence: "caller-wins"
2250
1849
  }).headers ?? {};
2251
- if (sessionId && !Object.keys(resolvedHeaders).some((key) => normalizeLowercaseStringOrEmpty(key) === "session_id") && usesNativeOpenAICodexResponsesBackend(model)) resolvedHeaders.session_id = sessionId;
1850
+ if (sessionId && !Object.keys(resolvedHeaders).some((key) => normalizeLowercaseStringOrEmpty(key) === "session_id") && usesNativeOpenAICodexResponsesBackend(model)) resolvedHeaders.session_id = clampOpenAIPromptCacheKey(sessionId) ?? sessionId;
2252
1851
  return resolvedHeaders;
2253
1852
  }
2254
1853
  function resolveOpenAISdkTimeoutMs(model) {
@@ -2268,114 +1867,20 @@ function buildOpenAISdkRequestOptions(model, signal, options) {
2268
1867
  ...timeout !== void 0 ? { timeout } : {}
2269
1868
  };
2270
1869
  }
2271
- function detectCompat(model) {
2272
- const { defaults } = detectOpenAICompletionsCompat(model);
2273
- return {
2274
- supportsStore: defaults.supportsStore,
2275
- supportsDeveloperRole: defaults.supportsDeveloperRole,
2276
- supportsReasoningEffort: defaults.supportsReasoningEffort,
2277
- reasoningEffortMap: {},
2278
- supportsUsageInStreaming: defaults.supportsUsageInStreaming,
2279
- maxTokensField: defaults.maxTokensField,
2280
- requiresToolResultName: false,
2281
- requiresAssistantAfterToolResult: false,
2282
- requiresThinkingAsText: false,
2283
- thinkingFormat: defaults.thinkingFormat,
2284
- visibleReasoningDetailTypes: defaults.visibleReasoningDetailTypes,
2285
- openRouterRouting: {},
2286
- vercelGatewayRouting: {},
2287
- supportsStrictMode: defaults.supportsStrictMode,
2288
- requiresReasoningContentOnAssistantMessages: defaults.requiresReasoningContentOnAssistantMessages,
2289
- requiresNonEmptyUserOrAssistantMessage: defaults.requiresNonEmptyUserOrAssistantMessage
2290
- };
2291
- }
2292
1870
  function getCompat(model) {
2293
- const detected = detectCompat(model);
1871
+ const resolved = resolveOpenAICompletionsCompat(model);
2294
1872
  const compat = model.compat ?? {};
2295
- const supportsStore = typeof compat.supportsStore === "boolean" ? compat.supportsStore : detected.supportsStore;
2296
- const supportsReasoningEffort = typeof compat.supportsReasoningEffort === "boolean" ? compat.supportsReasoningEffort : detected.supportsReasoningEffort;
2297
1873
  return {
2298
- supportsStore,
2299
- supportsDeveloperRole: compat.supportsDeveloperRole ?? detected.supportsDeveloperRole,
2300
- supportsReasoningEffort,
2301
- reasoningEffortMap: resolveOpenAIReasoningEffortMap(model, detected.reasoningEffortMap),
2302
- supportsUsageInStreaming: compat.supportsUsageInStreaming ?? detected.supportsUsageInStreaming,
2303
- maxTokensField: compat.maxTokensField ?? detected.maxTokensField,
2304
- requiresToolResultName: compat.requiresToolResultName ?? detected.requiresToolResultName,
2305
- requiresAssistantAfterToolResult: compat.requiresAssistantAfterToolResult ?? detected.requiresAssistantAfterToolResult,
2306
- requiresThinkingAsText: compat.requiresThinkingAsText ?? detected.requiresThinkingAsText,
2307
- thinkingFormat: compat.thinkingFormat ?? detected.thinkingFormat,
2308
- openRouterRouting: compat.openRouterRouting ?? {},
2309
- vercelGatewayRouting: compat.vercelGatewayRouting ?? detected.vercelGatewayRouting,
2310
- supportsStrictMode: compat.supportsStrictMode ?? detected.supportsStrictMode,
2311
- supportsPromptCacheKey: compat.supportsPromptCacheKey === true,
2312
- supportsLongCacheRetention: compat.supportsLongCacheRetention !== false,
1874
+ ...resolved,
1875
+ cacheControlFormat: resolved.cacheControlFormat,
1876
+ reasoningEffortMap: resolveOpenAIReasoningEffortMap(model, {}),
1877
+ openRouterRouting: resolved.openRouterRouting ?? {},
1878
+ vercelGatewayRouting: resolved.vercelGatewayRouting,
2313
1879
  requiresStringContent: compat.requiresStringContent ?? false,
2314
- strictMessageKeys: compat.strictMessageKeys === true,
2315
- visibleReasoningDetailTypes: compat.visibleReasoningDetailTypes ?? detected.visibleReasoningDetailTypes,
2316
- requiresReasoningContentOnAssistantMessages: compat.requiresReasoningContentOnAssistantMessages ?? detected.requiresReasoningContentOnAssistantMessages,
2317
- requiresNonEmptyUserOrAssistantMessage: detected.requiresNonEmptyUserOrAssistantMessage
1880
+ strictMessageKeys: compat.strictMessageKeys === true
2318
1881
  };
2319
1882
  }
2320
1883
  //#endregion
2321
- //#region packages/ai/src/transports/openai-transport-shared.ts
2322
- /** Shared options, usage shape, cache identity, ordering, and stream scheduling for OpenAI APIs. */
2323
- const MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS = 12;
2324
- const MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS = 64;
2325
- const GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP = "skip_thought_signature_validator";
2326
- const log = {
2327
- debug(message, data) {
2328
- getAiTransportHost().logDebug("openai-transport", () => ({
2329
- message,
2330
- data
2331
- }));
2332
- },
2333
- info(message, data) {
2334
- getAiTransportHost().logInfo("openai-transport", message, data);
2335
- },
2336
- warn(message, data) {
2337
- getAiTransportHost().logWarn("openai-transport", message, data);
2338
- }
2339
- };
2340
- function throwIfModelStreamAborted(signal) {
2341
- if (signal?.aborted) throw new Error("Request was aborted");
2342
- }
2343
- function createModelStreamCooperativeScheduler(signal) {
2344
- let lastYieldedAt = Date.now();
2345
- let eventsSinceYield = 0;
2346
- return { async afterEvent() {
2347
- throwIfModelStreamAborted(signal);
2348
- eventsSinceYield += 1;
2349
- const now = Date.now();
2350
- if (eventsSinceYield < MODEL_STREAM_COOPERATIVE_YIELD_MAX_EVENTS && now - lastYieldedAt < MODEL_STREAM_COOPERATIVE_YIELD_INTERVAL_MS) return;
2351
- eventsSinceYield = 0;
2352
- lastYieldedAt = now;
2353
- await new Promise((resolve) => {
2354
- setTimeout(resolve, 0);
2355
- });
2356
- throwIfModelStreamAborted(signal);
2357
- } };
2358
- }
2359
- function resolveCacheRetention(cacheRetention) {
2360
- if (cacheRetention === "short" || cacheRetention === "long" || cacheRetention === "none") return cacheRetention;
2361
- if (typeof process !== "undefined" && process.env.OPENCLAW_CACHE_RETENTION === "long") return "long";
2362
- return "short";
2363
- }
2364
- function resolvePromptCacheKey(options, cacheRetention) {
2365
- if (cacheRetention === "none") return;
2366
- return clampOpenAIPromptCacheKey(options?.promptCacheKey ?? options?.sessionId);
2367
- }
2368
- function compareTransportToolText(left, right) {
2369
- const leftText = left ?? "";
2370
- const rightText = right ?? "";
2371
- if (leftText < rightText) return -1;
2372
- if (leftText > rightText) return 1;
2373
- return 0;
2374
- }
2375
- function sortTransportToolsByName(tools) {
2376
- return tools.toSorted((left, right) => compareTransportToolText(left.name, right.name) || compareTransportToolText(left.description, right.description));
2377
- }
2378
- //#endregion
2379
1884
  //#region packages/ai/src/transports/openai-completions-transport.ts
2380
1885
  function hasToolHistory(messages) {
2381
1886
  return messages.some((message) => message.role === "toolResult" || message.role === "assistant" && Array.isArray(message.content) && message.content.some((block) => block.type === "toolCall"));
@@ -3288,7 +2793,7 @@ function convertTools(tools, compat, model) {
3288
2793
  });
3289
2794
  return {
3290
2795
  projection,
3291
- tools: sortTransportToolsByName(projection.tools).map((tool) => {
2796
+ tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
3292
2797
  const functionTool = {
3293
2798
  name: tool.name,
3294
2799
  description: tool.description,
@@ -3485,7 +2990,12 @@ function buildOpenAICompletionsParams(model, context, options) {
3485
2990
  }
3486
2991
  if (options?.temperature !== void 0) params.temperature = options.temperature;
3487
2992
  if (options?.topP !== void 0) params.top_p = options.topP;
3488
- if (options?.responseFormat !== void 0) params.response_format = options.responseFormat;
2993
+ const responseFormat = resolveOpenAICompletionsResponseFormat(shouldOmitOllamaCompatResponseFormat({
2994
+ provider: model.provider,
2995
+ baseUrl: model.baseUrl,
2996
+ hasTools: () => Boolean(context.tools?.length)
2997
+ }) ? void 0 : options?.responseFormat, compat.supportsJsonSchemaResponseFormat);
2998
+ if (responseFormat !== void 0) params.response_format = responseFormat;
3489
2999
  if (options?.frequencyPenalty !== void 0) params.frequency_penalty = options.frequencyPenalty;
3490
3000
  if (options?.presencePenalty !== void 0) params.presence_penalty = options.presencePenalty;
3491
3001
  if (options?.seed !== void 0) params.seed = options.seed;
@@ -3784,1443 +3294,96 @@ function applyOpenAIResponsesPayloadPolicy(payloadObj, policy) {
3784
3294
  if (policy.shouldStripInputStatus) stripInputItemStatuses(payloadObj.input);
3785
3295
  }
3786
3296
  //#endregion
3787
- //#region packages/ai/src/transports/openai-responses-replay.ts
3788
- /** Resolves the assistant message id that can be replayed to OpenAI Responses. */
3789
- function resolveReplayableResponsesMessageId(params) {
3790
- if (!params.replayResponsesItemIds) return;
3791
- if (!params.textSignatureId) return params.fallbackOrdinal === 0 ? params.fallbackId : `${params.fallbackId}_${params.fallbackOrdinal}`;
3792
- return params.previousReplayItemWasReasoning ? params.textSignatureId : void 0;
3297
+ //#region packages/ai/src/transports/openai-responses-params-internal.ts
3298
+ function convertResponsesTools(tools, model, options) {
3299
+ const projection = projectOpenAITools(tools);
3300
+ const strict = resolveOpenAIStrictToolFlagWithDiagnostics(projection, options?.strict, {
3301
+ transport: "responses",
3302
+ model
3303
+ });
3304
+ return {
3305
+ projection,
3306
+ tools: sortPromptCacheToolsByName(projection.tools).map((tool) => {
3307
+ const result = {
3308
+ type: "function",
3309
+ name: tool.name,
3310
+ description: tool.description,
3311
+ parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model.compat)
3312
+ };
3313
+ if (strict !== void 0) result.strict = strict;
3314
+ return result;
3315
+ })
3316
+ };
3793
3317
  }
3794
- //#endregion
3795
- //#region packages/ai/src/transports/openai-responses-terminal-outcome.ts
3796
- function readIncompleteReason(response) {
3797
- const details = response?.incomplete_details;
3798
- if (!isRecord(details)) return;
3799
- return typeof details.reason === "string" ? details.reason : void 0;
3800
- }
3801
- /** Record usage, cost and stop reason from a terminal Responses event onto the output. */
3802
- function recordResponsesTerminalOutcome(params) {
3803
- const { response, output, model } = params;
3804
- const usage = response?.usage;
3805
- const mappedUsage = mapResponsesTerminalUsage(usage);
3806
- if (mappedUsage) {
3807
- const reasoningTokens = readResponsesReasoningTokens(usage);
3808
- output.usage = {
3809
- ...mappedUsage,
3810
- ...reasoningTokens === void 0 ? {} : { reasoningTokens },
3811
- cost: {
3812
- input: 0,
3813
- output: 0,
3814
- cacheRead: 0,
3815
- cacheWrite: 0,
3816
- total: 0
3817
- }
3818
- };
3819
- }
3820
- calculateCost(model, output.usage);
3821
- if (params.applyServiceTierPricing) params.applyServiceTierPricing(output.usage, response?.service_tier ?? params.serviceTier);
3822
- const terminal = resolveResponsesTerminalStopReason({
3823
- status: response?.status,
3824
- incompleteReason: readIncompleteReason(response),
3825
- hasToolCall: output.content.some((block) => block.type === "toolCall")
3318
+ function getPromptCacheRetention(baseUrl, cacheRetention) {
3319
+ if (cacheRetention !== "long") return;
3320
+ return baseUrl?.includes("api.openai.com") ? "24h" : void 0;
3321
+ }
3322
+ function resolveOpenAIReasoningEffort(options) {
3323
+ return normalizeOpenAIReasoningEffort(options?.reasoningEffort ?? options?.reasoning ?? "high");
3324
+ }
3325
+ function hasResponsesWebSearchTool(tools) {
3326
+ if (!Array.isArray(tools)) return false;
3327
+ return tools.some((tool) => {
3328
+ if (!isRecord(tool)) return false;
3329
+ if (tool.type === "web_search") return true;
3330
+ if (tool.type === "function" && tool.name === "web_search") return true;
3331
+ const fn = tool.function;
3332
+ return isRecord(fn) && fn.name === "web_search";
3826
3333
  });
3827
- output.stopReason = terminal.stopReason;
3828
- if (terminal.errorMessage) output.errorMessage = terminal.errorMessage;
3829
3334
  }
3830
- //#endregion
3831
- //#region packages/media-core/src/inline-image-data-url.ts
3832
- /** Prefix used to distinguish inline data URLs from remote/local image references. */
3833
- const INLINE_IMAGE_DATA_URL_PREFIX = "data:";
3834
- const IMAGE_SIGNATURES = [
3835
- {
3836
- mime: "image/png",
3837
- matches: (buffer) => buffer.length >= 8 && buffer[0] === 137 && buffer[1] === 80 && buffer[2] === 78 && buffer[3] === 71 && buffer[4] === 13 && buffer[5] === 10 && buffer[6] === 26 && buffer[7] === 10
3838
- },
3839
- {
3840
- mime: "image/jpeg",
3841
- matches: (buffer) => buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255
3842
- },
3843
- {
3844
- mime: "image/webp",
3845
- matches: (buffer) => buffer.length >= 12 && buffer.subarray(0, 4).toString("ascii") === "RIFF" && buffer.subarray(8, 12).toString("ascii") === "WEBP"
3846
- },
3847
- {
3848
- mime: "image/gif",
3849
- matches: (buffer) => buffer.length >= 6 && (buffer.subarray(0, 6).toString("ascii") === "GIF87a" || buffer.subarray(0, 6).toString("ascii") === "GIF89a")
3850
- },
3851
- {
3852
- mime: "image/bmp",
3853
- matches: (buffer) => buffer.length >= 2 && buffer[0] === 66 && buffer[1] === 77
3335
+ function raiseMinimalReasoningForResponsesWebSearch(params) {
3336
+ if (params.effort !== "minimal" || !hasResponsesWebSearchTool(params.tools)) return params.effort;
3337
+ for (const effort of [
3338
+ "low",
3339
+ "medium",
3340
+ "high"
3341
+ ]) {
3342
+ const resolved = resolveOpenAIReasoningEffortForModel({
3343
+ model: params.model,
3344
+ effort
3345
+ });
3346
+ if (resolved && resolved !== "none" && resolved !== "minimal") return resolved;
3854
3347
  }
3348
+ return params.effort;
3349
+ }
3350
+ const OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS = [
3351
+ "max_output_tokens",
3352
+ "metadata",
3353
+ "prompt_cache_retention",
3354
+ "service_tier",
3355
+ "temperature",
3356
+ "top_p"
3855
3357
  ];
3856
- const HEIC_BRANDS = /* @__PURE__ */ new Set([
3857
- "heic",
3858
- "heix",
3859
- "hevc",
3860
- "hevx",
3861
- "heis",
3862
- "heim",
3863
- "hevm",
3864
- "hevs"
3865
- ]);
3866
- const HEIF_BRANDS = /* @__PURE__ */ new Set(["mif1", "msf1"]);
3867
- const IMAGE_SIGNATURE_PREFIX_BASE64_CHARS = 128;
3868
- const INLINE_IMAGE_DATA_URL_MIMES = /* @__PURE__ */ new Set([
3869
- "image/png",
3870
- "image/jpeg",
3871
- "image/webp",
3872
- "image/gif"
3873
- ]);
3874
- function startsWithDataUrl(value) {
3875
- return value.slice(0, 5).toLowerCase() === INLINE_IMAGE_DATA_URL_PREFIX;
3358
+ function stripOpenAICodexResponsesUnsupportedTextFields(params) {
3359
+ const text = params.text;
3360
+ if (!text || typeof text !== "object" || Array.isArray(text)) return;
3361
+ const sanitizedText = { ...text };
3362
+ delete sanitizedText.format;
3363
+ if (Object.keys(sanitizedText).length > 0) params.text = sanitizedText;
3364
+ else delete params.text;
3876
3365
  }
3877
- function sniffIsoBmffImageMime(buffer) {
3878
- if (buffer.length < 12 || buffer.subarray(4, 8).toString("ascii") !== "ftyp") return;
3879
- const brands = [buffer.subarray(8, 12).toString("ascii")];
3880
- for (let offset = 16; offset + 4 <= buffer.length; offset += 4) brands.push(buffer.subarray(offset, offset + 4).toString("ascii"));
3881
- if (brands.some((brand) => HEIC_BRANDS.has(brand))) return "image/heic";
3882
- if (brands.some((brand) => HEIF_BRANDS.has(brand))) return "image/heif";
3366
+ function sanitizeOpenAICodexResponsesParams(model, params) {
3367
+ if (!usesNativeOpenAICodexResponsesBackend(model)) return params;
3368
+ for (const key of OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS) delete params[key];
3369
+ stripOpenAICodexResponsesUnsupportedTextFields(params);
3370
+ return params;
3883
3371
  }
3884
- /** Sniffs supported inline image formats from decoded bytes. */
3885
- function sniffInlineImageMime(buffer) {
3886
- return IMAGE_SIGNATURES.find((signature) => signature.matches(buffer))?.mime ?? sniffIsoBmffImageMime(buffer);
3372
+ function buildOpenAICodexResponsesInstructions(context) {
3373
+ if (!context.systemPrompt) return;
3374
+ return sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt));
3887
3375
  }
3888
- function isImageMimeType(value) {
3889
- return value.trim().toLowerCase().startsWith("image/");
3890
- }
3891
- /** Canonicalizes trusted inline image base64 and rejects malformed or non-image payloads. */
3892
- function sanitizeInlineImageBase64(params) {
3893
- if (!isImageMimeType(params.mimeType)) return;
3894
- const canonicalPayload = canonicalizeBase64(params.base64);
3895
- if (!canonicalPayload) return;
3896
- const sniffedMimeType = sniffInlineImageMime(Buffer.from(canonicalPayload.slice(0, IMAGE_SIGNATURE_PREFIX_BASE64_CHARS), "base64"));
3897
- if (!sniffedMimeType) return;
3898
- return {
3899
- mimeType: sniffedMimeType,
3900
- base64: canonicalPayload
3901
- };
3902
- }
3903
- function parseInlineImageDataUrl(value) {
3904
- if (!startsWithDataUrl(value)) return {
3905
- metadata: [],
3906
- payload: value
3907
- };
3908
- const commaIndex = value.indexOf(",");
3909
- if (commaIndex < 0) return;
3910
- return {
3911
- metadata: value.slice(5, commaIndex).split(";").map((part) => part.trim()),
3912
- payload: value.slice(commaIndex + 1)
3913
- };
3914
- }
3915
- function metadataAllowsImageBase64(metadata) {
3916
- const [mimeType, ...options] = metadata;
3917
- return mimeType !== void 0 && isImageMimeType(mimeType) && options.some((part) => part.toLowerCase() === "base64");
3918
- }
3919
- function sanitizeInlineImageDataUrlWithAllowedMimes(imageUrl, allowedMimes) {
3920
- const parsed = parseInlineImageDataUrl(imageUrl);
3921
- if (!parsed) return;
3922
- if (parsed.metadata.length === 0) return imageUrl;
3923
- if (!metadataAllowsImageBase64(parsed.metadata)) return;
3924
- const [mimeType] = parsed.metadata;
3925
- const sanitized = sanitizeInlineImageBase64({
3926
- mimeType: mimeType ?? "",
3927
- base64: parsed.payload
3928
- });
3929
- if (!sanitized) return;
3930
- if (allowedMimes && !allowedMimes.has(sanitized.mimeType)) return;
3931
- return `data:${sanitized.mimeType};base64,${sanitized.base64}`;
3932
- }
3933
- /** Canonicalizes provider-safe inline image data URLs and rejects unsupported formats. */
3934
- function sanitizeInlineImageDataUrl(imageUrl) {
3935
- return sanitizeInlineImageDataUrlWithAllowedMimes(imageUrl, INLINE_IMAGE_DATA_URL_MIMES);
3936
- }
3937
- //#endregion
3938
- //#region packages/ai/src/transports/responses-image-payload-sanitizer.ts
3939
- /**
3940
- * Sanitizes OpenAI Responses payloads before transport. Invalid inline images
3941
- * are replaced with text placeholders so the request remains valid and
3942
- * auditable.
3943
- */
3944
- const IMAGE_OMITTED_TEXT = "omitted image payload: invalid inline image data";
3945
- function invalidSnakeImage() {
3946
- return {
3947
- type: "input_text",
3948
- text: `[${IMAGE_OMITTED_TEXT}]`
3949
- };
3950
- }
3951
- function sanitizeValue(value) {
3952
- if (Array.isArray(value)) return value.map(sanitizeValue);
3953
- if (!isRecord(value)) return value;
3954
- if (value.type === "input_image" && typeof value.image_url === "string") {
3955
- const imageUrl = sanitizeInlineImageDataUrl(value.image_url);
3956
- return imageUrl ? {
3957
- ...value,
3958
- image_url: imageUrl
3959
- } : invalidSnakeImage();
3960
- }
3961
- const next = {};
3962
- for (const [key, child] of Object.entries(value)) next[key] = sanitizeValue(child);
3963
- return next;
3964
- }
3965
- /** Sanitize inline image fields inside a Responses API payload. */
3966
- function sanitizeResponsesImagePayload(params) {
3967
- if (!Array.isArray(params.input)) return params;
3968
- return {
3969
- ...params,
3970
- input: sanitizeValue(params.input)
3971
- };
3972
- }
3973
- //#endregion
3974
- //#region packages/ai/src/transports/openai-responses-transport.ts
3975
- /**
3976
- * OpenAI Responses transport for Azure variants, replay, reasoning, and payload policy.
3977
- */
3978
- const DEFAULT_AZURE_OPENAI_API_VERSION = "preview";
3979
- const OPENAI_CODEX_RESPONSES_EMPTY_INPUT_TEXT = " ";
3980
- const OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS = "Follow the user request.";
3981
- const AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS = 3e4;
3982
- const RESPONSE_FAILED_NO_DETAILS_MESSAGE = "Unknown error (no error details in response)";
3983
- const OPENAI_RESPONSES_REASONING_REPLAY_META_KEY = "__openclaw_replay";
3984
- const OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY = "openclawReasoningReplay";
3985
- const OPENAI_RESPONSES_REPLAY_ITEM_ID_MAX_LENGTH = 64;
3986
- function stringifyUnknown(value, fallback = "") {
3987
- if (typeof value === "string") return value;
3988
- if (typeof value === "number" || typeof value === "boolean") return String(value);
3989
- return fallback;
3990
- }
3991
- function stringifyJsonLike(value, fallback = "") {
3992
- if (typeof value === "string") return value;
3993
- if (value && typeof value === "object") return JSON.stringify(value);
3994
- if (typeof value === "number" || typeof value === "boolean") return String(value);
3995
- return fallback;
3996
- }
3997
- function getServiceTierCostMultiplier(serviceTier) {
3998
- switch (serviceTier) {
3999
- case "flex": return .5;
4000
- case "priority": return 2;
4001
- default: return 1;
4002
- }
4003
- }
4004
- function applyServiceTierPricing(usage, serviceTier) {
4005
- const multiplier = getServiceTierCostMultiplier(serviceTier);
4006
- if (multiplier === 1) return;
4007
- usage.cost.input *= multiplier;
4008
- usage.cost.output *= multiplier;
4009
- usage.cost.cacheRead *= multiplier;
4010
- usage.cost.cacheWrite *= multiplier;
4011
- usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
4012
- }
4013
- function safeDebugValue(value) {
4014
- if (typeof value === "string") return value;
4015
- if (typeof value === "number" || typeof value === "boolean") return String(value);
4016
- if (value === null) return "null";
4017
- if (value === void 0) return "undefined";
4018
- return Array.isArray(value) ? "array" : typeof value;
4019
- }
4020
- function responseInputTextChars(input) {
4021
- if (typeof input === "string") return input.length;
4022
- if (Array.isArray(input)) return input.reduce((total, item) => total + responseInputTextChars(item), 0);
4023
- if (!input || typeof input !== "object") return 0;
4024
- const record = input;
4025
- let total = 0;
4026
- if (typeof record.text === "string") total += record.text.length;
4027
- if (typeof record.content === "string") total += record.content.length;
4028
- else if (Array.isArray(record.content)) total += responseInputTextChars(record.content);
4029
- return total;
4030
- }
4031
- function responseInputRoles(input) {
4032
- if (!Array.isArray(input)) return "";
4033
- const roles = /* @__PURE__ */ new Set();
4034
- for (const item of input) if (item && typeof item === "object") {
4035
- const role = item.role;
4036
- if (typeof role === "string" && role.trim()) roles.add(role.trim());
4037
- }
4038
- return [...roles].toSorted().join(",");
4039
- }
4040
- function readToolPayloadField(record, field) {
4041
- try {
4042
- return record[field];
4043
- } catch {
4044
- return;
4045
- }
4046
- }
4047
- function readResponsesToolDisplayName(tool) {
4048
- if (!tool || typeof tool !== "object") return "";
4049
- const record = tool;
4050
- const name = readToolPayloadField(record, "name");
4051
- if (typeof name === "string") return name;
4052
- const fn = readToolPayloadField(record, "function");
4053
- if (fn && typeof fn === "object") {
4054
- const fnName = readToolPayloadField(fn, "name");
4055
- if (typeof fnName === "string") return fnName;
4056
- }
4057
- const type = readToolPayloadField(record, "type");
4058
- return typeof type === "string" && type !== "function" ? type : "";
4059
- }
4060
- function summarizeResponsesTools(tools) {
4061
- if (!Array.isArray(tools)) return "count=0";
4062
- const names = tools.map(readResponsesToolDisplayName).filter(Boolean);
4063
- const mode = resolveModelPayloadDebugMode();
4064
- const maxNames = mode === "tools" || mode === "full-redacted" ? names.length : 12;
4065
- const label = maxNames >= names.length ? "names" : "sample";
4066
- const shown = names.slice(0, maxNames).join(",");
4067
- return `count=${tools.length}${shown ? ` ${label}=${shown}` : ""}`;
4068
- }
4069
- function stringifyRedactedPayload(value) {
4070
- try {
4071
- const encoded = JSON.stringify(value);
4072
- if (!encoded) return "<empty>";
4073
- const redacted = redactSensitiveText(encoded, { mode: "tools" });
4074
- return redacted.length > 8e3 ? `${truncateUtf16Safe(redacted, 8e3)}…<truncated>` : redacted;
4075
- } catch {
4076
- return "<unserializable>";
4077
- }
4078
- }
4079
- function stringifyRedactedEvent(value) {
4080
- const redacted = stringifyRedactedPayload(value);
4081
- return redacted.length > 2e3 ? `${truncateUtf16Safe(redacted, 2e3)}…<truncated>` : redacted;
4082
- }
4083
- const RESPONSE_FAILED_FAILURE_FIELD_KEYS = [
4084
- "error",
4085
- "incomplete_details",
4086
- "status_details",
4087
- "failure_reason",
4088
- "last_error",
4089
- "provider_error",
4090
- "error_details"
4091
- ];
4092
- function readResponseFailedString(record, key) {
4093
- return stringifyUnknown(record?.[key]);
4094
- }
4095
- function buildResponsesFailedEventSummary(message, responseId, observation) {
4096
- const summary = { message };
4097
- if (responseId) summary.responseId = responseId;
4098
- if (observation) summary.observation = observation;
4099
- return summary;
4100
- }
4101
- function isResponseFailedIdentifierKey(key) {
4102
- const normalized = key.replace(/[-_\s]/g, "").toLowerCase();
4103
- return normalized === "requestid" || normalized === "xrequestid" || normalized === "providerrequestid" || normalized === "providerresponseid" || normalized === "litellmrequestid" || normalized.includes("request") && normalized.endsWith("id") || normalized.includes("provider") && normalized.endsWith("id");
4104
- }
4105
- function collectResponseFailedIdentifierHashes(value, opts = {}) {
4106
- const path = opts.path ?? "";
4107
- const depth = opts.depth ?? 0;
4108
- const identifierKey = opts.identifierKey ?? "";
4109
- const out = opts.out ?? [];
4110
- const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
4111
- if (out.length >= 12 || depth > 4 || !value || typeof value !== "object") return out;
4112
- if (seen.has(value)) return out;
4113
- seen.add(value);
4114
- if (Array.isArray(value)) {
4115
- for (const [index, item] of value.entries()) {
4116
- if (index >= 8 || out.length >= 12) break;
4117
- const itemString = typeof item === "string" || typeof item === "number" ? String(item).trim() : "";
4118
- if (identifierKey && isResponseFailedIdentifierKey(identifierKey) && itemString) {
4119
- out.push(`${path}[${index}]=${redactIdentifier(itemString, { len: 12 })}`);
4120
- continue;
4121
- }
4122
- collectResponseFailedIdentifierHashes(item, {
4123
- path: `${path}[${index}]`,
4124
- depth: depth + 1,
4125
- identifierKey,
4126
- out,
4127
- seen
4128
- });
4129
- }
4130
- return out;
4131
- }
4132
- for (const [key, child] of Object.entries(value)) {
4133
- if (out.length >= 12) break;
4134
- const childPath = path ? `${path}.${key}` : key;
4135
- const childString = typeof child === "string" || typeof child === "number" ? String(child).trim() : "";
4136
- if (isResponseFailedIdentifierKey(key) && childString) {
4137
- out.push(`${childPath}=${redactIdentifier(childString, { len: 12 })}`);
4138
- continue;
4139
- }
4140
- collectResponseFailedIdentifierHashes(child, {
4141
- path: childPath,
4142
- depth: depth + 1,
4143
- identifierKey: isResponseFailedIdentifierKey(key) ? key : void 0,
4144
- out,
4145
- seen
4146
- });
4147
- }
4148
- return out;
4149
- }
4150
- function redactResponseFailedDiagnosticValue(value, opts = {}) {
4151
- const key = opts.key ?? "";
4152
- const depth = opts.depth ?? 0;
4153
- if (typeof value === "string" || typeof value === "number") return key && isResponseFailedIdentifierKey(key) ? redactIdentifier(String(value), { len: 12 }) : value;
4154
- if (depth > 6 || !value || typeof value !== "object") return value;
4155
- const seen = opts.seen ?? /* @__PURE__ */ new WeakSet();
4156
- if (seen.has(value)) return "<circular>";
4157
- seen.add(value);
4158
- if (Array.isArray(value)) return value.slice(0, 16).map((item) => redactResponseFailedDiagnosticValue(item, {
4159
- key,
4160
- depth: depth + 1,
4161
- seen
4162
- }));
4163
- const out = {};
4164
- for (const [childKey, child] of Object.entries(value)) out[childKey] = redactResponseFailedDiagnosticValue(child, {
4165
- key: childKey,
4166
- depth: depth + 1,
4167
- seen
4168
- });
4169
- return out;
4170
- }
4171
- function buildResponsesFailedFailureFields(response) {
4172
- if (!response) return {};
4173
- const fields = {};
4174
- for (const key of RESPONSE_FAILED_FAILURE_FIELD_KEYS) if (response[key] !== void 0 && response[key] !== null) fields[key] = response[key];
4175
- return fields;
4176
- }
4177
- function buildResponsesFailedNoDetailsObservation(event, model, response = isRecord(event.response) ? event.response : void 0) {
4178
- const failureFields = redactResponseFailedDiagnosticValue(buildResponsesFailedFailureFields(response));
4179
- const metadataKeys = isRecord(response?.metadata) ? Object.keys(response.metadata).toSorted() : [];
4180
- const responsePreview = {
4181
- id: readResponseFailedString(response, "id"),
4182
- status: readResponseFailedString(response, "status"),
4183
- model: readResponseFailedString(response, "model"),
4184
- object: readResponseFailedString(response, "object"),
4185
- failureFields,
4186
- metadataKeys
4187
- };
4188
- return {
4189
- event: "openai_responses_response_failed_without_details",
4190
- provider: model.provider,
4191
- api: model.api,
4192
- transportModel: model.id,
4193
- providerRuntimeFailureKind: "no_error_details",
4194
- responseId: responsePreview.id,
4195
- responseStatus: responsePreview.status,
4196
- responseModel: responsePreview.model,
4197
- responseObject: responsePreview.object,
4198
- metadataKeys,
4199
- requestIdHashes: collectResponseFailedIdentifierHashes(event),
4200
- failureFieldsPreview: stringifyRedactedEvent(failureFields),
4201
- responsePreview: stringifyRedactedEvent(responsePreview)
4202
- };
4203
- }
4204
- function summarizeResponsesFailedNoDetailsObservation(observation) {
4205
- const requestIds = observation.requestIdHashes.join(",");
4206
- const metadataKeys = observation.metadataKeys.join(",");
4207
- return `responseId=${safeDebugValue(observation.responseId || void 0)} responseStatus=${safeDebugValue(observation.responseStatus || void 0)} responseModel=${safeDebugValue(observation.responseModel || void 0)} requestIds=${requestIds || "none"} metadataKeys=${metadataKeys || "none"} failureFields=${observation.failureFieldsPreview}`;
4208
- }
4209
- function normalizeResponsesFailedEvent(event, model) {
4210
- const response = isRecord(event.response) ? event.response : void 0;
4211
- const responseId = readResponseFailedString(response, "id") || void 0;
4212
- const error = isRecord(response?.error) ? response.error : void 0;
4213
- if (error) {
4214
- const code = readResponseFailedString(error, "code").trim();
4215
- const message = readResponseFailedString(error, "message").trim();
4216
- if (code || message) return buildResponsesFailedEventSummary(`${code || "unknown"}: ${message || "no message"}`, responseId);
4217
- }
4218
- const incompleteReason = readResponseFailedString(isRecord(response?.incomplete_details) ? response.incomplete_details : void 0, "reason");
4219
- if (incompleteReason) return buildResponsesFailedEventSummary(`incomplete: ${incompleteReason}`, responseId);
4220
- return buildResponsesFailedEventSummary(RESPONSE_FAILED_NO_DETAILS_MESSAGE, responseId, buildResponsesFailedNoDetailsObservation(event, model, response));
4221
- }
4222
- function logResponsesFailedNoDetails(observation) {
4223
- log.warn(`[responses] response.failed missing error details provider=${observation.provider} api=${observation.api} model=${observation.transportModel} ` + summarizeResponsesFailedNoDetailsObservation(observation), observation);
4224
- }
4225
- function summarizeResponsesPayload(params) {
4226
- if (!params || typeof params !== "object") return "payload=non-object";
4227
- const record = params;
4228
- const input = record.input;
4229
- const reasoning = record.reasoning && typeof record.reasoning === "object" ? record.reasoning : void 0;
4230
- const text = record.text && typeof record.text === "object" ? record.text : void 0;
4231
- const parts = [
4232
- `fields=${Object.keys(record).toSorted().join(",")}`,
4233
- `model=${safeDebugValue(record.model)}`,
4234
- `stream=${safeDebugValue(record.stream)}`,
4235
- `inputItems=${Array.isArray(input) ? input.length : typeof input}`,
4236
- `inputRoles=${responseInputRoles(input) || "none"}`,
4237
- `inputTextChars=${responseInputTextChars(input)}`,
4238
- `tools=${summarizeResponsesTools(record.tools)}`,
4239
- `reasoningEffort=${safeDebugValue(reasoning?.effort)}`,
4240
- `reasoningSummary=${safeDebugValue(reasoning?.summary)}`,
4241
- `textVerbosity=${safeDebugValue(text?.verbosity)}`,
4242
- `serviceTier=${safeDebugValue(record.service_tier)}`,
4243
- `store=${safeDebugValue(record.store)}`,
4244
- `promptCacheKey=${record.prompt_cache_key === void 0 ? "absent" : "present"}`,
4245
- `metadataKeys=${record.metadata && typeof record.metadata === "object" ? Object.keys(record.metadata).toSorted().join(",") : "none"}`
4246
- ];
4247
- if (resolveModelPayloadDebugMode() === "full-redacted") parts.push(`payload=${stringifyRedactedPayload(record)}`);
4248
- return parts.join(" ");
4249
- }
4250
- function summarizeOpenAITransportError(error) {
4251
- if (!error || typeof error !== "object") return `type=${typeof error} message=${safeDebugValue(error)}`;
4252
- const record = error;
4253
- const cause = record.cause && typeof record.cause === "object" ? record.cause : void 0;
4254
- return [
4255
- `name=${safeDebugValue(record.name)}`,
4256
- `status=${safeDebugValue(record.status)}`,
4257
- `code=${safeDebugValue(record.code)}`,
4258
- `type=${safeDebugValue(record.type)}`,
4259
- `causeName=${safeDebugValue(cause?.name)}`,
4260
- `causeCode=${safeDebugValue(cause?.code)}`,
4261
- `message=${error instanceof Error ? error.message : safeDebugValue(error)}`
4262
- ].join(" ");
4263
- }
4264
- function isInvalidEncryptedContentError(error) {
4265
- if (!error || typeof error !== "object") return false;
4266
- const record = error;
4267
- if (record.code === "invalid_encrypted_content" || record.code === "thinking_signature_invalid") return true;
4268
- const message = typeof record.message === "string" ? record.message : "";
4269
- return message.includes("invalid_encrypted_content") || message.includes("thinking_signature_invalid") || record.status === 400 && message.toLowerCase().includes("could not decrypt the provided encrypted_content");
4270
- }
4271
- function stripEncryptedContentFields(value) {
4272
- if (!value || typeof value !== "object") return {
4273
- value,
4274
- changed: false
4275
- };
4276
- if (Array.isArray(value)) {
4277
- let changed = false;
4278
- const next = value.map((item) => {
4279
- const stripped = stripEncryptedContentFields(item);
4280
- changed ||= stripped.changed;
4281
- return stripped.value;
4282
- });
4283
- return changed ? {
4284
- value: next,
4285
- changed: true
4286
- } : {
4287
- value,
4288
- changed: false
4289
- };
4290
- }
4291
- let changed = false;
4292
- const next = {};
4293
- for (const [key, child] of Object.entries(value)) {
4294
- if (key === "encrypted_content") {
4295
- changed = true;
4296
- continue;
4297
- }
4298
- const stripped = stripEncryptedContentFields(child);
4299
- changed ||= stripped.changed;
4300
- next[key] = stripped.value;
4301
- }
4302
- return changed ? {
4303
- value: next,
4304
- changed: true
4305
- } : {
4306
- value,
4307
- changed: false
4308
- };
4309
- }
4310
- function stripResponsesRequestEncryptedContent(params) {
4311
- const stripped = stripEncryptedContentFields(params.input);
4312
- if (!stripped.changed) return params;
4313
- return {
4314
- ...params,
4315
- input: stripped.value
4316
- };
4317
- }
4318
- function hashOptionalReplayContextValue(value) {
4319
- const normalized = value?.trim();
4320
- return normalized ? shortHash(normalized) : void 0;
4321
- }
4322
- function buildOpenAIResponsesReplayContext(model, options) {
4323
- return {
4324
- provider: model.provider,
4325
- api: model.api,
4326
- model: model.id,
4327
- baseUrlHash: hashOptionalReplayContextValue(model.baseUrl),
4328
- sessionHash: hashOptionalReplayContextValue(options?.sessionId),
4329
- authProfileHash: hashOptionalReplayContextValue(options?.authProfileId)
4330
- };
4331
- }
4332
- function buildOpenAIResponsesReasoningReplayMetadata(model, options) {
4333
- return {
4334
- v: 1,
4335
- source: "openai-responses",
4336
- ...buildOpenAIResponsesReplayContext(model, options)
4337
- };
4338
- }
4339
- function tagOpenAIResponsesReasoningReplayItem(item, model, options) {
4340
- if (!("encrypted_content" in item)) return item;
4341
- return {
4342
- ...item,
4343
- [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: buildOpenAIResponsesReasoningReplayMetadata(model, options)
4344
- };
4345
- }
4346
- function isOpenAIResponsesReasoningReplayMetadata(value) {
4347
- if (!value || typeof value !== "object") return false;
4348
- const record = value;
4349
- return record.v === 1 && record.source === "openai-responses" && typeof record.provider === "string" && typeof record.api === "string" && typeof record.model === "string" && (record.baseUrlHash === void 0 || typeof record.baseUrlHash === "string") && (record.sessionHash === void 0 || typeof record.sessionHash === "string") && (record.authProfileHash === void 0 || typeof record.authProfileHash === "string");
4350
- }
4351
- function encryptedReasoningReplayMetadataMatches(metadata, context) {
4352
- if (!metadata) return false;
4353
- return metadata.provider === context.provider && metadata.api === context.api && metadata.model === context.model && metadata.baseUrlHash === context.baseUrlHash && metadata.sessionHash === context.sessionHash && metadata.authProfileHash === context.authProfileHash;
4354
- }
4355
- function readOpenAIResponsesReasoningReplayBlockMetadata(block) {
4356
- const value = block[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY];
4357
- return isOpenAIResponsesReasoningReplayMetadata(value) ? value : void 0;
4358
- }
4359
- function normalizeOpenAIResponsesReasoningReplayItem(item) {
4360
- const record = item;
4361
- if (record.type !== "reasoning" || Array.isArray(record.summary)) return item;
4362
- return {
4363
- ...record,
4364
- summary: []
4365
- };
4366
- }
4367
- function prepareOpenAIResponsesReasoningItemForReplay(item, context, blockMetadata) {
4368
- const { [OPENAI_RESPONSES_REASONING_REPLAY_META_KEY]: rawMetadata, ...rest } = item;
4369
- if (!("encrypted_content" in rest)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
4370
- if (encryptedReasoningReplayMetadataMatches(blockMetadata ?? (isOpenAIResponsesReasoningReplayMetadata(rawMetadata) ? rawMetadata : void 0), context)) return normalizeOpenAIResponsesReasoningReplayItem(rest);
4371
- return normalizeOpenAIResponsesReasoningReplayItem(stripEncryptedContentFields(rest).value);
4372
- }
4373
- async function createResponsesStreamWithEncryptedContentRetry(params) {
4374
- try {
4375
- return await params.client.responses.create(params.request, params.requestOptions);
4376
- } catch (error) {
4377
- const retryRequest = stripResponsesRequestEncryptedContent(params.request);
4378
- if (!isInvalidEncryptedContentError(error) || retryRequest === params.request) throw error;
4379
- log.warn(`[responses] retrying without encrypted reasoning content provider=${params.model.provider} api=${params.model.api} model=${params.model.id}`);
4380
- return await params.client.responses.create(retryRequest, params.requestOptions);
4381
- }
4382
- }
4383
- function resolveAzureOpenAIApiVersion(env = process.env) {
4384
- return env.AZURE_OPENAI_API_VERSION?.trim() || DEFAULT_AZURE_OPENAI_API_VERSION;
4385
- }
4386
- function shortHash(value) {
4387
- return sha256HexPrefix(value, 16);
4388
- }
4389
- function normalizeResponsesReplayItemId(id, prefix) {
4390
- if (!id) return;
4391
- if (id.length <= OPENAI_RESPONSES_REPLAY_ITEM_ID_MAX_LENGTH) return id;
4392
- return `${prefix}_${shortHash(id)}`;
4393
- }
4394
- function isSafeResponsesReplayItemId(id) {
4395
- return typeof id === "string" && id.length > 0 && id.length <= OPENAI_RESPONSES_REPLAY_ITEM_ID_MAX_LENGTH;
4396
- }
4397
- function encodeTextSignatureV1(id, phase) {
4398
- return JSON.stringify({
4399
- v: 1,
4400
- id,
4401
- ...phase ? { phase } : {}
4402
- });
4403
- }
4404
- function parseTextSignature(signature) {
4405
- if (!signature) return;
4406
- if (signature.startsWith("{")) try {
4407
- const parsed = JSON.parse(signature);
4408
- if (parsed.v === 1) {
4409
- const id = typeof parsed.id === "string" ? parsed.id : void 0;
4410
- const phase = parsed.phase === "commentary" || parsed.phase === "final_answer" ? parsed.phase : void 0;
4411
- if (id !== void 0 || phase !== void 0) return {
4412
- id,
4413
- phase
4414
- };
4415
- return;
4416
- }
4417
- } catch {}
4418
- return { id: signature };
4419
- }
4420
- function buildResponsesInputMessage(role, content) {
4421
- return {
4422
- type: "message",
4423
- role,
4424
- content
4425
- };
4426
- }
4427
- function convertResponsesMessages(model, context, allowedToolCallProviders, options) {
4428
- const messages = [];
4429
- const shouldReplayReasoningItems = options?.replayReasoningItems ?? true;
4430
- const shouldReplayResponsesItemIds = options?.replayResponsesItemIds ?? true;
4431
- const replayContext = buildOpenAIResponsesReplayContext(model, {
4432
- sessionId: options?.sessionId,
4433
- authProfileId: options?.authProfileId
4434
- });
4435
- const shouldNormalizeSameModelToolCallIds = model.provider === "github-copilot";
4436
- const sanitizeIdPart = (part) => part.replace(/[^a-zA-Z0-9_-]/g, "_").replace(/_+$/, "");
4437
- const normalizeIdPart = (part) => {
4438
- const sanitized = sanitizeIdPart(part);
4439
- return (sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized).replace(/_+$/, "");
4440
- };
4441
- const buildForeignResponsesItemId = (itemId) => {
4442
- const normalized = `fc_${shortHash(itemId)}`;
4443
- return normalized.length > 64 ? normalized.slice(0, 64) : normalized;
4444
- };
4445
- const buildSameProviderCopilotResponsesItemId = (itemId) => {
4446
- const sanitized = sanitizeIdPart(itemId);
4447
- const candidate = sanitized.startsWith("fc_") ? sanitized : `fc_${sanitized}`;
4448
- return candidate.length > 64 ? buildForeignResponsesItemId(itemId) : candidate;
4449
- };
4450
- const normalizeToolCallId = (id, _targetModel, source) => {
4451
- if (!allowedToolCallProviders.has(model.provider)) return normalizeIdPart(id);
4452
- if (!id.includes("|")) return normalizeIdPart(id);
4453
- const separatorIndex = id.indexOf("|");
4454
- const callId = id.slice(0, separatorIndex);
4455
- const itemId = id.slice(separatorIndex + 1);
4456
- const normalizedCallId = normalizeIdPart(callId);
4457
- let normalizedItemId = source.provider !== model.provider || source.api !== model.api ? buildForeignResponsesItemId(itemId) : model.provider === "github-copilot" ? buildSameProviderCopilotResponsesItemId(itemId) : normalizeIdPart(itemId);
4458
- if (!normalizedItemId.startsWith("fc_")) normalizedItemId = normalizeIdPart(`fc_${normalizedItemId}`);
4459
- return `${normalizedCallId}|${normalizedItemId}`;
4460
- };
4461
- const transformedMessages = transformTransportMessages(context.messages, model, normalizeToolCallId, { normalizeSameModelToolCallIds: shouldNormalizeSameModelToolCallIds });
4462
- if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) messages.push(buildResponsesInputMessage(model.reasoning && options?.supportsDeveloperRole !== false ? "developer" : "system", [{
4463
- type: "input_text",
4464
- text: sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt))
4465
- }]));
4466
- let msgIndex = 0;
4467
- for (const msg of transformedMessages) {
4468
- if (msg.role === "user") if (typeof msg.content === "string") messages.push(buildResponsesInputMessage("user", [{
4469
- type: "input_text",
4470
- text: sanitizeTransportPayloadText(msg.content)
4471
- }]));
4472
- else {
4473
- const content = msg.content.map((item) => item.type === "text" ? {
4474
- type: "input_text",
4475
- text: sanitizeTransportPayloadText(item.text)
4476
- } : {
4477
- type: "input_image",
4478
- detail: "auto",
4479
- image_url: `data:${item.mimeType};base64,${item.data}`
4480
- }).filter((item) => model.input.includes("image") || item.type !== "input_image");
4481
- if (content.length > 0) messages.push(buildResponsesInputMessage("user", content));
4482
- }
4483
- else if (msg.role === "assistant") {
4484
- const output = [];
4485
- let textFallbackOrdinal = 0;
4486
- let previousReplayItemWasReasoning = false;
4487
- const isDifferentModel = msg.model !== model.id && msg.provider === model.provider && msg.api === model.api;
4488
- for (const block of msg.content) if (block.type === "thinking") {
4489
- if (shouldReplayReasoningItems && block.thinkingSignature && block.thinkingSignature.startsWith("{")) {
4490
- const replayableReasoningItem = prepareOpenAIResponsesReasoningItemForReplay(JSON.parse(block.thinkingSignature), replayContext, readOpenAIResponsesReasoningReplayBlockMetadata(block));
4491
- if (!shouldReplayResponsesItemIds) delete replayableReasoningItem.id;
4492
- if (shouldReplayResponsesItemIds && model.provider === "github-copilot" && !isSafeResponsesReplayItemId(replayableReasoningItem.id)) continue;
4493
- output.push(replayableReasoningItem);
4494
- previousReplayItemWasReasoning = true;
4495
- }
4496
- } else if (block.type === "text") {
4497
- const textSignature = parseTextSignature(block.textSignature);
4498
- let msgId = resolveReplayableResponsesMessageId({
4499
- replayResponsesItemIds: shouldReplayResponsesItemIds,
4500
- textSignatureId: textSignature?.id,
4501
- fallbackId: `msg_${msgIndex}`,
4502
- fallbackOrdinal: textFallbackOrdinal,
4503
- previousReplayItemWasReasoning
4504
- });
4505
- if (!textSignature?.id) textFallbackOrdinal += 1;
4506
- msgId = normalizeResponsesReplayItemId(msgId, "msg");
4507
- const messageItem = {
4508
- type: "message",
4509
- role: "assistant",
4510
- content: [{
4511
- type: "output_text",
4512
- text: sanitizeTransportPayloadText(block.text),
4513
- annotations: []
4514
- }],
4515
- status: "completed",
4516
- ...msgId ? { id: msgId } : {},
4517
- phase: textSignature?.phase
4518
- };
4519
- output.push(messageItem);
4520
- previousReplayItemWasReasoning = false;
4521
- } else if (block.type === "toolCall") {
4522
- const separatorIndex = block.id.indexOf("|");
4523
- const callId = separatorIndex === -1 ? block.id : block.id.slice(0, separatorIndex);
4524
- const itemIdRaw = separatorIndex === -1 ? void 0 : block.id.slice(separatorIndex + 1);
4525
- const itemId = shouldReplayResponsesItemIds && !(isDifferentModel && itemIdRaw?.startsWith("fc_")) ? itemIdRaw : void 0;
4526
- output.push({
4527
- type: "function_call",
4528
- ...itemId ? { id: itemId } : {},
4529
- call_id: callId,
4530
- name: block.name,
4531
- arguments: typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {})
4532
- });
4533
- previousReplayItemWasReasoning = false;
4534
- }
4535
- if (output.length > 0) messages.push(...output);
4536
- } else if (msg.role === "toolResult") {
4537
- const textResult = extractToolResultText(msg.content);
4538
- const sanitizedTextResult = sanitizeTransportPayloadText(textResult);
4539
- const hasText = sanitizedTextResult.trim().length > 0;
4540
- const mediaPlaceholder = describeToolResultMediaPlaceholder(msg.content);
4541
- const hasImages = msg.content.some(isImageWithMediaPayload);
4542
- const separatorIndex = msg.toolCallId.indexOf("|");
4543
- const callId = separatorIndex === -1 ? msg.toolCallId : msg.toolCallId.slice(0, separatorIndex);
4544
- messages.push({
4545
- type: "function_call_output",
4546
- call_id: callId,
4547
- output: hasImages && model.input.includes("image") ? [...hasText ? [{
4548
- type: "input_text",
4549
- text: sanitizedTextResult
4550
- }] : mediaPlaceholder === "(see attached media)" ? [{
4551
- type: "input_text",
4552
- text: mediaPlaceholder
4553
- }] : [], ...msg.content.filter(isImageWithMediaPayload).map((item) => ({
4554
- type: "input_image",
4555
- detail: "auto",
4556
- image_url: `data:${item.mimeType};base64,${item.data}`
4557
- }))] : sanitizeNonEmptyTransportPayloadText(textResult, mediaPlaceholder ?? "(no output)")
4558
- });
4559
- }
4560
- msgIndex += 1;
4561
- }
4562
- return messages;
4563
- }
4564
- function convertResponsesTools(tools, model, options) {
4565
- const projection = projectOpenAITools(tools);
4566
- const strict = resolveOpenAIStrictToolFlagWithDiagnostics(projection, options?.strict, {
4567
- transport: "responses",
4568
- model
4569
- });
4570
- return {
4571
- projection,
4572
- tools: sortTransportToolsByName(projection.tools).map((tool) => {
4573
- const result = {
4574
- type: "function",
4575
- name: tool.name,
4576
- description: tool.description,
4577
- parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, model.compat)
4578
- };
4579
- if (strict !== void 0) result.strict = strict;
4580
- return result;
4581
- })
4582
- };
4583
- }
4584
- async function processResponsesStream(openaiStream, output, stream, model, options) {
4585
- const resolveToolCallId = (item, fallbackId) => {
4586
- const callId = stringifyUnknown(item.call_id).trim();
4587
- const itemId = stringifyUnknown(item.id).trim();
4588
- const [fallbackCallId = "", fallbackItemId = ""] = (fallbackId ?? "").split("|");
4589
- const resolvedCallId = callId || fallbackCallId;
4590
- const resolvedItemId = itemId || fallbackItemId;
4591
- if (resolvedCallId) return resolvedItemId ? `${resolvedCallId}|${resolvedItemId}` : resolvedCallId;
4592
- const generatedCallId = `call_${randomUUID().replaceAll("-", "").slice(0, 24)}`;
4593
- return resolvedItemId ? `${generatedCallId}|${resolvedItemId}` : generatedCallId;
4594
- };
4595
- let currentItem = null;
4596
- let currentBlock = null;
4597
- const streamingToolCalls = createResponsesToolCallTracker();
4598
- let lastTextBlock = null;
4599
- let pendingMessageText = null;
4600
- const streamStartedAt = Date.now();
4601
- let eventCount = 0;
4602
- const eventTypes = /* @__PURE__ */ new Map();
4603
- const sseDebugMode = resolveModelSseDebugMode();
4604
- const blockIndex = () => output.content.length - 1;
4605
- const readIdentityValue = (value) => {
4606
- return (typeof value === "string" ? value.trim() : "") || void 0;
4607
- };
4608
- const resolveCompletedToolCallName = (toolCall, value) => {
4609
- const streamedName = readIdentityValue(toolCall?.block.name);
4610
- const completedName = readIdentityValue(value);
4611
- if (streamedName && completedName && streamedName !== completedName) throw new Error(`Responses stream changed tool-call function name from ${streamedName} to ${completedName}`);
4612
- const name = completedName ?? streamedName;
4613
- if (!name) throw new Error("Responses stream completed tool call without a function name");
4614
- return name;
4615
- };
4616
- const appendPendingMessageDelta = (delta) => {
4617
- pendingMessageText = `${pendingMessageText ?? ""}${delta}`;
4618
- const priorText = stringifyUnknown(lastTextBlock?.block.text);
4619
- if (priorText.startsWith(pendingMessageText) || pendingMessageText.startsWith(priorText)) return;
4620
- const phase = currentItem?.type === "message" ? currentItem.phase ?? void 0 : void 0;
4621
- currentBlock = {
4622
- type: "text",
4623
- text: pendingMessageText,
4624
- ...currentItem?.type === "message" && phase ? { textSignature: encodeTextSignatureV1(stringifyUnknown(currentItem.id), phase) } : {}
4625
- };
4626
- output.content.push(currentBlock);
4627
- stream.push({
4628
- type: "text_start",
4629
- contentIndex: blockIndex(),
4630
- partial: output
4631
- });
4632
- stream.push({
4633
- type: "text_delta",
4634
- contentIndex: blockIndex(),
4635
- delta: pendingMessageText
4636
- });
4637
- pendingMessageText = null;
4638
- };
4639
- const appendTerminalResponseTextItem = (item) => {
4640
- const text = readResponsesOutputMessageText(item);
4641
- if (!text) return;
4642
- const phase = item.phase ?? void 0;
4643
- const collapse = resolveResponsesMessageSnapshotCollapse({
4644
- prior: lastTextBlock && {
4645
- text: stringifyUnknown(lastTextBlock.block.text),
4646
- phase: lastTextBlock.phase
4647
- },
4648
- nextText: text,
4649
- nextPhase: phase
4650
- });
4651
- if (collapse.kind === "extend" && lastTextBlock) {
4652
- lastTextBlock.block.text = collapse.text;
4653
- lastTextBlock.block.textSignature = encodeTextSignatureV1(stringifyUnknown(item.id), phase);
4654
- stream.push({
4655
- type: "text_end",
4656
- contentIndex: lastTextBlock.index,
4657
- content: collapse.text,
4658
- partial: output
4659
- });
4660
- return;
4661
- }
4662
- const block = {
4663
- type: "text",
4664
- text,
4665
- textSignature: encodeTextSignatureV1(stringifyUnknown(item.id), phase)
4666
- };
4667
- output.content.push(block);
4668
- lastTextBlock = {
4669
- block,
4670
- index: blockIndex(),
4671
- phase
4672
- };
4673
- stream.push({
4674
- type: "text_start",
4675
- contentIndex: blockIndex(),
4676
- partial: output
4677
- });
4678
- stream.push({
4679
- type: "text_end",
4680
- contentIndex: blockIndex(),
4681
- content: text,
4682
- partial: output
4683
- });
4684
- };
4685
- const appendCompletedResponseToolCallItem = (item) => {
4686
- const args = parseStreamingJson(stringifyJsonLike(item.arguments, "{}"));
4687
- const name = resolveCompletedToolCallName(void 0, item.name);
4688
- const block = {
4689
- type: "toolCall",
4690
- id: resolveToolCallId(item),
4691
- name,
4692
- arguments: args,
4693
- partialJson: stringifyJsonLike(item.arguments, "{}")
4694
- };
4695
- output.content.push(block);
4696
- stream.push({
4697
- type: "toolcall_start",
4698
- contentIndex: blockIndex(),
4699
- partial: output
4700
- });
4701
- stream.push({
4702
- type: "toolcall_end",
4703
- contentIndex: blockIndex(),
4704
- toolCall: {
4705
- type: "toolCall",
4706
- id: block.id,
4707
- name: block.name,
4708
- arguments: args
4709
- },
4710
- partial: output
4711
- });
4712
- };
4713
- const backfillTerminalResponseOutput = (response, backfillOptions) => {
4714
- if (output.content.length > 0 || !Array.isArray(response?.output)) return;
4715
- for (const rawItem of response.output) {
4716
- if (!isRecord(rawItem)) continue;
4717
- if (rawItem.type === "message") {
4718
- appendTerminalResponseTextItem(rawItem);
4719
- continue;
4720
- }
4721
- lastTextBlock = null;
4722
- if (backfillOptions.includeToolCalls && rawItem.type === "function_call") appendCompletedResponseToolCallItem(rawItem);
4723
- }
4724
- };
4725
- const guardedStream = withFirstStreamEventTimeout(openaiStream, {
4726
- provider: model.provider,
4727
- api: model.api,
4728
- model: model.id,
4729
- timeoutMs: options?.firstEventTimeoutMs ?? 0,
4730
- stage: "responses",
4731
- abort: options?.abortFirstEventStream,
4732
- onTimeout: options?.onFirstEventTimeout,
4733
- 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."
4734
- });
4735
- const cooperativeScheduler = createModelStreamCooperativeScheduler(options?.signal);
4736
- for await (const rawEvent of guardedStream) {
4737
- throwIfModelStreamAborted(options?.signal);
4738
- const event = rawEvent;
4739
- const type = stringifyUnknown(event.type);
4740
- eventCount += 1;
4741
- eventTypes.set(type, (eventTypes.get(type) ?? 0) + 1);
4742
- if (eventCount === 1) emitModelTransportDebug(log, `[responses] first_event provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - streamStartedAt} type=${type}`);
4743
- if (sseDebugMode === "peek" && eventCount <= 5) emitModelTransportDebug(log, `[responses] event_peek provider=${model.provider} api=${model.api} model=${model.id} index=${eventCount} type=${type} event=${stringifyRedactedEvent(event)}`);
4744
- if (type === "response.created") output.responseId = stringifyUnknown(event.response?.id);
4745
- else if (type === "response.output_item.added") {
4746
- const item = event.item;
4747
- if (item.type !== "message") {
4748
- lastTextBlock = null;
4749
- pendingMessageText = null;
4750
- }
4751
- if (item.type === "reasoning") {
4752
- currentItem = item;
4753
- currentBlock = {
4754
- type: "thinking",
4755
- thinking: ""
4756
- };
4757
- output.content.push(currentBlock);
4758
- stream.push({
4759
- type: "thinking_start",
4760
- contentIndex: blockIndex(),
4761
- partial: output
4762
- });
4763
- } else if (item.type === "message") {
4764
- currentItem = item;
4765
- if (lastTextBlock) {
4766
- currentBlock = null;
4767
- pendingMessageText = "";
4768
- } else {
4769
- const phase = item.phase ?? void 0;
4770
- currentBlock = {
4771
- type: "text",
4772
- text: "",
4773
- ...phase ? { textSignature: encodeTextSignatureV1(stringifyUnknown(item.id), phase) } : {}
4774
- };
4775
- output.content.push(currentBlock);
4776
- stream.push({
4777
- type: "text_start",
4778
- contentIndex: blockIndex(),
4779
- partial: output
4780
- });
4781
- }
4782
- } else if (item.type === "function_call") {
4783
- const toolCallBlock = {
4784
- type: "toolCall",
4785
- id: resolveToolCallId(item),
4786
- name: readIdentityValue(item.name) ?? "",
4787
- arguments: {},
4788
- partialJson: stringifyJsonLike(item.arguments)
4789
- };
4790
- const contentIndex = output.content.length;
4791
- const toolCallState = {
4792
- block: toolCallBlock,
4793
- contentIndex,
4794
- argumentStreamReliable: true,
4795
- ...readResponsesToolCallItemIdentity(item)
4796
- };
4797
- streamingToolCalls.register(event, toolCallState);
4798
- currentItem = item;
4799
- currentBlock = toolCallBlock;
4800
- output.content.push(toolCallBlock);
4801
- stream.push({
4802
- type: "toolcall_start",
4803
- contentIndex,
4804
- partial: output
4805
- });
4806
- }
4807
- } else if (type === "response.reasoning_summary_text.delta") {
4808
- if (currentItem?.type === "reasoning" && currentBlock?.type === "thinking") {
4809
- currentBlock.thinking = `${stringifyUnknown(currentBlock.thinking)}${stringifyUnknown(event.delta)}`;
4810
- stream.push({
4811
- type: "thinking_delta",
4812
- contentIndex: blockIndex(),
4813
- delta: stringifyUnknown(event.delta),
4814
- partial: output
4815
- });
4816
- }
4817
- } else if (isResponsesTextDeltaEventType(type) || type === "response.refusal.delta") {
4818
- if (currentItem?.type === "message") {
4819
- if (pendingMessageText !== null) appendPendingMessageDelta(stringifyUnknown(event.delta));
4820
- else if (currentBlock?.type === "text") {
4821
- currentBlock.text = `${stringifyUnknown(currentBlock.text)}${stringifyUnknown(event.delta)}`;
4822
- stream.push({
4823
- type: "text_delta",
4824
- contentIndex: blockIndex(),
4825
- delta: stringifyUnknown(event.delta)
4826
- });
4827
- }
4828
- }
4829
- } else if (type === "response.function_call_arguments.delta") {
4830
- const toolCall = streamingToolCalls.resolve(event);
4831
- if (toolCall) {
4832
- toolCall.block.partialJson = `${stringifyJsonLike(toolCall.block.partialJson)}${stringifyJsonLike(event.delta)}`;
4833
- toolCall.block.arguments = parseStreamingJson(stringifyJsonLike(toolCall.block.partialJson));
4834
- stream.push({
4835
- type: "toolcall_delta",
4836
- contentIndex: toolCall.contentIndex,
4837
- delta: stringifyJsonLike(event.delta),
4838
- partial: output
4839
- });
4840
- } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
4841
- } else if (type === "response.function_call_arguments.done") {
4842
- const toolCall = streamingToolCalls.resolve(event);
4843
- if (toolCall) {
4844
- const previousPartialJson = stringifyJsonLike(toolCall.block.partialJson);
4845
- const doneArguments = typeof event.arguments === "string" ? event.arguments : void 0;
4846
- if (doneArguments !== void 0 && (doneArguments.length > 0 || previousPartialJson === "")) {
4847
- toolCall.block.partialJson = doneArguments;
4848
- toolCall.block.arguments = parseStreamingJson(doneArguments);
4849
- toolCall.argumentStreamReliable = true;
4850
- }
4851
- if (doneArguments?.startsWith(previousPartialJson)) {
4852
- const delta = doneArguments.slice(previousPartialJson.length);
4853
- if (delta.length > 0) stream.push({
4854
- type: "toolcall_delta",
4855
- contentIndex: toolCall.contentIndex,
4856
- delta,
4857
- partial: output
4858
- });
4859
- }
4860
- } else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
4861
- } else if (type === "response.output_item.done") {
4862
- const item = event.item;
4863
- if (item.type !== "message") {
4864
- lastTextBlock = null;
4865
- pendingMessageText = null;
4866
- }
4867
- if (item.type === "reasoning" && currentBlock?.type === "thinking") {
4868
- const summary = Array.isArray(item.summary) ? item.summary.map((part) => {
4869
- return part.text ?? "";
4870
- }).join("\n\n") : "";
4871
- currentBlock.thinking = summary;
4872
- currentBlock.thinkingSignature = JSON.stringify(item);
4873
- if ("encrypted_content" in item) currentBlock[OPENAI_RESPONSES_REASONING_REPLAY_BLOCK_META_KEY] = buildOpenAIResponsesReasoningReplayMetadata(model, {
4874
- authProfileId: options?.authProfileId,
4875
- sessionId: options?.sessionId
4876
- });
4877
- stream.push({
4878
- type: "thinking_end",
4879
- contentIndex: blockIndex(),
4880
- content: stringifyUnknown(currentBlock.thinking),
4881
- partial: output
4882
- });
4883
- currentBlock = null;
4884
- } else if (item.type === "message" && (currentBlock?.type === "text" || pendingMessageText !== null)) {
4885
- const finalText = (Array.isArray(item.content) ? item.content : []).map((part) => {
4886
- const contentPart = part;
4887
- return isResponsesTextContentPartType(contentPart.type) ? contentPart.text ?? "" : contentPart.refusal ?? "";
4888
- }).join("");
4889
- const phase = item.phase ?? void 0;
4890
- const collapse = pendingMessageText !== null ? resolveResponsesMessageSnapshotCollapse({
4891
- prior: lastTextBlock && {
4892
- text: stringifyUnknown(lastTextBlock.block.text),
4893
- phase: lastTextBlock.phase
4894
- },
4895
- nextText: finalText,
4896
- nextPhase: phase
4897
- }) : { kind: "keep" };
4898
- pendingMessageText = null;
4899
- if (collapse.kind === "extend" && lastTextBlock) {
4900
- lastTextBlock.block.text = collapse.text;
4901
- lastTextBlock.block.textSignature = encodeTextSignatureV1(stringifyUnknown(item.id), phase);
4902
- stream.push({
4903
- type: "text_end",
4904
- contentIndex: lastTextBlock.index,
4905
- content: collapse.text,
4906
- partial: output
4907
- });
4908
- } else {
4909
- if (currentBlock?.type !== "text") {
4910
- currentBlock = {
4911
- type: "text",
4912
- text: "",
4913
- ...phase ? { textSignature: encodeTextSignatureV1(stringifyUnknown(item.id), phase) } : {}
4914
- };
4915
- output.content.push(currentBlock);
4916
- stream.push({
4917
- type: "text_start",
4918
- contentIndex: blockIndex(),
4919
- partial: output
4920
- });
4921
- }
4922
- currentBlock.text = finalText;
4923
- currentBlock.textSignature = encodeTextSignatureV1(stringifyUnknown(item.id), phase);
4924
- lastTextBlock = {
4925
- block: currentBlock,
4926
- index: blockIndex(),
4927
- phase
4928
- };
4929
- stream.push({
4930
- type: "text_end",
4931
- contentIndex: blockIndex(),
4932
- content: stringifyUnknown(currentBlock.text),
4933
- partial: output
4934
- });
4935
- }
4936
- currentBlock = null;
4937
- } else if (item.type === "function_call") {
4938
- const streamingToolCall = streamingToolCalls.resolve(event, readResponsesToolCallItemIdentity(item));
4939
- if (!streamingToolCall && streamingToolCalls.hasActive()) {
4940
- await cooperativeScheduler.afterEvent();
4941
- continue;
4942
- }
4943
- const completedName = resolveCompletedToolCallName(streamingToolCall, item.name);
4944
- const streamedPartialJson = streamingToolCall ? stringifyJsonLike(streamingToolCall.block.partialJson) : "";
4945
- const completedArguments = typeof item.arguments === "string" ? item.arguments : void 0;
4946
- if (streamingToolCall && !streamingToolCall.argumentStreamReliable && !completedArguments) {
4947
- await cooperativeScheduler.afterEvent();
4948
- continue;
4949
- }
4950
- const finalPartialJson = completedArguments !== void 0 && (completedArguments.length > 0 || !streamedPartialJson) ? completedArguments : streamedPartialJson || "{}";
4951
- const args = parseStreamingJson(finalPartialJson);
4952
- let toolCallBlock;
4953
- let contentIndex;
4954
- if (streamingToolCall) {
4955
- toolCallBlock = streamingToolCall.block;
4956
- contentIndex = streamingToolCall.contentIndex;
4957
- } else {
4958
- toolCallBlock = {
4959
- type: "toolCall",
4960
- id: resolveToolCallId(item),
4961
- name: completedName,
4962
- arguments: args,
4963
- partialJson: finalPartialJson
4964
- };
4965
- output.content.push(toolCallBlock);
4966
- contentIndex = blockIndex();
4967
- stream.push({
4968
- type: "toolcall_start",
4969
- contentIndex,
4970
- partial: output
4971
- });
4972
- }
4973
- const currentToolCallId = resolveToolCallId(item, typeof toolCallBlock.id === "string" ? toolCallBlock.id : void 0);
4974
- toolCallBlock.id = currentToolCallId;
4975
- toolCallBlock.name = completedName;
4976
- toolCallBlock.arguments = args;
4977
- toolCallBlock.partialJson = finalPartialJson;
4978
- stream.push({
4979
- type: "toolcall_end",
4980
- contentIndex,
4981
- toolCall: {
4982
- type: "toolCall",
4983
- id: currentToolCallId,
4984
- name: completedName,
4985
- arguments: args
4986
- },
4987
- partial: output
4988
- });
4989
- if (streamingToolCall) streamingToolCalls.forget(streamingToolCall);
4990
- if (currentBlock === toolCallBlock) {
4991
- currentBlock = null;
4992
- currentItem = null;
4993
- }
4994
- }
4995
- } else if (type === "response.completed" || type === "response.incomplete") {
4996
- if (streamingToolCalls.hasActive()) throw new Error("Responses stream completed with unresolved tool calls");
4997
- const response = event.response;
4998
- if (typeof response?.id === "string") output.responseId = response.id;
4999
- if (type === "response.completed") backfillTerminalResponseOutput(response, { includeToolCalls: true });
5000
- recordResponsesTerminalOutcome({
5001
- response,
5002
- output,
5003
- model,
5004
- serviceTier: options?.serviceTier,
5005
- applyServiceTierPricing: options?.applyServiceTierPricing
5006
- });
5007
- if (type === "response.incomplete" && output.stopReason === "length") backfillTerminalResponseOutput(response, { includeToolCalls: false });
5008
- } else if (type === "error") throw new Error(`Error Code ${stringifyUnknown(event.code, "unknown")}: ${stringifyUnknown(event.message, "Unknown error")}`);
5009
- else if (type === "response.failed") {
5010
- const failure = normalizeResponsesFailedEvent(event, model);
5011
- if (failure.responseId) output.responseId = failure.responseId;
5012
- if (failure.observation) logResponsesFailedNoDetails(failure.observation);
5013
- throw new Error(failure.message);
5014
- }
5015
- await cooperativeScheduler.afterEvent();
5016
- }
5017
- if (streamingToolCalls.hasActive()) throw new Error("Responses stream ended with unresolved tool calls");
5018
- const eventTypeSummary = [...eventTypes.entries()].slice(0, 12).map(([eventType, count]) => `${eventType}:${count}`).join(",");
5019
- emitModelTransportDebug(log, `[responses] stream_done provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - streamStartedAt} events=${eventCount} types=${eventTypeSummary} stopReason=${output.stopReason ?? "unset"} contentBlocks=${output.content.length}`);
5020
- }
5021
- function readResponsesOutputMessageText(item) {
5022
- return (Array.isArray(item.content) ? item.content : []).map((part) => {
5023
- if (!isRecord(part)) return "";
5024
- if (part.type === "output_text" || part.type === "text") return stringifyUnknown(part.text);
5025
- if (part.type === "refusal") return stringifyUnknown(part.refusal);
5026
- return "";
5027
- }).join("");
5028
- }
5029
- function resolveProviderTransportTurnState(model, params) {
5030
- const normalizedProvider = model.provider.trim().toLowerCase();
5031
- const allowRuntimePluginLoad = normalizedProvider === "openai" || normalizedProvider === "azure-openai" || normalizedProvider === "azure-openai-responses";
5032
- return getAiTransportHost().plugin.resolveTransportTurnState({
5033
- provider: model.provider,
5034
- modelId: model.id,
5035
- allowRuntimePluginLoad,
5036
- context: {
5037
- provider: model.provider,
5038
- modelId: model.id,
5039
- model,
5040
- sessionId: params.sessionId,
5041
- turnId: params.turnId,
5042
- attempt: params.attempt,
5043
- transport: params.transport
5044
- }
5045
- });
5046
- }
5047
- function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId) {
5048
- return new OpenAI({
5049
- apiKey,
5050
- baseURL: model.baseUrl,
5051
- dangerouslyAllowBrowser: true,
5052
- defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId),
5053
- fetch: buildGuardedModelFetch(model),
5054
- ...buildOpenAISdkClientOptions(model)
5055
- });
5056
- }
5057
- function createOpenAIResponsesTransportStreamFn() {
5058
- return (model, context, options) => {
5059
- const responsesOptions = options;
5060
- const eventStream = createAssistantMessageEventStream();
5061
- const stream = eventStream;
5062
- (async () => {
5063
- const output = {
5064
- role: "assistant",
5065
- content: [],
5066
- api: model.api,
5067
- provider: model.provider,
5068
- model: model.id,
5069
- usage: {
5070
- input: 0,
5071
- output: 0,
5072
- cacheRead: 0,
5073
- cacheWrite: 0,
5074
- totalTokens: 0,
5075
- cost: {
5076
- input: 0,
5077
- output: 0,
5078
- cacheRead: 0,
5079
- cacheWrite: 0,
5080
- total: 0
5081
- }
5082
- },
5083
- stopReason: "stop",
5084
- timestamp: Date.now()
5085
- };
5086
- let firstEventAbort;
5087
- try {
5088
- const apiKey = options?.apiKey || getEnvApiKey(model.provider) || "";
5089
- const turnState = resolveProviderTransportTurnState(model, {
5090
- sessionId: options?.sessionId,
5091
- turnId: randomUUID(),
5092
- attempt: 1,
5093
- transport: "stream"
5094
- });
5095
- const client = createOpenAIResponsesClient(model, context, apiKey, options?.headers, turnState?.headers, options?.sessionId);
5096
- let params = buildOpenAIResponsesParams(model, context, responsesOptions, turnState?.metadata);
5097
- const nextParams = await options?.onPayload?.(params, model);
5098
- if (nextParams !== void 0) params = nextParams;
5099
- if (!isOpenAICodexResponsesModel(model)) params = mergeTransportMetadata(params, turnState?.metadata);
5100
- params = sanitizeOpenAICodexResponsesParams(model, params);
5101
- params = sanitizeResponsesImagePayload(params);
5102
- if (options?.openclawCodeModeToolSurface === true) {
5103
- enforceCodeModeResponsesToolSurface(params);
5104
- assertCodeModeResponsesToolSurface(params);
5105
- }
5106
- const requestStartedAt = Date.now();
5107
- firstEventAbort = createFirstStreamEventAbortController(options?.signal);
5108
- const requestOptions = buildOpenAISdkRequestOptions(model, firstEventAbort.signal, { stream: true });
5109
- emitModelTransportDebug(log, `[responses] start provider=${model.provider} api=${model.api} model=${model.id} baseUrl=${formatModelTransportDebugBaseUrl(model.baseUrl)} timeoutMs=${safeDebugValue(requestOptions?.timeout)} apiKey=${apiKey ? "present" : "missing"} ${summarizeResponsesPayload(params)}`);
5110
- const responseStream = await createResponsesStreamWithEncryptedContentRetry({
5111
- client,
5112
- request: params,
5113
- requestOptions,
5114
- model
5115
- });
5116
- emitModelTransportDebug(log, `[responses] headers provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - requestStartedAt}`);
5117
- stream.push({
5118
- type: "start",
5119
- partial: output
5120
- });
5121
- await processResponsesStream(responseStream, output, stream, model, {
5122
- serviceTier: responsesOptions?.serviceTier,
5123
- applyServiceTierPricing,
5124
- firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options),
5125
- abortFirstEventStream: firstEventAbort.abort,
5126
- onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
5127
- signal: options?.signal,
5128
- authProfileId: responsesOptions?.authProfileId,
5129
- sessionId: options?.sessionId
5130
- });
5131
- if (options?.signal?.aborted) throw new Error("Request was aborted");
5132
- if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error("An unknown error occurred");
5133
- stream.push({
5134
- type: "done",
5135
- reason: output.stopReason,
5136
- message: output
5137
- });
5138
- stream.end();
5139
- } catch (error) {
5140
- log.warn(`[responses] error provider=${model.provider} api=${model.api} model=${model.id} ` + summarizeOpenAITransportError(error));
5141
- assignTransportErrorDetails(output, error, options?.signal);
5142
- stream.push({
5143
- type: "error",
5144
- reason: output.stopReason,
5145
- error: output
5146
- });
5147
- stream.end();
5148
- } finally {
5149
- firstEventAbort?.dispose();
5150
- }
5151
- })();
5152
- return eventStream;
5153
- };
5154
- }
5155
- function getPromptCacheRetention(baseUrl, cacheRetention) {
5156
- if (cacheRetention !== "long") return;
5157
- return baseUrl?.includes("api.openai.com") ? "24h" : void 0;
5158
- }
5159
- function resolveOpenAIReasoningEffort(options) {
5160
- return normalizeOpenAIReasoningEffort(options?.reasoningEffort ?? options?.reasoning ?? "high");
5161
- }
5162
- function hasResponsesWebSearchTool(tools) {
5163
- if (!Array.isArray(tools)) return false;
5164
- return tools.some((tool) => {
5165
- if (!isRecord(tool)) return false;
5166
- if (tool.type === "web_search") return true;
5167
- if (tool.type === "function" && tool.name === "web_search") return true;
5168
- const fn = tool.function;
5169
- return isRecord(fn) && fn.name === "web_search";
5170
- });
5171
- }
5172
- function raiseMinimalReasoningForResponsesWebSearch(params) {
5173
- if (params.effort !== "minimal" || !hasResponsesWebSearchTool(params.tools)) return params.effort;
5174
- for (const effort of [
5175
- "low",
5176
- "medium",
5177
- "high"
5178
- ]) {
5179
- const resolved = resolveOpenAIReasoningEffortForModel({
5180
- model: params.model,
5181
- effort
5182
- });
5183
- if (resolved && resolved !== "none" && resolved !== "minimal") return resolved;
5184
- }
5185
- return params.effort;
5186
- }
5187
- const OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS = [
5188
- "max_output_tokens",
5189
- "metadata",
5190
- "prompt_cache_retention",
5191
- "service_tier",
5192
- "temperature",
5193
- "top_p"
5194
- ];
5195
- function stripOpenAICodexResponsesUnsupportedTextFields(params) {
5196
- const text = params.text;
5197
- if (!text || typeof text !== "object" || Array.isArray(text)) return;
5198
- const sanitizedText = { ...text };
5199
- delete sanitizedText.format;
5200
- if (Object.keys(sanitizedText).length > 0) params.text = sanitizedText;
5201
- else delete params.text;
5202
- }
5203
- function sanitizeOpenAICodexResponsesParams(model, params) {
5204
- if (!usesNativeOpenAICodexResponsesBackend(model)) return params;
5205
- for (const key of OPENAI_CODEX_RESPONSES_UNSUPPORTED_PARAMS) delete params[key];
5206
- stripOpenAICodexResponsesUnsupportedTextFields(params);
5207
- return params;
5208
- }
5209
- function buildOpenAICodexResponsesInstructions(context) {
5210
- if (!context.systemPrompt) return;
5211
- return sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt));
5212
- }
5213
- function resolveOpenAICodexResponsesInstructions(model, context) {
5214
- const instructions = buildOpenAICodexResponsesInstructions(context);
5215
- if (instructions && instructions.trim().length > 0) return instructions;
5216
- return usesNativeOpenAICodexResponsesBackend(model) ? OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS : void 0;
3376
+ function resolveOpenAICodexResponsesInstructions(model, context) {
3377
+ const instructions = buildOpenAICodexResponsesInstructions(context);
3378
+ if (instructions && instructions.trim().length > 0) return instructions;
3379
+ return usesNativeOpenAICodexResponsesBackend(model) ? OPENAI_CODEX_RESPONSES_DEFAULT_INSTRUCTIONS : void 0;
5217
3380
  }
5218
3381
  function ensureOpenAICodexResponsesInput(messages, context) {
5219
3382
  if (messages.length > 0 || !context.systemPrompt) return;
5220
3383
  if (!buildOpenAICodexResponsesInstructions(context)) throw new Error("OpenAI Codex Responses requires non-empty input when only systemPrompt is provided.");
5221
3384
  messages.push(buildResponsesInputMessage("user", [{
5222
3385
  type: "input_text",
5223
- text: OPENAI_CODEX_RESPONSES_EMPTY_INPUT_TEXT
3386
+ text: " "
5224
3387
  }]));
5225
3388
  }
5226
3389
  function resolveOpenAIResponsesTextFormat(responseFormat) {
@@ -5309,7 +3472,180 @@ function buildOpenAIResponsesParams(model, context, options, metadata) {
5309
3472
  applyOpenAIResponsesPayloadPolicy(params, payloadPolicy);
5310
3473
  return sanitizeOpenAICodexResponsesParams(model, params);
5311
3474
  }
5312
- function createAzureOpenAIResponsesTransportStreamFn() {
3475
+ //#endregion
3476
+ //#region packages/media-core/src/inline-image-data-url.ts
3477
+ /** Prefix used to distinguish inline data URLs from remote/local image references. */
3478
+ const INLINE_IMAGE_DATA_URL_PREFIX = "data:";
3479
+ const IMAGE_SIGNATURES = [
3480
+ {
3481
+ mime: "image/png",
3482
+ matches: (buffer) => buffer.length >= 8 && buffer[0] === 137 && buffer[1] === 80 && buffer[2] === 78 && buffer[3] === 71 && buffer[4] === 13 && buffer[5] === 10 && buffer[6] === 26 && buffer[7] === 10
3483
+ },
3484
+ {
3485
+ mime: "image/jpeg",
3486
+ matches: (buffer) => buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255
3487
+ },
3488
+ {
3489
+ mime: "image/webp",
3490
+ matches: (buffer) => buffer.length >= 12 && buffer.subarray(0, 4).toString("ascii") === "RIFF" && buffer.subarray(8, 12).toString("ascii") === "WEBP"
3491
+ },
3492
+ {
3493
+ mime: "image/gif",
3494
+ matches: (buffer) => buffer.length >= 6 && (buffer.subarray(0, 6).toString("ascii") === "GIF87a" || buffer.subarray(0, 6).toString("ascii") === "GIF89a")
3495
+ },
3496
+ {
3497
+ mime: "image/bmp",
3498
+ matches: (buffer) => buffer.length >= 2 && buffer[0] === 66 && buffer[1] === 77
3499
+ }
3500
+ ];
3501
+ const HEIC_BRANDS = /* @__PURE__ */ new Set([
3502
+ "heic",
3503
+ "heix",
3504
+ "hevc",
3505
+ "hevx",
3506
+ "heis",
3507
+ "heim",
3508
+ "hevm",
3509
+ "hevs"
3510
+ ]);
3511
+ const HEIF_BRANDS = /* @__PURE__ */ new Set(["mif1", "msf1"]);
3512
+ const IMAGE_SIGNATURE_PREFIX_BASE64_CHARS = 128;
3513
+ const INLINE_IMAGE_DATA_URL_MIMES = /* @__PURE__ */ new Set([
3514
+ "image/png",
3515
+ "image/jpeg",
3516
+ "image/webp",
3517
+ "image/gif"
3518
+ ]);
3519
+ function startsWithDataUrl(value) {
3520
+ return value.slice(0, 5).toLowerCase() === INLINE_IMAGE_DATA_URL_PREFIX;
3521
+ }
3522
+ function sniffIsoBmffImageMime(buffer) {
3523
+ if (buffer.length < 12 || buffer.subarray(4, 8).toString("ascii") !== "ftyp") return;
3524
+ const brands = [buffer.subarray(8, 12).toString("ascii")];
3525
+ for (let offset = 16; offset + 4 <= buffer.length; offset += 4) brands.push(buffer.subarray(offset, offset + 4).toString("ascii"));
3526
+ if (brands.some((brand) => HEIC_BRANDS.has(brand))) return "image/heic";
3527
+ if (brands.some((brand) => HEIF_BRANDS.has(brand))) return "image/heif";
3528
+ }
3529
+ /** Sniffs supported inline image formats from decoded bytes. */
3530
+ function sniffInlineImageMime(buffer) {
3531
+ return IMAGE_SIGNATURES.find((signature) => signature.matches(buffer))?.mime ?? sniffIsoBmffImageMime(buffer);
3532
+ }
3533
+ function isImageMimeType(value) {
3534
+ return value.trim().toLowerCase().startsWith("image/");
3535
+ }
3536
+ /** Canonicalizes trusted inline image base64 and rejects malformed or non-image payloads. */
3537
+ function sanitizeInlineImageBase64(params) {
3538
+ if (!isImageMimeType(params.mimeType)) return;
3539
+ const canonicalPayload = canonicalizeBase64(params.base64);
3540
+ if (!canonicalPayload) return;
3541
+ const sniffedMimeType = sniffInlineImageMime(Buffer.from(canonicalPayload.slice(0, IMAGE_SIGNATURE_PREFIX_BASE64_CHARS), "base64"));
3542
+ if (!sniffedMimeType) return;
3543
+ return {
3544
+ mimeType: sniffedMimeType,
3545
+ base64: canonicalPayload
3546
+ };
3547
+ }
3548
+ function parseInlineImageDataUrl(value) {
3549
+ if (!startsWithDataUrl(value)) return {
3550
+ metadata: [],
3551
+ payload: value
3552
+ };
3553
+ const commaIndex = value.indexOf(",");
3554
+ if (commaIndex < 0) return;
3555
+ return {
3556
+ metadata: value.slice(5, commaIndex).split(";").map((part) => part.trim()),
3557
+ payload: value.slice(commaIndex + 1)
3558
+ };
3559
+ }
3560
+ function metadataAllowsImageBase64(metadata) {
3561
+ const [mimeType, ...options] = metadata;
3562
+ return mimeType !== void 0 && isImageMimeType(mimeType) && options.some((part) => part.toLowerCase() === "base64");
3563
+ }
3564
+ function sanitizeInlineImageDataUrlWithAllowedMimes(imageUrl, allowedMimes) {
3565
+ const parsed = parseInlineImageDataUrl(imageUrl);
3566
+ if (!parsed) return;
3567
+ if (parsed.metadata.length === 0) return imageUrl;
3568
+ if (!metadataAllowsImageBase64(parsed.metadata)) return;
3569
+ const [mimeType] = parsed.metadata;
3570
+ const sanitized = sanitizeInlineImageBase64({
3571
+ mimeType: mimeType ?? "",
3572
+ base64: parsed.payload
3573
+ });
3574
+ if (!sanitized) return;
3575
+ if (allowedMimes && !allowedMimes.has(sanitized.mimeType)) return;
3576
+ return `data:${sanitized.mimeType};base64,${sanitized.base64}`;
3577
+ }
3578
+ /** Canonicalizes provider-safe inline image data URLs and rejects unsupported formats. */
3579
+ function sanitizeInlineImageDataUrl(imageUrl) {
3580
+ return sanitizeInlineImageDataUrlWithAllowedMimes(imageUrl, INLINE_IMAGE_DATA_URL_MIMES);
3581
+ }
3582
+ //#endregion
3583
+ //#region packages/ai/src/transports/responses-image-payload-sanitizer.ts
3584
+ /**
3585
+ * Sanitizes OpenAI Responses payloads before transport. Invalid inline images
3586
+ * are replaced with text placeholders so the request remains valid and
3587
+ * auditable.
3588
+ */
3589
+ const IMAGE_OMITTED_TEXT = "omitted image payload: invalid inline image data";
3590
+ function invalidSnakeImage() {
3591
+ return {
3592
+ type: "input_text",
3593
+ text: `[${IMAGE_OMITTED_TEXT}]`
3594
+ };
3595
+ }
3596
+ function sanitizeValue(value) {
3597
+ if (Array.isArray(value)) return value.map(sanitizeValue);
3598
+ if (!isRecord(value)) return value;
3599
+ if (value.type === "input_image" && typeof value.image_url === "string") {
3600
+ const imageUrl = sanitizeInlineImageDataUrl(value.image_url);
3601
+ return imageUrl ? {
3602
+ ...value,
3603
+ image_url: imageUrl
3604
+ } : invalidSnakeImage();
3605
+ }
3606
+ const next = {};
3607
+ for (const [key, child] of Object.entries(value)) next[key] = sanitizeValue(child);
3608
+ return next;
3609
+ }
3610
+ /** Sanitize inline image fields inside a Responses API payload. */
3611
+ function sanitizeResponsesImagePayload(params) {
3612
+ if (!Array.isArray(params.input)) return params;
3613
+ return {
3614
+ ...params,
3615
+ input: sanitizeValue(params.input)
3616
+ };
3617
+ }
3618
+ //#endregion
3619
+ //#region packages/ai/src/transports/openai-responses-client.ts
3620
+ function resolveProviderTransportTurnState(model, params) {
3621
+ const normalizedProvider = model.provider.trim().toLowerCase();
3622
+ const allowRuntimePluginLoad = normalizedProvider === "openai" || normalizedProvider === "azure-openai" || normalizedProvider === "azure-openai-responses";
3623
+ return getAiTransportHost().plugin.resolveTransportTurnState({
3624
+ provider: model.provider,
3625
+ modelId: model.id,
3626
+ allowRuntimePluginLoad,
3627
+ context: {
3628
+ provider: model.provider,
3629
+ modelId: model.id,
3630
+ model,
3631
+ sessionId: params.sessionId,
3632
+ turnId: params.turnId,
3633
+ attempt: params.attempt,
3634
+ transport: params.transport
3635
+ }
3636
+ });
3637
+ }
3638
+ function createOpenAIResponsesClient(model, context, apiKey, optionHeaders, turnHeaders, sessionId) {
3639
+ return new OpenAI({
3640
+ apiKey,
3641
+ baseURL: model.baseUrl,
3642
+ dangerouslyAllowBrowser: true,
3643
+ defaultHeaders: buildOpenAIClientHeaders(model, context, optionHeaders, turnHeaders, sessionId),
3644
+ fetch: buildGuardedModelFetch(model),
3645
+ ...buildOpenAISdkClientOptions(model)
3646
+ });
3647
+ }
3648
+ function createResponsesTransportExecutor(config) {
5313
3649
  return (model, context, options) => {
5314
3650
  const responsesOptions = options;
5315
3651
  const eventStream = createAssistantMessageEventStream();
@@ -5318,7 +3654,7 @@ function createAzureOpenAIResponsesTransportStreamFn() {
5318
3654
  const output = {
5319
3655
  role: "assistant",
5320
3656
  content: [],
5321
- api: "azure-openai-responses",
3657
+ api: config.outputApi ?? model.api,
5322
3658
  provider: model.provider,
5323
3659
  model: model.id,
5324
3660
  usage: {
@@ -5347,9 +3683,8 @@ function createAzureOpenAIResponsesTransportStreamFn() {
5347
3683
  attempt: 1,
5348
3684
  transport: "stream"
5349
3685
  });
5350
- const client = createAzureOpenAIClient(model, context, apiKey, options?.headers, turnState?.headers);
5351
- const deploymentName = resolveAzureDeploymentName(model);
5352
- let params = buildAzureOpenAIResponsesParams(model, context, responsesOptions, deploymentName, turnState?.metadata);
3686
+ const client = config.createClient(model, context, apiKey, options?.headers, turnState?.headers, options?.sessionId);
3687
+ let params = config.buildRequest(model, context, responsesOptions, turnState?.metadata);
5353
3688
  const nextParams = await options?.onPayload?.(params, model);
5354
3689
  if (nextParams !== void 0) params = nextParams;
5355
3690
  if (!isOpenAICodexResponsesModel(model)) params = mergeTransportMetadata(params, turnState?.metadata);
@@ -5361,23 +3696,31 @@ function createAzureOpenAIResponsesTransportStreamFn() {
5361
3696
  }
5362
3697
  const requestStartedAt = Date.now();
5363
3698
  firstEventAbort = createFirstStreamEventAbortController(options?.signal);
5364
- const requestOptions = buildOpenAISdkRequestOptions(model, firstEventAbort.signal);
3699
+ const requestOptions = buildOpenAISdkRequestOptions(model, firstEventAbort.signal, config.streamRequest ? { stream: true } : void 0);
5365
3700
  emitModelTransportDebug(log, `[responses] start provider=${model.provider} api=${model.api} model=${model.id} baseUrl=${formatModelTransportDebugBaseUrl(model.baseUrl)} timeoutMs=${safeDebugValue(requestOptions?.timeout)} apiKey=${apiKey ? "present" : "missing"} ${summarizeResponsesPayload(params)}`);
5366
- const responseStream = await client.responses.create(params, requestOptions);
3701
+ const responseStream = await config.createResponseStream({
3702
+ client,
3703
+ request: params,
3704
+ requestOptions,
3705
+ model
3706
+ });
5367
3707
  emitModelTransportDebug(log, `[responses] headers provider=${model.provider} api=${model.api} model=${model.id} elapsedMs=${Date.now() - requestStartedAt}`);
5368
3708
  stream.push({
5369
3709
  type: "start",
5370
3710
  partial: output
5371
3711
  });
5372
- await processResponsesStream(responseStream, output, stream, model, {
5373
- firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options) ?? AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS,
3712
+ await processResponsesStream(observeResponsesStream(responseStream, model), output, stream, model, {
3713
+ ...config.pricingOptions?.(responsesOptions),
3714
+ firstEventTimeoutMs: getFirstStreamEventTimeoutMs(options) ?? config.firstEventTimeoutMs,
5374
3715
  abortFirstEventStream: firstEventAbort.abort,
5375
3716
  onFirstEventTimeout: getFirstStreamEventTimeoutHandler(options),
5376
3717
  signal: options?.signal,
5377
- authProfileId: responsesOptions?.authProfileId,
5378
- sessionId: options?.sessionId
3718
+ reasoningReplayMetadata: buildOpenAIResponsesReasoningReplayMetadata(model, {
3719
+ authProfileId: responsesOptions?.authProfileId,
3720
+ sessionId: options?.sessionId
3721
+ })
5379
3722
  });
5380
- if (options?.signal?.aborted) throw new Error("Request was aborted");
3723
+ if (options?.signal?.aborted) throw transportAbortError(options.signal);
5381
3724
  if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error("An unknown error occurred");
5382
3725
  stream.push({
5383
3726
  type: "done",
@@ -5386,6 +3729,7 @@ function createAzureOpenAIResponsesTransportStreamFn() {
5386
3729
  });
5387
3730
  stream.end();
5388
3731
  } catch (error) {
3732
+ if (error instanceof ResponsesStreamFailure && error.observation) logResponsesFailedNoDetails(error.observation);
5389
3733
  log.warn(`[responses] error provider=${model.provider} api=${model.api} model=${model.id} ` + summarizeOpenAITransportError(error));
5390
3734
  assignTransportErrorDetails(output, error, options?.signal);
5391
3735
  stream.push({
@@ -5401,6 +3745,27 @@ function createAzureOpenAIResponsesTransportStreamFn() {
5401
3745
  return eventStream;
5402
3746
  };
5403
3747
  }
3748
+ function createOpenAIResponsesTransportStreamFn() {
3749
+ return createResponsesTransportExecutor({
3750
+ streamRequest: true,
3751
+ createClient: createOpenAIResponsesClient,
3752
+ buildRequest: buildOpenAIResponsesParams,
3753
+ createResponseStream: createResponsesStreamWithEncryptedContentRetry,
3754
+ pricingOptions: (options) => ({
3755
+ serviceTier: options?.serviceTier,
3756
+ applyServiceTierPricing
3757
+ })
3758
+ });
3759
+ }
3760
+ function createAzureOpenAIResponsesTransportStreamFn() {
3761
+ return createResponsesTransportExecutor({
3762
+ outputApi: "azure-openai-responses",
3763
+ firstEventTimeoutMs: AZURE_RESPONSES_FIRST_EVENT_TIMEOUT_MS,
3764
+ createClient: createAzureOpenAIClient,
3765
+ buildRequest: (model, context, options, metadata) => buildAzureOpenAIResponsesParams(model, context, options, resolveAzureDeploymentName(model), metadata),
3766
+ createResponseStream: async ({ client, request, requestOptions }) => await client.responses.create(request, requestOptions)
3767
+ });
3768
+ }
5404
3769
  function normalizeAzureBaseUrl(baseUrl) {
5405
3770
  return baseUrl.replace(/\/+$/, "");
5406
3771
  }
@@ -5432,6 +3797,9 @@ function buildAzureOpenAIResponsesParams(model, context, options, deploymentName
5432
3797
  delete params.store;
5433
3798
  return params;
5434
3799
  }
3800
+ //#endregion
3801
+ //#region packages/ai/src/transports/openai-responses-transport.ts
3802
+ /** OpenAI Responses transport facade. */
5435
3803
  const responsesTesting = {
5436
3804
  getCompat,
5437
3805
  assertCodeModeResponsesToolSurface,
@@ -5698,4 +4066,4 @@ function prepareModelForSimpleCompletion(params) {
5698
4066
  return applyProviderSimpleCompletionWrapper(apiRegistry, model, cfg);
5699
4067
  }
5700
4068
  //#endregion
5701
- export { GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, coerceTransportToolCallArguments, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, hasOpenAICompatibleConversationTurn, isOpenAICodexResponsesModel, log, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, quoteUnsafeIntegerLiterals, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveCacheRetention, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortTransportToolsByName, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, usesNativeOpenAICodexResponsesBackend };
4069
+ export { GEMINI_THOUGHT_SIGNATURE_VALIDATOR_SKIP, applyAnthropicEphemeralCacheControlMarkers, applyAnthropicPayloadPolicyToParams, applyOpenAIResponsesPayloadPolicy, assertCodeModeResponsesToolSurface, assignTransportErrorDetails, buildOpenAIClientHeaders, buildOpenAICompletionsParams, buildOpenAISdkClientOptions, buildOpenAISdkRequestOptions, buildTransportAwareSimpleStreamFn, canonicalizeMaxTokensParam, coerceTransportToolCallArguments, createAnthropicMessagesTransportStreamFn, createAzureOpenAIResponsesTransportStreamFn, createBoundaryAwareStreamFnForModel, createDeepSeekTextFilter, createEmptyTransportUsage, createModelStreamCooperativeScheduler, createOpenAICompletionsTransportStreamFn, createOpenAIResponsesTransportStreamFn, createOpenClawTransportStreamFnForModel, createTransportAwareStreamFnForModel, createWritableTransportEventStream, detectOpenAICompletionsCompat, emitModelTransportDebug, enforceCodeModeResponsesToolSurface, failTransportStream, finalizeTransportStream, flattenCompletionMessagesToStringContent, formatModelTransportDebugBaseUrl, formatModelTransportDebugUrl, getCompat, hasOpenAICompatibleConversationTurn, isCodeModeModelVisibleToolName, isOpenAICodexResponsesModel, log, mergeTransportHeaders, mergeTransportMetadata, normalizeCodexResponsesBaseUrlForOpenAISdk, parseJsonObjectPreservingUnsafeIntegers, parseJsonPreservingUnsafeIntegers, prepareModelForSimpleCompletion, prepareTransportAwareSimpleModel, quoteUnsafeIntegerLiterals, resolveAnthropicEphemeralCacheControl, resolveAnthropicMessagesUrl, resolveAnthropicPayloadPolicy, resolveCacheRetention, resolveMaxTokensParam, resolveModelPayloadDebugMode, resolveModelSseDebugMode, resolveOpenAICompletionsCompat, resolveOpenAIReasoningEffortMap, resolveOpenAIResponsesPayloadPolicy, resolveOpenAIStrictToolFlagWithDiagnostics, resolvePromptCacheKey, resolveReplayableResponsesMessageId, resolveTransportAwareSimpleApi, sanitizeNonEmptyTransportPayloadText, sanitizeResponsesImagePayload, sanitizeTransportPayloadText, sortPromptCacheToolsByName as sortTransportToolsByName, stripCompletionMessagesToRoleContent, throwIfModelStreamAborted, transportAbortError, usesNativeOpenAICodexResponsesBackend };