mirror of
https://gh-proxy.org/https://github.com/klinsmaya/CLIProxyAPI.git
synced 2026-11-08 01:16:47 +08:00
feat(executor): normalize parallel_tool_calls based on tools presence
- Added `normalizeCodexParallelToolCallsForTools` to conditionally remove `parallel_tool_calls` when `tools` are missing or empty. - Integrated normalization into Codex executor workflows for improved request handling. - Introduced unit tests to validate behavior across different tool scenarios. Closes: #3903
This commit is contained in:
@@ -829,6 +829,7 @@ func (e *CodexExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, re
|
||||
body = ensureImageGenerationTool(body, baseModel, auth)
|
||||
}
|
||||
body = sanitizeOpenAIResponsesReasoningEncryptedContent(ctx, "codex executor", body)
|
||||
body = normalizeCodexParallelToolCallsForTools(body)
|
||||
body, replayScope, errReplay := applyCodexReasoningReplayCacheRequired(ctx, from, req, opts, body)
|
||||
if errReplay != nil {
|
||||
return resp, errReplay
|
||||
@@ -1004,6 +1005,7 @@ func (e *CodexExecutor) executeCompact(ctx context.Context, auth *cliproxyauth.A
|
||||
body = ensureImageGenerationTool(body, baseModel, auth)
|
||||
}
|
||||
body = sanitizeOpenAIResponsesReasoningEncryptedContent(ctx, "codex executor", body)
|
||||
body = normalizeCodexParallelToolCallsForTools(body)
|
||||
reporter.SetTranslatedReasoningEffort(body, to.String())
|
||||
|
||||
url := strings.TrimSuffix(baseURL, "/") + "/responses/compact"
|
||||
@@ -1113,6 +1115,7 @@ func (e *CodexExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
|
||||
body = ensureImageGenerationTool(body, baseModel, auth)
|
||||
}
|
||||
body = sanitizeOpenAIResponsesReasoningEncryptedContent(ctx, "codex executor", body)
|
||||
body = normalizeCodexParallelToolCallsForTools(body)
|
||||
body, replayScope, errReplay := applyCodexReasoningReplayCacheRequired(ctx, from, req, opts, body)
|
||||
if errReplay != nil {
|
||||
return nil, errReplay
|
||||
@@ -1775,6 +1778,21 @@ func ensureImageGenerationTool(body []byte, baseModel string, auth *cliproxyauth
|
||||
return body
|
||||
}
|
||||
|
||||
func normalizeCodexParallelToolCallsForTools(body []byte) []byte {
|
||||
if !gjson.GetBytes(body, "parallel_tool_calls").Exists() {
|
||||
return body
|
||||
}
|
||||
|
||||
tools := gjson.GetBytes(body, "tools")
|
||||
hasTools := tools.Exists() && tools.IsArray() && len(tools.Array()) > 0
|
||||
if hasTools {
|
||||
return body
|
||||
}
|
||||
|
||||
body, _ = sjson.DeleteBytes(body, "parallel_tool_calls")
|
||||
return body
|
||||
}
|
||||
|
||||
func publishCodexImageToolUsage(ctx context.Context, reporter *helps.UsageReporter, body []byte, completedData []byte) {
|
||||
detail, ok := helps.ParseCodexImageToolUsage(completedData)
|
||||
if !ok {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package executor
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
func TestNormalizeCodexParallelToolCallsForTools_DropsWhenToolsMissing(t *testing.T) {
|
||||
body := []byte(`{"model":"gpt-5.4","parallel_tool_calls":true,"input":"hi"}`)
|
||||
|
||||
out := normalizeCodexParallelToolCallsForTools(body)
|
||||
|
||||
if gjson.GetBytes(out, "parallel_tool_calls").Exists() {
|
||||
t.Fatalf("parallel_tool_calls should be removed when tools are missing: %s", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeCodexParallelToolCallsForTools_DropsWhenToolsEmpty(t *testing.T) {
|
||||
body := []byte(`{"model":"gpt-5.4","tools":[],"parallel_tool_calls":false,"input":"hi"}`)
|
||||
|
||||
out := normalizeCodexParallelToolCallsForTools(body)
|
||||
|
||||
if gjson.GetBytes(out, "parallel_tool_calls").Exists() {
|
||||
t.Fatalf("parallel_tool_calls should be removed when tools are empty: %s", string(out))
|
||||
}
|
||||
if !gjson.GetBytes(out, "tools").Exists() {
|
||||
t.Fatalf("tools should be preserved: %s", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeCodexParallelToolCallsForTools_PreservesWhenToolsPresent(t *testing.T) {
|
||||
body := []byte(`{"model":"gpt-5.4","tools":[{"type":"function","name":"lookup"}],"parallel_tool_calls":true,"input":"hi"}`)
|
||||
|
||||
out := normalizeCodexParallelToolCallsForTools(body)
|
||||
|
||||
if !gjson.GetBytes(out, "parallel_tool_calls").Bool() {
|
||||
t.Fatalf("parallel_tool_calls should be preserved when tools are present: %s", string(out))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user