fix(codex): convert Grok client keepalive SSE frames to comments

- Add Grok client detection via User-Agent (including Gin context fallback) in a new `grokbuild` helper.
- Transform keepalive SSE `event`/`data` frames into `: keepalive` comments when streaming to Grok clients.
- Keep keepalive frames untouched for non-Grok clients while preserving existing stream translation behavior.

Closes: #5171
This commit is contained in:
Luis Pater
2026-08-22 20:58:35 +08:00
parent d5b57a2d8a
commit 4d68ca8a63
4 changed files with 529 additions and 2 deletions

View File

@@ -8,6 +8,7 @@ import (
"net/http"
"strings"
"github.com/router-for-me/CLIProxyAPI/v7/internal/client/grokbuild"
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
"github.com/router-for-me/CLIProxyAPI/v7/internal/runtime/executor/helps"
"github.com/router-for-me/CLIProxyAPI/v7/internal/thinking"
@@ -38,6 +39,7 @@ func (e *CodexExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
from := opts.SourceFormat
responseFormat := cliproxyexecutor.ResponseFormatOrSource(opts)
isGrokClient := grokbuild.IsGrokClientContext(ctx, opts.Headers)
to := sdktranslator.FromString("codex")
originalPayloadSource := req.Payload
if len(opts.OriginalRequest) > 0 {
@@ -163,7 +165,10 @@ func (e *CodexExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
isHandshake := false
terminalSuccess := false
if bytes.HasPrefix(line, dataTag) {
if transformed, ok := grokbuild.TransformKeepaliveSSELine(translatedLine, isGrokClient); ok {
translatedLine = transformed
isHandshake = true
} else if bytes.HasPrefix(line, dataTag) {
data := bytes.TrimSpace(line[5:])
data = helps.RestoreCodexMultiAgentV2Response(data, optimizeMultiAgentV2)
translatedLine = append([]byte("data: "), data...)
@@ -287,7 +292,9 @@ func (e *CodexExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.Au
translatedLine := bytes.Clone(line)
terminalSuccess := false
if bytes.HasPrefix(line, dataTag) {
if transformed, ok := grokbuild.TransformKeepaliveSSELine(translatedLine, isGrokClient); ok {
translatedLine = transformed
} else if bytes.HasPrefix(line, dataTag) {
data := bytes.TrimSpace(line[5:])
data = helps.RestoreCodexMultiAgentV2Response(data, optimizeMultiAgentV2)
translatedLine = append([]byte("data: "), data...)