1. 18 Feb, 2026 2 commits
  2. 17 Feb, 2026 1 commit
  3. 16 Feb, 2026 1 commit
  4. 14 Feb, 2026 2 commits
    • shaw's avatar
      feat: 区分 Anthropic 5m/1h 缓存创建 token 的差异化计费 · a817cafe
      shaw authored
      Anthropic API 的 cache_creation 对象区分了 ephemeral_5m 和 ephemeral_1h
      两种缓存创建 token,1h 单价远高于 5m(如 claude-3-5-haiku: 5m=$1/MTok,
      1h=$6/MTok)。此前系统统一按 5m 单价计费,导致计费偏低。
      
      后端:
      - pricing_service: 加载 LiteLLM 的 cache_creation_input_token_cost_above_1hr
      - billing_service: GetModelPricing 启用分类计费(安全守卫 1h>5m),
        CalculateCost 按 5m/1h 分别计费,无明细时回退到 5m 单价
      - gateway_service: parseSSEUsage/handleNonStreamingResponse 用 gjson
        提取嵌套 cache_creation 对象的 ephemeral_5m/1h_input_tokens
      - antigravity_gateway_service: extractSSEUsage/extractClaudeUsage 同步提取
      - usage_log: 修复 GORM column tag 确保写入正确的数据库列
      - 新增迁移 054: 删除 GORM 自动生成的重复列
      
      前端:
      - 使用记录 tooltip 展示 5m/1h 缓存创建明细(带彩色 badge 区分)
      - 表格单元格缓存写入数值旁显示 1h 标识
      a817cafe
    • Kortan's avatar
      ab14df04
  5. 13 Feb, 2026 3 commits
    • shaw's avatar
      fix: Anthropic 429 限流使用精确的窗口重置时间而非聚合最大值 · e6814314
      shaw authored
      当账号仅触发 5h 窗口限流时,旧逻辑从聚合头
      anthropic-ratelimit-unified-reset 读取重置时间,该值为所有窗口的
      最大值(即 7d 重置时间),导致账号被标记为不可调度约 6 天。
      
      新增 calculateAnthropic429ResetTime 函数,解析 Anthropic 的
      per-window 头(5h-utilization/reset、7d-utilization/reset、
      surpassed-threshold),判断实际触发的窗口并使用对应的重置时间:
      - 仅 5h 超标 → 使用 5h-reset(约 5 小时)
      - 仅 7d 超标 → 使用 7d-reset
      - 两者均超标 → 使用 7d-reset(较长冷却)
      - per-window 头不存在 → 回退到聚合头(向后兼容)
      e6814314
    • shaw's avatar
      fix: 修复 gosec 配置文件格式错误导致 CI 失败 · 5248097f
      shaw authored
      gosec -conf 只支持 JSON 格式,将 .gosec.yaml 转换为 .gosec.json
      5248097f
    • wucm667's avatar
      chore: 配置 gosec 排除规则 · 5f4eb9f9
      wucm667 authored
      - 新增 backend/.gosec.yaml 配置文件,排除 G704 (SSRF) 检查
      - 更新 security-scan.yml workflow,使用 gosec 配置文件
      - 原因:作为 API 网关平台,需要代理请求到配置的上游服务,所有上游 URL 来自管理员配置而非用户输入
      5f4eb9f9
  6. 11 Feb, 2026 6 commits
    • kyx236's avatar
      feat(admin): Add group filtering for account listings · fe1d46a8
      kyx236 authored
      - Add groupID parameter to ListAccounts and ListWithFilters methods
      - Implement account filtering by group ID in repository query
      - Add group query parameter parsing in account handler
      - Update all ListAccounts/ListWithFilters call sites with groupID parameter
      - Add group filter UI component to AccountTableFilters
      - Add i18n translations for group filter label in English and Chinese
      - Update API contract and test stubs to reflect new signature
      - Enable filtering accounts by their assigned groups in admin panel
      fe1d46a8
    • kyx236's avatar
      feat(admin): Add email search and rate limit filtering for accounts and redeem codes · 04a1a7c2
      kyx236 authored
      - Add used_by_email column to redeem code export CSV for better user identification
      - Implement rate_limited status filter in account listing with RateLimitResetAt check
      - Extend redeem code search to include user email in addition to code matching
      - Add API key search capability to user listing filters
      - Display user email in redeem code table used_by column for improved visibility
      - Update search placeholders in UI to reflect expanded search capabilities (email, username, notes, API key)
      - Improve Chinese and English localization strings for search hints
      04a1a7c2
    • sususu98's avatar
      fix: include Gemini thoughtsTokenCount in output token billing · d21d70a5
      sususu98 authored
      Gemini 2.5 Pro/Flash thinking models return thoughtsTokenCount separately
      from candidatesTokenCount in usageMetadata, but this field was not parsed
      or included in billing calculations, causing thinking tokens to be
      unbilled.
      
      - Add ThoughtsTokenCount field to GeminiUsageMetadata struct
      - Include thoughtsTokenCount in OutputTokens across all 3 Gemini usage
        parsing paths (non-streaming, streaming, compat layer)
      - Add tests covering thinking token scenarios
      
      Closes #554
      d21d70a5
    • Edric Li's avatar
      feat(antigravity): 添加 onboardUser 支持并修复 project_id 补齐逻辑 · a4a46a86
      Edric Li authored
      - 新增 OnboardUser API 客户端方法,支持账号 onboarding 获取 project_id
      - loadProjectIDWithRetry 增加 onboard 回退:LoadCodeAssist 未返回 project_id 时自动触发 onboarding
      - GetAccessToken 中 project_id 补齐改用轻量 FillProjectID 替代全量 RefreshAccountToken
      - 补齐逻辑增加 5 分钟冷却机制,防止频繁重试
      - OnboardUser 轮询等待改为 context 感知,支持提前取消
      - 提取 mergeCredentials 辅助方法消除重复代码
      - 新增 extractProjectIDFromOnboardResponse 和 resolveDefaultTierID 单元测试
      a4a46a86
    • SilentFlower's avatar
      [UPDATE] 优化思考预算逻辑与代码结构 · 6ae82e04
      SilentFlower authored
      🧠 refactor(antigravity): 完善 thinking 预算分配策略并重构工具构建逻辑
      6ae82e04
    • SilentFlower's avatar
      [UPDATE] 增强 Claude Thinking 模式支持与 Opus 4.6 动态预算适配 · 19cca11e
      SilentFlower authored
       feat(antigravity): 支持 thinking adaptive 类型并适配 Opus 4.6 动态预算
      🧪 test(gateway): 增加 thinking 模式解析与签名块过滤的边界用例测试
      19cca11e
  7. 10 Feb, 2026 8 commits
  8. 09 Feb, 2026 16 commits
    • Edric Li's avatar
      feat: MODEL_CAPACITY_EXHAUSTED 使用固定1s间隔重试60次,不切换账号 · 6114f69c
      Edric Li authored
      MODEL_CAPACITY_EXHAUSTED (503) 表示模型容量不足,所有账号共享同一容量池,
      切换账号无意义。改为固定1s间隔重试最多60次,重试耗尽后直接返回上游错误。
      
      - 新增 antigravityModelCapacityRetryMaxAttempts=60 和 antigravityModelCapacityRetryWait=1s
      - shouldTriggerAntigravitySmartRetry 新增 isModelCapacityExhausted 返回值
      - handleSmartRetry 对 MODEL_CAPACITY_EXHAUSTED 使用独立重试策略
      - handleModelRateLimit 对 MODEL_CAPACITY_EXHAUSTED 仅标记 Handled,不设限流
      - 重试耗尽后不设置模型限流、不清除粘性会话、不切换账号
      6114f69c
    • Edric Li's avatar
      feat: same-account retry before failover for transient errors · d6c2921f
      Edric Li authored
      For retryable transient errors (Google 400 "invalid project resource name"
      and empty stream responses), retry on the same account up to 2 times
      (with 500ms delay) before switching to another account.
      
      - Add RetryableOnSameAccount field to UpstreamFailoverError
      - Add same-account retry loop in both Gemini and Claude/OpenAI handler paths
      - Move temp-unschedule from service layer to handler layer (only after
        all same-account retries exhausted)
      - Reduce temp-unschedule cooldown from 30 minutes to 1 minute
      d6c2921f
    • Edric Li's avatar
      feat: failover and temp-unschedule on empty stream response · 61c73287
      Edric Li authored
      - Empty stream responses now return UpstreamFailoverError instead of
        plain 502, triggering automatic account switching (up to 10 retries)
      - Add tempUnscheduleEmptyResponse: accounts returning empty responses
        are temp-unscheduled for 30 minutes
      - Apply to both Claude and Gemini non-streaming paths
      - Align googleConfigErrorCooldown from 60m to 30m for consistency
      61c73287
    • Edric Li's avatar
      feat: failover and temp-unschedule on Google "Invalid project resource name" 400 · 89905ec4
      Edric Li authored
      Google 后端间歇性返回 400 "Invalid project resource name" 错误,
      此前该错误直接透传给客户端且不触发账号切换,导致请求失败。
      
      - 在 Antigravity 和 Gemini 两个平台的所有转发路径中,
        精确匹配该错误消息后触发 failover 自动换号重试
      - 命中后将账号临时封禁 1 小时,避免反复调度到同一故障账号
      - 提取共享函数 isGoogleProjectConfigError / tempUnscheduleGoogleConfigError
        消除跨 Service 的代码重复
      89905ec4
    • Rose Ding's avatar
      test: 添加单账号 503 退避重试机制的单元测试 · e4bc3515
      Rose Ding authored
      
      
      覆盖 Service 层和 Handler 层的所有新增逻辑:
      - isSingleAccountRetry context 标记检查
      - handleSmartRetry 中 503 + SingleAccountRetry 分支
      - handleSingleAccountRetryInPlace 原地重试逻辑
      - antigravityRetryLoop 预检查跳过限流
      - sleepAntigravitySingleAccountBackoff 固定延迟退避
      - 端到端集成场景验证
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      e4bc3515
    • erio's avatar
    • erio's avatar
      a70d37a6
    • erio's avatar
      fix: skip rate limiting when custom error codes don't match upstream status · 6892e84a
      erio authored
      Add ShouldHandleErrorCode guard at the entry of handleGeminiUpstreamError
      and AntigravityGatewayService.handleUpstreamError so that accounts with
      custom error codes (e.g. [599]) are not rate-limited when the upstream
      returns a non-matching status (e.g. 429).
      6892e84a
    • erio's avatar
      feat: ErrorPolicySkipped returns 500 instead of upstream status code · 73f45574
      erio authored
      When custom error codes are enabled and the upstream error code is NOT
      in the configured list, return HTTP 500 to the client instead of
      transparently forwarding the original status code.
      
      Also adds integration test TestCustomErrorCode599 verifying that 429,
      500, 503, 401, 403 all return 500 without triggering SetRateLimited
      or SetError.
      73f45574
    • Rose Ding's avatar
      fix: 单账号分组首次 503 不设模型限流标记,避免后续请求雪崩 · 021abfca
      Rose Ding authored
      单账号 antigravity 分组收到 503 (MODEL_CAPACITY_EXHAUSTED) 时,
      原逻辑会设置 ~29s 模型限流标记。由于只有一个账号无法切换,
      后续所有新请求在预检查时命中限流 → 几毫秒内直接返回 503,
      导致约 30 秒的雪崩窗口。
      
      修复:在 Handler 入口处检查分组是否只有单个 antigravity 账号,
      如果是则提前设置 SingleAccountRetry context 标记,让 Service 层
      首次 503 就走原地重试逻辑(不设限流标记),避免污染后续请求。
      021abfca
    • Rose Ding's avatar
      feat: 添加 Antigravity 单账号 503 退避重试机制 · f6cfab99
      Rose Ding authored
      当分组内只有一个可用账号且上游返回 503 (MODEL_CAPACITY_EXHAUSTED) 时,
      不再设置模型限流+切换账号(因为切换回来还是同一个账号),而是在 Service 层
      原地等待+重试,避免双重等待问题。
      
      主要变更:
      - Handler 层:检测单账号 503 场景,清除排除列表并设置 SingleAccountRetry 标记
      - Service 层:新增 handleSingleAccountRetryInPlace 原地重试逻辑
      - Service 层:预检查跳过单账号模式下的限流检查
      - 新增 ctxkey.SingleAccountRetry 上下文标记
      f6cfab99
    • shaw's avatar
      chore: update version · 51572b5d
      shaw authored
      51572b5d
    • QTom's avatar
      04cedce9
    • QTom's avatar
      feat(admin): 新增 CRS 同步预览和账号选择功能 · 5e0d7894
      QTom authored
      - 后端新增 PreviewFromCRS 接口,允许用户先预览 CRS 中的账号
      - 后端支持在同步时选择特定账号,不选中的账号将被跳过
      - 前端重构 SyncFromCrsModal 为三步向导:输入凭据 → 预览账号 → 执行同步
      - 改进表单无障碍性:添加 for/id 关联和 required 属性
      - 修复 Back 按钮返回时的状态清理
      - 新增 buildSelectedSet 和 shouldCreateAccount 的单元测试
      - 完整的向后兼容性:旧客户端不发送 selected_account_ids 时行为不变
      5e0d7894
    • erio's avatar
      fix: resolve CI failures from scope removal refactor · 9a479d1b
      erio authored
      - Fix gofmt alignment in ops_realtime_models.go
      - Remove SetAntigravityQuotaScopeLimit mock from api_contract_test.go
      - Add UpdateSortOrders mock to mockGroupRepoForGateway
      9a479d1b
    • erio's avatar
      refactor: replace scope-level rate limiting with model-level rate limiting · fc095bf0
      erio authored
      Merge functional changes from develop branch:
      - Remove AntigravityQuotaScope system (claude/gemini_text/gemini_image)
      - Replace with per-model rate limiting using resolveAntigravityModelKey
      - Remove model load statistics (IncrModelCallCount/GetModelLoadBatch)
      - Simplify account selection to unified priority→load→LRU algorithm
      - Remove SetAntigravityQuotaScopeLimit from AccountRepository
      - Clean up scope-related UI indicators and API fields
      fc095bf0
  9. 08 Feb, 2026 1 commit
    • erio's avatar
      feat: shuffle accounts within same sort group to prevent thundering herd · 1af06aed
      erio authored
      Add post-sort shuffle for accounts with identical (priority, loadRate,
      lastUsedAt) to break deterministic ordering when concurrent requests
      read the same scheduler snapshot. Applies to both Antigravity and
      OpenAI scheduling paths, plus the sortAccountsByPriorityAndLastUsed
      helper.
      
      Keeps upstream CallCount/ModelLoadInfo scheduling intact; shuffle is
      additive and only randomises within equivalent-rank groups.
      1af06aed