From 1ddb3b3168cf2ed84adcad3921e9bb9153b211db Mon Sep 17 00:00:00 2001 From: Travis Cao Date: Thu, 13 Aug 2026 23:53:16 +0800 Subject: [PATCH] =?UTF-8?q?fix(desktop):=20one-shot=20Responses=20?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E4=BD=93=E4=B8=8D=E5=86=8D=E5=8F=91=E9=80=81?= =?UTF-8?q?=E7=A9=BA=20tools=20=E4=B8=8B=E7=9A=84=20tool=5Fchoice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit api.x.ai 对「tools 为空 + tool_choice」直接 400(invalid-argument: "A tool_choice was set on the request but no tools were specified"), 导致 xAI 会话的 Auto-review 评审 100% 失败,3 次重试后弹 AUTO_REVIEW_UNAVAILABLE,全部动作退回手动确认。 one-shot 请求从不声明 tools,删除硬编码的 tool_choice:'auto' 即可; 与 anthropic-responses-bridge translate-request 的既有约定对齐 (bridge 只在有 function tools 时才下发 tool_choice)。 两个上游端点均已实测(2026-08-13): - api.x.ai/v1/responses(grok-4.6):原 body 400,去掉 tool_choice 后 200 - chatgpt.com/backend-api/codex/responses(gpt-5.6-sol):去掉后仍 200 fix #2684 Signed-off-by: Travis Cao --- .../main/utility-model/__tests__/oneShotCandidates.test.ts | 7 ++++++- apps/desktop/src/main/utility-model/oneShotCandidates.ts | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src/main/utility-model/__tests__/oneShotCandidates.test.ts b/apps/desktop/src/main/utility-model/__tests__/oneShotCandidates.test.ts index 7bfac0bfedf..0d41108bb72 100644 --- a/apps/desktop/src/main/utility-model/__tests__/oneShotCandidates.test.ts +++ b/apps/desktop/src/main/utility-model/__tests__/oneShotCandidates.test.ts @@ -1584,10 +1584,15 @@ describe('utility one-shot candidates', () => { expect(result).toMatchObject({ ok: true, providerId: 'xai', model: 'xai/grok-4.3' }); expect(fetchMock).toHaveBeenCalledWith('https://xai.example/v1/responses', expect.anything()); - expect(JSON.parse(String(fetchMock.mock.calls[0]?.[1]?.body))).toMatchObject({ + const body = JSON.parse(String(fetchMock.mock.calls[0]?.[1]?.body)) as Record; + expect(body).toMatchObject({ model: 'grok-4.3', reasoning: { effort: 'low' }, }); + // api.x.ai rejects tool_choice when the request declares no tools + // (HTTP 400 invalid-argument), which failed every Auto-review verdict + // on xAI sessions. One-shot requests never declare tools. + expect(body).not.toHaveProperty('tool_choice'); }); it.each(['xai/grok-code-fast', 'xai/grok-build-preview'])( diff --git a/apps/desktop/src/main/utility-model/oneShotCandidates.ts b/apps/desktop/src/main/utility-model/oneShotCandidates.ts index 3462bcc59be..9b3bad6e9d1 100644 --- a/apps/desktop/src/main/utility-model/oneShotCandidates.ts +++ b/apps/desktop/src/main/utility-model/oneShotCandidates.ts @@ -974,7 +974,12 @@ async function requestProviderHttpText(input: { input: [{ type: 'message', role: 'user', content: [{ type: 'input_text', text: input.prompt }] }], ...(!minimal ? { tools: [], - tool_choice: 'auto', + // No tool_choice: one-shot requests never declare tools, and standard + // Responses endpoints reject tool_choice without tools — api.x.ai + // returns HTTP 400 "A tool_choice was set on the request but no tools + // were specified" (2026-08-13 实测), which broke every Auto-review on + // xAI sessions. The private Codex endpoint accepts the body without + // tool_choice (2026-08-13 实测, gpt-5.6-sol). parallel_tool_calls: false, store: false, stream: true,