Merge origin/main into codex/modeltester-attachment-review-fixes
This commit is contained in:
@@ -31,14 +31,14 @@ describe('resolveConversationFileCapability', () => {
|
||||
imageMode: 'native',
|
||||
audioMode: 'unsupported',
|
||||
documentMode: 'inline_only',
|
||||
reason: '',
|
||||
reason: '当前界面的会话附件会以内联文档方式发送。',
|
||||
});
|
||||
expect(resolveConversationFileCapability('gemini')).toEqual({
|
||||
supported: true,
|
||||
imageMode: 'native',
|
||||
audioMode: 'native',
|
||||
documentMode: 'inline_only',
|
||||
reason: '',
|
||||
reason: '当前界面的会话附件会以内联文档方式发送。',
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ export function resolveConversationFileCapability(
|
||||
imageMode: 'native',
|
||||
audioMode: 'unsupported',
|
||||
documentMode: 'inline_only',
|
||||
reason: '',
|
||||
reason: '当前界面的会话附件会以内联文档方式发送。',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ export function resolveConversationFileCapability(
|
||||
imageMode: 'native',
|
||||
audioMode: 'native',
|
||||
documentMode: 'inline_only',
|
||||
reason: '',
|
||||
reason: '当前界面的会话附件会以内联文档方式发送。',
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -223,30 +223,52 @@ describe('modelTesterSession', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('extracts both uploaded references and inline attachments from user messages', () => {
|
||||
const message = createConversationUserMessage('请重新发送附件', [
|
||||
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([
|
||||
{
|
||||
fileId: 'file-metapi-123',
|
||||
filename: 'paper.pdf',
|
||||
filename: 'brief.pdf',
|
||||
mimeType: 'application/pdf',
|
||||
},
|
||||
{
|
||||
filename: 'voice.mp3',
|
||||
mimeType: 'audio/mpeg',
|
||||
data: 'data:audio/mpeg;base64,QUFBQQ==',
|
||||
data: 'data:application/pdf;base64,JVBERi0xLjQK',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
expect(extractConversationUploadedFilesFromMessage(message)).toEqual([
|
||||
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-123',
|
||||
filename: 'paper.pdf',
|
||||
mimeType: 'application/pdf',
|
||||
},
|
||||
{
|
||||
filename: 'voice.mp3',
|
||||
mimeType: 'audio/mpeg',
|
||||
data: 'data:audio/mpeg;base64,QUFBQQ==',
|
||||
fileId: 'file-metapi-456',
|
||||
filename: 'appendix.txt',
|
||||
mimeType: 'text/plain',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -918,17 +918,26 @@ export const extractConversationUploadedFilesFromMessage = (
|
||||
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() : '';
|
||||
const data = typeof part.data === 'string' ? part.data.trim() : '';
|
||||
|
||||
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 } : {}),
|
||||
...(typeof part.filename === 'string' && part.filename.trim()
|
||||
? { filename: part.filename.trim() }
|
||||
: {}),
|
||||
...(typeof part.mimeType === 'string' && part.mimeType.trim()
|
||||
? { mimeType: part.mimeType.trim() }
|
||||
: {}),
|
||||
...(filename ? { filename } : {}),
|
||||
...(mimeType ? { mimeType } : {}),
|
||||
...(data ? { data } : {}),
|
||||
}];
|
||||
});
|
||||
|
||||
@@ -16,6 +16,7 @@ describe('buildSiteSaveAction', () => {
|
||||
url: 'https://a.example.com/',
|
||||
externalCheckinUrl: 'https://checkin.a.example.com',
|
||||
platform: 'new-api',
|
||||
proxyUrl: 'socks5://127.0.0.1:1080',
|
||||
customHeaders: '{"x-site-token":"alpha"}',
|
||||
useSystemProxy: false,
|
||||
globalWeight: 1.2,
|
||||
@@ -29,6 +30,7 @@ describe('buildSiteSaveAction', () => {
|
||||
url: 'https://a.example.com/',
|
||||
externalCheckinUrl: 'https://checkin.a.example.com',
|
||||
platform: 'new-api',
|
||||
proxyUrl: 'socks5://127.0.0.1:1080',
|
||||
customHeaders: '{"x-site-token":"alpha"}',
|
||||
useSystemProxy: false,
|
||||
globalWeight: 1.2,
|
||||
@@ -44,6 +46,7 @@ describe('buildSiteSaveAction', () => {
|
||||
url: 'https://b.example.com',
|
||||
externalCheckinUrl: '',
|
||||
platform: 'one-api',
|
||||
proxyUrl: '',
|
||||
useSystemProxy: true,
|
||||
customHeaders: '',
|
||||
globalWeight: 0.8,
|
||||
@@ -58,6 +61,7 @@ describe('buildSiteSaveAction', () => {
|
||||
url: 'https://b.example.com',
|
||||
externalCheckinUrl: '',
|
||||
platform: 'one-api',
|
||||
proxyUrl: '',
|
||||
useSystemProxy: true,
|
||||
customHeaders: '',
|
||||
globalWeight: 0.8,
|
||||
@@ -74,6 +78,7 @@ describe('buildSiteSaveAction', () => {
|
||||
url: 'https://c.example.com',
|
||||
externalCheckinUrl: '',
|
||||
platform: '',
|
||||
proxyUrl: '',
|
||||
useSystemProxy: false,
|
||||
customHeaders: '',
|
||||
globalWeight: 1,
|
||||
@@ -85,16 +90,20 @@ describe('buildSiteSaveAction', () => {
|
||||
it('does not expose deprecated apiKey in site editor state', () => {
|
||||
expect(emptySiteForm()).not.toHaveProperty('apiKey');
|
||||
expect(emptySiteForm().customHeaders).toEqual([emptySiteCustomHeader()]);
|
||||
expect(emptySiteForm().proxyUrl).toBe('');
|
||||
expect(siteFormFromSite({
|
||||
name: 'site-d',
|
||||
url: 'https://d.example.com',
|
||||
externalCheckinUrl: null,
|
||||
platform: 'new-api',
|
||||
proxyUrl: null,
|
||||
proxyUrl: 'http://127.0.0.1:8080',
|
||||
customHeaders: '{"x-site-token":"alpha"}',
|
||||
globalWeight: 1,
|
||||
apiKey: 'sk-legacy-site-key',
|
||||
})).not.toHaveProperty('apiKey');
|
||||
expect(siteFormFromSite({
|
||||
proxyUrl: 'http://127.0.0.1:8080',
|
||||
}).proxyUrl).toBe('http://127.0.0.1:8080');
|
||||
});
|
||||
|
||||
it('parses custom headers json into key value rows', () => {
|
||||
|
||||
@@ -8,6 +8,7 @@ export type SiteForm = {
|
||||
url: string;
|
||||
externalCheckinUrl: string;
|
||||
platform: string;
|
||||
proxyUrl: string;
|
||||
useSystemProxy: boolean;
|
||||
customHeaders: SiteCustomHeaderField[];
|
||||
globalWeight: string;
|
||||
@@ -22,6 +23,7 @@ export type SiteSavePayload = {
|
||||
url: string;
|
||||
externalCheckinUrl: string;
|
||||
platform: string;
|
||||
proxyUrl: string;
|
||||
useSystemProxy: boolean;
|
||||
customHeaders: string;
|
||||
globalWeight: number;
|
||||
@@ -45,6 +47,7 @@ export function emptySiteForm(): SiteForm {
|
||||
url: '',
|
||||
externalCheckinUrl: '',
|
||||
platform: '',
|
||||
proxyUrl: '',
|
||||
useSystemProxy: false,
|
||||
customHeaders: [emptySiteCustomHeader()],
|
||||
globalWeight: '1',
|
||||
@@ -76,8 +79,9 @@ function parseCustomHeadersForEditor(raw: unknown): SiteCustomHeaderField[] {
|
||||
}
|
||||
}
|
||||
|
||||
export function siteFormFromSite(site: Partial<Omit<SiteForm, 'customHeaders' | 'globalWeight' | 'externalCheckinUrl' | 'useSystemProxy'>> & {
|
||||
export function siteFormFromSite(site: Partial<Omit<SiteForm, 'customHeaders' | 'globalWeight' | 'externalCheckinUrl' | 'proxyUrl' | 'useSystemProxy'>> & {
|
||||
externalCheckinUrl?: string | null;
|
||||
proxyUrl?: string | null;
|
||||
useSystemProxy?: boolean | null;
|
||||
customHeaders?: string | null;
|
||||
globalWeight?: number | string | null;
|
||||
@@ -89,6 +93,7 @@ export function siteFormFromSite(site: Partial<Omit<SiteForm, 'customHeaders' |
|
||||
url: site.url ?? '',
|
||||
externalCheckinUrl: site.externalCheckinUrl ?? '',
|
||||
platform: site.platform ?? '',
|
||||
proxyUrl: site.proxyUrl ?? '',
|
||||
useSystemProxy: !!site.useSystemProxy,
|
||||
customHeaders: parseCustomHeadersForEditor(site.customHeaders),
|
||||
globalWeight,
|
||||
|
||||
Reference in New Issue
Block a user