diff --git a/open-sse/translator/helpers/geminiHelper.ts b/open-sse/translator/helpers/geminiHelper.ts index 312e90ae7c..01a9fc2392 100644 --- a/open-sse/translator/helpers/geminiHelper.ts +++ b/open-sse/translator/helpers/geminiHelper.ts @@ -76,6 +76,42 @@ export function convertOpenAIContentToParts(content) { if (item.type === "text") { parts.push({ text: item.text }); } else { + // 1. Handle Gemini native inline_data injected into OpenAI arrays (e.g. Cherry Studio) + const geminiInline = item.inline_data || item.inlineData; + if (geminiInline?.data) { + parts.push({ + inlineData: { + mimeType: geminiInline.mime_type || geminiInline.mimeType || "application/pdf", + data: geminiInline.data.replace(/^data:[a-zA-Z0-9/+-]+;base64,/, ""), + }, + }); + continue; + } + + // 2. Handle Claude-style source blocks commonly used by AI clients + if (item.source?.type === "base64" && item.source?.data) { + parts.push({ + inlineData: { + mimeType: item.source.media_type || "application/pdf", + data: item.source.data.replace(/^data:[a-zA-Z0-9/+-]+;base64,/, ""), + }, + }); + continue; + } + + // 3. Handle raw data strings (e.g. {"type": "file", "data": "JVBER...", "mime_type": "..."}) + if (typeof item.data === "string" && !item.data.startsWith("http")) { + const rawData = item.data.replace(/^data:[a-zA-Z0-9/+-]+;base64,/, ""); + parts.push({ + inlineData: { + mimeType: item.mime_type || item.media_type || "application/octet-stream", + data: rawData, + }, + }); + continue; + } + + // 4. Standard OpenAI Data URIs const fileData = item.image_url?.url || item.file_url?.url || item.file?.url || item.document?.url; if (typeof fileData === "string" && fileData.startsWith("data:")) {