From 3613174cf653b77508c0ed10eda816d658c928c1 Mon Sep 17 00:00:00 2001 From: YahooYuan666 Date: Thu, 1 Oct 2026 02:16:22 +0800 Subject: [PATCH] fix(grok): fail over silent-refusal empty response.completed on Grok Responses streams Issue #5009 added a failover guard for OpenAI Responses streams that terminate with an empty response.completed (no output, no usage, no error), but the guard is gated on PlatformOpenAI. Grok platform accounts reach the same handler (forwardGrokResponses -> handleStreamingResponseWithReasoning) and exhibit the same upstream silent-refusal shape, so their empty completions are relayed to the client as successful empty turns: Responses SDK clients map the empty completed to finishReason stop and accept the turn with no retry. Extend the guard to PlatformGrok, matching the unconditional guard on the passthrough path (openai_gateway_passthrough.go). Fixes #7774 --- .../internal/service/openai_gateway_response_handling.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/internal/service/openai_gateway_response_handling.go b/backend/internal/service/openai_gateway_response_handling.go index 95e5db3193..d4c8f723b6 100644 --- a/backend/internal/service/openai_gateway_response_handling.go +++ b/backend/internal/service/openai_gateway_response_handling.go @@ -687,8 +687,12 @@ func (s *OpenAIGatewayService) handleStreamingResponseWithReasoning(ctx context. // OpenAI Responses streams that terminate with an empty // response.completed (no output, no usage, no error, nothing sent // to the client) are silent upstream refusals: fail over instead of - // recording a successful 0/0 usage turn (issue #5009). - if account != nil && account.Platform == PlatformOpenAI && + // recording a successful 0/0 usage turn (issue #5009). Grok + // subscriptions behind vendor gateways show the same silent-refusal + // shape on /v1/responses (forwardGrokResponses reaches this same + // handler), so cover PlatformGrok too — the passthrough-path guard + // is already unconditional. + if account != nil && (account.Platform == PlatformOpenAI || account.Platform == PlatformGrok) && (eventType == "response.completed" || eventType == "response.done") && !sawFailedEvent && !responsesSemanticOutputSeen && !clientOutputStarted && openAIResponsesCompletedEventIsEmpty(dataBytes, usage) {