From c797159bf54b1f7595c72d92b9d0367effbe8c7a Mon Sep 17 00:00:00 2001 From: seng1e <23146482+seng1e@users.noreply.github.com> Date: Thu, 2 Jul 2026 11:09:50 +0800 Subject: [PATCH] fix(openai): skip Codex image bridge injections for /responses/compact The Codex image_generation bridge block in Forward injects tools:[image_generation] and tool_choice:"auto" (since #3498) into every Codex request, including /responses/compact. The upstream compact endpoint rejects tool_choice with 400 "Unknown parameter: 'tool_choice'", so every remote compaction fails once the bridge is enabled. Guard the whole image generation block with !isCompactRequest. Fixes #3629 --- .../service/openai_gateway_service.go | 4 ++- .../openai_image_generation_controls_test.go | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/backend/internal/service/openai_gateway_service.go b/backend/internal/service/openai_gateway_service.go index 6de5164a9c..88d3d9e7d1 100644 --- a/backend/internal/service/openai_gateway_service.go +++ b/backend/internal/service/openai_gateway_service.go @@ -2794,7 +2794,9 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco return nil, errors.New("image generation disabled for group") } - if imageGenerationAllowed && (codexImageGenerationBridgeEnabled || isOpenAIImageGenerationModel(requestView.Model) || openAIRequestBodyImageGenerationToolNeedsNormalization(body) || isOpenAIImageGenerationModel(upstreamModel)) { + // /responses/compact 是会话压缩请求:上游不接受 tool_choice(400 unknown_parameter), + // 注入 image_generation 工具也没有意义,整块豁免。 + if imageGenerationAllowed && !isCompactRequest && (codexImageGenerationBridgeEnabled || isOpenAIImageGenerationModel(requestView.Model) || openAIRequestBodyImageGenerationToolNeedsNormalization(body) || isOpenAIImageGenerationModel(upstreamModel)) { decoded, decodeErr := ensureReqBody() if decodeErr != nil { return nil, decodeErr diff --git a/backend/internal/service/openai_image_generation_controls_test.go b/backend/internal/service/openai_image_generation_controls_test.go index e0834fa105..6061a0bf9c 100644 --- a/backend/internal/service/openai_image_generation_controls_test.go +++ b/backend/internal/service/openai_image_generation_controls_test.go @@ -208,6 +208,35 @@ func TestOpenAIGatewayServiceForward_CodexBridgePreservesExistingToolChoice(t *t require.Equal(t, "image_generation", gjson.GetBytes(upstream.lastBody, "tool_choice.type").String()) } +func TestOpenAIGatewayServiceForward_CodexBridgeSkipsCompactRequests(t *testing.T) { + gin.SetMode(gin.TestMode) + + upstream := &httpUpstreamRecorder{ + resp: &http.Response{ + StatusCode: http.StatusOK, + Header: http.Header{"Content-Type": []string{"application/json"}}, + Body: io.NopCloser(strings.NewReader(`{"id":"resp_codex_compact","model":"gpt-5.4","usage":{"input_tokens":1,"output_tokens":1}}`)), + }, + } + svc := newOpenAIImageGenerationControlTestService(upstream) + svc.cfg.Gateway.CodexImageGenerationBridgeEnabled = true + c, _ := newOpenAIImageGenerationControlTestContext(true, "codex_cli_rs/0.98.0") + c.Request = httptest.NewRequest(http.MethodPost, "/openai/v1/responses/compact", nil) + c.Request.Header.Set("User-Agent", "codex_cli_rs/0.98.0") + account := newOpenAIImageGenerationControlTestAccount() + + // /responses/compact 上游不接受 tool_choice,bridge 注入必须整体豁免 compact 请求。 + result, err := svc.Forward(context.Background(), c, account, []byte(`{"model":"gpt-5.4","input":"summarize the conversation","stream":false}`)) + + require.NoError(t, err) + require.NotNil(t, result) + require.NotNil(t, upstream.lastReq) + require.False(t, gjson.GetBytes(upstream.lastBody, "tool_choice").Exists()) + require.False(t, gjson.GetBytes(upstream.lastBody, `tools.#(type=="image_generation")`).Exists()) + instructions := gjson.GetBytes(upstream.lastBody, "instructions").String() + require.NotContains(t, instructions, "image_generation") +} + func TestOpenAIGatewayService_CodexImageGenerationBridgeOverridePrecedence(t *testing.T) { groupID := int64(4242)