diff --git a/src/adapters/openai-responses/passthrough.ts b/src/adapters/openai-responses/passthrough.ts index 57c7ccf0e6b..3bf077c358b 100644 --- a/src/adapters/openai-responses/passthrough.ts +++ b/src/adapters/openai-responses/passthrough.ts @@ -40,7 +40,7 @@ import { emittedFastWire, } from "../../providers/fastwire"; import { dropResponsesReasoningInputItems, mapRoutedResponsesReasoningEffort, normalizeConfiguredReasoningSummaryDelivery, sanitizeReasoningInputContent, stripDisabledReasoningSummaries, stripDisabledVerbosity, stripNoneReasoningSummary, stripUnsupportedReasoningSummaryDelivery } from "./reasoning"; -import { scrubOcxCompactionItems, stripCanonicalOnlyInputItems, stripCanonicalOnlyToolFields, stripCanonicalOnlyTopLevelFields, stripInternalChatMessageMetadataPassthrough, stripInvalidItemIds, stripItemIdsWhenUnstored, stripProviderInputItemMetadata, stripRejectedSamplingParams } from "./request-strips"; +import { repairUrlCitationAnnotations, scrubOcxCompactionItems, stripCanonicalOnlyInputItems, stripCanonicalOnlyToolFields, stripCanonicalOnlyTopLevelFields, stripInternalChatMessageMetadataPassthrough, stripInvalidItemIds, stripItemIdsWhenUnstored, stripProviderInputItemMetadata, stripRejectedSamplingParams } from "./scrubOcxCompactionItems"; import { notePlaintextReasoningDropped } from "./plaintext-reasoning-notice"; import { stripCanonicalForwardPromptCacheOptions, stripDeprecatedPromptCacheRetention } from "./prompt-cache"; import { isPlainObject } from "./internal"; @@ -315,7 +315,7 @@ export function createResponsesPassthroughAdapter(provider: OcxProviderConfig): outBody = repairLegacyDottedToolCallNames(outBody); // Shared HTTP/WS outbound projection, including concrete combo/fallback destinations. if (isOpenAiOperatedResponsesDestination(provider)) { - outBody = stripProviderInputItemMetadata(outBody); + outBody = repairUrlCitationAnnotations(stripProviderInputItemMetadata(outBody)); } if (!isCanonicalOpenAiForwardProvider(provider)) { if (provider.preserveResponsesMessageMetadata !== true) { diff --git a/src/adapters/openai-responses/request-strips.ts b/src/adapters/openai-responses/request-strips.ts index 6fb0f591854..bef193b32bb 100644 --- a/src/adapters/openai-responses/request-strips.ts +++ b/src/adapters/openai-responses/request-strips.ts @@ -24,7 +24,7 @@ export function stripProviderInputItemMetadata(body: unknown): unknown { input ??= [...body.input]; input[index] = next; } - return repairUrlCitationAnnotations(input ? { ...body, input } : body); + return input ? { ...body, input } : body; } function isUrlCitationIndex(value: unknown): value is number { diff --git a/src/server/responses/compact.ts b/src/server/responses/compact.ts index 28cb3fbc718..bc689e91fc9 100644 --- a/src/server/responses/compact.ts +++ b/src/server/responses/compact.ts @@ -25,7 +25,7 @@ import { parseRequest } from "../../responses/parser"; import { buildCompactV1Output, COMPACT_PROMPT, decodeCompactionSummary, extractCompactUserMessages } from "../../responses/compaction"; import { applyReasoningRetention, appendRetentionNotice, type ReasoningRetentionResult } from "../../responses/reasoning-retention"; import { FORWARD_HEADERS, sanitizeReasoningInputContent } from "../../adapters/openai-responses"; -import { stripProviderInputItemMetadata } from "../../adapters/openai-responses/request-strips"; +import { repairUrlCitationAnnotations, stripProviderInputItemMetadata } from "../../adapters/openai-responses/request-strips"; import { expandPreviousResponseInput, previousResponseProviderState, rememberResponseState } from "../../responses/state"; import { repairLegacyDottedToolCallNames } from "../../responses/legacy-dotted-tool-name-repair"; import { NoEligiblePolicyCandidateError, routeCompactionModel } from "../../router"; @@ -950,7 +950,7 @@ export async function handleResponsesCompact( // call-name repair the adapter applies. A damaged item here refuses the compaction itself, // which is the request a long task depends on to keep going. // This branch is OpenAI-only and bypasses the adapter's Google replay projection (#7111). - const compactBody = repairLegacyDottedToolCallNames( + let compactBody = repairLegacyDottedToolCallNames( stripProviderInputItemMetadata(sanitizeReasoningInputContent(compactBodyRaw, { preserveRawReasoningContent: !isOpenAiOperatedResponsesDestination(compactProvider) && compactProvider.preserveResponsesReasoningContent === true, @@ -959,7 +959,9 @@ export async function handleResponsesCompact( requirePlaintextReasoning: requireCompactPlaintextReasoning, })), ) as typeof compactBodyRaw; - { + if (isOpenAiOperatedResponsesDestination(compactProvider)) { + compactBody = repairUrlCitationAnnotations(compactBody) as typeof compactBodyRaw; + } const binding = conversationStateBindingFromAuth(authCtx, codexPoolAffinityKey(req.headers)); if (binding) { // Refused rather than scrubbed: an uploaded file is content the caller attached, not