Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
15ce914a
Unverified
Commit
15ce914a
authored
Apr 24, 2026
by
Wesley Liddick
Committed by
GitHub
Apr 24, 2026
Browse files
Merge pull request #1910 from slovx2/fix/codex-tool-call-ids
fix(openai): 修复 Codex 工具调用 call_id 处理
parents
d162604f
959af1c8
Changes
4
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/openai_codex_transform.go
View file @
15ce914a
...
@@ -658,12 +658,14 @@ func filterCodexInput(input []any, preserveReferences bool) []any {
...
@@ -658,12 +658,14 @@ func filterCodexInput(input []any, preserveReferences bool) []any {
}
}
}
}
if
!
isCodexToolCallItemType
(
typ
)
{
ensureCopy
()
delete
(
newItem
,
"call_id"
)
}
if
!
preserveReferences
{
if
!
preserveReferences
{
ensureCopy
()
ensureCopy
()
delete
(
newItem
,
"id"
)
delete
(
newItem
,
"id"
)
if
!
isCodexToolCallItemType
(
typ
)
{
delete
(
newItem
,
"call_id"
)
}
}
}
filtered
=
append
(
filtered
,
newItem
)
filtered
=
append
(
filtered
,
newItem
)
...
@@ -672,10 +674,20 @@ func filterCodexInput(input []any, preserveReferences bool) []any {
...
@@ -672,10 +674,20 @@ func filterCodexInput(input []any, preserveReferences bool) []any {
}
}
func
isCodexToolCallItemType
(
typ
string
)
bool
{
func
isCodexToolCallItemType
(
typ
string
)
bool
{
if
typ
==
""
{
switch
typ
{
case
"function_call"
,
"tool_call"
,
"local_shell_call"
,
"tool_search_call"
,
"custom_tool_call"
,
"function_call_output"
,
"mcp_tool_call_output"
,
"custom_tool_call_output"
,
"tool_search_output"
:
return
true
default
:
return
false
return
false
}
}
return
strings
.
HasSuffix
(
typ
,
"_call"
)
||
strings
.
HasSuffix
(
typ
,
"_call_output"
)
}
}
func
normalizeCodexTools
(
reqBody
map
[
string
]
any
)
bool
{
func
normalizeCodexTools
(
reqBody
map
[
string
]
any
)
bool
{
...
...
backend/internal/service/openai_codex_transform_test.go
View file @
15ce914a
...
@@ -92,6 +92,78 @@ func TestApplyCodexOAuthTransform_ToolContinuationNormalizesToolReferenceIDsOnly
...
@@ -92,6 +92,78 @@ func TestApplyCodexOAuthTransform_ToolContinuationNormalizesToolReferenceIDsOnly
require
.
Equal
(
t
,
"fc1"
,
second
[
"call_id"
])
require
.
Equal
(
t
,
"fc1"
,
second
[
"call_id"
])
}
}
func
TestApplyCodexOAuthTransform_ToolSearchOutputPreservesCallID
(
t
*
testing
.
T
)
{
reqBody
:=
map
[
string
]
any
{
"model"
:
"gpt-5.2"
,
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"tool_search_output"
,
"call_id"
:
"call_1"
,
"output"
:
"ok"
},
},
}
applyCodexOAuthTransform
(
reqBody
,
false
,
false
)
input
,
ok
:=
reqBody
[
"input"
]
.
([]
any
)
require
.
True
(
t
,
ok
)
require
.
Len
(
t
,
input
,
1
)
first
,
ok
:=
input
[
0
]
.
(
map
[
string
]
any
)
require
.
True
(
t
,
ok
)
require
.
Equal
(
t
,
"tool_search_output"
,
first
[
"type"
])
require
.
Equal
(
t
,
"fc1"
,
first
[
"call_id"
])
}
func
TestApplyCodexOAuthTransform_CustomAndMCPToolOutputsPreserveCallID
(
t
*
testing
.
T
)
{
reqBody
:=
map
[
string
]
any
{
"model"
:
"gpt-5.2"
,
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"custom_tool_call_output"
,
"call_id"
:
"call_custom"
,
"output"
:
"ok"
},
map
[
string
]
any
{
"type"
:
"mcp_tool_call_output"
,
"call_id"
:
"call_mcp"
,
"output"
:
"ok"
},
},
}
applyCodexOAuthTransform
(
reqBody
,
false
,
false
)
input
,
ok
:=
reqBody
[
"input"
]
.
([]
any
)
require
.
True
(
t
,
ok
)
require
.
Len
(
t
,
input
,
2
)
first
,
ok
:=
input
[
0
]
.
(
map
[
string
]
any
)
require
.
True
(
t
,
ok
)
require
.
Equal
(
t
,
"fccustom"
,
first
[
"call_id"
])
second
,
ok
:=
input
[
1
]
.
(
map
[
string
]
any
)
require
.
True
(
t
,
ok
)
require
.
Equal
(
t
,
"fcmcp"
,
second
[
"call_id"
])
}
func
TestApplyCodexOAuthTransform_ImageAndWebSearchCallsDoNotGainCallID
(
t
*
testing
.
T
)
{
reqBody
:=
map
[
string
]
any
{
"model"
:
"gpt-5.2"
,
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"image_generation_call"
,
"id"
:
"ig_123"
,
"status"
:
"completed"
},
map
[
string
]
any
{
"type"
:
"web_search_call"
,
"call_id"
:
"call_bad"
,
"status"
:
"completed"
},
},
"tool_choice"
:
"auto"
,
}
applyCodexOAuthTransform
(
reqBody
,
false
,
false
)
input
,
ok
:=
reqBody
[
"input"
]
.
([]
any
)
require
.
True
(
t
,
ok
)
require
.
Len
(
t
,
input
,
2
)
first
,
ok
:=
input
[
0
]
.
(
map
[
string
]
any
)
require
.
True
(
t
,
ok
)
require
.
Equal
(
t
,
"ig_123"
,
first
[
"id"
])
_
,
hasCallID
:=
first
[
"call_id"
]
require
.
False
(
t
,
hasCallID
)
second
,
ok
:=
input
[
1
]
.
(
map
[
string
]
any
)
require
.
True
(
t
,
ok
)
_
,
hasCallID
=
second
[
"call_id"
]
require
.
False
(
t
,
hasCallID
)
}
func
TestApplyCodexOAuthTransform_ExplicitStoreFalsePreserved
(
t
*
testing
.
T
)
{
func
TestApplyCodexOAuthTransform_ExplicitStoreFalsePreserved
(
t
*
testing
.
T
)
{
// 续链场景:显式 store=false 不再强制为 true,保持 false。
// 续链场景:显式 store=false 不再强制为 true,保持 false。
...
...
backend/internal/service/openai_tool_continuation.go
View file @
15ce914a
...
@@ -21,7 +21,7 @@ type FunctionCallOutputValidation struct {
...
@@ -21,7 +21,7 @@ type FunctionCallOutputValidation struct {
}
}
// NeedsToolContinuation 判定请求是否需要工具调用续链处理。
// NeedsToolContinuation 判定请求是否需要工具调用续链处理。
// 满足以下任一信号即视为续链:previous_response_id、input 内包含
function_call_output
/item_reference、
// 满足以下任一信号即视为续链:previous_response_id、input 内包含
工具输出
/item_reference、
// 或显式声明 tools/tool_choice。
// 或显式声明 tools/tool_choice。
func
NeedsToolContinuation
(
reqBody
map
[
string
]
any
)
bool
{
func
NeedsToolContinuation
(
reqBody
map
[
string
]
any
)
bool
{
if
reqBody
==
nil
{
if
reqBody
==
nil
{
...
@@ -46,7 +46,7 @@ func NeedsToolContinuation(reqBody map[string]any) bool {
...
@@ -46,7 +46,7 @@ func NeedsToolContinuation(reqBody map[string]any) bool {
continue
continue
}
}
itemType
,
_
:=
itemMap
[
"type"
]
.
(
string
)
itemType
,
_
:=
itemMap
[
"type"
]
.
(
string
)
if
i
temType
==
"function_call_output"
||
itemType
==
"item_reference"
{
if
i
sCodexToolCallItemType
(
itemType
)
||
itemType
==
"item_reference"
{
return
true
return
true
}
}
}
}
...
...
backend/internal/service/openai_tool_continuation_test.go
View file @
15ce914a
...
@@ -17,6 +17,9 @@ func TestNeedsToolContinuationSignals(t *testing.T) {
...
@@ -17,6 +17,9 @@ func TestNeedsToolContinuationSignals(t *testing.T) {
{
name
:
"previous_response_id"
,
body
:
map
[
string
]
any
{
"previous_response_id"
:
"resp_1"
},
want
:
true
},
{
name
:
"previous_response_id"
,
body
:
map
[
string
]
any
{
"previous_response_id"
:
"resp_1"
},
want
:
true
},
{
name
:
"previous_response_id_blank"
,
body
:
map
[
string
]
any
{
"previous_response_id"
:
" "
},
want
:
false
},
{
name
:
"previous_response_id_blank"
,
body
:
map
[
string
]
any
{
"previous_response_id"
:
" "
},
want
:
false
},
{
name
:
"function_call_output"
,
body
:
map
[
string
]
any
{
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"function_call_output"
}}},
want
:
true
},
{
name
:
"function_call_output"
,
body
:
map
[
string
]
any
{
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"function_call_output"
}}},
want
:
true
},
{
name
:
"tool_search_output"
,
body
:
map
[
string
]
any
{
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"tool_search_output"
}}},
want
:
true
},
{
name
:
"custom_tool_call_output"
,
body
:
map
[
string
]
any
{
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"custom_tool_call_output"
}}},
want
:
true
},
{
name
:
"mcp_tool_call_output"
,
body
:
map
[
string
]
any
{
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"mcp_tool_call_output"
}}},
want
:
true
},
{
name
:
"item_reference"
,
body
:
map
[
string
]
any
{
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"item_reference"
}}},
want
:
true
},
{
name
:
"item_reference"
,
body
:
map
[
string
]
any
{
"input"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"item_reference"
}}},
want
:
true
},
{
name
:
"tools"
,
body
:
map
[
string
]
any
{
"tools"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"function"
}}},
want
:
true
},
{
name
:
"tools"
,
body
:
map
[
string
]
any
{
"tools"
:
[]
any
{
map
[
string
]
any
{
"type"
:
"function"
}}},
want
:
true
},
{
name
:
"tools_empty"
,
body
:
map
[
string
]
any
{
"tools"
:
[]
any
{}},
want
:
false
},
{
name
:
"tools_empty"
,
body
:
map
[
string
]
any
{
"tools"
:
[]
any
{}},
want
:
false
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment