fix cross-protocol conversation file compatibility

This commit is contained in:
cita
2026-03-20 21:48:05 +08:00
parent 5f744c3382
commit 2890b7daf3
20 changed files with 619 additions and 63 deletions
@@ -16,16 +16,16 @@ describe('resolveConversationFileCapability', () => {
});
});
it('marks Claude and Gemini as inline-only document transports', () => {
it('marks Claude and Gemini picker flows as inline-only document transports', () => {
expect(resolveConversationFileCapability('claude')).toEqual({
supported: true,
documentMode: 'inline_only',
reason: '当前协议会以内联文档方式发送会话附件。',
reason: '当前界面的会话附件会以内联文档方式发送。',
});
expect(resolveConversationFileCapability('gemini')).toEqual({
supported: true,
documentMode: 'inline_only',
reason: '当前协议会以内联文档方式发送会话附件。',
reason: '当前界面的会话附件会以内联文档方式发送。',
});
});
});
@@ -21,7 +21,7 @@ export function resolveConversationFileCapability(
return {
supported: true,
documentMode: 'inline_only',
reason: '当前协议会以内联文档方式发送会话附件。',
reason: '当前界面的会话附件会以内联文档方式发送。',
};
}
@@ -15,6 +15,7 @@ import {
collectModelTesterModelNames,
countConversationTurns,
createConversationUserMessage,
extractConversationUploadedFilesFromMessage,
filterModelTesterModelNames,
parseCustomRequestBody,
parseModelTesterSession,
@@ -222,6 +223,56 @@ describe('modelTesterSession', () => {
]);
});
it('extracts inline conversation file data for retry flows', () => {
const files = extractConversationUploadedFilesFromMessage({
id: 'u1',
role: 'user',
content: '请总结附件',
createAt: 1,
parts: [
{
type: 'input_file',
filename: 'brief.pdf',
mimeType: 'application/pdf',
data: 'data:application/pdf;base64,JVBERi0xLjQK',
},
],
});
expect(files).toEqual([
{
filename: 'brief.pdf',
mimeType: 'application/pdf',
data: 'data:application/pdf;base64,JVBERi0xLjQK',
},
]);
});
it('extracts uploaded file references for retry flows', () => {
const files = extractConversationUploadedFilesFromMessage({
id: 'u2',
role: 'user',
content: '请继续分析',
createAt: 2,
parts: [
{
type: 'input_file',
fileId: 'file-metapi-456',
filename: 'appendix.txt',
mimeType: 'text/plain',
},
],
});
expect(files).toEqual([
{
fileId: 'file-metapi-456',
filename: 'appendix.txt',
mimeType: 'text/plain',
},
]);
});
it('preserves file reference parts when building responses conversation payloads', () => {
const payload = buildApiPayload(
[{
@@ -901,6 +901,37 @@ export const createConversationUserMessage = (
});
};
export const extractConversationUploadedFilesFromMessage = (
message: ChatMessage,
): ConversationUploadedFile[] => {
const parts = Array.isArray(message.parts) ? message.parts : [];
return parts.flatMap((part) => {
if (part.type !== 'input_file') return [];
const fileId = typeof part.fileId === 'string' && part.fileId.trim()
? part.fileId.trim()
: null;
const filename = typeof part.filename === 'string' && part.filename.trim()
? part.filename.trim()
: null;
const mimeType = typeof part.mimeType === 'string' && part.mimeType.trim()
? part.mimeType.trim()
: null;
const data = typeof part.data === 'string' && part.data.trim()
? part.data.trim()
: null;
if (!fileId && !data) return [];
return [{
...(fileId ? { fileId } : {}),
...(filename ? { filename } : {}),
...(mimeType ? { mimeType } : {}),
...(data ? { data } : {}),
}];
});
};
export const createLoadingAssistantMessage = (): ChatMessage =>
createMessage('assistant', '', {
status: MESSAGE_STATUS.LOADING,