{"version":3,"file":"adapter.mjs","names":["#baseline"],"sources":["../../../../src/batteries/llm/openai_responses/adapter.ts"],"sourcesContent":["/**\n * Cross-environment executor adapter for the OpenAI Responses API.\n *\n * @module @nhtio/adk/batteries/llm/openai_responses/adapter\n *\n * @remarks\n * Cross-environment LLM adapter for the OpenAI Responses wire shape — a flat `input: Item[]` array\n * (not `messages[]`), where a tool call and its result are two SIBLING top-level items\n * (`function_call` / `function_call_output`), and the system prompt defaults to a top-level\n * `instructions` string rather than a leading message item.\n *\n * The adapter is built around the same three pluggable layers as `openai_chat_completions`:\n *\n * 1. **Translation helpers** — the swappable functions exported from `./helpers` turn ADK\n *    primitives into Responses wire shapes. Consumers override individual helpers via\n *    `options.helpers.*`.\n * 2. **Three-layer options merging** — constructor baseline, per-`executor()` overrides, and\n *    per-iteration `ctx.stash.openaiResponses` overrides combine with key-by-key precedence for\n *    `headers`/`helpers`/`retry` and wholesale replacement for everything else. The merged shape\n *    is re-validated on every iteration.\n * 3. **Cross-env transport** — hand-rolled `fetch` + SSE parsing, mirroring\n *    `openai_chat_completions/adapter.ts`'s transport exactly. No `openai` SDK dependency.\n *\n * This adapter is STATELESS by design: `store: false` is always sent (never a settable option),\n * and the full `input` array is resent every iteration. There is no `[DONE]` sentinel on the\n * Responses SSE stream — termination is `response.completed` / `.incomplete` / `.failed`; EOF\n * without one of these is a best-effort recovery, not a hard failure: it warn-logs and drains\n * whatever was accumulated rather than nacking with {@link E_OPENAI_RESPONSES_STREAM_ERROR} (that\n * exception is reserved for a genuine stream-level error, e.g. the connection itself failing).\n *\n * Recoverable-failure handling: a 400 whose body matches `invalid_encrypted_content` drops every\n * reasoning item from the resolved input and retries the request once — a documented real-world\n * failure mode when a persisted reasoning `Thought` outlives a server-side key rotation. A 400\n * matching the reasoning/output-item pairing violation phrases translates to\n * {@link E_OPENAI_RESPONSES_REASONING_REPLAY_REJECTED} instead of a generic HTTP error.\n *\n * `background` is NOT supported: this executor has no polling/resumption loop for a\n * `queued`/`in_progress` background response (the Responses API's async mode; see\n * https://platform.openai.com/docs/guides/background), so `background: true` is rejected up front\n * by the options schema (`E_INVALID_OPENAI_RESPONSES_OPTIONS`, see `validation.ts`) rather than\n * reaching this executor at all — accepting it here would otherwise fall straight into the\n * ordinary streaming/non-streaming response handling below and treat the initial\n * `queued`/`in_progress` response body as a complete, empty answer, silently discarding whatever\n * the background job eventually produces.\n */\n\nimport { DateTime } from 'luxon'\nimport { sha256 } from 'js-sha256'\nimport { v6 as uuidv6 } from 'uuid'\nimport { validateOptions } from './validation'\nimport { isError, isInstanceOf, isObject } from '@nhtio/adk/guards'\nimport { resolveToolCallParser } from '../chat_common/tool_parsers'\nimport { canonicalStringify } from '../../../lib/utils/canonical_json'\nimport { InMemorySpoolStore } from '@nhtio/adk/batteries/storage/in_memory'\nimport { looksLikeSpooledArtifact, normalizeToolName } from '../chat_common/helpers'\nimport {\n  computeBackoff,\n  sleepWithJitter,\n  parseRetryAfter,\n  linkAbortSignals,\n} from '../../../lib/utils/retry'\nimport {\n  Tokenizable,\n  ToolCall,\n  Message,\n  Thought,\n  SpooledArtifact,\n  Media,\n  ArtifactTool,\n} from '@nhtio/adk/common'\nimport {\n  E_INVALID_OPENAI_RESPONSES_OPTIONS,\n  E_OPENAI_RESPONSES_CONTEXT_OVERFLOW,\n  E_OPENAI_RESPONSES_HTTP_ERROR,\n  E_OPENAI_RESPONSES_STREAM_ERROR,\n  E_OPENAI_RESPONSES_STREAM_STALLED,\n  E_OPENAI_RESPONSES_REQUEST_TIMEOUT,\n  E_OPENAI_RESPONSES_INVALID_TOOL_CALL_ARGS,\n  E_OPENAI_RESPONSES_REASONING_REPLAY_REJECTED,\n} from './exceptions'\nimport {\n  defaultDescriptionToChatCompletionsJsonSchema,\n  defaultRenderUntrustedContent,\n  defaultRenderTrustedContent,\n  defaultRenderStandingInstructions,\n  defaultRenderMemories,\n  defaultRenderRetrievables,\n  defaultRenderRetrievableHandleBody,\n  defaultRenderRetrievableSafetyDirective,\n  defaultRenderFirstPartyRetrievables,\n  defaultRenderThirdPartyPublicRetrievables,\n  defaultRenderThirdPartyPrivateRetrievables,\n  defaultRenderArtifactHandleBody,\n  defaultRenderThought,\n  defaultFilterThoughts,\n  defaultToolsToChatCompletionsTools,\n  defaultRenderChatCompletionsSystemPrompt,\n  defaultRenderOpenAIResponsesMediaBlocks,\n  defaultRenderOpenAIResponsesTimelineMessage,\n  defaultRenderOpenAIResponsesToolCallResult,\n  defaultToolsToOpenAIResponsesTools,\n  fingerprintOpenAIResponsesPrefix,\n  defaultRenderOpenAIResponsesReasoningItem,\n  defaultBuildOpenAIResponsesInput,\n  defaultCreateResponsesOutputSlotMachine,\n  normalizeOpenAIResponsesItemId,\n} from './helpers'\nimport type { Tool, Memory } from '@nhtio/adk/common'\nimport type { DispatchContext } from '@nhtio/adk/types'\nimport type { TokenEncoding, TokenEncodingId } from '@nhtio/adk/types'\nimport type {\n  DispatchExecutorFn,\n  DispatchExecutorHelpers,\n  GenerationStats,\n} from '@nhtio/adk/dispatch_runner'\nimport type {\n  OpenAIResponsesAdapterOptions,\n  OpenAIResponsesHelpers,\n  ChatCompletionsRetryConfig,\n  OpenAIResponsesRequestBody,\n  OpenAIResponsesInputItem,\n  OpenAIResponsesInputContentBlock,\n  OpenAIResponsesReasoningItem,\n  OpenAIResponsesFunctionCallItem,\n  OpenAIResponsesStreamEvent,\n  OpenAIResponsesResponseObject,\n  OpenAIResponsesReasoningReplayPayload,\n  OpenAIResponsesTool,\n} from './types'\n\n// ─── ADK-control keys (stripped before sending the request body) ──────────\n\nconst ADK_CONTROL_KEYS: ReadonlySet<string> = new Set([\n  'apiKey',\n  'baseURL',\n  'organization',\n  'project',\n  'headers',\n  'fetch',\n  'stream',\n  'bucketOrder',\n  'contextWindow',\n  'selfIdentity',\n  'thoughtSurfacing',\n  'tokenEncoding',\n  'replayCompatibility',\n  'helpers',\n  'streamIdleTimeoutMs',\n  'requestTimeoutMs',\n  'retry',\n  'strictToolChoice',\n  // `strict` configures the EMITTED TOOL DECLARATIONS (it becomes each function tool's own\n  // `strict` field via `toolsToOpenAIResponsesTools`) — it is not a top-level Responses request\n  // property. Without this entry the generic body spread forwarded it verbatim, so an adapter\n  // constructed with `strict: true` put `\"strict\": true` on the wire alongside `model`/`input`,\n  // where the API can reject the request before generation. Verified against the real wire body:\n  // the keys sent were `input, instructions, model, store, stream, strict`.\n  'strict',\n  'autoAck',\n  'unsupportedMediaPolicy',\n  'localToolCallParser',\n  'forgeToolsFilter',\n  'spoolStore',\n  // Responses-specific ADK control\n  'systemPromptChannel',\n  'reasoningReplay',\n  // Observability hooks — never sent to the provider.\n  'onRawGeneration',\n  'onPromptAssembled',\n  'toolCallIdFilter',\n])\n\n// ─── Option merging ───────────────────────────────────────────────────────────\n\nconst mergeRetry = (\n  layers: ReadonlyArray<ChatCompletionsRetryConfig | undefined>\n): ChatCompletionsRetryConfig | undefined => {\n  let merged: ChatCompletionsRetryConfig | undefined\n  for (const layer of layers) {\n    if (!layer) continue\n    merged = { ...(merged ?? {}), ...layer }\n  }\n  return merged\n}\n\nconst mergeHeaders = (\n  layers: ReadonlyArray<Record<string, string> | undefined>\n): Record<string, string> | undefined => {\n  let merged: Record<string, string> | undefined\n  for (const layer of layers) {\n    if (!layer) continue\n    merged = { ...(merged ?? {}), ...layer }\n  }\n  return merged\n}\n\nconst mergeHelpers = (\n  layers: ReadonlyArray<Partial<OpenAIResponsesHelpers> | undefined>\n): Partial<OpenAIResponsesHelpers> | undefined => {\n  let merged: Partial<OpenAIResponsesHelpers> | undefined\n  for (const layer of layers) {\n    if (!layer) continue\n    merged = { ...(merged ?? {}), ...layer }\n  }\n  return merged\n}\n\nconst mergeOptions = (\n  baseline: OpenAIResponsesAdapterOptions,\n  exec: Partial<OpenAIResponsesAdapterOptions> | undefined,\n  stash: Partial<OpenAIResponsesAdapterOptions> | undefined\n): Partial<OpenAIResponsesAdapterOptions> => {\n  const layers = [baseline as Partial<OpenAIResponsesAdapterOptions>, exec ?? {}, stash ?? {}]\n  const out: Record<string, unknown> = {}\n  for (const layer of layers) {\n    for (const [k, v] of Object.entries(layer)) {\n      if (v === undefined) continue\n      if (k === 'headers' || k === 'helpers' || k === 'retry') continue\n      out[k] = v\n    }\n  }\n  const headers = mergeHeaders(layers.map((l) => l.headers))\n  if (headers !== undefined) out.headers = headers\n  const helpers = mergeHelpers(layers.map((l) => l.helpers))\n  if (helpers !== undefined) out.helpers = helpers\n  const retry = mergeRetry(layers.map((l) => l.retry))\n  if (retry !== undefined) out.retry = retry\n  return out as Partial<OpenAIResponsesAdapterOptions>\n}\n\n// ─── Helper resolution ────────────────────────────────────────────────────────\n\nconst resolveHelpers = (\n  overrides: Partial<OpenAIResponsesHelpers> | undefined\n): OpenAIResponsesHelpers => {\n  const src = overrides ?? {}\n  return {\n    descriptionToChatCompletionsJsonSchema:\n      src.descriptionToChatCompletionsJsonSchema ?? defaultDescriptionToChatCompletionsJsonSchema,\n    renderUntrustedContent: src.renderUntrustedContent ?? defaultRenderUntrustedContent,\n    renderTrustedContent: src.renderTrustedContent ?? defaultRenderTrustedContent,\n    renderStandingInstructions: src.renderStandingInstructions ?? defaultRenderStandingInstructions,\n    renderMemories: src.renderMemories ?? defaultRenderMemories,\n    renderRetrievables: src.renderRetrievables ?? defaultRenderRetrievables,\n    renderRetrievableHandleBody:\n      src.renderRetrievableHandleBody ?? defaultRenderRetrievableHandleBody,\n    renderRetrievableSafetyDirective:\n      src.renderRetrievableSafetyDirective ?? defaultRenderRetrievableSafetyDirective,\n    renderFirstPartyRetrievables:\n      src.renderFirstPartyRetrievables ?? defaultRenderFirstPartyRetrievables,\n    renderThirdPartyPublicRetrievables:\n      src.renderThirdPartyPublicRetrievables ?? defaultRenderThirdPartyPublicRetrievables,\n    renderThirdPartyPrivateRetrievables:\n      src.renderThirdPartyPrivateRetrievables ?? defaultRenderThirdPartyPrivateRetrievables,\n    renderArtifactHandleBody: src.renderArtifactHandleBody ?? defaultRenderArtifactHandleBody,\n    renderThought: src.renderThought ?? defaultRenderThought,\n    filterThoughts: src.filterThoughts ?? defaultFilterThoughts,\n    toolsToChatCompletionsTools:\n      src.toolsToChatCompletionsTools ?? defaultToolsToChatCompletionsTools,\n    renderChatCompletionsSystemPrompt:\n      src.renderChatCompletionsSystemPrompt ?? defaultRenderChatCompletionsSystemPrompt,\n    renderOpenAIResponsesMediaBlocks:\n      src.renderOpenAIResponsesMediaBlocks ?? defaultRenderOpenAIResponsesMediaBlocks,\n    renderOpenAIResponsesTimelineMessage:\n      src.renderOpenAIResponsesTimelineMessage ?? defaultRenderOpenAIResponsesTimelineMessage,\n    renderOpenAIResponsesToolCallResult:\n      src.renderOpenAIResponsesToolCallResult ?? defaultRenderOpenAIResponsesToolCallResult,\n    toolsToOpenAIResponsesTools:\n      src.toolsToOpenAIResponsesTools ?? defaultToolsToOpenAIResponsesTools,\n    fingerprintOpenAIResponsesPrefix:\n      src.fingerprintOpenAIResponsesPrefix ?? fingerprintOpenAIResponsesPrefix,\n    renderOpenAIResponsesReasoningItem:\n      src.renderOpenAIResponsesReasoningItem ?? defaultRenderOpenAIResponsesReasoningItem,\n    buildOpenAIResponsesInput: src.buildOpenAIResponsesInput ?? defaultBuildOpenAIResponsesInput,\n    createResponsesOutputSlotMachine:\n      src.createResponsesOutputSlotMachine ?? defaultCreateResponsesOutputSlotMachine,\n  }\n}\n\n// ─── ID helpers ───────────────────────────────────────────────────────────────\n\n// Canonical (key-order-insensitive) checksum — MUST match the contract documented on\n// canonicalStringify and used by Tool.executor + dispatch_runner's streaming helper, so\n// ctx.toolCallCount(checksum) detects semantically-identical repeat calls regardless of argument\n// key order.\nconst computeChecksum = (tool: string, args: unknown): string =>\n  sha256(canonicalStringify({ tool, args }))\n\nconst nowIso = (): string => DateTime.now().toISO() ?? new Date().toISOString()\n\n// ─── Token measurement ────────────────────────────────────────────────────────\n\nconst estimateTokensOf = async (\n  value: { estimateTokens: (encoding: TokenEncoding) => number | Promise<number> },\n  encoding: TokenEncodingId\n): Promise<number> => {\n  return Promise.resolve(value.estimateTokens(encoding as TokenEncoding))\n}\n\n// ─── Generation-stats extraction ───────────────────────────────────────────────\n\nconst extractGenerationStats = (input: {\n  model: string\n  usage?: OpenAIResponsesResponseObject['usage']\n  finishReason?: string | null\n  raw: Record<string, unknown>\n}): GenerationStats => {\n  const stats: GenerationStats = {\n    provider: 'openai_responses',\n    model: input.model,\n    raw: input.raw,\n  }\n  const usage = input.usage\n  if (usage) {\n    const cached = usage.input_tokens_details?.cached_tokens ?? 0\n    if (typeof usage.input_tokens === 'number') {\n      stats.promptTokens = Math.max(0, usage.input_tokens - cached)\n    }\n    if (typeof usage.output_tokens === 'number') stats.completionTokens = usage.output_tokens\n    if (typeof usage.total_tokens === 'number') stats.totalTokens = usage.total_tokens\n  }\n  if (typeof input.finishReason === 'string') stats.finishReason = input.finishReason\n  return stats\n}\n\n// ─── Stop-reason mapping ───────────────────────────────────────────────────────\n\nconst mapStopReason = (\n  status: OpenAIResponsesResponseObject['status'],\n  incompleteReason: string | undefined,\n  hadToolCalls: boolean\n): string => {\n  if (status === 'completed') return hadToolCalls ? 'tool_calls' : 'stop'\n  if (status === 'incomplete') {\n    if (incompleteReason === 'content_filter') return 'content_filter'\n    return 'length'\n  }\n  return 'error'\n}\n\n// ─── Reasoning-replay error detection ─────────────────────────────────────────\n\nconst INVALID_ENCRYPTED_CONTENT_PHRASE = 'invalid_encrypted_content'\n// Both directions of the bidirectional pairing constraint (openai/openai-node#1791). The first\n// phrase catches a REASONING item rejected for missing its required FOLLOWING item; the second\n// catches the mirror case reported as that issue's headline error — a MESSAGE item rejected for\n// missing its required PRECEDING reasoning item (`Item 'msg_…' of type 'message' was provided\n// without its required preceding item of type 'reasoning'`), which the narrower\n// \"of type 'reasoning' was provided without\" phrasing does not match.\nconst REASONING_PAIRING_PHRASES = [\n  \"of type 'reasoning' was provided without\",\n  \"was provided without its required preceding item of type 'reasoning'\",\n  'items are not persisted when store is set to false',\n]\n\nconst bodyMatches = (body: string, phrases: ReadonlyArray<string>): boolean => {\n  const lower = body.toLowerCase()\n  return phrases.some((p) => lower.includes(p.toLowerCase()))\n}\n\n// ─── SSE framing ────────────────────────────────────────────────────────────────\n\n// A blank line delimits SSE frames. Tolerate CRLF alongside LF — some gateways/proxies\n// normalise line endings to \\r\\n, which a bare `\\n\\n` search never matches.\nconst SSE_FRAME_SEPARATOR = /\\r?\\n\\r?\\n/\n\n// ─── Adapter class ────────────────────────────────────────────────────────────\n\n/**\n * Opinionated cross-environment LLM adapter for the OpenAI Responses wire shape.\n *\n * @remarks\n * Construction validates options eagerly via {@link validateOptions} and throws\n * {@link E_INVALID_OPENAI_RESPONSES_OPTIONS} on failure. The returned instance is reusable: call\n * {@link OpenAIResponsesAdapter.executor} once per `DispatchRunner` configuration.\n *\n * Per-iteration overrides live on the active `DispatchContext`'s `stash.openaiResponses` slot and\n * take highest precedence — they merge into the executor-scope shape on every iteration.\n * `headers`, `helpers`, and `retry` merge key-by-key across all three layers; every other field is\n * replaced wholesale at the highest layer that sets it.\n */\nexport class OpenAIResponsesAdapter {\n  /**\n   * Customary key for per-iteration overrides on `ctx.stash`. The adapter reads\n   * `ctx.stash.get(OpenAIResponsesAdapter.STASH_KEY, {})` at the start of every iteration and\n   * merges the value into the resolved options shape.\n   */\n  public static readonly STASH_KEY = 'openaiResponses' as const\n\n  readonly #baseline: OpenAIResponsesAdapterOptions\n\n  /**\n   * @param options - Constructor-baseline options. Re-validated on every iteration after\n   *   per-dispatch and per-iteration overrides are layered in.\n   * @throws {@link E_INVALID_OPENAI_RESPONSES_OPTIONS} when `options` does not satisfy\n   *   `openAIResponsesOptionsSchema`.\n   */\n  constructor(options: unknown) {\n    this.#baseline = validateOptions(options)\n  }\n\n  /**\n   * Returns a `DispatchExecutorFn` bound to this adapter's baseline plus optional executor-scope\n   * overrides. The returned function is reusable across iterations — every iteration re-merges\n   * with `ctx.stash[STASH_KEY]` and re-validates the result.\n   *\n   * @param overrides - Optional executor-scope overrides. Higher precedence than the baseline,\n   *   lower precedence than `ctx.stash[STASH_KEY]`.\n   * @returns A `DispatchExecutorFn` suitable for `DispatchRunner`.\n   */\n  executor(overrides?: Partial<OpenAIResponsesAdapterOptions>): DispatchExecutorFn {\n    const baseline = this.#baseline\n    const adapterClass = OpenAIResponsesAdapter\n    return async (ctx: DispatchContext, helpers: DispatchExecutorHelpers): Promise<void> => {\n      const localWarn = (msg: string): void => {\n        helpers.log.warn({ kind: 'helper-warning', message: msg })\n      }\n\n      // ── Step 1: merge & validate ──────────────────────────────────────────\n      const stashRaw = ctx.stash.get(adapterClass.STASH_KEY, {}) as unknown\n      const stashOverrides =\n        stashRaw && typeof stashRaw === 'object'\n          ? (stashRaw as Partial<OpenAIResponsesAdapterOptions>)\n          : {}\n      const mergedRaw = mergeOptions(baseline, overrides, stashOverrides)\n      const merged = validateOptions(mergedRaw)\n\n      if (merged.tokenEncoding !== null && merged.contextWindow === undefined) {\n        throw new E_INVALID_OPENAI_RESPONSES_OPTIONS([\n          'tokenEncoding is non-null but contextWindow is undefined',\n        ])\n      }\n\n      // ── Step 2: resolve helpers ───────────────────────────────────────────\n      const resolvedHelpers = resolveHelpers(merged.helpers)\n\n      // ── Step 3: artifact-reader tools ─────────────────────────────────────\n      // Forged by the DispatchRunner CORE into `ctx.tools` before the input pipeline runs\n      // (generation is a generic core concern; this battery owns only representation). Read the\n      // pre-forged `ctx.tools` directly — no local merge, no bindContext here.\n\n      // ── Step 4: pre-render tool-call results ──────────────────────────────\n      const renderedToolCallResults = new Map<\n        ToolCall,\n        string | OpenAIResponsesInputContentBlock[]\n      >()\n      for (const tc of ctx.turnToolCalls) {\n        const rendered = await resolvedHelpers.renderOpenAIResponsesToolCallResult({\n          toolCall: tc,\n          results: tc.results as\n            | Tokenizable\n            | SpooledArtifact\n            | SpooledArtifact[]\n            | Media\n            | Media[],\n          tool: ctx.tools.get(tc.tool) as Tool | ArtifactTool | undefined,\n          renderUntrustedContent: resolvedHelpers.renderUntrustedContent,\n          renderTrustedContent: resolvedHelpers.renderTrustedContent,\n          renderOpenAIResponsesMediaBlocks: resolvedHelpers.renderOpenAIResponsesMediaBlocks,\n          renderArtifactHandleBody: resolvedHelpers.renderArtifactHandleBody,\n          unsupportedMediaPolicy: merged.unsupportedMediaPolicy ?? 'throw',\n          warn: localWarn,\n        })\n        renderedToolCallResults.set(tc, rendered)\n      }\n\n      // ── Step 5: context window enforcement ────────────────────────────────\n      if (merged.tokenEncoding !== null && merged.contextWindow !== undefined) {\n        const encoding = merged.tokenEncoding as TokenEncodingId\n        let spTokens = await estimateTokensOf(ctx.systemPrompt, encoding)\n        let siTokens = 0\n        {\n          // The wire ships ONE `<system_instructions kind=\"developer-rules\">` block wrapping every\n          // standing instruction (+68 chars over a 15-char body), not the raw strings. Counting the\n          // rendered block captures both the bodies and that wrapper.\n          const siBlock = resolvedHelpers.renderStandingInstructions(ctx.standingInstructions)\n          if (siBlock.length > 0) {\n            siTokens = await estimateTokensOf(new Tokenizable(siBlock), encoding)\n          }\n        }\n        let memTokens = 0\n        for (const mem of ctx.turnMemories as Set<Memory>) {\n          memTokens += await estimateTokensOf(mem.content, encoding)\n        }\n        let retTokens = 0\n        for (const r of ctx.turnRetrievables) {\n          retTokens +=\n            !r.inline && SpooledArtifact.isSpooledArtifact(r.content) && r.content.hasSizeHints()\n              ? r.content.estimateHandleTokens(\n                  r.id,\n                  encoding as TokenEncoding,\n                  resolvedHelpers.renderRetrievableHandleBody\n                )\n              : await estimateTokensOf(r.content, encoding)\n        }\n        let tlTokens = 0\n        for (const msg of ctx.turnMessages) {\n          if (msg.content !== undefined) {\n            // Count the RENDERED message, not the raw content. Every timeline message goes on the\n            // wire wrapped in an identity envelope — `<message_<id> from=… role=… createdAt=…>` —\n            // which the guard previously ignored entirely. Measured: a 30-char message ships as\n            // 118 chars (3.9x), and the envelope is a near-fixed ~90 chars regardless of body\n            // length, so a 40-turn conversation of short messages leaked ~880 tokens the guard\n            // never saw. Rendering it here is the honest measure: it is the same helper the\n            // builder uses, so the count tracks the wire by construction rather than by a\n            // hand-maintained estimate that drifts when the envelope changes.\n            const renderedMsg = await resolvedHelpers.renderOpenAIResponsesTimelineMessage({\n              message: msg,\n              selfIdentity: merged.selfIdentity ?? 'assistant',\n              // Media is tallied separately below, from byte length; asking this renderer to\n              // resolve attachments would duplicate the base64 work and can throw under\n              // `unsupportedMediaPolicy: 'throw'` purely to measure it.\n              unsupportedMediaPolicy: 'synthetic-description',\n              renderOpenAIResponsesMediaBlocks: resolvedHelpers.renderOpenAIResponsesMediaBlocks,\n              renderUntrustedContent: resolvedHelpers.renderUntrustedContent,\n              renderTrustedContent: resolvedHelpers.renderTrustedContent,\n            })\n            const renderedText =\n              renderedMsg === null\n                ? ''\n                : (\n                    ((renderedMsg as { content?: unknown }).content as\n                      | Array<{ type: string; text?: string }>\n                      | undefined) ?? []\n                  )\n                    .filter((b) => b.type === 'input_text')\n                    .map((b) => b.text ?? '')\n                    .join('')\n            tlTokens += await estimateTokensOf(\n              new Tokenizable(renderedText.length > 0 ? renderedText : msg.content.toString()),\n              encoding\n            )\n          }\n          // A message's ATTACHMENTS render into real wire content — `renderOpenAIResponsesTimeline\n          // Message` turns each one into `input_image`/`input_file` blocks carrying a base64\n          // payload — so they must be tallied too. Counting only `msg.content` left a user turn\n          // with an image attachment entirely invisible to the guard, which is the same\n          // undercount already fixed for rendered tool-call results below, one code path over.\n          //\n          // The media is measured by its own byte length rather than by rendering it here:\n          // re-rendering would duplicate the base64 work (and can throw under\n          // `unsupportedMediaPolicy: 'throw'`) purely to measure it. base64 inflates bytes by 4/3,\n          // and a token is ~4 base64 chars, so `byteLength / 3` is the honest FLOOR for the\n          // payload — same doctrine as the tool-declaration and native-block floors.\n          for (const media of msg.attachments ?? []) {\n            try {\n              const bytes = await media.byteLength()\n              if (bytes !== undefined && Number.isFinite(bytes) && bytes > 0) {\n                tlTokens += Math.ceil(bytes / 3)\n              }\n            } catch {\n              /* unreadable attachment — cannot measure it; the floor simply omits it */\n            }\n          }\n        }\n        for (const th of ctx.turnThoughts) {\n          // Same envelope problem as messages: a surfaced thought ships wrapped in\n          // `<thought_<id> nonce=… kind=… from=… createdAt=…>`, measured at +113 chars over a\n          // 19-char body. Count the rendered form so the tally tracks the wire.\n          const renderedThought = resolvedHelpers.renderThought(th.content.toString(), {\n            nonce: th.id,\n            kind: 'self-reasoning',\n            from: String(th.identity?.identifier ?? merged.selfIdentity ?? 'assistant'),\n            createdAt: th.createdAt?.toISO?.() ?? undefined,\n          })\n          tlTokens += await estimateTokensOf(new Tokenizable(renderedThought), encoding)\n        }\n        for (const rendered of renderedToolCallResults.values()) {\n          if (typeof rendered === 'string') {\n            tlTokens += await estimateTokensOf(new Tokenizable(rendered), encoding)\n            continue\n          }\n          // Count EVERY block that is actually transmitted, not just `input_text`. A native\n          // `input_image`/`input_file` block carries a base64 payload in `image_url`/`file_data`\n          // that is real request content; filtering those out understated the request by the\n          // entire attachment, so a prompt the guard accepted could still exceed the provider's\n          // window. Tallying the block's own wire JSON keeps this an honest FLOOR (the provider\n          // bills images by its own tiling rules, which are not reproducible client-side) rather\n          // than a pretend-exact count — same doctrine as the tool-declaration floor below.\n          for (const block of rendered) {\n            const text =\n              block.type === 'input_text' ? block.text : JSON.stringify(block satisfies object)\n            tlTokens += await estimateTokensOf(new Tokenizable(text), encoding)\n          }\n        }\n        // Tool-call REQUEST items. A tool call goes on the wire as two sibling items — the\n        // `function_call` (carrying `name` + `arguments`) and its `function_call_output` — but only\n        // the OUTPUT was tallied above, via `renderedToolCallResults`. A prior call with large\n        // arguments was therefore invisible to the guard. Counting the `function_call` item's own\n        // wire JSON keeps this the same honest FLOOR as the blocks above.\n        for (const tc of ctx.turnToolCalls) {\n          const argsText = typeof tc.args === 'string' ? tc.args : JSON.stringify(tc.args ?? {})\n          const callItemJson = JSON.stringify({\n            type: 'function_call',\n            call_id: tc.id,\n            name: tc.tool,\n            arguments: argsText,\n          })\n          tlTokens += await estimateTokensOf(new Tokenizable(callItemJson), encoding)\n        }\n        // Tool DECLARATIONS: tally the tokens of the wire `tools` JSON as an honest FLOOR — same\n        // rationale as `openai_chat_completions/adapter.ts`.\n        let toolTokens = 0\n        const visibleTools = ctx.tools.visible()\n        if (visibleTools.length > 0) {\n          const toolsJson = JSON.stringify(\n            resolvedHelpers.toolsToOpenAIResponsesTools(visibleTools, {\n              descriptionToChatCompletionsJsonSchema: (d: unknown) =>\n                resolvedHelpers.descriptionToChatCompletionsJsonSchema(d as never),\n              strict: merged.strict,\n            })\n          )\n          toolTokens = await estimateTokensOf(new Tokenizable(toolsJson), encoding)\n        }\n        const total = spTokens + siTokens + memTokens + retTokens + tlTokens + toolTokens\n        const perBucketObj = {\n          systemPrompt: spTokens,\n          standingInstructions: siTokens,\n          memories: memTokens,\n          retrievables: retTokens,\n          timeline: tlTokens,\n          tools: toolTokens,\n        }\n        helpers.log.debug({\n          kind: 'context-window-usage',\n          message: `Context window usage: ${total}/${merged.contextWindow} tokens`,\n          payload: {\n            total,\n            limit: merged.contextWindow,\n            encoding,\n            perBucket: perBucketObj,\n          },\n        })\n        if (total > merged.contextWindow) {\n          const perBucket = JSON.stringify(perBucketObj)\n          throw new E_OPENAI_RESPONSES_CONTEXT_OVERFLOW([\n            total,\n            merged.contextWindow,\n            encoding,\n            perBucket,\n          ])\n        }\n      }\n\n      // ── Step 5b: tool_choice + forged artifact-tools guard ────────────────\n      const toolChoice = merged.tool_choice\n      const forcedToolNames: string[] = []\n      if (toolChoice && typeof toolChoice === 'object' && toolChoice.type === 'function') {\n        forcedToolNames.push(toolChoice.name)\n      }\n      const forcedForgedHits: Array<{ toolName: string }> = []\n      for (const name of forcedToolNames) {\n        const t = ctx.tools.get(name) as { ephemeral?: boolean } | undefined\n        if (t?.ephemeral === true) {\n          forcedForgedHits.push({ toolName: name })\n        }\n      }\n      if (forcedForgedHits.length > 0) {\n        if (merged.strictToolChoice === true) {\n          throw new E_INVALID_OPENAI_RESPONSES_OPTIONS([\n            `tool_choice forces forged ephemeral artifact-query tool(s): ${forcedForgedHits\n              .map((h) => h.toolName)\n              .join(\n                ', '\n              )} — these may not exist on the next iteration. Remove the override or unset strictToolChoice.`,\n          ])\n        }\n        helpers.log.warn({\n          kind: 'tool-choice-forged-artifact',\n          message: `tool_choice forces ${forcedForgedHits.length} forged ephemeral artifact-query tool(s); this is almost always a misconfiguration`,\n          payload: { toolNames: forcedForgedHits.map((h) => h.toolName) },\n        })\n      }\n\n      // ── Step 6: build request body ────────────────────────────────────────\n      const buildInput = async (\n        dropReasoning: boolean\n      ): Promise<{\n        instructions?: string\n        input: OpenAIResponsesInputItem[]\n        tools?: OpenAIResponsesTool[]\n        fingerprintableLength: number\n      }> => {\n        return resolvedHelpers.buildOpenAIResponsesInput({\n          model: merged.model,\n          systemPrompt: ctx.systemPrompt,\n          // The live dispatch context, so a DYNAMIC system prompt (a `Tokenizable` built from a\n          // `(ctx) => string` resolver) sees it. Previously nothing passed this, so such a prompt\n          // rendered against `undefined` and quietly dropped everything it read from context.\n          renderCtx: ctx,\n          standingInstructions: ctx.standingInstructions,\n          memories: ctx.turnMemories,\n          retrievables: ctx.turnRetrievables,\n          messages: ctx.turnMessages,\n          thoughts: dropReasoning ? [] : ctx.turnThoughts,\n          toolCalls: ctx.turnToolCalls,\n          tools: ctx.tools,\n          strict: merged.strict,\n          renderedToolCallResults,\n          bucketOrder: merged.bucketOrder ?? [\n            'standingInstructions',\n            'memories',\n            'retrievables',\n            'timeline',\n          ],\n          selfIdentity: merged.selfIdentity ?? 'assistant',\n          thoughtSurfacing: merged.thoughtSurfacing ?? 'all-self',\n          replayCompatibility: merged.replayCompatibility ?? [],\n          reasoningReplay: dropReasoning ? 'off' : (merged.reasoningReplay ?? 'off'),\n          systemPromptChannel: merged.systemPromptChannel ?? 'instructions',\n          unsupportedMediaPolicy: merged.unsupportedMediaPolicy ?? 'throw',\n          renderOpenAIResponsesToolCallResult: resolvedHelpers.renderOpenAIResponsesToolCallResult,\n          renderOpenAIResponsesMediaBlocks: resolvedHelpers.renderOpenAIResponsesMediaBlocks,\n          renderChatCompletionsSystemPrompt: resolvedHelpers.renderChatCompletionsSystemPrompt,\n          renderStandingInstructions: resolvedHelpers.renderStandingInstructions,\n          renderMemories: resolvedHelpers.renderMemories,\n          renderRetrievables: resolvedHelpers.renderRetrievables,\n          renderRetrievableSafetyDirective: resolvedHelpers.renderRetrievableSafetyDirective,\n          renderFirstPartyRetrievables: resolvedHelpers.renderFirstPartyRetrievables,\n          renderThirdPartyPublicRetrievables: resolvedHelpers.renderThirdPartyPublicRetrievables,\n          renderThirdPartyPrivateRetrievables: resolvedHelpers.renderThirdPartyPrivateRetrievables,\n          renderRetrievableHandleBody: resolvedHelpers.renderRetrievableHandleBody,\n          renderOpenAIResponsesTimelineMessage:\n            resolvedHelpers.renderOpenAIResponsesTimelineMessage,\n          renderOpenAIResponsesReasoningItem: resolvedHelpers.renderOpenAIResponsesReasoningItem,\n          fingerprintOpenAIResponsesPrefix: resolvedHelpers.fingerprintOpenAIResponsesPrefix,\n          toolsToOpenAIResponsesTools: resolvedHelpers.toolsToOpenAIResponsesTools,\n          descriptionToChatCompletionsJsonSchema:\n            resolvedHelpers.descriptionToChatCompletionsJsonSchema,\n          renderThought: resolvedHelpers.renderThought,\n          filterThoughts: resolvedHelpers.filterThoughts,\n          renderUntrustedContent: resolvedHelpers.renderUntrustedContent,\n          renderTrustedContent: resolvedHelpers.renderTrustedContent,\n          warn: localWarn,\n        })\n      }\n\n      let assembled = await buildInput(false)\n\n      const stream = merged.stream ?? true\n      const buildBody = (a: {\n        instructions?: string\n        input: OpenAIResponsesInputItem[]\n        tools?: OpenAIResponsesTool[]\n      }): OpenAIResponsesRequestBody => {\n        const b: OpenAIResponsesRequestBody = {\n          model: merged.model,\n          input: a.input,\n          stream,\n          store: false,\n        }\n        if (a.instructions !== undefined) b.instructions = a.instructions\n        for (const [k, v] of Object.entries(merged)) {\n          if (ADK_CONTROL_KEYS.has(k)) continue\n          if (\n            k === 'model' ||\n            k === 'input' ||\n            k === 'stream' ||\n            k === 'store' ||\n            k === 'instructions' ||\n            k === 'tool_choice' ||\n            k === 'tools'\n          )\n            continue\n          if (v === undefined) continue\n          ;(b as Record<string, unknown>)[k] = v\n        }\n        if (merged.tool_choice !== undefined) b.tool_choice = merged.tool_choice\n        if (a.tools && a.tools.length > 0) b.tools = a.tools\n        // reasoningReplay 'encrypted' auto-adds 'reasoning.encrypted_content' to `include`.\n        if (merged.reasoningReplay === 'encrypted') {\n          const include = new Set(b.include ?? [])\n          include.add('reasoning.encrypted_content')\n          b.include = Array.from(include)\n        }\n        return b\n      }\n\n      let body = buildBody(assembled)\n\n      const dispatchStreamId = uuidv6()\n\n      if (merged.onPromptAssembled) {\n        try {\n          merged.onPromptAssembled({\n            battery: 'openai_responses',\n            kind: 'request-body',\n            messages: body.input,\n            tools: body.tools,\n            requestBody: body,\n            streamed: stream,\n            streamId: dispatchStreamId,\n          })\n        } catch {\n          /* observer errors are non-fatal */\n        }\n      }\n\n      // ── Step 7: POST with retry / timeout loop ────────────────────────────\n      const rawBase = merged.baseURL ?? 'https://api.openai.com/v1'\n      const baseURL = rawBase.endsWith('/') ? rawBase.slice(0, -1) : rawBase\n      const url = `${baseURL}/responses`\n\n      const buildHeaders = (): Record<string, string> => {\n        const h: Record<string, string> = { 'Content-Type': 'application/json' }\n        if (stream) h['Accept'] = 'text/event-stream'\n        if (merged.apiKey) h['Authorization'] = `Bearer ${merged.apiKey}`\n        if (merged.organization) h['OpenAI-Organization'] = merged.organization\n        if (merged.project) h['OpenAI-Project'] = merged.project\n        if (merged.headers) Object.assign(h, merged.headers)\n        return h\n      }\n\n      const retryCfg: ChatCompletionsRetryConfig = {\n        maxAttempts: merged.retry?.maxAttempts ?? 1,\n        baseDelayMs: merged.retry?.baseDelayMs ?? 500,\n        maxDelayMs: merged.retry?.maxDelayMs ?? 30_000,\n        retriableStatuses: merged.retry?.retriableStatuses ?? [429, 502, 503, 504],\n        honorRetryAfter: merged.retry?.honorRetryAfter ?? true,\n      }\n\n      const fetchFn = merged.fetch ?? globalThis.fetch\n      const maxAttempts = retryCfg.maxAttempts ?? 1\n\n      // The one-time reasoning-drop retry (Known Gotcha / recoverable-failure handling) is\n      // ORTHOGONAL to the retry/backoff loop below — it re-assembles the request body once (with\n      // every reasoning item stripped) and re-enters the whole POST loop fresh, rather than being\n      // counted against `maxAttempts`.\n      let usedReasoningDropRetry = false\n\n      let response: Response | undefined\n      let attempt = 1\n      let attemptStartedAtMs = Date.now()\n      let disposeLink: () => void = () => {}\n      requestLoop: while (attempt <= maxAttempts) {\n        if (ctx.abortSignal.aborted) return\n\n        const internalController = new AbortController()\n        let timeoutHandle: ReturnType<typeof setTimeout> | undefined\n        // When THIS attempt's HTTP exchange began. `requestTimeoutMs` is a whole-exchange budget,\n        // so the body-read deadline further down is measured from here rather than from the moment\n        // headers arrived — otherwise a response that spent most of the budget before sending\n        // headers was granted a second, full interval to stream its body.\n        attemptStartedAtMs = Date.now()\n        const requestTimeoutMs = merged.requestTimeoutMs ?? 0\n        if (requestTimeoutMs > 0) {\n          timeoutHandle = setTimeout(() => internalController.abort(), requestTimeoutMs)\n        }\n        disposeLink()\n        const { signal: linkedSignal, dispose: disposeCurrentLink } = linkAbortSignals([\n          ctx.abortSignal,\n          internalController.signal,\n        ])\n        disposeLink = disposeCurrentLink\n\n        try {\n          response = await fetchFn(url, {\n            method: 'POST',\n            headers: buildHeaders(),\n            body: JSON.stringify(body),\n            signal: linkedSignal,\n          })\n        } catch (err) {\n          if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n          if (ctx.abortSignal.aborted) return\n          if (internalController.signal.aborted) {\n            helpers.log.warn({\n              kind: 'request-timeout',\n              message: `Request timed out after ${requestTimeoutMs}ms on attempt ${attempt}/${maxAttempts}`,\n              payload: { requestTimeoutMs, attempt, maxAttempts },\n            })\n            if (attempt < maxAttempts) {\n              const delay = computeBackoff(attempt, retryCfg)\n              await sleepWithJitter(delay, ctx.abortSignal)\n              attempt += 1\n              continue\n            }\n            ctx.nack(new E_OPENAI_RESPONSES_REQUEST_TIMEOUT([requestTimeoutMs]))\n            return\n          }\n          helpers.log.error({\n            kind: 'transport-error',\n            message: `Transport failure on attempt ${attempt}/${maxAttempts}: ${isError(err) ? err.message : String(err)}`,\n            payload: { attempt, maxAttempts, detail: isError(err) ? err.message : String(err) },\n          })\n          if (attempt < maxAttempts) {\n            const delay = computeBackoff(attempt, retryCfg)\n            await sleepWithJitter(delay, ctx.abortSignal)\n            attempt += 1\n            continue\n          }\n          ctx.nack(new E_OPENAI_RESPONSES_HTTP_ERROR([0, isError(err) ? err.message : String(err)]))\n          return\n        }\n\n        if (timeoutHandle !== undefined) clearTimeout(timeoutHandle)\n\n        if (!response.ok) {\n          const status = response.status\n          const errBody = await response.text().catch(() => '')\n\n          // ── Recoverable-failure handling: a rejected REPLAYED reasoning item ──\n          //\n          // Two upstream 400s mean the same thing — \"the reasoning item you replayed is not\n          // acceptable\" — and both have the same safe recovery: strip every reasoning item and\n          // resend. They are handled identically:\n          //\n          //   1. `invalid_encrypted_content` — a persisted `encrypted_content` payload outlived a\n          //      server-side key rotation.\n          //   2. A reasoning/output-item PAIRING violation — the adjacency constraint reported in\n          //      `openai/openai-node#1791` (see below).\n          //\n          // Case 2 previously nacked immediately, killing the turn and telling the caller to set\n          // `reasoningReplay: 'off'` by hand. That was the wrong default for a failure the adapter\n          // can recover from unaided, and it mattered most exactly where the constraint is least\n          // certain: the pairing rule is UNDOCUMENTED, and the official docs actively contradict\n          // it (the reasoning guide and cookbook both state that irrelevant reasoning items are\n          // silently discarded — \"including them is harmless\"), while #1791 reports a hard 400\n          // reproduced across five official SDKs. Because our adjacency sweep enforces a stricter\n          // rule than the documented span rule, an upstream behavior shift could make the sweep\n          // wrong — and the correct outcome then is a turn that degrades to no-replay, not a turn\n          // that dies. The retry is still ONE-SHOT, so a genuinely broken request cannot loop.\n          if (\n            status === 400 &&\n            !usedReasoningDropRetry &&\n            bodyMatches(errBody, [INVALID_ENCRYPTED_CONTENT_PHRASE, ...REASONING_PAIRING_PHRASES])\n          ) {\n            usedReasoningDropRetry = true\n            helpers.log.warn({\n              kind: 'reasoning-replay-rejected',\n              message:\n                'Upstream rejected a replayed reasoning item; dropping all reasoning items and retrying once.',\n              payload: { status, body: errBody.slice(0, 512) },\n            })\n            assembled = await buildInput(true)\n            body = buildBody(assembled)\n            // Give the REBUILT request its own transport-retry budget. Plain `continue` leaves\n            // `attempt` where the failed original left it, so a reasoning rejection arriving on the\n            // last attempt handed the replacement a fully-spent budget: one transient 503 on the\n            // rebuilt request then ended the turn, even though the recovery itself had worked. That\n            // contradicts this block's own contract (the reasoning-drop retry is ORTHOGONAL to the\n            // retry/backoff loop, not counted against it).\n            //\n            // Deliberately a FRESH BUDGET, not an unbounded one: `usedReasoningDropRetry` is\n            // one-shot, so this reset can happen at most once per dispatch. Worst case is one\n            // additional `maxAttempts` worth of POSTs, never a loop.\n            attempt = 1\n            continue requestLoop\n          }\n\n          // ── Reasoning/output-item pairing violation translation ─────────────\n          // Reached only when the reasoning-free retry ALSO failed, so the rejection is not\n          // attributable to a replayed reasoning item after all — the self-explaining error is\n          // then the honest answer rather than a recovery the adapter has already tried.\n          if (status === 400 && bodyMatches(errBody, REASONING_PAIRING_PHRASES)) {\n            const offendingId =\n              assembled.input.find((i): i is OpenAIResponsesReasoningItem => i.type === 'reasoning')\n                ?.id ?? 'unknown'\n            ctx.nack(new E_OPENAI_RESPONSES_REASONING_REPLAY_REJECTED([offendingId, errBody]))\n            return\n          }\n\n          const retriable = (retryCfg.retriableStatuses ?? [429, 502, 503, 504]).includes(status)\n          if (retriable && attempt < maxAttempts) {\n            let delay = computeBackoff(attempt, retryCfg)\n            if (retryCfg.honorRetryAfter !== false) {\n              const ra = response.headers.get('Retry-After')\n              if (ra) {\n                const raMs = parseRetryAfter(ra)\n                if (raMs > 0) delay = Math.min(Math.max(delay, raMs), retryCfg.maxDelayMs ?? 30_000)\n              }\n            }\n            helpers.log.warn({\n              kind: 'retry-attempt',\n              message: `HTTP ${status} on attempt ${attempt}/${maxAttempts}; retrying in ~${delay}ms`,\n              payload: {\n                reason: 'http-status',\n                status,\n                delayMs: delay,\n                attempt: attempt + 1,\n                maxAttempts,\n              },\n            })\n            await sleepWithJitter(delay, ctx.abortSignal)\n            attempt += 1\n            continue\n          }\n          helpers.log.error({\n            kind: 'http-error',\n            message: `HTTP ${status} (terminal): ${errBody.slice(0, 256)}`,\n            payload: { status, body: errBody, attempt, maxAttempts, retriable },\n          })\n          ctx.nack(new E_OPENAI_RESPONSES_HTTP_ERROR([status, errBody]))\n          return\n        }\n\n        break\n      }\n\n      if (!response) return\n\n      const spoolStore = merged.spoolStore ?? new InMemorySpoolStore()\n\n      // ── Inner helper: persist + execute one assembled tool call ───────────\n      const executeAndPersistToolCall = async (call: {\n        id: string\n        name: string\n        args: string\n      }): Promise<void> => {\n        // Resolve the vendor id once at ingress so reporting, persistence, and spooling agree.\n        const callId = merged.toolCallIdFilter?.(call.id, ctx) ?? call.id\n        const tool = ctx.tools.get(call.name)\n        let args: Record<string, unknown> = {}\n        let parseError: InstanceType<typeof E_OPENAI_RESPONSES_INVALID_TOOL_CALL_ARGS> | undefined\n        if (call.args && call.args.length > 0) {\n          try {\n            const parsed: unknown = JSON.parse(call.args)\n            if (isObject(parsed)) {\n              args = parsed\n            } else {\n              const receivedKind = Array.isArray(parsed)\n                ? 'array'\n                : parsed === null\n                  ? 'null'\n                  : typeof parsed\n              parseError = new E_OPENAI_RESPONSES_INVALID_TOOL_CALL_ARGS([\n                `must be a JSON object; received ${receivedKind}`,\n                call.args,\n              ])\n            }\n          } catch {\n            parseError = new E_OPENAI_RESPONSES_INVALID_TOOL_CALL_ARGS([\n              'are not valid JSON',\n              call.args,\n            ])\n          }\n        }\n        const completedAt = nowIso()\n        if (parseError !== undefined) {\n          const toolName = normalizeToolName(call.name)\n          const results = new Tokenizable(parseError.message)\n          helpers.reportToolCall(callId, { tool: toolName, args })\n          helpers.reportToolCall(callId, { results, isError: true, isComplete: true })\n          const checksum = computeChecksum(toolName, args)\n          await ctx.storeToolCall(\n            new ToolCall({\n              id: callId,\n              tool: toolName,\n              args,\n              checksum,\n              isComplete: true,\n              isError: true,\n              results,\n              createdAt: completedAt,\n              updatedAt: completedAt,\n              completedAt,\n            })\n          )\n          return\n        }\n        if (!tool) {\n          const toolName = normalizeToolName(call.name)\n          const available = ctx.tools\n            .all()\n            .map((t) => t.name)\n            .sort()\n          const errText =\n            available.length > 0\n              ? `Tool not found: ${toolName}. Available tools: ${available.join(', ')}.`\n              : `Tool not found: ${toolName}. No tools are available this turn.`\n          const results = new Tokenizable(errText)\n          helpers.reportToolCall(callId, { tool: toolName, args })\n          helpers.reportToolCall(callId, { results, isError: true, isComplete: true })\n          const checksum = computeChecksum(toolName, args)\n          await ctx.storeToolCall(\n            new ToolCall({\n              id: callId,\n              tool: toolName,\n              args,\n              checksum,\n              isComplete: true,\n              isError: true,\n              results,\n              createdAt: completedAt,\n              updatedAt: completedAt,\n              completedAt,\n            })\n          )\n          return\n        }\n        helpers.reportToolCall(callId, { tool: tool.name, args })\n        const isArtifactTool = ArtifactTool.isArtifactTool(tool)\n        let results: Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[] =\n          new Tokenizable('')\n        let toolHadError = false\n        try {\n          const raw = await tool.executor(ctx)(args)\n          if (isArtifactTool) {\n            if (Tokenizable.isTokenizable(raw)) {\n              results = raw\n            } else if (typeof raw === 'string') {\n              results = new Tokenizable(raw)\n            } else {\n              throw new Error(\n                `ArtifactTool \"${tool.name}\" returned a non-string/non-Tokenizable value`\n              )\n            }\n          } else if (Media.isMedia(raw)) {\n            results = raw\n          } else if (Array.isArray(raw) && raw.length > 0 && raw.every((m) => Media.isMedia(m))) {\n            results = raw as Media[]\n          } else if (looksLikeSpooledArtifact(raw)) {\n            results = raw as SpooledArtifact\n          } else if (typeof raw === 'string' || isInstanceOf(raw, 'Uint8Array', Uint8Array)) {\n            const reader = await spoolStore.write(callId, raw as string | Uint8Array)\n            const ArtifactCtor = (tool as Tool).artifactConstructor?.() ?? SpooledArtifact\n            results = new ArtifactCtor(reader)\n          } else {\n            const reader = await spoolStore.write(callId, String(raw))\n            const ArtifactCtor = (tool as Tool).artifactConstructor?.() ?? SpooledArtifact\n            results = new ArtifactCtor(reader)\n          }\n        } catch (err) {\n          toolHadError = true\n          let detailMsg = isError(err) ? err.message : String(err)\n          if (\n            isError(err) &&\n            isError(err.cause) &&\n            err.cause.message &&\n            err.cause.message !== err.message\n          ) {\n            detailMsg = `${detailMsg} ${err.cause.message}`\n          }\n          results = new Tokenizable(detailMsg)\n        }\n        helpers.reportToolCall(callId, { results, isError: toolHadError, isComplete: true })\n        const checksum = computeChecksum(tool.name, args)\n        const completedAt2 = nowIso()\n        await ctx.storeToolCall(\n          new ToolCall({\n            id: callId,\n            tool: tool.name,\n            args,\n            checksum,\n            isComplete: true,\n            isError: toolHadError,\n            results,\n            fromArtifactTool: isArtifactTool,\n            inline: isArtifactTool,\n            createdAt: completedAt2,\n            updatedAt: completedAt2,\n            completedAt: completedAt2,\n          })\n        )\n      }\n\n      // FALLBACK tool-call recovery — consulted only when the provider returned zero structured\n      // calls AND the caller opted in via `localToolCallParser`.\n      const parseFallbackToolCalls = (\n        content: string\n      ): Array<{ id: string; name: string; args: string }> => {\n        if (merged.localToolCallParser === undefined) return []\n        if (typeof content !== 'string' || content.length === 0) return []\n        const parser = resolveToolCallParser(merged.localToolCallParser)\n        const toolNames = ctx.tools.visible().map((t) => t.name)\n        return parser(content, { toolNames }).calls.map((c) => ({\n          id: uuidv6(),\n          name: c.name,\n          args: JSON.stringify(c.arguments),\n        }))\n      }\n\n      const selfIdentity = merged.selfIdentity ?? 'assistant'\n\n      // The wire shape a persisted reasoning item will actually REPLAY as, which is what the next\n      // turn's adjacency sweep hashes. Under `summary-only` the renderer strips `content` and\n      // `encrypted_content` (see `renderOpenAIResponsesReasoningItem`), so an accumulator that\n      // recorded the FULL item produced a prefix the sweep never reproduces and every later item\n      // dropped as stale. Building the replay shape here keeps persist and validate in agreement\n      // for every mode.\n      const replayShapeOf = (slot: {\n        itemId: string\n        summaryText: string\n        reasoningText: string\n        encryptedContent?: string\n      }): OpenAIResponsesInputItem => {\n        const summaryOnly = merged.reasoningReplay === 'summary-only'\n        return {\n          type: 'reasoning',\n          id: normalizeOpenAIResponsesItemId(slot.itemId, 'rs'),\n          summary:\n            slot.summaryText.length > 0 ? [{ type: 'summary_text', text: slot.summaryText }] : [],\n          ...(!summaryOnly && slot.reasoningText.length > 0\n            ? { content: [{ type: 'reasoning_text', text: slot.reasoningText }] }\n            : {}),\n          ...(!summaryOnly && slot.encryptedContent\n            ? { encrypted_content: slot.encryptedContent }\n            : {}),\n        }\n      }\n\n      // ── Persist a reasoning Thought from a finalized thinking slot ─────────\n      const persistThought = async (\n        slot: {\n          itemId: string\n          summaryText: string\n          reasoningText: string\n          encryptedContent?: string\n        },\n        pairedItemId: string | undefined,\n        // Explicit timestamp so a caller draining several slots can order them monotonically —\n        // see `stampFor` in the streaming drain. Defaults to \"now\" for the non-streaming path.\n        stamp: string = nowIso(),\n        // Items produced EARLIER IN THIS SAME RESPONSE that will sit between the request prefix\n        // and this reasoning item once the whole response is replayed on the next turn.\n        //\n        // Without this, a response carrying two or more reasoning items replayed only the FIRST.\n        // Every item's fingerprint was taken over the request prefix alone, but the next turn's\n        // adjacency sweep re-derives each candidate's hash through its OWN position — which for\n        // the second reasoning item includes the first reasoning item and its paired message. The\n        // hashes could not match, so every item after the first was dropped as stale.\n        precedingReplayItems: OpenAIResponsesInputItem[] = []\n      ): Promise<void> => {\n        const content = slot.reasoningText.length > 0 ? slot.reasoningText : slot.summaryText\n        let payload: OpenAIResponsesReasoningReplayPayload | undefined\n        if (merged.reasoningReplay !== 'off') {\n          const item: OpenAIResponsesReasoningItem = {\n            type: 'reasoning',\n            id: normalizeOpenAIResponsesItemId(slot.itemId, 'rs'),\n            summary:\n              slot.summaryText.length > 0 ? [{ type: 'summary_text', text: slot.summaryText }] : [],\n            ...(slot.reasoningText.length > 0\n              ? { content: [{ type: 'reasoning_text', text: slot.reasoningText }] }\n              : {}),\n            ...(slot.encryptedContent ? { encrypted_content: slot.encryptedContent } : {}),\n          }\n          const prefixFingerprint = await resolvedHelpers.fingerprintOpenAIResponsesPrefix({\n            model: merged.model,\n            instructions: assembled.instructions,\n            // Pass `assembled.tools` THROUGH, without an `?? []` fallback: the next turn's\n            // adjacency sweep re-derives this hash against the same `undefined`-when-empty shape.\n            // Coercing to `[]` here hashes different bytes than the sweep does and drops every\n            // replayed reasoning item as stale whenever no tools are registered.\n            tools: assembled.tools,\n            // Hash the sweep-visible request prefix PLUS whatever this same response already\n            // contributed ahead of this item (see `precedingReplayItems`). On the next turn the\n            // sweep hashes exactly this sequence when it reaches this item's position.\n            //\n            // `throughItem` is the length of that combined array: the sweep-visible region of the\n            // request (a trailing-bucket item is appended AFTER the sweep runs, so it is absent\n            // from every prefix the sweep hashes — including it here would guarantee a mismatch\n            // whenever `bucketOrder` puts a non-empty bucket after `'timeline'`) plus the\n            // preceding items from this response.\n            input: [\n              ...assembled.input.slice(0, assembled.fingerprintableLength),\n              ...precedingReplayItems,\n            ],\n            throughItem: assembled.fingerprintableLength + precedingReplayItems.length,\n          })\n          payload = {\n            variant: 'responses-reasoning',\n            item,\n            pairedItemId,\n            prefixFingerprint,\n          }\n        }\n        await ctx.storeThought(\n          new Thought({\n            id: slot.itemId,\n            content,\n            identity: selfIdentity,\n            payload,\n            replayCompatibility: payload ? 'openai-responses-reasoning-v1' : undefined,\n            createdAt: stamp,\n            updatedAt: stamp,\n          })\n        )\n      }\n\n      // ── Step 8: streaming path ────────────────────────────────────────────\n      if (stream) {\n        if (!response.body) {\n          ctx.nack(new E_OPENAI_RESPONSES_STREAM_ERROR(['response has no body']))\n          return\n        }\n        const reader = response.body.getReader()\n        const decoder = new TextDecoder()\n        const slotMachine = resolvedHelpers.createResponsesOutputSlotMachine()\n        const streamId = dispatchStreamId\n\n        let buffer = ''\n        let idleTimer: ReturnType<typeof setTimeout> | undefined\n        let stalled = false\n        let terminalSeen = false\n        let terminalStatus: OpenAIResponsesResponseObject['status'] | undefined\n        let incompleteReason: string | undefined\n        let finalUsage: OpenAIResponsesResponseObject['usage'] | undefined\n        let finalModel: string | undefined\n        let finalRaw: Record<string, unknown> = {}\n        const collectedToolCalls: Array<{ id: string; name: string; args: string }> = []\n        let sawMessageDelta = false\n\n        const idleMs = merged.streamIdleTimeoutMs ?? 0\n        const armIdleTimer = (): void => {\n          if (idleMs <= 0) return\n          if (idleTimer) clearTimeout(idleTimer)\n          idleTimer = setTimeout(() => {\n            stalled = true\n            helpers.log.warn({\n              kind: 'stream-idle-timeout',\n              message: `SSE stream went idle for ${idleMs}ms; cancelling`,\n              payload: { idleMs },\n            })\n            reader.cancel().catch(() => {\n              /* swallow */\n            })\n          }, idleMs)\n        }\n        const clearIdleTimer = (): void => {\n          if (idleTimer) {\n            clearTimeout(idleTimer)\n            idleTimer = undefined\n          }\n        }\n\n        const drainAndPersist = async (): Promise<void> => {\n          // Persist every open text / thinking slot.\n          const orderedIndices = Array.from(slotMachine.slots().keys()).sort((a, b) => a - b)\n          // Timestamps are derived MONOTONICALLY from each slot's position in output-index order,\n          // never from independent `nowIso()` calls. Two back-to-back `nowIso()` calls return an\n          // identical ISO string ~998 times in 1000, and `buildOpenAIResponsesInput` pushes\n          // messages into the timeline before thoughts and then stable-sorts by `createdAt` — so\n          // on a tie the assistant message sorted AHEAD of its own reasoning item, leaving that\n          // item last with nothing after it, and the adjacency sweep dropped it as unpaired. That\n          // made reasoning replay fail most of the time even under the default configuration.\n          const drainBaseMs = DateTime.now().toMillis()\n          // Same multi-reasoning accumulator as the non-streaming path: items from THIS response\n          // that will precede a later reasoning item once the whole response replays next turn.\n          const replayedSoFar: OpenAIResponsesInputItem[] = []\n          const stampFor = (pos: number): string =>\n            DateTime.fromMillis(drainBaseMs + pos).toISO() ??\n            new Date(drainBaseMs + pos).toISOString()\n          for (const [pos, idx] of orderedIndices.entries()) {\n            const slot = slotMachine.getSlot(idx)\n            if (!slot) continue\n            if (slot.kind === 'text') {\n              if (slot.text.length > 0 || slot.refusal.length > 0) {\n                sawMessageDelta = true\n                const text = slot.refusal.length > 0 ? slot.refusal : slot.text\n                helpers.reportMessage(slot.itemId || streamId, '', { isComplete: true })\n                await ctx.storeMessage(\n                  new Message({\n                    id: slot.itemId || streamId,\n                    role: 'assistant',\n                    content: text,\n                    identity: selfIdentity,\n                    createdAt: stampFor(pos),\n                    updatedAt: stampFor(pos),\n                  })\n                )\n                replayedSoFar.push({\n                  type: 'message',\n                  role: 'assistant',\n                  status: 'completed',\n                  id: slot.itemId || streamId,\n                  content: [{ type: 'output_text', text, annotations: [] }],\n                })\n              }\n            } else if (slot.kind === 'thinking') {\n              helpers.reportThought(slot.itemId || streamId, '', { isComplete: true })\n              // `pairedItemId` records the id of the item that FOLLOWS this reasoning item on the\n              // wire (per its own contract in types.ts) — look ahead to the next slot in output-index\n              // order, not back at whatever slot preceded this one.\n              const nextIdx = orderedIndices[pos + 1]\n              const nextSlot = nextIdx !== undefined ? slotMachine.getSlot(nextIdx) : undefined\n              const pairedItemId = nextSlot?.itemId\n              await persistThought(slot, pairedItemId, stampFor(pos), [...replayedSoFar])\n              replayedSoFar.push(replayShapeOf(slot))\n            } else if (slot.kind === 'toolCall') {\n              collectedToolCalls.push({\n                id: `${slot.callId}|${slot.itemId}`,\n                name: slot.name,\n                args: slot.args,\n              })\n            }\n          }\n\n          if (finalUsage !== undefined || terminalStatus !== undefined) {\n            const calls = collectedToolCalls.length > 0\n            helpers.reportGenerationStats(\n              extractGenerationStats({\n                model: finalModel ?? merged.model,\n                usage: finalUsage,\n                finishReason: mapStopReason(terminalStatus, incompleteReason, calls),\n                raw:\n                  Object.keys(finalRaw).length > 0\n                    ? finalRaw\n                    : { usage: finalUsage, status: terminalStatus },\n              })\n            )\n          }\n\n          const nativeCalls = collectedToolCalls\n          const combinedText = Array.from(slotMachine.slots().values())\n            .filter((s): s is Extract<typeof s, { kind: 'text' }> => s.kind === 'text')\n            .map((s) => (s.refusal.length > 0 ? s.refusal : s.text))\n            .join('')\n          const calls = nativeCalls.length > 0 ? nativeCalls : parseFallbackToolCalls(combinedText)\n\n          if (merged.onRawGeneration) {\n            try {\n              merged.onRawGeneration({\n                rawText: combinedText,\n                cleanedText: combinedText,\n                reasoning: Array.from(slotMachine.slots().values())\n                  .filter(\n                    (s): s is Extract<typeof s, { kind: 'thinking' }> => s.kind === 'thinking'\n                  )\n                  .map((s) => (s.reasoningText.length > 0 ? s.reasoningText : s.summaryText)),\n                toolCalls: calls.map((c) => {\n                  let parsedArgs: Record<string, unknown> = {}\n                  try {\n                    const p: unknown = JSON.parse(c.args || '{}')\n                    if (isObject(p)) parsedArgs = p as Record<string, unknown>\n                  } catch {\n                    /* leave args empty on unparseable JSON */\n                  }\n                  return { name: c.name, arguments: parsedArgs as never }\n                }),\n                streamed: true,\n                streamId: dispatchStreamId,\n              })\n            } catch {\n              /* observer errors are non-fatal */\n            }\n          }\n\n          helpers.log.debug({\n            kind: 'stream-finalised',\n            message: `Stream finalised: ${calls.length} tool call(s), message=${sawMessageDelta}`,\n            payload: { toolCallCount: calls.length, sawMessageDelta, terminalSeen },\n          })\n\n          if (calls.length === 0) {\n            if (merged.autoAck) ctx.ack()\n            return\n          }\n          for (const call of calls) {\n            if (ctx.abortSignal.aborted) return\n            await executeAndPersistToolCall(call)\n          }\n        }\n\n        // Processes one SSE frame's `data:` lines. Returns `'stop'` once a terminal event (or a\n        // fatal stream-level error) has been handled — the caller must stop reading and return\n        // immediately — or `'continue'` otherwise. Extracted so the SAME logic can run once more\n        // on whatever is left in `buffer` after EOF (Known finding: a final frame lacking its\n        // trailing blank-line separator was previously left unprocessed and silently dropped).\n        const processFrame = async (frame: string): Promise<'stop' | 'continue'> => {\n          // Per the SSE spec an event's `data:` FIELDS are concatenated (newline-separated) and the\n          // result parsed ONCE — a single JSON value may legally be split across several `data:`\n          // lines. Parsing each line independently produced two invalid JSON fragments and silently\n          // skipped both, losing the whole event. OpenAI does not split events today, but an\n          // intermediary may, exactly as one already forced the CRLF handling above.\n          //\n          // Concatenating per frame is a superset of the previous behaviour for the single-line\n          // case (one field joins to itself), so nothing that parsed before stops parsing.\n          const dataLines = frame\n            .split('\\n')\n            .filter((line) => line.startsWith('data:'))\n            .map((line) => line.slice(5).trim())\n          for (const data of dataLines.length > 1 ? [dataLines.join('\\n')] : dataLines) {\n            if (data.length === 0) continue\n            let payload: OpenAIResponsesStreamEvent\n            try {\n              payload = JSON.parse(data) as OpenAIResponsesStreamEvent\n            } catch {\n              helpers.log.trace({\n                kind: 'sse-parse-failure',\n                message: 'Failed to parse SSE chunk as JSON; skipping',\n                payload: { dataPreview: data.slice(0, 256) },\n              })\n              continue\n            }\n            // The union's structural fallback member (`OpenAIResponsesStreamEventBase &\n            // Record<string, unknown>`, covering every event type this battery does not act\n            // on) carries a loose `type: string`, which prevents TypeScript from narrowing the\n            // discriminant inside a `switch` the way it would for a \"closed\" union — the same\n            // issue documented in `helpers.ts`'s output-slot-machine `openSlot`/`finalizeSlot`.\n            // Cast to the specific event type inside each case rather than rely on narrowing.\n            switch (payload.type) {\n              case 'response.output_item.added': {\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.output_item.added' }\n                >\n                const slot = slotMachine.openSlot(ev.output_index, ev.item)\n                if (!slot) {\n                  helpers.log.debug({\n                    kind: 'unhandled-output-item',\n                    message: `No slot opened for output item type \"${ev.item.type}\" at index ${ev.output_index}`,\n                    payload: { itemType: ev.item.type, outputIndex: ev.output_index },\n                  })\n                }\n                break\n              }\n              case 'response.output_text.delta': {\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.output_text.delta' }\n                >\n                slotMachine.appendText(ev.output_index, ev.delta)\n                sawMessageDelta = true\n                helpers.reportMessage(String(ev.item_id || streamId), ev.delta)\n                break\n              }\n              case 'response.refusal.delta': {\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.refusal.delta' }\n                >\n                slotMachine.appendRefusal(ev.output_index, ev.delta)\n                sawMessageDelta = true\n                helpers.reportMessage(String(ev.item_id || streamId), ev.delta)\n                break\n              }\n              case 'response.reasoning_summary_text.delta': {\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.reasoning_summary_text.delta' }\n                >\n                slotMachine.appendReasoningSummary(ev.output_index, ev.delta)\n                helpers.reportThought(String(ev.item_id || streamId), ev.delta)\n                break\n              }\n              case 'response.reasoning_text.delta': {\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.reasoning_text.delta' }\n                >\n                slotMachine.appendReasoningText(ev.output_index, ev.delta)\n                helpers.reportThought(String(ev.item_id || streamId), ev.delta)\n                break\n              }\n              case 'response.function_call_arguments.delta': {\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.function_call_arguments.delta' }\n                >\n                slotMachine.appendFunctionCallArgumentsDelta(ev.output_index, ev.delta)\n                break\n              }\n              case 'response.function_call_arguments.done': {\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.function_call_arguments.done' }\n                >\n                slotMachine.setFunctionCallArgumentsDone(ev.output_index, ev.arguments)\n                break\n              }\n              case 'response.output_item.done': {\n                // The ONLY point at which a reasoning item's encrypted_content is captured\n                // (Known Gotcha #3) — never at `.added`, before it's populated.\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.output_item.done' }\n                >\n                slotMachine.finalizeSlot(ev.output_index, ev.item)\n                break\n              }\n              case 'response.completed':\n              case 'response.incomplete': {\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.completed' | 'response.incomplete' }\n                >\n                terminalSeen = true\n                terminalStatus = ev.response.status\n                incompleteReason = ev.response.incomplete_details?.reason ?? undefined\n                finalUsage = ev.response.usage\n                finalModel = ev.response.model\n                finalRaw = { ...ev.response } as unknown as Record<string, unknown>\n                // Backfill `encrypted_content` from the terminal event's own `response.output`\n                // for any reasoning item whose `.done` event omitted it.\n                const output = ev.response.output ?? []\n                for (const [i, item] of output.entries()) {\n                  if (item && item.type === 'reasoning') {\n                    const reasoningItem = item as OpenAIResponsesReasoningItem\n                    if (reasoningItem.encrypted_content) {\n                      slotMachine.backfillEncryptedContent(i, reasoningItem.encrypted_content)\n                    }\n                  }\n                }\n                clearIdleTimer()\n                await drainAndPersist()\n                return 'stop'\n              }\n              case 'response.failed': {\n                const ev = payload as Extract<\n                  OpenAIResponsesStreamEvent,\n                  { type: 'response.failed' }\n                >\n                terminalSeen = true\n                clearIdleTimer()\n                const msg = ev.response.error?.message ?? 'response.failed'\n                ctx.nack(new E_OPENAI_RESPONSES_STREAM_ERROR([msg]))\n                return 'stop'\n              }\n              case 'error': {\n                const ev = payload as Extract<OpenAIResponsesStreamEvent, { type: 'error' }>\n                terminalSeen = true\n                clearIdleTimer()\n                ctx.nack(new E_OPENAI_RESPONSES_STREAM_ERROR([ev.message]))\n                return 'stop'\n              }\n              default:\n                // Every other event type (response.created, .in_progress,\n                // content_part.added/.done, hosted-tool progress events, etc.) — not acted on.\n                break\n            }\n          }\n          return 'continue'\n        }\n\n        // `requestTimeoutMs` bounds the COMPLETE HTTP exchange, not just the headers. The\n        // per-attempt timer above is cleared as soon as `fetch` resolves — which happens on\n        // headers — so without this a response whose BODY then stalls waits forever whenever\n        // `streamIdleTimeoutMs` is unset (verified: with `requestTimeoutMs: 300` and a body that\n        // never yields a byte, the dispatch hung indefinitely). The deadline is measured from the\n        // START OF THE ATTEMPT (not from when headers arrived) and races every `reader.read()`,\n        // so slow headers and a slow body share one budget rather than getting one each.\n        const bodyTimeoutMs = merged.requestTimeoutMs ?? 0\n        const bodyDeadline = bodyTimeoutMs > 0 ? attemptStartedAtMs + bodyTimeoutMs : undefined\n        const readWithDeadline = async (): Promise<\n          ReadableStreamReadResult<Uint8Array> | 'timeout'\n        > => {\n          if (bodyDeadline === undefined) return reader.read()\n          const remaining = bodyDeadline - Date.now()\n          if (remaining <= 0) return 'timeout'\n          let timer: ReturnType<typeof setTimeout> | undefined\n          try {\n            return await Promise.race([\n              reader.read(),\n              new Promise<'timeout'>((resolve) => {\n                timer = setTimeout(() => resolve('timeout'), remaining)\n              }),\n            ])\n          } finally {\n            if (timer !== undefined) clearTimeout(timer)\n          }\n        }\n\n        try {\n          armIdleTimer()\n          while (true) {\n            const read = await readWithDeadline()\n            if (read === 'timeout') {\n              clearIdleTimer()\n              reader.cancel().catch(() => {\n                /* swallow */\n              })\n              helpers.log.warn({\n                kind: 'request-timeout',\n                message: `Response body exceeded requestTimeoutMs (${bodyTimeoutMs}ms) while streaming`,\n                payload: { requestTimeoutMs: bodyTimeoutMs },\n              })\n              ctx.nack(new E_OPENAI_RESPONSES_REQUEST_TIMEOUT([bodyTimeoutMs]))\n              return\n            }\n            const { done, value } = read\n            if (done) break\n            armIdleTimer()\n            if (ctx.abortSignal.aborted) {\n              clearIdleTimer()\n              return\n            }\n            buffer += decoder.decode(value, { stream: true })\n            let sepMatch = SSE_FRAME_SEPARATOR.exec(buffer)\n            while (sepMatch !== null) {\n              const frame = buffer.slice(0, sepMatch.index)\n              buffer = buffer.slice(sepMatch.index + sepMatch[0].length)\n              if ((await processFrame(frame)) === 'stop') return\n              sepMatch = SSE_FRAME_SEPARATOR.exec(buffer)\n            }\n          }\n          // EOF: flush the decoder's own internal state (a dangling multi-byte UTF-8 sequence split\n          // across the last two chunks) and process whatever is left in `buffer` as one final frame\n          // even without its own trailing blank-line separator — a terminal event (or any other\n          // event) arriving as the very last bytes of the stream, with no `\\n\\n` after it, was\n          // previously left sitting in `buffer` and silently dropped when the loop broke.\n          buffer += decoder.decode()\n          if (buffer.trim().length > 0) {\n            const finalFrame = buffer\n            buffer = ''\n            if ((await processFrame(finalFrame)) === 'stop') return\n          }\n          clearIdleTimer()\n          if (stalled) {\n            // DELIBERATE ASYMMETRY with the EOF path below: a stall DISCARDS accumulated state\n            // rather than draining it, even though both arrive here holding the same partial slots.\n            //\n            // The difference is what the two conditions tell you about the stream. EOF means the\n            // provider CLOSED it — the turn is over and whatever arrived is all there will ever be,\n            // so draining preserves a complete-if-short answer. A stall means the connection is\n            // still OPEN and simply quiet: more content may well be in flight, and the reader is\n            // being cancelled underneath it. Persisting a mid-sentence fragment as though it were\n            // the model's answer would put text into history that the model never finished, which\n            // the next turn would then treat as a completed assistant turn.\n            //\n            // The nack is therefore the whole outcome: the caller retries the turn rather than\n            // inheriting a truncated answer. Same treatment in `openai_chat_completions` and\n            // `anthropic_messages` — the convention was previously undocumented in all three,\n            // which reads as an oversight rather than a choice, so it is stated here.\n            ctx.nack(new E_OPENAI_RESPONSES_STREAM_STALLED([idleMs]))\n            return\n          }\n          if (!terminalSeen) {\n            helpers.log.warn({\n              kind: 'sse-eof-without-terminal-event',\n              message:\n                'SSE stream ended without a terminal event (response.completed/.incomplete/.failed); draining accumulated state',\n            })\n            await drainAndPersist()\n          }\n        } catch (err) {\n          clearIdleTimer()\n          if (ctx.abortSignal.aborted) return\n          if (stalled) {\n            ctx.nack(new E_OPENAI_RESPONSES_STREAM_STALLED([idleMs]))\n            return\n          }\n          helpers.log.error({\n            kind: 'stream-error',\n            message: `SSE stream failed: ${isError(err) ? err.message : String(err)}`,\n            payload: { detail: isError(err) ? err.message : String(err) },\n          })\n          ctx.nack(new E_OPENAI_RESPONSES_STREAM_ERROR([isError(err) ? err.message : String(err)]))\n          return\n        }\n        return\n      }\n\n      // ── Step 9: non-streaming path ────────────────────────────────────────\n      let parsed: OpenAIResponsesResponseObject\n      try {\n        // `response.json()` consumes the BODY, and the per-attempt timer was cleared the moment\n        // `fetch` resolved (which happens on headers) — so a response whose body then stalls hung\n        // forever here despite a configured `requestTimeoutMs`. Verified before fixing: with\n        // `requestTimeoutMs: 200` and a body that never yields a byte, the dispatch never returned.\n        //\n        // Bounded by the SAME whole-exchange deadline the streaming path uses (measured from\n        // `attemptStartedAtMs`, not from when headers arrived), so slow headers and a slow body\n        // share one budget rather than getting one each.\n        const jsonTimeoutMs = merged.requestTimeoutMs ?? 0\n        if (jsonTimeoutMs > 0) {\n          const remaining = attemptStartedAtMs + jsonTimeoutMs - Date.now()\n          let timer: ReturnType<typeof setTimeout> | undefined\n          const timedOut = Symbol('timeout')\n          const raced = await Promise.race([\n            response.json(),\n            new Promise<typeof timedOut>((resolve) => {\n              timer = setTimeout(() => resolve(timedOut), Math.max(0, remaining))\n            }),\n          ]).finally(() => {\n            if (timer !== undefined) clearTimeout(timer)\n          })\n          if (raced === timedOut) {\n            helpers.log.warn({\n              kind: 'request-timeout',\n              message: `Response body exceeded requestTimeoutMs (${jsonTimeoutMs}ms) while parsing`,\n              payload: { requestTimeoutMs: jsonTimeoutMs },\n            })\n            ctx.nack(new E_OPENAI_RESPONSES_REQUEST_TIMEOUT([jsonTimeoutMs]))\n            return\n          }\n          parsed = raced as OpenAIResponsesResponseObject\n        } else {\n          parsed = (await response.json()) as OpenAIResponsesResponseObject\n        }\n      } catch (err) {\n        ctx.nack(new E_OPENAI_RESPONSES_STREAM_ERROR([isError(err) ? err.message : String(err)]))\n        return\n      }\n\n      const output = parsed.output ?? []\n      const responseId = parsed.id ?? uuidv6()\n\n      const nativeCalls: Array<{ id: string; name: string; args: string }> = []\n      let combinedText = ''\n      // Same monotonic-timestamp scheme as the streaming drain: derive each persisted record's\n      // stamp from its position in `output` rather than calling `nowIso()` per item. Independent\n      // calls collide on the same millisecond ~998 times in 1000, and a tie lets the assistant\n      // message sort ahead of its own reasoning item (messages are pushed into the timeline before\n      // thoughts, then stable-sorted), orphaning it so the adjacency sweep drops it.\n      const outputBaseMs = DateTime.now().toMillis()\n      const stampAt = (pos: number): string =>\n        DateTime.fromMillis(outputBaseMs + pos).toISO() ??\n        new Date(outputBaseMs + pos).toISOString()\n      // Deliberately does NOT include `function_call`/`function_call_output` items from this\n      // response, despite a review finding asking for them. A `ToolCall` is stamped with\n      // `createdAt = completedAt` at EXECUTION time — after every item in the response that\n      // requested it — and `buildOpenAIResponsesInput` orders the timeline by `createdAt`. So an\n      // in-response tool call sorts AFTER the reasoning item, not before it. Verified on the wire:\n      // turn 2 assembled as `role:user | message | function_call | function_call_output`, with the\n      // tool call last. Adding it to the prefix would corrupt a hash that currently matches.\n      // Items from THIS response that will precede the next reasoning item once the whole response\n      // is replayed next turn, in the same wire shapes `buildOpenAIResponsesInput` emits: a\n      // replayed reasoning item verbatim, and own-assistant text as the OUTPUT-message shape\n      // (`renderOwnAssistantOutputItem`). Passed to `persistThought` so each item's fingerprint\n      // covers the prefix the adjacency sweep will actually see at its position — without it, only\n      // the first reasoning item in a multi-reasoning response ever replayed.\n      const replayedSoFar: OpenAIResponsesInputItem[] = []\n      for (const [i, item] of output.entries()) {\n        if (!item) continue\n        if (item.type === 'message') {\n          const msgItem = item as Extract<typeof item, { type: 'message' }>\n          const parts: string[] = []\n          let refusal = ''\n          for (const part of msgItem.content) {\n            if (part.type === 'output_text') parts.push(part.text)\n            else if (part.type === 'refusal') refusal = part.refusal\n          }\n          const text = refusal.length > 0 ? refusal : parts.join('')\n          combinedText += text\n          if (text.length > 0) {\n            const messageId = msgItem.id ?? `${responseId}:message:${i}`\n            helpers.reportMessage(messageId, text, { isComplete: true })\n            await ctx.storeMessage(\n              new Message({\n                id: messageId,\n                role: 'assistant',\n                content: text,\n                identity: selfIdentity,\n                createdAt: stampAt(i),\n                updatedAt: stampAt(i),\n              })\n            )\n            // Own-assistant text replays as the OUTPUT-message shape, so record it in that exact\n            // form for any later reasoning item's fingerprint prefix.\n            replayedSoFar.push({\n              type: 'message',\n              role: 'assistant',\n              status: 'completed',\n              id: messageId,\n              content: [{ type: 'output_text', text, annotations: [] }],\n            })\n          }\n        } else if (item.type === 'reasoning') {\n          const reasoningItem = item as OpenAIResponsesReasoningItem\n          const summaryText = (reasoningItem.summary ?? []).map((s) => s.text).join('\\n\\n')\n          const reasoningText = (reasoningItem.content ?? []).map((c) => c.text).join('\\n\\n')\n          const thoughtId = reasoningItem.id\n          helpers.reportThought(thoughtId, reasoningText.length > 0 ? reasoningText : summaryText, {\n            isComplete: true,\n          })\n          // `pairedItemId` records the id of the item that FOLLOWS this reasoning item on the wire\n          // (per its own contract in types.ts) — look ahead to the next output entry, not back at\n          // whatever preceded this one.\n          // `output[i + 1]` may be NULL, not merely undefined — the array is provider-supplied and\n          // its element type is nullable, which is exactly why the loop head guards with\n          // `if (!item) continue`. That guard does not cover this LOOKAHEAD: `'id' in null` throws\n          // `TypeError: Cannot use 'in' operator to search for 'id' in null`, killing the whole\n          // dispatch (no message persisted, no thought persisted, turn lost) whenever a null sits\n          // between a reasoning item and its paired output item. A truthiness check covers null and\n          // undefined together.\n          const nextItem = output[i + 1]\n          const pairedItemId = nextItem && 'id' in nextItem ? nextItem.id : undefined\n          await persistThought(\n            {\n              itemId: reasoningItem.id,\n              summaryText,\n              reasoningText,\n              ...(reasoningItem.encrypted_content\n                ? { encryptedContent: reasoningItem.encrypted_content }\n                : {}),\n            },\n            pairedItemId,\n            stampAt(i),\n            [...replayedSoFar]\n          )\n          // This item will itself precede any LATER reasoning item on replay.\n          replayedSoFar.push(\n            replayShapeOf({\n              itemId: reasoningItem.id,\n              summaryText,\n              reasoningText,\n              ...(reasoningItem.encrypted_content\n                ? { encryptedContent: reasoningItem.encrypted_content }\n                : {}),\n            })\n          )\n        } else if (item.type === 'function_call') {\n          const fcItem = item as OpenAIResponsesFunctionCallItem\n          nativeCalls.push({\n            id: fcItem.id ? `${fcItem.call_id}|${fcItem.id}` : fcItem.call_id,\n            name: fcItem.name,\n            args: fcItem.arguments,\n          })\n        } else {\n          // Hosted/unrecognized output item type — never replayed, debug-log only.\n          helpers.log.debug({\n            kind: 'unhandled-output-item',\n            message: `Unhandled output item type \"${item.type}\" at index ${i}`,\n            payload: { itemType: item.type, index: i },\n          })\n        }\n      }\n\n      if (isObject(parsed.usage) || typeof parsed.status === 'string') {\n        helpers.reportGenerationStats(\n          extractGenerationStats({\n            model: parsed.model ?? merged.model,\n            usage: parsed.usage,\n            finishReason: mapStopReason(\n              parsed.status,\n              parsed.incomplete_details?.reason ?? undefined,\n              nativeCalls.length > 0\n            ),\n            raw: { ...parsed } as unknown as Record<string, unknown>,\n          })\n        )\n      }\n\n      if (parsed.status === 'failed' || parsed.status === 'cancelled') {\n        const msg = parsed.error?.message ?? `response ${parsed.status}`\n        ctx.nack(new E_OPENAI_RESPONSES_STREAM_ERROR([msg]))\n        return\n      }\n\n      const calls = nativeCalls.length > 0 ? nativeCalls : parseFallbackToolCalls(combinedText)\n\n      if (merged.onRawGeneration) {\n        try {\n          merged.onRawGeneration({\n            rawText: combinedText,\n            cleanedText: combinedText,\n            reasoning: output\n              .filter((i): i is OpenAIResponsesReasoningItem => i?.type === 'reasoning')\n              .map(\n                (i) =>\n                  (i.content ?? []).map((c) => c.text).join('\\n\\n') ||\n                  (i.summary ?? []).map((s) => s.text).join('\\n\\n')\n              ),\n            toolCalls: calls.map((c) => {\n              let parsedArgs: Record<string, unknown> = {}\n              try {\n                const p: unknown = JSON.parse(c.args || '{}')\n                if (isObject(p)) parsedArgs = p as Record<string, unknown>\n              } catch {\n                /* leave args empty on unparseable JSON */\n              }\n              return { name: c.name, arguments: parsedArgs as never }\n            }),\n            streamed: false,\n            streamId: dispatchStreamId,\n          })\n        } catch {\n          /* observer errors are non-fatal */\n        }\n      }\n\n      if (calls.length === 0) {\n        if (merged.autoAck) ctx.ack()\n        return\n      }\n      for (const call of calls) {\n        if (ctx.abortSignal.aborted) return\n        await executeAndPersistToolCall(call)\n      }\n    }\n  }\n\n  /**\n   * Returns `true` when `value` is an {@link OpenAIResponsesAdapter} instance.\n   *\n   * @param value - The value to test.\n   * @returns `true` when `value` is an `OpenAIResponsesAdapter` instance.\n   */\n  public static isOpenAIResponsesAdapter(value: unknown): value is OpenAIResponsesAdapter {\n    return isInstanceOf(value, 'OpenAIResponsesAdapter', OpenAIResponsesAdapter)\n  }\n}\n"],"mappings":"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"}