Files
metapi/src/shared/conversationFileTypes.js
T

95 lines
3.7 KiB
JavaScript

export const CONVERSATION_DOCUMENT_ACCEPT_PARTS = ['.pdf', '.txt', '.md', '.markdown', '.json'];
const GENERIC_MIME_TYPES = new Set([
'application/octet-stream',
'binary/octet-stream',
]);
const DOCUMENT_MIME_TYPES = new Set([
'application/json',
'application/pdf',
'text/markdown',
'text/plain',
]);
const DOCUMENT_EXTENSIONS = ['.json', '.md', '.markdown', '.pdf', '.txt'];
const IMAGE_EXTENSIONS = ['.avif', '.bmp', '.gif', '.jpeg', '.jpg', '.png', '.svg', '.webp'];
const AUDIO_EXTENSIONS = ['.aac', '.flac', '.m4a', '.mp3', '.ogg', '.wav', '.weba'];
function normalizeValue(value) {
return (value || '').trim().toLowerCase();
}
function normalizeMimeType(value) {
const normalized = normalizeValue(value);
const [essence] = normalized.split(';');
return (essence || '').trim();
}
export function inferConversationFileMimeType(filename) {
const normalized = normalizeValue(filename);
if (normalized.endsWith('.pdf')) return 'application/pdf';
if (normalized.endsWith('.txt')) return 'text/plain';
if (normalized.endsWith('.md') || normalized.endsWith('.markdown')) return 'text/markdown';
if (normalized.endsWith('.json')) return 'application/json';
if (normalized.endsWith('.png')) return 'image/png';
if (normalized.endsWith('.jpg') || normalized.endsWith('.jpeg')) return 'image/jpeg';
if (normalized.endsWith('.gif')) return 'image/gif';
if (normalized.endsWith('.webp')) return 'image/webp';
if (normalized.endsWith('.svg')) return 'image/svg+xml';
if (normalized.endsWith('.avif')) return 'image/avif';
if (normalized.endsWith('.bmp')) return 'image/bmp';
if (normalized.endsWith('.wav')) return 'audio/wav';
if (normalized.endsWith('.mp3')) return 'audio/mpeg';
if (normalized.endsWith('.m4a')) return 'audio/mp4';
if (normalized.endsWith('.ogg')) return 'audio/ogg';
if (normalized.endsWith('.aac')) return 'audio/aac';
if (normalized.endsWith('.flac')) return 'audio/flac';
if (normalized.endsWith('.weba')) return 'audio/webm';
return 'application/octet-stream';
}
export function resolveConversationFileMimeType(mimeType, filename) {
const normalizedMimeType = normalizeMimeType(mimeType);
if (normalizedMimeType && !GENERIC_MIME_TYPES.has(normalizedMimeType)) {
return normalizedMimeType;
}
return inferConversationFileMimeType(filename);
}
export function classifyConversationFileMimeType(mimeType) {
const normalized = normalizeMimeType(mimeType);
if (normalized.startsWith('image/')) return 'image';
if (normalized.startsWith('audio/')) return 'audio';
return 'document';
}
export function detectConversationFileKind(file) {
const mimeType = normalizeMimeType(file?.mimeType);
if (mimeType) {
if (mimeType.startsWith('image/')) return 'image';
if (mimeType.startsWith('audio/')) return 'audio';
if (DOCUMENT_MIME_TYPES.has(mimeType)) return 'document';
if (!GENERIC_MIME_TYPES.has(mimeType)) return 'unknown';
}
const filename = normalizeValue(file?.filename);
if (!filename) return 'unknown';
if (DOCUMENT_EXTENSIONS.some((extension) => filename.endsWith(extension))) return 'document';
if (IMAGE_EXTENSIONS.some((extension) => filename.endsWith(extension))) return 'image';
if (AUDIO_EXTENSIONS.some((extension) => filename.endsWith(extension))) return 'audio';
return 'unknown';
}
export function isSupportedConversationFileMimeType(mimeType) {
const normalized = normalizeMimeType(mimeType);
return DOCUMENT_MIME_TYPES.has(normalized)
|| normalized.startsWith('image/')
|| normalized.startsWith('audio/');
}
export function buildConversationAcceptList(input) {
const parts = [];
if (input.document) parts.push(...CONVERSATION_DOCUMENT_ACCEPT_PARTS);
if (input.image) parts.push('image/*');
if (input.audio) parts.push('audio/*');
return parts.join(',');
}