diff --git a/packages/llm-providers/src/openai-compatible/chat/convert-to-openai-compatible-chat-messages.test.ts b/packages/llm-providers/src/openai-compatible/chat/convert-to-openai-compatible-chat-messages.test.ts index 5b8c7b5b35..09cf152e44 100644 --- a/packages/llm-providers/src/openai-compatible/chat/convert-to-openai-compatible-chat-messages.test.ts +++ b/packages/llm-providers/src/openai-compatible/chat/convert-to-openai-compatible-chat-messages.test.ts @@ -74,6 +74,33 @@ describe('user messages', () => { ]) }) + it('should not double-wrap an already-complete data URL', async () => { + const result = convertToOpenAICompatibleChatMessages([ + { + role: 'user', + content: [ + { + type: 'file', + data: 'data:image/png;base64,AAECAw==', + mediaType: 'image/png', + }, + ], + }, + ]) + + expect(result).toEqual([ + { + role: 'user', + content: [ + { + type: 'image_url', + image_url: { url: 'data:image/png;base64,AAECAw==' }, + }, + ], + }, + ]) + }) + it('should handle URL-based images', async () => { const result = convertToOpenAICompatibleChatMessages([ { diff --git a/packages/llm-providers/src/openai-compatible/chat/convert-to-openai-compatible-chat-messages.ts b/packages/llm-providers/src/openai-compatible/chat/convert-to-openai-compatible-chat-messages.ts index 1c984d6438..b1a5c129c9 100644 --- a/packages/llm-providers/src/openai-compatible/chat/convert-to-openai-compatible-chat-messages.ts +++ b/packages/llm-providers/src/openai-compatible/chat/convert-to-openai-compatible-chat-messages.ts @@ -41,14 +41,21 @@ export function convertToOpenAICompatibleChatMessages( const mediaType = part.mediaType === 'image/*' ? 'image/jpeg' : part.mediaType + const dataUrl = + part.data instanceof URL + ? part.data.toString() + : typeof part.data === 'string' && + part.data.startsWith('data:') + ? // Already a complete data URL (e.g. produced by a + // screenshot tool): wrapping it again would nest a + // second `data:;base64,` prefix inside the + // payload, which providers reject as invalid base64. + part.data + : `data:${mediaType};base64,${convertToBase64(part.data)}` + return { type: 'image_url', - image_url: { - url: - part.data instanceof URL - ? part.data.toString() - : `data:${mediaType};base64,${convertToBase64(part.data)}`, - }, + image_url: { url: dataUrl }, ...partMetadata, } } else {