Merge branch 'claude-code-best:main' into main

This commit is contained in:
HitMargin
2026-04-06 12:30:53 +08:00
committed by GitHub
14 changed files with 641 additions and 21 deletions

View File

@@ -199,4 +199,69 @@ describe('anthropicMessagesToGemini', () => {
},
])
})
test('converts base64 image to inlineData', () => {
const result = anthropicMessagesToGemini(
[makeUserMsg([
{ type: 'text', text: 'describe this' },
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/png',
data: 'iVBORw0KGgo=',
},
},
])],
[] as any,
)
expect(result.contents).toEqual([
{
role: 'user',
parts: [
{ text: 'describe this' },
{ inlineData: { mimeType: 'image/png', data: 'iVBORw0KGgo=' } },
],
},
])
})
test('converts url image to text fallback', () => {
const result = anthropicMessagesToGemini(
[makeUserMsg([
{
type: 'image',
source: {
type: 'url',
url: 'https://example.com/img.png',
},
},
])],
[] as any,
)
expect(result.contents).toEqual([
{
role: 'user',
parts: [{ text: '[image: https://example.com/img.png]' }],
},
])
})
test('defaults to image/png when media_type is missing', () => {
const result = anthropicMessagesToGemini(
[makeUserMsg([
{
type: 'image',
source: {
type: 'base64',
data: 'ABC123',
},
},
])],
[] as any,
)
expect(result.contents[0].parts[0]).toEqual({
inlineData: { mimeType: 'image/png', data: 'ABC123' },
})
})
})

View File

@@ -113,6 +113,26 @@ function convertUserContentBlockToGeminiParts(
]
}
// 将 Anthropic image 块转换为 Gemini inlineData
if (block.type === 'image') {
const source = block.source as Record<string, unknown> | undefined
if (source?.type === 'base64' && typeof source.data === 'string') {
const mediaType = (source.media_type as string) || 'image/png'
return [
{
inlineData: {
mimeType: mediaType,
data: source.data,
},
},
]
}
// url 类型的图片Gemini 不直接支持,转为文本描述
if (source?.type === 'url' && typeof source.url === 'string') {
return createTextGeminiParts(`[image: ${source.url}]`)
}
}
return []
}

View File

@@ -10,12 +10,18 @@ export type GeminiFunctionResponse = {
response?: Record<string, unknown>
}
export type GeminiInlineData = {
mimeType: string
data: string
}
export type GeminiPart = {
text?: string
thought?: boolean
thoughtSignature?: string
functionCall?: GeminiFunctionCall
functionResponse?: GeminiFunctionResponse
inlineData?: GeminiInlineData
}
export type GeminiContent = {