feat: 支持 openai 图片兼容

This commit is contained in:
claude-code-best
2026-04-06 10:48:27 +08:00
parent dee2ffd638
commit eca1acc662
5 changed files with 238 additions and 2 deletions

View File

@@ -75,6 +75,7 @@ function convertInternalUserMessage(
} else if (Array.isArray(content)) {
const textParts: string[] = []
const toolResults: BetaToolResultBlockParam[] = []
const imageParts: Array<{ type: 'image_url'; image_url: { url: string } }> = []
for (const block of content) {
if (typeof block === 'string') {
@@ -83,11 +84,26 @@ function convertInternalUserMessage(
textParts.push(block.text)
} else if (block.type === 'tool_result') {
toolResults.push(block as BetaToolResultBlockParam)
} else if (block.type === 'image') {
const imagePart = convertImageBlockToOpenAI(block as Record<string, unknown>)
if (imagePart) {
imageParts.push(imagePart)
}
}
// Skip image, document, thinking, cache_edits, etc.
}
if (textParts.length > 0) {
// 如果有图片,构建多模态 content 数组
if (imageParts.length > 0) {
const multiContent: Array<{ type: 'text'; text: string } | { type: 'image_url'; image_url: { url: string } }> = []
if (textParts.length > 0) {
multiContent.push({ type: 'text', text: textParts.join('\n') })
}
multiContent.push(...imageParts)
result.push({
role: 'user',
content: multiContent,
} satisfies ChatCompletionUserMessageParam)
} else if (textParts.length > 0) {
result.push({
role: 'user',
content: textParts.join('\n'),
@@ -182,3 +198,38 @@ function convertInternalAssistantMessage(
return [result]
}
/**
* 将 Anthropic image 块转换为 OpenAI image_url 格式。
*
* Anthropic 格式: { type: "image", source: { type: "base64", media_type: "image/png", data: "..." } }
* OpenAI 格式: { type: "image_url", image_url: { url: "data:image/png;base64,..." } }
*/
function convertImageBlockToOpenAI(
block: Record<string, unknown>,
): { type: 'image_url'; image_url: { url: string } } | null {
const source = block.source as Record<string, unknown> | undefined
if (!source) return null
if (source.type === 'base64' && typeof source.data === 'string') {
const mediaType = (source.media_type as string) || 'image/png'
return {
type: 'image_url',
image_url: {
url: `data:${mediaType};base64,${source.data}`,
},
}
}
// url 类型的图片直接传递
if (source.type === 'url' && typeof source.url === 'string') {
return {
type: 'image_url',
image_url: {
url: source.url,
},
}
}
return null
}