Files
CLIProxyAPI/internal
lamtran 303685c230 fix(executor/xai): drop orphaned tool_choice when Claude tools array is empty
When Claude Code sends a stop-hook evaluator request (or any request
without tools), the payload includes "tools": [] (empty array). The
claude->codex translator unconditionally emits tools: [] + tool_choice:
"auto" + parallel_tool_calls: true into the Codex Responses shape.

When that payload is routed to xAI, the upstream rejects with HTTP 400:
"A tool_choice was set on the request but no tools were specified."

Fix entirely in the xAI executor (translator package is policy-locked):
add normalizeXAIToolChoiceForTools() after normalizeXAITools() to drop
tool_choice and parallel_tool_calls whenever tools end up absent or
empty (covering both the empty-from-source case and the
all-filtered-out case where every tool was an unsupported type such as
tool_search or image_generation).

Per code-review feedback: always remove parallel_tool_calls when tools
are missing (not gated on tool_choice presence) and existence-check
each key before sjson delete to avoid unnecessary JSON parse/copy.

Verification:
- go build -o test-output ./cmd/server
- go test ./internal/runtime/executor/... -count=1
- 5 new regression tests cover empty / missing / present / orphaned
  parallel_tool_calls / no-op-when-both-absent.
2026-05-31 23:13:15 +07:00
..