diff --git a/backend/internal/handler/composite_platform_test.go b/backend/internal/handler/composite_platform_test.go index 30f837f3c5..a879f9ffe5 100644 --- a/backend/internal/handler/composite_platform_test.go +++ b/backend/internal/handler/composite_platform_test.go @@ -22,16 +22,19 @@ func TestCompositeTargetPlatformAllowedResolvesKnownAllowedModel(t *testing.T) { require.Equal(t, service.PlatformOpenAI, platform) } -func TestOpenAICompatibleMessagesTargetAllowsCompositeGrokModel(t *testing.T) { +func TestOpenAICompatibleTextTargetAllowsCompositeGrokModel(t *testing.T) { gin.SetMode(gin.TestMode) - c, _ := gin.CreateTestContext(httptest.NewRecorder()) - c.Request = httptest.NewRequest("POST", "/v1/messages", nil) - apiKey := &service.APIKey{Group: &service.Group{Platform: service.PlatformComposite}} - require.True(t, openAICompatibleMessagesTargetAllowed(c, apiKey, "grok-4.3")) - platform, ok := service.ResolvedTargetPlatformFromContext(c.Request.Context()) - require.True(t, ok) - require.Equal(t, service.PlatformGrok, platform) + for _, path := range []string{"/v1/messages", "/v1/chat/completions"} { + c, _ := gin.CreateTestContext(httptest.NewRecorder()) + c.Request = httptest.NewRequest("POST", path, nil) + apiKey := &service.APIKey{Group: &service.Group{Platform: service.PlatformComposite}} + + require.True(t, openAICompatibleTextTargetAllowed(c, apiKey, "grok-4.3"), "path=%s", path) + platform, ok := service.ResolvedTargetPlatformFromContext(c.Request.Context()) + require.True(t, ok, "path=%s", path) + require.Equal(t, service.PlatformGrok, platform, "path=%s", path) + } } func TestCompositeTargetPlatformAllowedRejectsWrongOrUnknownModel(t *testing.T) { diff --git a/backend/internal/handler/openai_chat_completions.go b/backend/internal/handler/openai_chat_completions.go index 8ccc4fb49e..7477057113 100644 --- a/backend/internal/handler/openai_chat_completions.go +++ b/backend/internal/handler/openai_chat_completions.go @@ -76,7 +76,7 @@ func (h *OpenAIGatewayHandler) ChatCompletions(c *gin.Context) { } reqModel := modelResult.String() ensureCompositeTargetPlatform(c, apiKey, reqModel) - if !compositeTargetPlatformAllowed(c, apiKey, reqModel, service.PlatformOpenAI) { + if !openAICompatibleTextTargetAllowed(c, apiKey, reqModel) { h.errorResponse(c, http.StatusBadRequest, "invalid_request_error", "Model is not supported by this OpenAI-compatible endpoint for composite groups") return } diff --git a/backend/internal/handler/openai_gateway_handler.go b/backend/internal/handler/openai_gateway_handler.go index f623f3dfff..1e5949f36f 100644 --- a/backend/internal/handler/openai_gateway_handler.go +++ b/backend/internal/handler/openai_gateway_handler.go @@ -147,7 +147,7 @@ func allowOpenAICompatibleMessagesDispatch(apiKey *service.APIKey) bool { return apiKey.Group.AllowMessagesDispatch } -func openAICompatibleMessagesTargetAllowed(c *gin.Context, apiKey *service.APIKey, model string) bool { +func openAICompatibleTextTargetAllowed(c *gin.Context, apiKey *service.APIKey, model string) bool { return compositeTargetPlatformAllowed(c, apiKey, model, service.PlatformOpenAI, service.PlatformGrok) } @@ -877,7 +877,7 @@ func (h *OpenAIGatewayHandler) Messages(c *gin.Context) { } reqModel := modelResult.String() ensureCompositeTargetPlatform(c, apiKey, reqModel) - if !openAICompatibleMessagesTargetAllowed(c, apiKey, reqModel) { + if !openAICompatibleTextTargetAllowed(c, apiKey, reqModel) { h.anthropicErrorResponse(c, http.StatusBadRequest, "invalid_request_error", "Model is not supported by this OpenAI-compatible endpoint for composite groups") return } diff --git a/backend/internal/server/routes/gateway_test.go b/backend/internal/server/routes/gateway_test.go index fbf56959f3..c3e871a803 100644 --- a/backend/internal/server/routes/gateway_test.go +++ b/backend/internal/server/routes/gateway_test.go @@ -208,6 +208,23 @@ func TestGatewayRoutesCompositeMessagesWithGrokModelUsesOpenAIGateway(t *testing require.NotContains(t, w.Body.String(), "composite groups") } +func TestGatewayRoutesCompositeChatCompletionsWithGrokModelUsesOpenAIGateway(t *testing.T) { + router := newGatewayRoutesTestRouter(service.PlatformComposite) + + for _, path := range []string{"/v1/chat/completions", "/chat/completions"} { + req := httptest.NewRequest(http.MethodPost, path, strings.NewReader(`{"model":"grok-4.3","messages":[{"role":"user","content":"hi"}]}`)) + req.Header.Set("Content-Type", "application/json") + w := httptest.NewRecorder() + + router.ServeHTTP(w, req) + + require.NotEqual(t, http.StatusNotFound, w.Code, "path=%s", path) + require.NotContains(t, w.Body.String(), "not supported") + require.NotContains(t, w.Body.String(), "OpenAI-compatible endpoint") + require.NotContains(t, w.Body.String(), "composite groups") + } +} + func TestGatewayRoutesNonGrokVideosAreRejectedAtPlatformGate(t *testing.T) { router := newGatewayRoutesTestRouter(service.PlatformOpenAI)