mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-05-08 22:56:55 +08:00
Codex CLI gates the built-in image_generation tool behind
AuthMode::Chatgpt (OAuth only). When clients connect via API key
auth through CPA, the tool is absent from requests, making image
generation unavailable through the reverse proxy.
Changes:
1. Inject image_generation tool (codex_executor.go):
Add ensureImageGenerationTool() that appends
{"type":"image_generation","output_format":"png"} to the tools
array if not already present. Applied to all three execution
paths: Execute, executeCompact, and ExecuteStream.
2. Route aliases for Codex CLI direct access (server.go):
Add /backend-api/codex/responses routes that map to the same
OpenAI Responses API handlers as /v1/responses. This allows
Codex CLI to connect via chatgpt_base_url config while keeping
AuthMode::Chatgpt, which enables the built-in image_generation
tool on the client side.
3. Unit tests (codex_executor_imagegen_test.go):
Cover no-tools, existing tools, already-present, empty array,
and mixed built-in tool scenarios.
90 lines
2.9 KiB
Go
90 lines
2.9 KiB
Go
package executor
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/tidwall/gjson"
|
|
)
|
|
|
|
func TestEnsureImageGenerationTool_NoTools(t *testing.T) {
|
|
body := []byte(`{"model":"gpt-5.4","input":"draw a cat"}`)
|
|
result := ensureImageGenerationTool(body)
|
|
|
|
tools := gjson.GetBytes(result, "tools")
|
|
if !tools.IsArray() {
|
|
t.Fatalf("expected tools array, got %v", tools.Type)
|
|
}
|
|
arr := tools.Array()
|
|
if len(arr) != 1 {
|
|
t.Fatalf("expected 1 tool, got %d", len(arr))
|
|
}
|
|
if arr[0].Get("type").String() != "image_generation" {
|
|
t.Fatalf("expected type=image_generation, got %s", arr[0].Get("type").String())
|
|
}
|
|
if arr[0].Get("output_format").String() != "png" {
|
|
t.Fatalf("expected output_format=png, got %s", arr[0].Get("output_format").String())
|
|
}
|
|
}
|
|
|
|
func TestEnsureImageGenerationTool_ExistingToolsWithoutImageGen(t *testing.T) {
|
|
body := []byte(`{"model":"gpt-5.4","tools":[{"type":"function","name":"get_weather","parameters":{}}]}`)
|
|
result := ensureImageGenerationTool(body)
|
|
|
|
tools := gjson.GetBytes(result, "tools")
|
|
arr := tools.Array()
|
|
if len(arr) != 2 {
|
|
t.Fatalf("expected 2 tools, got %d", len(arr))
|
|
}
|
|
if arr[0].Get("type").String() != "function" {
|
|
t.Fatalf("expected first tool type=function, got %s", arr[0].Get("type").String())
|
|
}
|
|
if arr[1].Get("type").String() != "image_generation" {
|
|
t.Fatalf("expected second tool type=image_generation, got %s", arr[1].Get("type").String())
|
|
}
|
|
}
|
|
|
|
func TestEnsureImageGenerationTool_AlreadyPresent(t *testing.T) {
|
|
body := []byte(`{"model":"gpt-5.4","tools":[{"type":"image_generation","output_format":"webp"},{"type":"function","name":"f1"}]}`)
|
|
result := ensureImageGenerationTool(body)
|
|
|
|
tools := gjson.GetBytes(result, "tools")
|
|
arr := tools.Array()
|
|
if len(arr) != 2 {
|
|
t.Fatalf("expected 2 tools (no duplicate), got %d", len(arr))
|
|
}
|
|
if arr[0].Get("output_format").String() != "webp" {
|
|
t.Fatalf("expected original output_format=webp preserved, got %s", arr[0].Get("output_format").String())
|
|
}
|
|
}
|
|
|
|
func TestEnsureImageGenerationTool_EmptyToolsArray(t *testing.T) {
|
|
body := []byte(`{"model":"gpt-5.4","tools":[]}`)
|
|
result := ensureImageGenerationTool(body)
|
|
|
|
tools := gjson.GetBytes(result, "tools")
|
|
arr := tools.Array()
|
|
if len(arr) != 1 {
|
|
t.Fatalf("expected 1 tool, got %d", len(arr))
|
|
}
|
|
if arr[0].Get("type").String() != "image_generation" {
|
|
t.Fatalf("expected type=image_generation, got %s", arr[0].Get("type").String())
|
|
}
|
|
}
|
|
|
|
func TestEnsureImageGenerationTool_WebSearchAndImageGen(t *testing.T) {
|
|
body := []byte(`{"model":"gpt-5.4","tools":[{"type":"web_search"}]}`)
|
|
result := ensureImageGenerationTool(body)
|
|
|
|
tools := gjson.GetBytes(result, "tools")
|
|
arr := tools.Array()
|
|
if len(arr) != 2 {
|
|
t.Fatalf("expected 2 tools, got %d", len(arr))
|
|
}
|
|
if arr[0].Get("type").String() != "web_search" {
|
|
t.Fatalf("expected first tool type=web_search, got %s", arr[0].Get("type").String())
|
|
}
|
|
if arr[1].Get("type").String() != "image_generation" {
|
|
t.Fatalf("expected second tool type=image_generation, got %s", arr[1].Get("type").String())
|
|
}
|
|
}
|