chore: codex transform fixes and feature compatibility

This commit is contained in:
yexueduxing
2026-03-12 20:52:35 +08:00
parent 826090e099
commit f16910d616
2 changed files with 72 additions and 4 deletions

View File

@@ -129,6 +129,41 @@ func applyCodexOAuthTransform(reqBody map[string]any, isCodexCLI bool, isCompact
}
}
// 兼容遗留的 functions 和 function_call转换为 tools 和 tool_choice
if functionsRaw, ok := reqBody["functions"]; ok {
if functions, k := functionsRaw.([]any); k {
tools := make([]any, 0, len(functions))
for _, f := range functions {
tools = append(tools, map[string]any{
"type": "function",
"function": f,
})
}
reqBody["tools"] = tools
}
delete(reqBody, "functions")
result.Modified = true
}
if fcRaw, ok := reqBody["function_call"]; ok {
if fcStr, ok := fcRaw.(string); ok {
// e.g. "auto", "none"
reqBody["tool_choice"] = fcStr
} else if fcObj, ok := fcRaw.(map[string]any); ok {
// e.g. {"name": "my_func"}
if name, ok := fcObj["name"].(string); ok && strings.TrimSpace(name) != "" {
reqBody["tool_choice"] = map[string]any{
"type": "function",
"function": map[string]any{
"name": name,
},
}
}
}
delete(reqBody, "function_call")
result.Modified = true
}
if normalizeCodexTools(reqBody) {
result.Modified = true
}
@@ -303,6 +338,18 @@ func filterCodexInput(input []any, preserveReferences bool) []any {
continue
}
typ, _ := m["type"].(string)
// 修复 OpenAI 上游的最新校验:"Expected an ID that begins with 'fc'"
fixIDPrefix := func(id string) string {
if id == "" || strings.HasPrefix(id, "fc") {
return id
}
if strings.HasPrefix(id, "call_") {
return "fc" + strings.TrimPrefix(id, "call_")
}
return "fc_" + id
}
if typ == "item_reference" {
if !preserveReferences {
continue
@@ -311,6 +358,9 @@ func filterCodexInput(input []any, preserveReferences bool) []any {
for key, value := range m {
newItem[key] = value
}
if id, ok := newItem["id"].(string); ok && id != "" {
newItem["id"] = fixIDPrefix(id)
}
filtered = append(filtered, newItem)
continue
}
@@ -330,10 +380,20 @@ func filterCodexInput(input []any, preserveReferences bool) []any {
}
if isCodexToolCallItemType(typ) {
if callID, ok := m["call_id"].(string); !ok || strings.TrimSpace(callID) == "" {
callID, ok := m["call_id"].(string)
if !ok || strings.TrimSpace(callID) == "" {
if id, ok := m["id"].(string); ok && strings.TrimSpace(id) != "" {
callID = id
ensureCopy()
newItem["call_id"] = id
newItem["call_id"] = callID
}
}
if callID != "" {
fixedCallID := fixIDPrefix(callID)
if fixedCallID != callID {
ensureCopy()
newItem["call_id"] = fixedCallID
}
}
}
@@ -344,6 +404,14 @@ func filterCodexInput(input []any, preserveReferences bool) []any {
if !isCodexToolCallItemType(typ) {
delete(newItem, "call_id")
}
} else {
if id, ok := newItem["id"].(string); ok && id != "" {
fixedID := fixIDPrefix(id)
if fixedID != id {
ensureCopy()
newItem["id"] = fixedID
}
}
}
filtered = append(filtered, newItem)

View File

@@ -33,12 +33,12 @@ func TestApplyCodexOAuthTransform_ToolContinuationPreservesInput(t *testing.T) {
first, ok := input[0].(map[string]any)
require.True(t, ok)
require.Equal(t, "item_reference", first["type"])
require.Equal(t, "ref1", first["id"])
require.Equal(t, "fc_ref1", first["id"])
// 校验 input[1] 为 map确保后续字段断言安全。
second, ok := input[1].(map[string]any)
require.True(t, ok)
require.Equal(t, "o1", second["id"])
require.Equal(t, "fc_o1", second["id"])
}
func TestApplyCodexOAuthTransform_ExplicitStoreFalsePreserved(t *testing.T) {