diff --git a/backend/internal/service/account_usage_service.go b/backend/internal/service/account_usage_service.go index 12cb87dd..2fa5f707 100644 --- a/backend/internal/service/account_usage_service.go +++ b/backend/internal/service/account_usage_service.go @@ -96,6 +96,7 @@ const ( apiCacheTTL = 3 * time.Minute windowStatsCacheTTL = 1 * time.Minute openAIProbeCacheTTL = 10 * time.Minute + openAICodexProbeVersion = "0.104.0" ) // UsageCache 封装账户使用量相关的缓存 @@ -400,7 +401,7 @@ func (s *AccountUsageService) probeOpenAICodexSnapshot(ctx context.Context, acco req.Header.Set("Accept", "text/event-stream") req.Header.Set("OpenAI-Beta", "responses=experimental") req.Header.Set("Originator", "codex_cli_rs") - req.Header.Set("Version", codexCLIVersion) + req.Header.Set("Version", openAICodexProbeVersion) req.Header.Set("User-Agent", codexCLIUserAgent) if s.identityCache != nil { if fp, fpErr := s.identityCache.GetFingerprint(reqCtx, account.ID); fpErr == nil && fp != nil && strings.TrimSpace(fp.UserAgent) != "" { diff --git a/backend/internal/service/openai_gateway_service_test.go b/backend/internal/service/openai_gateway_service_test.go index 6c8f4f52..c8efe6b3 100644 --- a/backend/internal/service/openai_gateway_service_test.go +++ b/backend/internal/service/openai_gateway_service_test.go @@ -1288,90 +1288,6 @@ func TestOpenAIUpdateCodexUsageSnapshotFromHeaders(t *testing.T) { } } -func TestOpenAIResponsesRequestPathSuffix(t *testing.T) { - gin.SetMode(gin.TestMode) - rec := httptest.NewRecorder() - c, _ := gin.CreateTestContext(rec) - - tests := []struct { - name string - path string - want string - }{ - {name: "exact v1 responses", path: "/v1/responses", want: ""}, - {name: "compact v1 responses", path: "/v1/responses/compact", want: "/compact"}, - {name: "compact alias responses", path: "/responses/compact/", want: "/compact"}, - {name: "nested suffix", path: "/openai/v1/responses/compact/detail", want: "/compact/detail"}, - {name: "unrelated path", path: "/v1/chat/completions", want: ""}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c.Request = httptest.NewRequest(http.MethodPost, tt.path, nil) - require.Equal(t, tt.want, openAIResponsesRequestPathSuffix(c)) - }) - } -} - -func TestOpenAIBuildUpstreamRequestOpenAIPassthroughPreservesCompactPath(t *testing.T) { - gin.SetMode(gin.TestMode) - rec := httptest.NewRecorder() - c, _ := gin.CreateTestContext(rec) - c.Request = httptest.NewRequest(http.MethodPost, "/v1/responses/compact", bytes.NewReader([]byte(`{"model":"gpt-5"}`))) - - svc := &OpenAIGatewayService{} - account := &Account{Type: AccountTypeOAuth} - - req, err := svc.buildUpstreamRequestOpenAIPassthrough(c.Request.Context(), c, account, []byte(`{"model":"gpt-5"}`), "token") - require.NoError(t, err) - require.Equal(t, chatgptCodexURL+"/compact", req.URL.String()) - require.Equal(t, "application/json", req.Header.Get("Accept")) - require.Equal(t, codexCLIVersion, req.Header.Get("Version")) - require.NotEmpty(t, req.Header.Get("Session_Id")) -} - -func TestOpenAIBuildUpstreamRequestCompactForcesJSONAcceptForOAuth(t *testing.T) { - gin.SetMode(gin.TestMode) - rec := httptest.NewRecorder() - c, _ := gin.CreateTestContext(rec) - c.Request = httptest.NewRequest(http.MethodPost, "/v1/responses/compact", bytes.NewReader([]byte(`{"model":"gpt-5"}`))) - - svc := &OpenAIGatewayService{} - account := &Account{ - Type: AccountTypeOAuth, - Credentials: map[string]any{"chatgpt_account_id": "chatgpt-acc"}, - } - - req, err := svc.buildUpstreamRequest(c.Request.Context(), c, account, []byte(`{"model":"gpt-5"}`), "token", false, "", true) - require.NoError(t, err) - require.Equal(t, chatgptCodexURL+"/compact", req.URL.String()) - require.Equal(t, "application/json", req.Header.Get("Accept")) - require.Equal(t, codexCLIVersion, req.Header.Get("Version")) - require.NotEmpty(t, req.Header.Get("Session_Id")) -} - -func TestOpenAIBuildUpstreamRequestPreservesCompactPathForAPIKeyBaseURL(t *testing.T) { - gin.SetMode(gin.TestMode) - rec := httptest.NewRecorder() - c, _ := gin.CreateTestContext(rec) - c.Request = httptest.NewRequest(http.MethodPost, "/responses/compact", bytes.NewReader([]byte(`{"model":"gpt-5"}`))) - - svc := &OpenAIGatewayService{cfg: &config.Config{ - Security: config.SecurityConfig{ - URLAllowlist: config.URLAllowlistConfig{Enabled: false}, - }, - }} - account := &Account{ - Type: AccountTypeAPIKey, - Platform: PlatformOpenAI, - Credentials: map[string]any{"base_url": "https://example.com/v1"}, - } - - req, err := svc.buildUpstreamRequest(c.Request.Context(), c, account, []byte(`{"model":"gpt-5"}`), "token", false, "", false) - require.NoError(t, err) - require.Equal(t, "https://example.com/v1/responses/compact", req.URL.String()) -} - // ==================== P1-08 修复:model 替换性能优化测试 ============= func TestReplaceModelInSSELine(t *testing.T) { svc := &OpenAIGatewayService{}