diff --git a/backend/internal/service/antigravity_gateway_service.go b/backend/internal/service/antigravity_gateway_service.go index 4922de3c..fa5b477b 100644 --- a/backend/internal/service/antigravity_gateway_service.go +++ b/backend/internal/service/antigravity_gateway_service.go @@ -1619,6 +1619,9 @@ func (s *AntigravityGatewayService) Forward(ctx context.Context, c *gin.Context, firstTokenMs = streamRes.firstTokenMs } + // Claude Max cache billing: 同步 ForwardResult.Usage 与客户端响应体一致 + applyClaudeMaxCacheBillingPolicyToUsage(usage, parsedRequestFromGinContext(c), claudeMaxGroupFromGinContext(c), originalModel, account.ID) + return &ForwardResult{ RequestID: requestID, Usage: *usage, diff --git a/backend/internal/service/gateway_record_usage_claude_max_test.go b/backend/internal/service/gateway_record_usage_claude_max_test.go index 2e1b5ae7..3cd86938 100644 --- a/backend/internal/service/gateway_record_usage_claude_max_test.go +++ b/backend/internal/service/gateway_record_usage_claude_max_test.go @@ -92,10 +92,10 @@ func TestRecordUsage_SimulateClaudeMaxEnabled_ProjectsUsageAndSkipsTTLOverride(t require.NotNil(t, repo.last) log := repo.last - require.Equal(t, 160, log.InputTokens) - require.Equal(t, 0, log.CacheCreationTokens) + require.Equal(t, 80, log.InputTokens) + require.Equal(t, 80, log.CacheCreationTokens) require.Equal(t, 0, log.CacheCreation5mTokens) - require.Equal(t, 0, log.CacheCreation1hTokens) + require.Equal(t, 80, log.CacheCreation1hTokens) require.False(t, log.CacheTTLOverridden, "simulate outcome should skip account ttl override") } @@ -195,5 +195,5 @@ func TestRecordUsage_SimulateClaudeMaxEnabled_ExistingCacheCreationBypassesSimul require.Equal(t, 120, log.CacheCreation5mTokens) require.Equal(t, 0, log.CacheCreation1hTokens) require.Equal(t, 120, log.CacheCreationTokens) - require.True(t, log.CacheTTLOverridden, "existing cache_creation with SimulateClaudeMax enabled should apply account ttl override") + require.False(t, log.CacheTTLOverridden, "existing cache_creation with SimulateClaudeMax enabled should skip account ttl override") } diff --git a/backend/internal/service/gateway_service.go b/backend/internal/service/gateway_service.go index 2b47509e..af34d472 100644 --- a/backend/internal/service/gateway_service.go +++ b/backend/internal/service/gateway_service.go @@ -5630,8 +5630,9 @@ func (s *GatewayService) RecordUsage(ctx context.Context, input *RecordUsageInpu if apiKey != nil { apiKeyGroup = apiKey.Group } - claudeMaxOutcome := detectClaudeMaxCacheBillingOutcomeForUsage(result.Usage, input.ParsedRequest, apiKeyGroup, result.Model) - simulatedClaudeMax := claudeMaxOutcome.Simulated + claudeMaxOutcome := applyClaudeMaxCacheBillingPolicyToUsage(&result.Usage, input.ParsedRequest, apiKeyGroup, result.Model, account.ID) + simulatedClaudeMax := claudeMaxOutcome.Simulated || + (shouldApplyClaudeMaxBillingRulesForUsage(apiKeyGroup, result.Model, input.ParsedRequest) && hasCacheCreationTokens(result.Usage)) // Cache TTL Override: 确保计费时 token 分类与账号设置一致 cacheTTLOverridden := false if account.IsCacheTTLOverrideEnabled() && !simulatedClaudeMax {