{"version":3,"file":"helpers.mjs","names":[],"sources":["../../../../src/batteries/llm/openai_responses/helpers.ts"],"sourcesContent":["/**\n * Swappable translation helpers for rendering ADK state into OpenAI Responses requests.\n *\n * @module @nhtio/adk/batteries/llm/openai_responses/helpers\n *\n * @remarks\n * The swappable translation helpers that turn ADK primitives into OpenAI Responses wire shapes.\n * Each helper is exported under its unprefixed name AND under a `default*` alias so consumers can\n * compose partial overrides. Helpers that compose other helpers receive their dependents via\n * explicit input arguments — never via module-level closure — so a swap at any layer propagates\n * correctly.\n *\n * The wire-shape-AGNOSTIC helpers (`renderUntrustedContent`, `renderMemories`,\n * `renderChatCompletionsSystemPrompt`, `descriptionToChatCompletionsJsonSchema`,\n * `canonicalFingerprint`, …) live in the shared, internal `../chat_common/helpers` submodule and\n * are re-exported here under their original names so every existing import keeps resolving. Only\n * the Responses-WIRE-SPECIFIC helpers (media mapping, timeline-message rendering, tool-call-result\n * rendering, the `buildOpenAIResponsesInput` assembler, the reasoning-replay machinery, the\n * fingerprint wrapper, the tool-declaration translator, and the streaming output-slot state\n * machine) are defined here.\n */\n\nimport { v6 as uuidv6 } from 'uuid'\nimport { Media } from '@nhtio/adk/common'\nimport { E_OPENAI_RESPONSES_UNSUPPORTED_MEDIA_MODALITY } from './exceptions'\nimport {\n  escapeXmlAttribute,\n  memoryToAttrs,\n  retrievableToAttrs,\n  neutraliseDeveloperRulesTag,\n  sanitizeMimeType,\n  sanitizeFilenameForDescription,\n  floorTrustTier,\n  looksLikeSpooledArtifact,\n  canonicalFingerprint,\n  defaultRenderArtifactHandleBody,\n  defaultRenderRetrievableHandleBody,\n  // Bound locally (not just re-exported below) so the trust-boundary fallback can build the\n  // envelope with the DEFAULT renderer when a consumer's override swallows its body.\n  defaultRenderTrustedContent,\n  defaultRenderUntrustedContent,\n} from '../chat_common/helpers'\nimport type { DispatchContext } from '@nhtio/adk/types'\nimport type { ChatHelpersCommon } from '../chat_common/types'\n\nimport type {\n  Tool,\n  ArtifactTool,\n  Tokenizable,\n  Memory,\n  Message,\n  Thought,\n  ToolCall,\n  Retrievable,\n  SpooledArtifact,\n  MediaModalityHazard,\n  MediaStashEntry,\n} from '@nhtio/adk/common'\nimport type {\n  OpenAIResponsesInputContentBlock,\n  OpenAIResponsesInputItem,\n  OpenAIResponsesMessageItem,\n  OpenAIResponsesOutputMessageItem,\n  OpenAIResponsesFunctionCallItem,\n  OpenAIResponsesFunctionCallOutputItem,\n  OpenAIResponsesReasoningItem,\n  OpenAIResponsesTool,\n  OpenAIResponsesHelpers,\n  OpenAIResponsesReasoningReplayPayload,\n  ResponsesOutputSlot,\n  ResponsesOutputSlotMachine,\n  UnsupportedMediaPolicy,\n  JsonSchema,\n  ReasoningReplayMode,\n} from './types'\n\n/** De-collides a Responses id while preserving a valid `fc_` item discriminator. */\nexport const deCollideOpenAIResponsesToolCallIds = (id: string, ctx: DispatchContext): string => {\n  if (![...ctx.turnToolCalls].some((tc) => tc.id === id)) return id\n  const separator = id.indexOf('|')\n  if (separator < 0) return uuidv6()\n  const itemId = id.slice(separator + 1)\n  return itemId.startsWith('fc_') ? `${uuidv6()}|${itemId}` : uuidv6()\n}\n\n// ─── Re-exported wire-shape-agnostic helpers (shared submodule) ───────────────\n// These are defined once in `../chat_common/helpers` and shared with the other Chat-family\n// batteries. Re-exported here (bare + `default*`) so every existing\n// `@nhtio/adk/batteries/llm/openai_responses` import keeps resolving unchanged.\nexport {\n  descriptionToChatCompletionsJsonSchema,\n  defaultDescriptionToChatCompletionsJsonSchema,\n  renderUntrustedContent,\n  defaultRenderUntrustedContent,\n  renderTrustedContent,\n  defaultRenderTrustedContent,\n  renderStandingInstructions,\n  defaultRenderStandingInstructions,\n  neutraliseDeveloperRulesTag,\n  stripEnvelopeSpecialTokens,\n  sanitizeMimeType,\n  sanitizeFilenameForDescription,\n  floorTrustTier,\n  renderMemories,\n  defaultRenderMemories,\n  renderRetrievableSafetyDirective,\n  defaultRenderRetrievableSafetyDirective,\n  renderFirstPartyRetrievables,\n  defaultRenderFirstPartyRetrievables,\n  renderThirdPartyPublicRetrievables,\n  defaultRenderThirdPartyPublicRetrievables,\n  renderThirdPartyPrivateRetrievables,\n  defaultRenderThirdPartyPrivateRetrievables,\n  renderRetrievables,\n  defaultRenderRetrievables,\n  renderRetrievableHandleBody,\n  defaultRenderRetrievableHandleBody,\n  renderArtifactHandleBody,\n  defaultRenderArtifactHandleBody,\n  renderThought,\n  defaultRenderThought,\n  filterThoughts,\n  defaultFilterThoughts,\n  toolsToChatCompletionsTools,\n  defaultToolsToChatCompletionsTools,\n  renderChatCompletionsSystemPrompt,\n  defaultRenderChatCompletionsSystemPrompt,\n  canonicalFingerprint,\n  defaultCanonicalFingerprint,\n  looksLikeSpooledArtifact,\n} from '../chat_common/helpers'\n\n// ─── Media rendering (Responses content-block specific) ──────────────────────\n\nconst DEFAULT_STASH_FALLBACK_KEYS: ReadonlyArray<string> = [\n  'text:transcript',\n  'text:caption',\n  'text:description',\n]\n\nconst modalityHazardToAttr = (h: MediaModalityHazard): 'inert' | 'extractable' | 'opaque' => {\n  if (h === 'inert') return 'inert'\n  if (h === 'extractable-instructions') return 'extractable'\n  return 'opaque'\n}\n\nconst isMediaTextStashEntry = (e: unknown): e is MediaStashEntry => {\n  if (!e || typeof e !== 'object') return false\n  const r = e as Record<string, unknown>\n  return typeof r.value === 'string' && typeof r.trustTier === 'string'\n}\n\nconst resolveFallbackStash = (\n  media: Media,\n  keys: ReadonlyArray<string>\n): { text: string; entryTier: MediaStashEntry['trustTier'] } | undefined => {\n  for (const key of keys) {\n    const entry = media.stash.get(key)\n    if (isMediaTextStashEntry(entry)) {\n      return { text: entry.value as string, entryTier: entry.trustTier }\n    }\n  }\n  return undefined\n}\n\nconst renderTextInEnvelope = (\n  text: string,\n  args: {\n    trustTier: MediaStashEntry['trustTier']\n    modality: 'inert' | 'extractable' | 'opaque'\n    nonce: string\n    toolName: string | undefined\n    renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n    renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n  }\n): string => {\n  if (args.trustTier === 'first-party') {\n    return args.renderTrustedContent(text, {\n      nonce: args.nonce,\n      kind: 'media-fallback',\n      tool: args.toolName,\n      modality: args.modality,\n    })\n  }\n  return args.renderUntrustedContent(text, {\n    nonce: args.nonce,\n    kind: 'media-fallback',\n    tool: args.toolName,\n    modality: args.modality,\n  })\n}\n\nconst formatBytesHumanReadable = (bytes: number | undefined): string => {\n  if (bytes === undefined || !Number.isFinite(bytes)) return 'unknown size'\n  if (bytes < 1024) return `${bytes} B`\n  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`\n}\n\nconst renderSyntheticMediaDescription = (media: Media, byteLen: number | undefined): string =>\n  `[media: ${sanitizeFilenameForDescription(media.filename)}, ${sanitizeMimeType(media.mimeType, media.kind === 'image' ? media.kind : undefined)}, ${formatBytesHumanReadable(byteLen)}]`\n\n/**\n * The inline media id-marker rendered immediately BEFORE each media content block — see the\n * identical convention documented in `openai_chat_completions/helpers.ts`.\n */\nconst renderMediaIdMarker = (media: Media): string =>\n  `[media id: ${media.id} | ${sanitizeFilenameForDescription(media.filename)}]`\n\n/**\n * Implements {@link OpenAIResponsesHelpers.renderOpenAIResponsesMediaBlocks}.\n *\n * @remarks\n * `image` maps to `input_image` (a data URI). `document` maps to `input_file` using the\n * NOW-CONFIRMED `file_data: 'data:<mime>;base64,<b64>'` shape (a live probe against the real\n * Responses API accepted this exact shape with `filename` alongside it — see the battery's design\n * notes). `audio`/`video` — and any other kind/mime this battery cannot natively express — route\n * through `unsupportedMediaPolicy`, unchanged.\n */\nexport const renderOpenAIResponsesMediaBlocks = async (input: {\n  media: Media\n  unsupportedMediaPolicy: UnsupportedMediaPolicy\n  renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n  renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n  warn?: (msg: string) => void\n}): Promise<OpenAIResponsesInputContentBlock[]> => {\n  const { media, unsupportedMediaPolicy, warn } = input\n  const modality = modalityHazardToAttr(media.modalityHazard)\n\n  const fallbackPath = async (\n    keys: ReadonlyArray<string>,\n    allowSyntheticFallthrough: boolean\n  ): Promise<OpenAIResponsesInputContentBlock[]> => {\n    const fallback = resolveFallbackStash(media, keys)\n    if (fallback) {\n      const text = renderTextInEnvelope(fallback.text, {\n        trustTier: floorTrustTier(media.trustTier, fallback.entryTier),\n        modality,\n        nonce: media.id,\n        toolName: undefined,\n        renderTrustedContent: input.renderTrustedContent,\n        renderUntrustedContent: input.renderUntrustedContent,\n      })\n      return [{ type: 'input_text', text: `${renderMediaIdMarker(media)}\\n${text}` }]\n    }\n    if (!allowSyntheticFallthrough) {\n      warn?.(\n        `unsupportedMediaPolicy='fallback-stash' for ${media.filename}: no matching stash entry — falling through to synthetic description.`\n      )\n    }\n    const byteLen = await media.byteLength()\n    const text = renderTextInEnvelope(renderSyntheticMediaDescription(media, byteLen), {\n      trustTier: media.trustTier,\n      modality,\n      nonce: media.id,\n      toolName: undefined,\n      renderTrustedContent: input.renderTrustedContent,\n      renderUntrustedContent: input.renderUntrustedContent,\n    })\n    return [{ type: 'input_text', text: `${renderMediaIdMarker(media)}\\n${text}` }]\n  }\n\n  const unsupported = async (): Promise<OpenAIResponsesInputContentBlock[]> => {\n    if (unsupportedMediaPolicy === 'throw') {\n      throw new E_OPENAI_RESPONSES_UNSUPPORTED_MEDIA_MODALITY([\n        media.kind,\n        media.mimeType,\n        media.filename,\n      ])\n    }\n    if (\n      unsupportedMediaPolicy === 'fallback-stash' ||\n      (typeof unsupportedMediaPolicy === 'object' &&\n        unsupportedMediaPolicy.mode === 'fallback-stash')\n    ) {\n      const keys =\n        typeof unsupportedMediaPolicy === 'object'\n          ? unsupportedMediaPolicy.stashKeys\n          : DEFAULT_STASH_FALLBACK_KEYS\n      return fallbackPath(keys, false)\n    }\n    return fallbackPath([], true)\n  }\n\n  if (media.kind === 'image') {\n    const safeMime = sanitizeMimeType(media.mimeType, 'image')\n    const b64 = await media.asBase64()\n    return [\n      { type: 'input_text', text: renderMediaIdMarker(media) },\n      {\n        type: 'input_image',\n        detail: 'auto',\n        image_url: `data:${safeMime};base64,${b64}`,\n      },\n    ]\n  }\n\n  if (media.kind === 'document') {\n    const safeMime = sanitizeMimeType(media.mimeType)\n    const b64 = await media.asBase64()\n    return [\n      { type: 'input_text', text: renderMediaIdMarker(media) },\n      {\n        type: 'input_file',\n        filename: media.filename,\n        file_data: `data:${safeMime};base64,${b64}`,\n      },\n    ]\n  }\n\n  // audio / video — no native Responses representation (confirmed against the openai SDK's own\n  // type definitions: ResponseInputContent has no audio member, and no video member either).\n  return unsupported()\n}\n/** Default OpenAI Responses media renderer; alias of {@link renderOpenAIResponsesMediaBlocks}. */\nexport const defaultRenderOpenAIResponsesMediaBlocks = renderOpenAIResponsesMediaBlocks\n\n// ─── renderOpenAIResponsesTimelineMessage ─────────────────────────────────────\n\n/**\n * Implements {@link OpenAIResponsesHelpers.renderOpenAIResponsesTimelineMessage}.\n *\n * @remarks\n * A USER message, or a peer-identity ASSISTANT message (a message from an assistant identity that\n * is not this adapter's own `selfIdentity`), renders as a plain `role`-carrying input message item\n * — the ADK's own prior assistant turns are NOT routed through this renderer; the caller renders\n * those via {@link renderOpenAIResponsesOwnAssistantMessage} instead, into the OUTPUT-message shape\n * the reasoning-pairing validator expects (see the module's Known Gotchas).\n */\nexport const renderOpenAIResponsesTimelineMessage = async (input: {\n  message: Message\n  selfIdentity: string\n  unsupportedMediaPolicy: UnsupportedMediaPolicy\n  renderOpenAIResponsesMediaBlocks: OpenAIResponsesHelpers['renderOpenAIResponsesMediaBlocks']\n  renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n  renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n  warn?: (msg: string) => void\n}): Promise<OpenAIResponsesInputItem | null> => {\n  const { message, selfIdentity, unsupportedMediaPolicy, warn } = input\n  const identifier =\n    message.identity?.identifier !== undefined && message.identity?.identifier !== null\n      ? String(message.identity.identifier)\n      : ''\n  const representationRaw =\n    message.identity?.representation !== undefined && message.identity?.representation !== null\n      ? message.identity.representation.toString()\n      : ''\n  const representation = representationRaw.length > 0 ? representationRaw : identifier\n  const text = neutraliseDeveloperRulesTag(\n    message.content !== undefined ? message.content.toString() : ''\n  )\n  const createdAtStr = message.createdAt.toISO?.() ?? ''\n  const createdAtAttr = createdAtStr ? ` createdAt=\"${escapeXmlAttribute(createdAtStr)}\"` : ''\n\n  let envelopeText: string\n  const role: 'user' | 'assistant' = message.role\n  if (message.role === 'user') {\n    if (identifier.length === 0) {\n      envelopeText = text\n    } else {\n      const fromAttr = escapeXmlAttribute(representation)\n      envelopeText = `<message_${message.id} from=\"${fromAttr}\" role=\"user\"${createdAtAttr}>\\n${text}\\n</message_${message.id}>`\n    }\n  } else {\n    // Peer-identity assistant turn — the ADK's own assistant turns never reach this renderer.\n    const fromAttr = escapeXmlAttribute(representation)\n    envelopeText = `<peer_agent_output_${message.id} from=\"${fromAttr}\"${createdAtAttr}>\\n${text}\\n</peer_agent_output_${message.id}>`\n  }\n\n  const content: OpenAIResponsesInputContentBlock[] = []\n  if (envelopeText.length > 0) {\n    content.push({ type: 'input_text', text: envelopeText })\n  }\n  for (const media of message.attachments) {\n    const blocks = await input.renderOpenAIResponsesMediaBlocks({\n      media,\n      unsupportedMediaPolicy,\n      renderUntrustedContent: input.renderUntrustedContent,\n      renderTrustedContent: input.renderTrustedContent,\n      warn,\n    })\n    for (const b of blocks) content.push(b)\n  }\n  if (content.length === 0) return null\n  const out: OpenAIResponsesMessageItem = { role, content }\n  void selfIdentity\n  return out\n}\n/** Default timeline-message renderer; alias of {@link renderOpenAIResponsesTimelineMessage}. */\nexport const defaultRenderOpenAIResponsesTimelineMessage = renderOpenAIResponsesTimelineMessage\n\n// ─── renderOpenAIResponsesToolCallResult ──────────────────────────────────────\n\n/**\n * Implements {@link OpenAIResponsesHelpers.renderOpenAIResponsesToolCallResult}.\n *\n * @remarks\n * Renders a tool call's result(s) into the shape a `function_call_output` item's `output` field\n * accepts — either a plain string or an array of content blocks when the result carries media —\n * mirroring `openai_chat_completions/helpers.ts`'s `renderChatCompletionsToolCallResult` structure.\n */\nexport const renderOpenAIResponsesToolCallResult = async (input: {\n  toolCall: ToolCall\n  results: Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[]\n  tool: Tool | ArtifactTool | undefined\n  renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n  renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n  renderOpenAIResponsesMediaBlocks: OpenAIResponsesHelpers['renderOpenAIResponsesMediaBlocks']\n  renderArtifactHandleBody?: ChatHelpersCommon['renderArtifactHandleBody']\n  unsupportedMediaPolicy: UnsupportedMediaPolicy\n  warn?: (msg: string) => void\n}): Promise<string | OpenAIResponsesInputContentBlock[]> => {\n  const { toolCall, results, tool, warn, unsupportedMediaPolicy } = input\n  const isTrusted =\n    tool !== null && tool !== undefined && (tool as { trusted?: boolean }).trusted === true\n\n  if (tool === undefined) {\n    warn?.(\n      `Tool \"${toolCall.tool}\" is not present in the bound tool registry at render time; defaulting to untrusted envelope.`\n    )\n  }\n\n  const isMediaResult = Media.isMedia(results)\n  const isMediaArrayResult =\n    Array.isArray(results) && results.length > 0 && results.every((r) => Media.isMedia(r))\n  if (isMediaResult || isMediaArrayResult) {\n    const mediaList = isMediaResult ? [results as Media] : (results as Media[])\n    const blocks: OpenAIResponsesInputContentBlock[] = []\n    for (const media of mediaList) {\n      const rendered = await input.renderOpenAIResponsesMediaBlocks({\n        media,\n        unsupportedMediaPolicy,\n        renderTrustedContent: input.renderTrustedContent,\n        renderUntrustedContent: input.renderUntrustedContent,\n        warn,\n      })\n      for (const b of rendered) blocks.push(b)\n    }\n    // Trust framing for tool-returned NATIVE media. A native `input_image`/`input_file` cannot be\n    // wrapped in a text envelope without destroying the wire representation the provider needs, so\n    // the boundary is emitted as text blocks that BRACKET the native ones. Without this, an\n    // untrusted tool's image/document arrived preceded only by an id marker — making instructions\n    // embedded in the media indistinguishable from first-party attachments. The envelope is keyed\n    // on the TOOL's `trusted` flag (same basis as every textual branch below), not on the media's\n    // own tier: the question here is whether the tool that produced it is trusted.\n    //\n    // The envelope is rendered around a unique SENTINEL body rather than an empty one, then split\n    // on that sentinel. Going through the configured renderer (instead of hand-writing the tags)\n    // keeps a consumer's overridden `renderTrustedContent`/`renderUntrustedContent` authoritative;\n    // splitting on a sentinel — rather than on a newline — makes the split independent of whatever\n    // delimiter that renderer happens to use.\n    const sentinel = `__adk_media_boundary_${toolCall.checksum}__`\n    const envelope = isTrusted\n      ? input.renderTrustedContent(sentinel, {\n          nonce: toolCall.checksum,\n          kind: 'trusted-tool-result-media',\n          tool: toolCall.tool,\n        })\n      : input.renderUntrustedContent(sentinel, {\n          nonce: toolCall.checksum,\n          kind: 'tool-result-media',\n          tool: toolCall.tool,\n        })\n    const sentinelAt = envelope.indexOf(sentinel)\n    if (sentinelAt < 0) {\n      // A custom renderer dropped the body entirely, so its output cannot be split into an\n      // open/close pair. FAIL SAFE: fall back to the DEFAULT renderer to build the boundary rather\n      // than shipping the media unframed. Returning the bare blocks here (the previous behaviour)\n      // meant any consumer override that swallowed its body silently disabled the trust boundary\n      // on exactly the untrusted tool media it exists to frame — a security control must not\n      // degrade to \"off\" because a pluggable renderer misbehaved.\n      warn?.(\n        `Trust-envelope renderer did not emit its body for tool \"${toolCall.tool}\"; falling back to the default renderer so the trust boundary is still applied.`\n      )\n      const fallbackEnvelope = isTrusted\n        ? defaultRenderTrustedContent(sentinel, {\n            nonce: toolCall.checksum,\n            kind: 'trusted-tool-result-media',\n            tool: toolCall.tool,\n          })\n        : defaultRenderUntrustedContent(sentinel, {\n            nonce: toolCall.checksum,\n            kind: 'tool-result-media',\n            tool: toolCall.tool,\n          })\n      const at = fallbackEnvelope.indexOf(sentinel)\n      // The default renderers always emit their body, so `at` cannot be < 0 here; the guard is\n      // belt-and-braces so a future change to them can never reintroduce unframed media.\n      if (at >= 0) {\n        return [\n          { type: 'input_text', text: fallbackEnvelope.slice(0, at).trimEnd() },\n          ...blocks,\n          { type: 'input_text', text: fallbackEnvelope.slice(at + sentinel.length).trimStart() },\n        ]\n      }\n      return blocks\n    }\n    const openTag = envelope.slice(0, sentinelAt).trimEnd()\n    const closeTag = envelope.slice(sentinelAt + sentinel.length).trimStart()\n    return [\n      { type: 'input_text', text: openTag },\n      ...blocks,\n      { type: 'input_text', text: closeTag },\n    ]\n  }\n\n  if (Array.isArray(results)) {\n    const parts: string[] = []\n    for (const a of results) {\n      parts.push(await (a as SpooledArtifact).asString())\n    }\n    const joined = parts.join('\\n\\n')\n    return isTrusted\n      ? input.renderTrustedContent(joined, {\n          nonce: toolCall.checksum,\n          kind: 'trusted-tool-result',\n          tool: toolCall.tool,\n        })\n      : input.renderUntrustedContent(joined, {\n          nonce: toolCall.checksum,\n          kind: 'tool-result',\n          tool: toolCall.tool,\n        })\n  }\n\n  const isSpooled = looksLikeSpooledArtifact(results)\n\n  if (isSpooled && toolCall.inline === false) {\n    const artifact = results as SpooledArtifact\n    let byteLength = 0\n    let lineCount = 0\n    try {\n      byteLength = await artifact.byteLength()\n    } catch {\n      byteLength = 0\n    }\n    try {\n      lineCount = await artifact.lineCount()\n    } catch {\n      lineCount = 0\n    }\n    const body = (input.renderArtifactHandleBody ?? defaultRenderArtifactHandleBody)({\n      callId: toolCall.id,\n      artifact,\n      byteLength,\n      lineCount,\n    })\n    return input.renderUntrustedContent(body, {\n      nonce: toolCall.checksum,\n      kind: 'artifact-handle',\n      tool: toolCall.tool,\n    })\n  }\n\n  let body: string\n  if (isSpooled) {\n    body = await (results as SpooledArtifact).asString()\n  } else {\n    body = (results as Tokenizable).toString()\n  }\n\n  return isTrusted\n    ? input.renderTrustedContent(body, {\n        nonce: toolCall.checksum,\n        kind: 'trusted-tool-result',\n        tool: toolCall.tool,\n      })\n    : input.renderUntrustedContent(body, {\n        nonce: toolCall.checksum,\n        kind: 'tool-result',\n        tool: toolCall.tool,\n      })\n}\n/** Default tool-call-result renderer; alias of {@link renderOpenAIResponsesToolCallResult}. */\nexport const defaultRenderOpenAIResponsesToolCallResult = renderOpenAIResponsesToolCallResult\n\n// ─── toolsToOpenAIResponsesTools ───────────────────────────────────────────────\n\n/**\n * Implements {@link OpenAIResponsesHelpers.toolsToOpenAIResponsesTools}.\n *\n * @remarks\n * `name` is TOP-LEVEL, unlike Chat Completions' `{type:'function', function:{name, ...}}` nesting.\n * Reuses the shared, unmodified `descriptionToChatCompletionsJsonSchema` for the JSON Schema body —\n * only the envelope differs.\n */\nexport const toolsToOpenAIResponsesTools = (\n  tools: ReadonlyArray<Tool | ArtifactTool>,\n  deps: { descriptionToChatCompletionsJsonSchema: (d: unknown) => JsonSchema; strict?: boolean }\n): OpenAIResponsesTool[] =>\n  tools.map((tool) => {\n    const described = tool.describe()\n    const parameters = deps.descriptionToChatCompletionsJsonSchema(described.inputSchema)\n    return {\n      type: 'function' as const,\n      name: described.name,\n      description: described.description,\n      parameters:\n        parameters && Object.keys(parameters).length > 0\n          ? parameters\n          : { type: 'object', properties: {} },\n      ...(deps.strict !== undefined ? { strict: deps.strict } : {}),\n    }\n  })\n/** Default tool-translation helper; alias of {@link toolsToOpenAIResponsesTools}. */\nexport const defaultToolsToOpenAIResponsesTools = toolsToOpenAIResponsesTools\n\n// ─── fingerprintOpenAIResponsesPrefix ─────────────────────────────────────────\n\n/**\n * Implements {@link OpenAIResponsesHelpers.fingerprintOpenAIResponsesPrefix}.\n *\n * @remarks\n * Computes the fingerprint used for OpenAI Responses reasoning-item replay. The input is the exact\n * assembled request prefix: `model`, `instructions`, `tools`, and `input` through (but not\n * including) the item at `throughItem`. Assembles the Responses-shaped prefix object and delegates\n * canonicalisation + hashing to the shared, wire-agnostic {@link canonicalFingerprint} primitive —\n * mirroring `fingerprintAnthropicMessagesPrefix`'s shape-and-slice pattern exactly: object keys are\n * recursively sorted; array order and item boundaries are preserved.\n */\nexport const fingerprintOpenAIResponsesPrefix = async (input: {\n  model: string\n  instructions?: string\n  tools?: OpenAIResponsesTool[]\n  input: OpenAIResponsesInputItem[]\n  throughItem?: number\n}): Promise<string> => {\n  const items =\n    input.throughItem === undefined ? input.input : input.input.slice(0, input.throughItem)\n  return canonicalFingerprint({\n    model: input.model,\n    instructions: input.instructions,\n    tools: input.tools,\n    input: items,\n  })\n}\n\n// ─── renderOpenAIResponsesReasoningItem ───────────────────────────────────────\n\n/**\n * Implements {@link OpenAIResponsesHelpers.renderOpenAIResponsesReasoningItem}.\n *\n * @remarks\n * Converts an eligible stored {@link OpenAIResponsesReasoningReplayPayload} into a wire `reasoning`\n * item, or `undefined` if ineligible (no payload, wrong variant, or a stale fingerprint). The\n * adjacency-sweep pass in {@link buildOpenAIResponsesInput} is what actually enforces the\n * reasoning/output-item pairing constraint (Known Gotcha #1) — this function only validates the\n * signature/fingerprint half of eligibility.\n *\n * Under `reasoningReplay: 'summary-only'`, the returned item strips `content`\n * (full reasoning text) and `encrypted_content` — only `summary` is replayed. `'encrypted'` (or any\n * other non-`'off'` mode) returns the stored item verbatim.\n */\nexport const renderOpenAIResponsesReasoningItem = (input: {\n  thought: Thought\n  prefixFingerprint: string\n  replayCompatibility: ReadonlyArray<string>\n  reasoningReplay: ReasoningReplayMode\n  warn?: (msg: string) => void\n}): OpenAIResponsesReasoningItem | undefined => {\n  if (!input.replayCompatibility.includes(input.thought.replayCompatibility ?? '')) return undefined\n  const payload = input.thought.payload as\n    | Partial<OpenAIResponsesReasoningReplayPayload>\n    | undefined\n  if (!payload || payload.variant !== 'responses-reasoning' || !payload.item) return undefined\n  if (payload.prefixFingerprint !== input.prefixFingerprint) {\n    input.warn?.(\n      `Dropping stale OpenAI Responses reasoning signature for thought ${input.thought.id}.`\n    )\n    return undefined\n  }\n  if (input.reasoningReplay === 'summary-only') {\n    const summaryOnly: OpenAIResponsesReasoningItem = { ...payload.item }\n    delete summaryOnly.content\n    delete summaryOnly.encrypted_content\n    return summaryOnly\n  }\n  return payload.item\n}\n/** Default reasoning-item renderer; alias of {@link renderOpenAIResponsesReasoningItem}. */\nexport const defaultRenderOpenAIResponsesReasoningItem = renderOpenAIResponsesReasoningItem\n\n// ─── buildOpenAIResponsesInput ─────────────────────────────────────────────────\n\ntype TimelineItem =\n  | { kind: 'message'; at: number; value: Message }\n  | { kind: 'thought'; at: number; value: Thought }\n  | { kind: 'toolCall'; at: number; value: ToolCall }\n\n/** Renders the ADK's OWN prior assistant text into the OUTPUT-message shape (see the module docs). */\nconst renderOwnAssistantOutputItem = (\n  message: Message\n): OpenAIResponsesOutputMessageItem | null => {\n  const text = neutraliseDeveloperRulesTag(message.content?.toString() ?? '')\n  if (text.length === 0) return null\n  return {\n    type: 'message',\n    role: 'assistant',\n    status: 'completed',\n    // Normalized, not passed through. `Message.id` is application-generated and unconstrained,\n    // while a Responses item id must satisfy the provider's charset and 64-character limit — an\n    // oversized or oddly-charactered id gets the whole continuation request rejected. This is the\n    // same normalization already applied to replayed reasoning item ids.\n    id: normalizeOpenAIResponsesItemId(message.id),\n    content: [{ type: 'output_text', text, annotations: [] }],\n  }\n}\n\n/**\n * Splits an ADK composite tool-call id (`` `${callId}|${itemId}` ``, per the plan's composite-id\n * convention) into its `call_id`/item-`id` parts. Drops a non-`fc_`-prefixed item id rather than\n * send an invalid one — the item id half is only ever meaningful when it came from a genuine prior\n * Responses `function_call` item.\n */\nconst splitCompositeToolCallId = (id: string): { callId: string; itemId: string | undefined } => {\n  if (!id.includes('|')) return { callId: id, itemId: undefined }\n  const [callId, itemId] = id.split('|')\n  if (!callId) return { callId: id, itemId: undefined }\n  if (!itemId || !itemId.startsWith('fc_')) return { callId, itemId: undefined }\n  return { callId, itemId }\n}\n\n/**\n * Implements {@link OpenAIResponsesHelpers.buildOpenAIResponsesInput}.\n *\n * @remarks\n * Algorithm (mirrors the plan's Part 2 spec exactly):\n *\n * 1. Leading `instructions` (or leading `developer`/`system`-role item, per `systemPromptChannel`)\n *    — ALWAYS ADK-rendered via `renderChatCompletionsSystemPrompt`; there is no consumer-facing\n *    escape hatch.\n * 2. Timeline: messages/thoughts/tool-calls merged and sorted by `createdAt`. A tool call renders\n *    as two SIBLING top-level items (`function_call` then `function_call_output`), with composite\n *    id splitting. A thought replays as a native `reasoning` item only when `reasoningReplay !==\n *    'off'` and a valid, prefix-matched signature exists; otherwise it renders as plain text.\n * 3. Reasoning-pairing enforcement pass — walks `input` left to right, dropping any `reasoning`\n *    item not immediately followed by its paired output item, and stripping the `id` from an\n *    output item whose paired reasoning item was just dropped.\n * 4. Trailing buckets (`bucketOrder` labels after `'timeline'`) render as a trailing\n *    `{type:'message', role:'system', ...}` item.\n *\n * ## Load-bearing invariants\n *\n * These are consequences of the step ORDER above, not incidental details. Both were unwritten\n * once, and both were violated in ways that silently disabled reasoning replay — so they are\n * stated here explicitly and pinned by executable tests (see\n * `tests/unit/batteries/llm/openai_responses/reasoning_replay.cross.spec.ts`, \"assembly\n * invariants\").\n *\n * 1. **The step-3 sweep only ever sees a PREFIX of the final `input`.** Step 4 appends the\n *    trailing bucket AFTER the sweep has run, so any item added there is invisible to every\n *    fingerprint the sweep computes. A reasoning-replay fingerprint must therefore cover only the\n *    sweep-visible region — that is what the returned `fingerprintableLength` marks, and why\n *    `persistThought` passes it as `throughItem`. Hashing the whole `input` instead cannot match\n *    on the next turn whenever a trailing bucket exists, and drops every replayed item as stale.\n *\n * 2. **A reasoning item must sort STRICTLY BEFORE the output item it is paired with.** The step-2\n *    timeline pushes messages before thoughts and then applies a STABLE sort by `createdAt`, so on\n *    an identical timestamp the message wins the tie and lands ahead of its own reasoning item —\n *    leaving that item unpaired, and the step-3 sweep drops it. Callers persisting a thought and\n *    its message from one response must therefore assign strictly increasing timestamps rather\n *    than calling a clock twice (two `DateTime.now()` calls collide ~998 times in 1000).\n *\n * 3. **`tools` is `undefined`, never `[]`, when the registry is empty** (see the return shape).\n *    Fingerprints on both the persist and validate side must use that same shape:\n *    `canonicalFingerprint` serialises `undefined` and `[]` to different bytes, so coercing on one\n *    side only makes every hash mismatch for tool-less agents.\n */\nexport const buildOpenAIResponsesInput = async (\n  input: Parameters<OpenAIResponsesHelpers['buildOpenAIResponsesInput']>[0]\n): Promise<Awaited<ReturnType<OpenAIResponsesHelpers['buildOpenAIResponsesInput']>>> => {\n  const tools = input.toolsToOpenAIResponsesTools(input.tools.visible(), {\n    descriptionToChatCompletionsJsonSchema: (d: unknown) =>\n      input.descriptionToChatCompletionsJsonSchema(d as never),\n    strict: input.strict,\n  })\n\n  // ── Step 1: leading system content ──────────────────────────────────────────\n  const leadingSystemText = await input.renderChatCompletionsSystemPrompt({\n    systemPrompt: input.systemPrompt,\n    // Forwarded so a dynamic `systemPrompt` resolves against the live dispatch context rather\n    // than `undefined`.\n    renderCtx: input.renderCtx,\n    standingInstructions: input.standingInstructions,\n    memories: input.memories,\n    retrievables: input.retrievables,\n    bucketOrder: input.bucketOrder,\n    renderStandingInstructions: input.renderStandingInstructions,\n    renderMemories: input.renderMemories,\n    renderRetrievables: input.renderRetrievables,\n    renderRetrievableHandleBody: input.renderRetrievableHandleBody,\n    renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n    renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n    renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n    renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n    renderUntrustedContent: input.renderUntrustedContent,\n  })\n\n  const items: OpenAIResponsesInputItem[] = []\n  let instructions: string | undefined\n  if (leadingSystemText.length > 0) {\n    if (input.systemPromptChannel === 'instructions') {\n      instructions = leadingSystemText\n    } else {\n      const role = input.systemPromptChannel === 'system-item' ? 'system' : 'developer'\n      items.push({ role, content: [{ type: 'input_text', text: leadingSystemText }] })\n    }\n  }\n\n  // ── Step 2: timeline ─────────────────────────────────────────────────────────\n  const buckets = input.bucketOrder\n  const timelineIdx = buckets.indexOf('timeline')\n  const includesTimeline = timelineIdx !== -1\n\n  // Track which reasoning items are candidates for the adjacency-sweep pass (step 3): the item\n  // itself, plus the thought it came from (for warn messages).\n  const reasoningCandidates: Array<{ item: OpenAIResponsesReasoningItem; thought: Thought }> = []\n\n  if (includesTimeline) {\n    const filteredThoughts = input.filterThoughts(\n      input.thoughts,\n      input.thoughtSurfacing,\n      input.selfIdentity,\n      input.replayCompatibility\n    )\n\n    const timeline: TimelineItem[] = []\n    for (const m of input.messages)\n      timeline.push({ kind: 'message', at: m.createdAt.toMillis(), value: m })\n    for (const t of filteredThoughts)\n      timeline.push({ kind: 'thought', at: t.createdAt.toMillis(), value: t })\n    for (const tc of input.toolCalls)\n      timeline.push({ kind: 'toolCall', at: tc.createdAt.toMillis(), value: tc })\n    timeline.sort((a, b) => a.at - b.at)\n\n    for (const entry of timeline) {\n      if (entry.kind === 'message') {\n        const m = entry.value\n        const identifier = String(m.identity?.identifier ?? '')\n        const isOwnOutput = m.role === 'assistant' && identifier === input.selfIdentity\n        if (isOwnOutput) {\n          const rendered = renderOwnAssistantOutputItem(m)\n          if (rendered) items.push(rendered)\n          for (const media of m.attachments) {\n            // Own-output attachments are rare in practice (assistant turns don't normally carry\n            // media), but rendered as trailing input_image/input_file blocks on a plain input\n            // message rather than lost, since the output-message shape has no attachment slot.\n            const blocks = await input.renderOpenAIResponsesMediaBlocks({\n              media,\n              unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n              renderUntrustedContent: input.renderUntrustedContent,\n              renderTrustedContent: input.renderTrustedContent,\n              warn: input.warn,\n            })\n            if (blocks.length > 0) items.push({ role: 'user', content: blocks })\n          }\n        } else {\n          const rendered = await input.renderOpenAIResponsesTimelineMessage({\n            message: m,\n            selfIdentity: input.selfIdentity,\n            unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n            renderOpenAIResponsesMediaBlocks: input.renderOpenAIResponsesMediaBlocks,\n            renderUntrustedContent: input.renderUntrustedContent,\n            renderTrustedContent: input.renderTrustedContent,\n            warn: input.warn,\n          })\n          if (rendered) items.push(rendered)\n        }\n      } else if (entry.kind === 'toolCall') {\n        const tc = entry.value\n        const { callId, itemId } = splitCompositeToolCallId(tc.id)\n        const functionCallItem: OpenAIResponsesFunctionCallItem = {\n          type: 'function_call',\n          call_id: callId,\n          name: tc.tool,\n          arguments: typeof tc.args === 'string' ? tc.args : JSON.stringify(tc.args ?? {}),\n          ...(itemId !== undefined ? { id: itemId } : {}),\n        }\n        items.push(functionCallItem)\n\n        let rendered = input.renderedToolCallResults.get(tc)\n        if (rendered === undefined) {\n          const tool = input.tools.get(tc.tool)\n          rendered = await input.renderOpenAIResponsesToolCallResult({\n            toolCall: tc,\n            results: tc.results as\n              | Tokenizable\n              | SpooledArtifact\n              | SpooledArtifact[]\n              | Media\n              | Media[],\n            tool,\n            renderUntrustedContent: input.renderUntrustedContent,\n            renderTrustedContent: input.renderTrustedContent,\n            renderOpenAIResponsesMediaBlocks: input.renderOpenAIResponsesMediaBlocks,\n            unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n            warn: input.warn,\n          })\n        }\n        const outputItem: OpenAIResponsesFunctionCallOutputItem = {\n          type: 'function_call_output',\n          call_id: callId,\n          output: rendered,\n        }\n        items.push(outputItem)\n      } else {\n        // thought\n        const thought = entry.value\n        const identifier = String(thought.identity?.identifier ?? '')\n        const isSelf = identifier === input.selfIdentity\n\n        let reasoningItem: OpenAIResponsesReasoningItem | undefined\n        if (input.reasoningReplay !== 'off') {\n          const payload = thought.payload as\n            | Partial<OpenAIResponsesReasoningReplayPayload>\n            | undefined\n          const prefixFingerprint =\n            typeof payload?.prefixFingerprint === 'string' ? payload.prefixFingerprint : ''\n          reasoningItem = input.renderOpenAIResponsesReasoningItem({\n            thought,\n            prefixFingerprint,\n            replayCompatibility: input.replayCompatibility,\n            reasoningReplay: input.reasoningReplay,\n            // Suppress the stale-signature warning here — the real validity check (against the\n            // ACTUAL prefix through this item's position) happens in the second pass below, which\n            // is where a definitive drop-and-warn decision belongs.\n            warn: undefined,\n          })\n        }\n        if (reasoningItem) {\n          items.push(reasoningItem)\n          reasoningCandidates.push({ item: reasoningItem, thought })\n        } else if (thought.payload === undefined) {\n          const text = input.renderThought(thought.content.toString(), {\n            nonce: thought.id,\n            kind: isSelf ? 'self-reasoning' : 'peer-reasoning',\n            from: identifier,\n            createdAt: thought.createdAt?.toISO?.() ?? undefined,\n          })\n          items.push({ role: 'assistant', content: [{ type: 'input_text', text }] })\n        }\n        // else: opaque, non-replayable, non-matching → elided (mirrors the Anthropic battery).\n      }\n    }\n  }\n\n  // ── Step 3: reasoning-pairing enforcement pass ──────────────────────────────\n  // Walk left to right; a `reasoning` item is only ever valid on the wire when it is IMMEDIATELY\n  // followed by its own paired output item (Known Gotcha #1 — openai/openai-node#1791). Re-derive\n  // the fingerprint through THIS item's actual position in the fully-assembled `items` array (not\n  // the position it was tentatively rendered at above, which may have shifted if an earlier\n  // reasoning item was dropped) and re-validate against the payload's own recorded pairing.\n  if (reasoningCandidates.length > 0) {\n    const dropIndices = new Set<number>()\n    // Id-strips are RECORDED here and applied after the loop. Applying them inline replaced\n    // `items[idx + 1]` with a new object, which broke `items.indexOf(candidate.item)` identity for\n    // any candidate that happened to BE that neighbour: its lookup returned -1, the `continue`\n    // skipped it, and it was never validated — so a stale reasoning item could reach the wire\n    // unchecked, the exact 400 this sweep exists to prevent.\n    const idStripIndices = new Set<number>()\n    for (const candidate of reasoningCandidates) {\n      const idx = items.indexOf(candidate.item)\n      if (idx < 0) continue\n      const payload = candidate.thought.payload as\n        | Partial<OpenAIResponsesReasoningReplayPayload>\n        | undefined\n      const prefixFingerprint = await input.fingerprintOpenAIResponsesPrefix({\n        model: input.model,\n        instructions,\n        // Hash the tools EXACTLY as this function returns them on the wire (`undefined` when the\n        // registry is empty, per the return shape below) — not the local `tools` array, which is\n        // always a real array. `canonicalFingerprint` emits `undefined` and `[]` as different\n        // bytes, so hashing the local array here while `persistThought` hashes the returned\n        // `assembled.tools` made every reasoning item drop as stale whenever no tools were\n        // registered, even with a byte-identical prefix.\n        tools: tools.length > 0 ? tools : undefined,\n        input: items,\n        throughItem: idx,\n      })\n      const nextItem = items[idx + 1]\n      const nextItemId = nextItem !== undefined && 'id' in nextItem ? nextItem.id : undefined\n      const pairingOk =\n        typeof payload?.prefixFingerprint === 'string' &&\n        payload.prefixFingerprint === prefixFingerprint &&\n        nextItem !== undefined &&\n        (payload.pairedItemId === undefined || nextItemId === payload.pairedItemId)\n      if (!pairingOk) {\n        input.warn?.(\n          `Dropping OpenAI Responses reasoning item for thought ${candidate.thought.id}: ${\n            nextItem === undefined\n              ? 'no paired output item follows it'\n              : payload?.pairedItemId !== undefined && nextItemId !== payload.pairedItemId\n                ? 'the following item is not its recorded pairing partner'\n                : 'stale or missing prefix fingerprint'\n          }.`\n        )\n        dropIndices.add(idx)\n        // Record (do NOT yet apply) the id-strip on the paired output item — an id-less item is\n        // not subject to the pairing check, so the request stays valid once its reasoning partner\n        // is gone. Deferred so this loop never mutates the array it is indexing into.\n        if (nextItem !== undefined && 'id' in nextItem && nextItem.id !== undefined) {\n          idStripIndices.add(idx + 1)\n        }\n      }\n    }\n    // Apply the recorded id-strips now that every candidate has been validated against a stable\n    // `items` array.\n    for (const stripIdx of idStripIndices) {\n      const target = items[stripIdx]\n      if (target === undefined) continue\n      const stripped: Record<string, unknown> = { ...target }\n      delete stripped.id\n      items[stripIdx] = stripped as unknown as OpenAIResponsesInputItem\n    }\n    if (dropIndices.size > 0) {\n      for (let i = items.length - 1; i >= 0; i--) {\n        if (dropIndices.has(i)) items.splice(i, 1)\n      }\n    }\n  }\n\n  // Everything appended from here on is INVISIBLE to the adjacency sweep above, so it must not\n  // enter a reasoning-replay fingerprint — see `fingerprintableLength` on the return value.\n  const fingerprintableLength = items.length\n\n  // ── Step 4: trailing buckets ─────────────────────────────────────────────────\n  if (includesTimeline) {\n    const trailingParts: string[] = []\n    for (let i = timelineIdx + 1; i < buckets.length; i++) {\n      const label = buckets[i]!\n      if (label === 'standingInstructions') {\n        const block = input.renderStandingInstructions(input.standingInstructions)\n        if (block.length > 0) trailingParts.push(block)\n      } else if (label === 'memories') {\n        const wrapped: Array<{ memory: Memory; attrs: ReturnType<typeof memoryToAttrs>['attrs'] }> =\n          []\n        for (const m of input.memories) wrapped.push(memoryToAttrs(m))\n        const block = input.renderMemories(wrapped)\n        if (block.length > 0) trailingParts.push(block)\n      } else if (label === 'retrievables') {\n        const wrapped: Array<{\n          retrievable: Retrievable\n          attrs: ReturnType<typeof retrievableToAttrs>['attrs']\n        }> = []\n        for (const r of input.retrievables) wrapped.push(retrievableToAttrs(r))\n        const block = await input.renderRetrievables(wrapped, {\n          renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n          renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n          renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n          renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n          renderUntrustedContent: input.renderUntrustedContent,\n        })\n        if (block.length > 0) trailingParts.push(block)\n      }\n    }\n    if (trailingParts.length > 0) {\n      items.push({\n        role: 'system',\n        content: [{ type: 'input_text', text: trailingParts.join('\\n\\n') }],\n      })\n    }\n  }\n\n  return {\n    ...(instructions !== undefined ? { instructions } : {}),\n    input: items,\n    ...(tools.length > 0 ? { tools } : {}),\n    fingerprintableLength,\n  }\n}\n/** Default history assembler; alias of {@link buildOpenAIResponsesInput}. */\nexport const defaultBuildOpenAIResponsesInput = buildOpenAIResponsesInput\n\n// ─── Output-slot state machine ─────────────────────────────────────────────────\n\n/**\n * Implements {@link OpenAIResponsesHelpers.createResponsesOutputSlotMachine}.\n *\n * @remarks\n * Streaming state keyed by `output_index` (one slot per output item — NOT a tool-call `index`,\n * unlike Chat Completions). `openSlot` deliberately opens NO slot for an unrecognized/hosted\n * server-side tool item type (`web_search_call`, `code_interpreter_call`, `mcp_call`, etc.) — Known\n * Gotcha #6 — so every subsequent event keyed to that `output_index` is silently ignored rather\n * than crashing on an unexpected slot kind.\n */\nexport const createResponsesOutputSlotMachine = (): ResponsesOutputSlotMachine => {\n  const slots = new Map<number, ResponsesOutputSlot>()\n\n  return {\n    openSlot(outputIndex, rawItem) {\n      let slot: ResponsesOutputSlot | undefined\n      if (rawItem.type === 'message') {\n        const item = rawItem as OpenAIResponsesOutputMessageItem\n        slot = { kind: 'text', itemId: item.id ?? `idx-${outputIndex}`, text: '', refusal: '' }\n      } else if (rawItem.type === 'reasoning') {\n        const item = rawItem as OpenAIResponsesReasoningItem\n        slot = {\n          kind: 'thinking',\n          itemId: item.id,\n          summaryText: '',\n          reasoningText: '',\n          ...(item.encrypted_content ? { encryptedContent: item.encrypted_content } : {}),\n        }\n      } else if (rawItem.type === 'function_call') {\n        const item = rawItem as OpenAIResponsesFunctionCallItem\n        slot = {\n          kind: 'toolCall',\n          itemId: item.id ?? `idx-${outputIndex}`,\n          callId: item.call_id,\n          name: item.name,\n          args: item.arguments ?? '',\n        }\n      } else {\n        // Hosted/unrecognized item type — no slot; caller's responsibility to debug-log.\n        return undefined\n      }\n      slots.set(outputIndex, slot)\n      return slot\n    },\n    getSlot(outputIndex) {\n      return slots.get(outputIndex)\n    },\n    appendText(outputIndex, delta) {\n      const slot = slots.get(outputIndex)\n      if (slot && slot.kind === 'text') slot.text += delta\n    },\n    appendRefusal(outputIndex, delta) {\n      const slot = slots.get(outputIndex)\n      if (slot && slot.kind === 'text') slot.refusal += delta\n    },\n    appendReasoningSummary(outputIndex, delta) {\n      const slot = slots.get(outputIndex)\n      if (slot && slot.kind === 'thinking') slot.summaryText += delta\n    },\n    appendReasoningText(outputIndex, delta) {\n      const slot = slots.get(outputIndex)\n      if (slot && slot.kind === 'thinking') slot.reasoningText += delta\n    },\n    appendFunctionCallArgumentsDelta(outputIndex, delta) {\n      const slot = slots.get(outputIndex)\n      if (slot && slot.kind === 'toolCall') slot.args += delta\n    },\n    setFunctionCallArgumentsDone(outputIndex, args) {\n      const slot = slots.get(outputIndex)\n      if (slot && slot.kind === 'toolCall') slot.args = args\n    },\n    finalizeSlot(outputIndex, rawItem) {\n      const slot = slots.get(outputIndex)\n      if (!slot) return\n      if (slot.kind === 'text' && rawItem.type === 'message') {\n        const item = rawItem as OpenAIResponsesOutputMessageItem\n        const textParts: string[] = []\n        for (const part of item.content) {\n          if (part.type === 'output_text') textParts.push(part.text)\n          else if (part.type === 'refusal') slot.refusal = part.refusal\n        }\n        if (textParts.length > 0) slot.text = textParts.join('')\n        if (item.id !== undefined) slot.itemId = item.id\n      } else if (slot.kind === 'thinking' && rawItem.type === 'reasoning') {\n        // The ONLY point at which a reasoning item's encrypted_content/signature is captured —\n        // NEVER at `.added`, before it's populated (Known Gotcha #3).\n        const item = rawItem as OpenAIResponsesReasoningItem\n        const summaryText = (item.summary ?? []).map((s) => s.text).join('\\n\\n')\n        const reasoningText = (item.content ?? []).map((c) => c.text).join('\\n\\n')\n        if (summaryText.length > 0) slot.summaryText = summaryText\n        if (reasoningText.length > 0) slot.reasoningText = reasoningText\n        if (item.encrypted_content) slot.encryptedContent = item.encrypted_content\n        slot.itemId = item.id\n      } else if (slot.kind === 'toolCall' && rawItem.type === 'function_call') {\n        const item = rawItem as OpenAIResponsesFunctionCallItem\n        if (item.arguments) slot.args = item.arguments\n        if (item.id !== undefined) slot.itemId = item.id\n        slot.callId = item.call_id\n        slot.name = item.name\n      }\n    },\n    backfillEncryptedContent(outputIndex, encryptedContent) {\n      const slot = slots.get(outputIndex)\n      if (slot && slot.kind === 'thinking' && !slot.encryptedContent) {\n        slot.encryptedContent = encryptedContent\n      }\n    },\n    slots() {\n      return slots\n    },\n  }\n}\n/** Default output-slot state machine factory; alias of {@link createResponsesOutputSlotMachine}. */\nexport const defaultCreateResponsesOutputSlotMachine = createResponsesOutputSlotMachine\n\n// ─── Item-id charset/length normalisation (Known Gotcha #5) ───────────────────\n\n/**\n * Normalises an ADK-authored id to the Responses item-id charset, and hashes+truncates ids over\n * the 64-character limit (Known Gotcha #5) rather than sending an oversized id verbatim.\n *\n * @remarks\n * Not part of the public {@link OpenAIResponsesHelpers} contract (no override seam is warranted for\n * a pure charset/length transform) — exported for the adapter and for direct unit testing.\n */\nexport const normalizeOpenAIResponsesItemId = (id: string, prefix = 'msg'): string => {\n  const cleaned = id.replace(/[^A-Za-z0-9_-]/g, '_')\n  if (cleaned.length <= 64) return cleaned\n  // Cheap, deterministic short hash — collisions are astronomically unlikely for this purpose\n  // (a debug-visible correlation id, not a security boundary) and no crypto dependency is needed\n  // synchronously here (unlike canonicalFingerprint, which is async).\n  let hash = 0\n  for (let i = 0; i < id.length; i++) {\n    hash = (hash * 31 + id.charCodeAt(i)) | 0\n  }\n  const shortHash = (hash >>> 0).toString(16).padStart(8, '0')\n  return `${prefix}_${shortHash}`\n}\n\n// Referenced for forward-compat with a future retrievable-handle-body override seam on this\n// battery; kept imported (and referenced) so the shared default stays available to consumers\n// composing partial `helpers` overrides without an unused-import lint failure.\nvoid defaultRenderRetrievableHandleBody\n"],"mappings":"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"}