mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-10-05 23:31:05 +08:00
fix(codex): preserve base64 PDF document blocks when converting Claude requests to Codex
Closes: #4765
This commit is contained in:
@@ -26,7 +26,7 @@ import (
|
||||
// The function performs the following transformations:
|
||||
// 1. Sets up a template with the model name and empty instructions field
|
||||
// 2. Processes system messages and converts them to developer input content
|
||||
// 3. Transforms message contents (text, image, tool_use, tool_result) to appropriate formats
|
||||
// 3. Transforms message contents (text, image, document, tool_use, tool_result) to appropriate formats
|
||||
// 4. Converts tools declarations to the expected format
|
||||
// 5. Adds additional configuration parameters for the Codex API
|
||||
// 6. Maps Claude thinking configuration to Codex reasoning settings
|
||||
@@ -129,6 +129,12 @@ func ConvertClaudeRequestToCodex(modelName string, inputRawJSON []byte, _ bool)
|
||||
contentItems = append(contentItems, content)
|
||||
}
|
||||
|
||||
appendDocumentContent := func(dataURL string) {
|
||||
content := []byte(`{"type":"input_file","file_data":"","filename":"document.pdf"}`)
|
||||
content, _ = sjson.SetBytes(content, "file_data", dataURL)
|
||||
contentItems = append(contentItems, content)
|
||||
}
|
||||
|
||||
appendReasoningContent := func(part gjson.Result) {
|
||||
if messageRole != "assistant" {
|
||||
return
|
||||
@@ -182,6 +188,22 @@ func ConvertClaudeRequestToCodex(modelName string, inputRawJSON []byte, _ bool)
|
||||
appendImageContent(dataURL)
|
||||
}
|
||||
}
|
||||
case "document":
|
||||
sourceResult := messageContentResult.Get("source")
|
||||
if sourceResult.Get("type").String() != "base64" {
|
||||
continue
|
||||
}
|
||||
mediaType := strings.TrimSpace(sourceResult.Get("media_type").String())
|
||||
if !strings.EqualFold(mediaType, "application/pdf") {
|
||||
continue
|
||||
}
|
||||
data := sourceResult.Get("data").String()
|
||||
if data == "" {
|
||||
data = sourceResult.Get("base64").String()
|
||||
}
|
||||
if data != "" {
|
||||
appendDocumentContent(fmt.Sprintf("data:%s;base64,%s", mediaType, data))
|
||||
}
|
||||
case "tool_use":
|
||||
flushMessage()
|
||||
functionCallMessage := []byte(`{"type":"function_call"}`)
|
||||
|
||||
@@ -508,6 +508,44 @@ func TestConvertClaudeRequestToCodex_AssistantThinkingSignatureToReasoningItem(t
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertClaudeRequestToCodex_PreservesBase64PDFDocumentContent(t *testing.T) {
|
||||
inputJSON := `{
|
||||
"messages": [{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "before"},
|
||||
{"type": "document", "source": {"type": "base64", "media_type": "application/pdf", "data": "JVBERi0xLjQK"}},
|
||||
{"type": "text", "text": "after"}
|
||||
]
|
||||
}]
|
||||
}`
|
||||
|
||||
result := ConvertClaudeRequestToCodex("gpt-5.6-sol", []byte(inputJSON), false)
|
||||
content := gjson.GetBytes(result, "input.0.content").Array()
|
||||
if len(content) != 3 {
|
||||
t.Fatalf("got %d content items, want 3. Output: %s", len(content), result)
|
||||
}
|
||||
|
||||
wantTypes := []string{"input_text", "input_file", "input_text"}
|
||||
for i, wantType := range wantTypes {
|
||||
if got := content[i].Get("type").String(); got != wantType {
|
||||
t.Fatalf("content[%d].type = %q, want %q. Output: %s", i, got, wantType, result)
|
||||
}
|
||||
}
|
||||
if got := content[0].Get("text").String(); got != "before" {
|
||||
t.Fatalf("content[0].text = %q, want %q", got, "before")
|
||||
}
|
||||
if got := content[1].Get("file_data").String(); got != "data:application/pdf;base64,JVBERi0xLjQK" {
|
||||
t.Fatalf("content[1].file_data = %q, want PDF data URL", got)
|
||||
}
|
||||
if got := content[1].Get("filename").String(); got != "document.pdf" {
|
||||
t.Fatalf("content[1].filename = %q, want %q", got, "document.pdf")
|
||||
}
|
||||
if got := content[2].Get("text").String(); got != "after" {
|
||||
t.Fatalf("content[2].text = %q, want %q", got, "after")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertClaudeRequestToCodex_PreservesContentOrderAcrossToolAndReasoningItems(t *testing.T) {
|
||||
signature := validCodexReasoningSignature()
|
||||
inputJSON := `{
|
||||
|
||||
Reference in New Issue
Block a user