mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-03 06:52:13 +08:00
fix(openai): convert string input to array for Codex OAuth responses endpoint
The ChatGPT backend-api codex/responses endpoint requires `input` to be an array, but the OpenAI Responses API spec allows it to be a plain string. When a client sends a string input, sub2api now converts it to the expected message array format. Empty/whitespace-only strings become an empty array to avoid triggering a 400 "Input must be a list" error.
This commit is contained in:
@@ -146,6 +146,22 @@ func applyCodexOAuthTransform(reqBody map[string]any, isCodexCLI bool, isCompact
|
|||||||
input = filterCodexInput(input, needsToolContinuation)
|
input = filterCodexInput(input, needsToolContinuation)
|
||||||
reqBody["input"] = input
|
reqBody["input"] = input
|
||||||
result.Modified = true
|
result.Modified = true
|
||||||
|
} else if inputStr, ok := reqBody["input"].(string); ok {
|
||||||
|
// ChatGPT codex endpoint requires input to be a list, not a string.
|
||||||
|
// Convert string input to the expected message array format.
|
||||||
|
trimmed := strings.TrimSpace(inputStr)
|
||||||
|
if trimmed != "" {
|
||||||
|
reqBody["input"] = []any{
|
||||||
|
map[string]any{
|
||||||
|
"type": "message",
|
||||||
|
"role": "user",
|
||||||
|
"content": inputStr,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reqBody["input"] = []any{}
|
||||||
|
}
|
||||||
|
result.Modified = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -249,6 +249,50 @@ func TestApplyCodexOAuthTransform_NonCodexCLI_PreservesExistingInstructions(t *t
|
|||||||
require.Equal(t, "old instructions", instructions)
|
require.Equal(t, "old instructions", instructions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApplyCodexOAuthTransform_StringInputConvertedToArray(t *testing.T) {
|
||||||
|
reqBody := map[string]any{"model": "gpt-5.4", "input": "Hello, world!"}
|
||||||
|
result := applyCodexOAuthTransform(reqBody, false, false)
|
||||||
|
require.True(t, result.Modified)
|
||||||
|
input, ok := reqBody["input"].([]any)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Len(t, input, 1)
|
||||||
|
msg, ok := input[0].(map[string]any)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Equal(t, "message", msg["type"])
|
||||||
|
require.Equal(t, "user", msg["role"])
|
||||||
|
require.Equal(t, "Hello, world!", msg["content"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyCodexOAuthTransform_EmptyStringInputBecomesEmptyArray(t *testing.T) {
|
||||||
|
reqBody := map[string]any{"model": "gpt-5.4", "input": ""}
|
||||||
|
result := applyCodexOAuthTransform(reqBody, false, false)
|
||||||
|
require.True(t, result.Modified)
|
||||||
|
input, ok := reqBody["input"].([]any)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Len(t, input, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyCodexOAuthTransform_WhitespaceStringInputBecomesEmptyArray(t *testing.T) {
|
||||||
|
reqBody := map[string]any{"model": "gpt-5.4", "input": " "}
|
||||||
|
result := applyCodexOAuthTransform(reqBody, false, false)
|
||||||
|
require.True(t, result.Modified)
|
||||||
|
input, ok := reqBody["input"].([]any)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Len(t, input, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyCodexOAuthTransform_StringInputWithToolsField(t *testing.T) {
|
||||||
|
reqBody := map[string]any{
|
||||||
|
"model": "gpt-5.4",
|
||||||
|
"input": "Run the tests",
|
||||||
|
"tools": []any{map[string]any{"type": "function", "name": "bash"}},
|
||||||
|
}
|
||||||
|
applyCodexOAuthTransform(reqBody, false, false)
|
||||||
|
input, ok := reqBody["input"].([]any)
|
||||||
|
require.True(t, ok)
|
||||||
|
require.Len(t, input, 1)
|
||||||
|
}
|
||||||
|
|
||||||
func TestIsInstructionsEmpty(t *testing.T) {
|
func TestIsInstructionsEmpty(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|||||||
Reference in New Issue
Block a user