1
0
forked from boos/BoosAPI

Merge pull request #216 from cita-777/codex/fix-responses-endpoint-memory

[codex] fix cross-protocol conversation file compatibility
This commit is contained in:
Cita
2026-03-20 21:53:13 +08:00
committed by GitHub
20 changed files with 619 additions and 63 deletions
@@ -40,15 +40,15 @@ describe('conversationFileCapabilities', () => {
});
});
it('describes inline-only document support for claude messages and gemini chat paths', () => {
it('describes native remote-document support for claude messages and inline-only support for gemini chat paths', () => {
expect(resolveConversationFileEndpointCapability({
sitePlatform: 'claude',
endpoint: 'messages',
})).toMatchObject({
image: 'native',
audio: 'unsupported',
document: 'inline_only',
preservesRemoteDocumentUrl: false,
document: 'native',
preservesRemoteDocumentUrl: true,
});
expect(resolveConversationFileEndpointCapability({
@@ -151,8 +151,8 @@ export function resolveConversationFileEndpointCapability(input: {
return {
image: 'native',
audio: 'unsupported',
document: 'inline_only',
preservesRemoteDocumentUrl: false,
document: 'native',
preservesRemoteDocumentUrl: true,
};
}
return {
@@ -165,6 +165,7 @@ export async function handleChatSurfaceRequest(
requestedModelHint: requestedModel,
requestCapabilities: {
hasNonImageFileInput,
conversationFileSummary,
},
};
const buildProviderHeaders = () => (
@@ -33,6 +33,7 @@ import {
import { dispatchRuntimeRequest } from '../../routes/proxy/runtimeExecutor.js';
import { detectDownstreamClientContext, type DownstreamClientContext } from '../../routes/proxy/downstreamClientContext.js';
import { insertProxyLog } from '../../services/proxyLogStore.js';
import { summarizeConversationFileInputsInOpenAiBody } from '../capabilities/conversationFileCapabilities.js';
const MAX_RETRIES = 2;
const GEMINI_MODEL_PROBES = [
@@ -685,6 +686,8 @@ export async function geminiProxyRoute(app: FastifyInstance) {
modelName: actualModel,
stream: isStreamAction,
});
const conversationFileSummary = summarizeConversationFileInputsInOpenAiBody(openAiBody);
const hasNonImageFileInput = conversationFileSummary.hasDocument;
const endpointCandidates = await resolveUpstreamEndpointCandidates(
{
site: selected.site,
@@ -693,12 +696,20 @@ export async function geminiProxyRoute(app: FastifyInstance) {
actualModel,
'openai',
requestedModel,
{
hasNonImageFileInput,
conversationFileSummary,
},
);
const endpointRuntimeContext = {
siteId: selected.site.id,
modelName: actualModel,
downstreamFormat: 'openai' as const,
requestedModelHint: requestedModel,
requestCapabilities: {
hasNonImageFileInput,
conversationFileSummary,
},
};
const buildEndpointRequest = (
endpoint: 'chat' | 'messages' | 'responses',
@@ -238,14 +238,6 @@ export async function handleOpenAiResponsesSurfaceRequest(
const responsesConversationFileSummary = summarizeConversationFileInputsInResponsesBody(normalizedResponsesBody);
const requiresNativeResponsesFileUrl = responsesConversationFileSummary.hasRemoteDocumentUrl
|| carriesResponsesFileUrlInput(normalizedResponsesBody.input);
if (requiresNativeResponsesFileUrl && String(selected.site.platform || '').trim().toLowerCase() === 'claude') {
return reply.code(400).send({
error: {
message: 'Responses input_file.file_url requires an upstream /v1/responses endpoint; current site only supports /v1/messages.',
type: 'invalid_request_error',
},
});
}
const endpointCandidates = await resolveUpstreamEndpointCandidates(
{
site: selected.site,
@@ -260,9 +252,6 @@ export async function handleOpenAiResponsesSurfaceRequest(
wantsNativeResponsesReasoning: prefersNativeResponsesReasoning,
},
);
if (requiresNativeResponsesFileUrl) {
endpointCandidates.splice(0, endpointCandidates.length, 'responses');
}
if (endpointCandidates.length === 0) {
endpointCandidates.push('responses', 'chat', 'messages');
}
@@ -273,6 +262,7 @@ export async function handleOpenAiResponsesSurfaceRequest(
requestedModelHint: requestedModel,
requestCapabilities: {
hasNonImageFileInput,
conversationFileSummary,
wantsNativeResponsesReasoning: prefersNativeResponsesReasoning,
},
};