fix(openai): detect official codex client by headers

This commit is contained in:
admin
2026-03-07 14:12:38 +08:00
parent 6411645ffc
commit da89583ccc
7 changed files with 170 additions and 14 deletions

View File

@@ -834,8 +834,10 @@ func logOpenAIInstructionsRequiredDebug(
}
userAgent := ""
originator := ""
if c != nil {
userAgent = strings.TrimSpace(c.GetHeader("User-Agent"))
originator = strings.TrimSpace(c.GetHeader("originator"))
}
fields := []zap.Field{
@@ -845,7 +847,7 @@ func logOpenAIInstructionsRequiredDebug(
zap.Int("upstream_status_code", upstreamStatusCode),
zap.String("upstream_error_message", msg),
zap.String("request_user_agent", userAgent),
zap.Bool("codex_official_client_match", openai.IsCodexCLIRequest(userAgent)),
zap.Bool("codex_official_client_match", openai.IsCodexOfficialClientByHeaders(userAgent, originator)),
}
fields = appendCodexCLIOnlyRejectedRequestFields(fields, c, requestBody)
@@ -968,6 +970,18 @@ func (s *OpenAIGatewayService) GenerateSessionHashWithFallback(c *gin.Context, b
return currentHash
}
func resolveOpenAIUpstreamOriginator(c *gin.Context, isOfficialClient bool) string {
if c != nil {
if originator := strings.TrimSpace(c.GetHeader("originator")); originator != "" {
return originator
}
}
if isOfficialClient {
return "codex_cli_rs"
}
return "opencode"
}
// BindStickySession sets session -> account binding with standard TTL.
func (s *OpenAIGatewayService) BindStickySession(ctx context.Context, groupID *int64, sessionHash string, accountID int64) error {
if sessionHash == "" || accountID <= 0 {
@@ -1489,7 +1503,7 @@ func (s *OpenAIGatewayService) Forward(ctx context.Context, c *gin.Context, acco
reqModel, reqStream, promptCacheKey := extractOpenAIRequestMetaFromBody(body)
originalModel := reqModel
isCodexCLI := openai.IsCodexCLIRequest(c.GetHeader("User-Agent")) || (s.cfg != nil && s.cfg.Gateway.ForceCodexCLI)
isCodexCLI := openai.IsCodexOfficialClientByHeaders(c.GetHeader("User-Agent"), c.GetHeader("originator")) || (s.cfg != nil && s.cfg.Gateway.ForceCodexCLI)
wsDecision := s.getOpenAIWSProtocolResolver().Resolve(account)
clientTransport := GetOpenAIClientTransport(c)
// 仅允许 WS 入站请求走 WS 上游,避免出现 HTTP -> WS 协议混用。
@@ -2664,11 +2678,7 @@ func (s *OpenAIGatewayService) buildUpstreamRequest(ctx context.Context, c *gin.
}
if account.Type == AccountTypeOAuth {
req.Header.Set("OpenAI-Beta", "responses=experimental")
if isCodexCLI {
req.Header.Set("originator", "codex_cli_rs")
} else {
req.Header.Set("originator", "opencode")
}
req.Header.Set("originator", resolveOpenAIUpstreamOriginator(c, isCodexCLI))
if isOpenAIResponsesCompactPath(c) {
req.Header.Set("accept", "application/json")
if req.Header.Get("version") == "" {