1. 18 Mar, 2026 5 commits
    • erio's avatar
      feat: map claude-haiku-4-5 variants to claude-sonnet-4-6 · af96c8ea
      erio authored
      Update model mapping target for claude-haiku-4-5 and
      claude-haiku-4-5-20251001 from claude-sonnet-4-5 to claude-sonnet-4-6.
      Includes migration script, default constants, and test updates.
      af96c8ea
    • shaw's avatar
      fix: 兼容 Claude Code v2.1.78+ 新 JSON 格式 metadata.user_id · a14babdc
      shaw authored
      Claude Code v2.1.78 起将 metadata.user_id 从拼接字符串改为 JSON:
      旧: user_{hex}_account_{uuid}_session_{uuid}
      新: {"device_id":"...","account_uuid":"...","session_id":"..."}
      
      新增集中解析/格式化模块 metadata_userid.go:
      - ParseMetadataUserID: 自动识别两种格式,提取 DeviceID/AccountUUID/SessionID
      - FormatMetadataUserID: 根据 UA 版本输出对应格式(>= 2.1.78 输出 JSON)
      - ExtractCLIVersion: 从 UA 提取版本号,消除与 ClaudeCodeValidator.ExtractVersion 的重复
      
      修改消费者统一使用新模块:
      - claude_code_validator: 用 ParseMetadataUserID 替代只匹配旧格式的 userIDPattern
      - identity_service: RewriteUserID/WithMasking 增加 fingerprintUA 参数,
        解析用 ParseMetadataUserID,输出用 FormatMetadataUserID(版本感知)
      - gateway_service: GenerateSessionHash 用 ParseMetadataUserID 提取 session_id,
        buildOAuthMetadataUserID 用 FormatMetadataUserID 输出版本匹配格式,
        两处 RewriteUserIDWithMasking 调用传入 fp.UserAgent
      - account_test_service: generateSessionString 改用 FormatMetadataUserID,
        自动跟随 DefaultHeaders UA 版本
      
      删除三个旧正则: userIDPattern, userIDRegex, sessionIDRegex
      统一 hex 匹配为 [a-fA-F0-9],修复旧 userIDRegex 只匹配小写的不一致
      a14babdc
    • QTom's avatar
      feat(admin): 分组管理新增容量列(并发/会话/RPM 实时聚合) · d4cc9871
      QTom authored
      
      
      复用 GroupCapacityService,在 admin 分组列表中添加容量列,
      显示每个分组的实时并发/会话/RPM 使用量和上限。
      Co-Authored-By: default avatarClaude Opus 4.6 (1M context) <noreply@anthropic.com>
      d4cc9871
    • QTom's avatar
      feat(admin): 分组管理列表新增用量列与账号数分类 · 961c30e7
      QTom authored
      
      
      分组管理列表增强:
      
      1. 今日/累计用量列:
         - 新增独立端点 GET /admin/groups/usage-summary
         - 一次查询返回所有分组的今日费用和累计费用(actual_cost)
         - 前端异步加载后合并显示在分组列表中
      
      2. 账号数区分可用/限流/总量:
         - 将账号数列从单一总量改为 badge 内多行展示
         - 可用: active + schedulable 的账号数(绿色)
         - 限流: rate_limit/overload/temp_unschedulable 的账号数(橙色,无限流时隐藏)
         - 总量: 全部关联账号数
      Co-Authored-By: default avatarClaude Opus 4.6 (1M context) <noreply@anthropic.com>
      961c30e7
    • Gemini Wen's avatar
      feat: add platform type filter to subscription management page · 50a3c7fa
      Gemini Wen authored
      
      
      Add a platform filter dropdown to the admin subscriptions view, allowing
      filtering subscriptions by platform (Anthropic, OpenAI, Gemini, etc.)
      through the group association.
      Co-Authored-By: default avatarClaude Opus 4.6 (1M context) <noreply@anthropic.com>
      50a3c7fa
  2. 17 Mar, 2026 2 commits
  3. 16 Mar, 2026 11 commits
    • erio's avatar
      refactor(antigravity): unify TestConnection with dispatch retry loop · a6f99cf5
      erio authored
      TestConnection now reuses antigravityRetryLoop instead of a standalone
      HTTP loop, gaining credits overages, smart retry, and 429/503 backoff
      for free. AccountSwitchError is caught and surfaced as a friendly
      message. Also populates RateLimitedModel in TempUnscheduled switch error.
      
      Test fixes:
      - Use RATE_LIMIT_EXCEEDED in 503 short-delay test to avoid 60x1s timeout
      - Clamp waitDuration=0 instead of 999s to avoid 15s max-wait timeout
      - Enhance mockSmartRetryUpstream with repeatLast and body caching
      a6f99cf5
    • erio's avatar
      feat(dashboard): add per-user drill-down for group, model, and endpoint distributions · 4b41e898
      erio authored
      Click on a group name, model name, or endpoint name in the distribution
      tables to expand and show per-user usage breakdown (requests, tokens,
      actual cost, standard cost).
      
      Backend: new GET /admin/dashboard/user-breakdown API with group_id,
      model, endpoint, endpoint_type filters.
      Frontend: clickable rows with expand/collapse sub-table in all three
      distribution charts.
      4b41e898
    • Elysia's avatar
      fix(usage): use real reset header for session window instead of prediction · 668e1647
      Elysia authored
      
      
      The 5h window reset time displayed for Setup Token accounts was inaccurate
      because UpdateSessionWindow predicted the window end as "current hour + 5h"
      instead of reading the actual `anthropic-ratelimit-unified-5h-reset` response
      header. This caused the countdown to differ from the official Claude page.
      
      Backend: parse the reset header (Unix timestamp) and use it as the real
      window end, falling back to the hour-truncated prediction only when the
      header is absent. Also correct stale predictions when a subsequent request
      provides the real reset time.
      
      Frontend: add a reactive 60s timer so the reset countdown in
      UsageProgressBar ticks down in real-time instead of freezing at the
      initial value.
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      668e1647
    • Elysia's avatar
      fix(oauth): extract system-role input items into instructions field · fa2e6188
      Elysia authored
      
      
      OAuth upstreams (ChatGPT) reject requests containing role:"system" in
      the input array with HTTP 400 "System messages are not allowed". Extract
      such items before forwarding and merge their content into the top-level
      instructions field, prepending to any existing value.
      Co-Authored-By: default avatarClaude Sonnet 4.6 <noreply@anthropic.com>
      fa2e6188
    • Ethan0x0000's avatar
    • QTom's avatar
      feat(backup): 备份/恢复异步化,解决 504 超时 · c1fab7f8
      QTom authored
      
      
      POST /backups 和 POST /backups/:id/restore 改为异步:立即返回 HTTP 202,
      后台 goroutine 独立执行 pg_dump → gzip → S3 上传,前端每 2s 轮询状态。
      
      后端:
      - 新增 StartBackup/StartRestore 方法,后台 goroutine 不依赖 HTTP 连接
      - Graceful shutdown 等待活跃操作完成,启动时清理孤立 running 记录
      - BackupRecord 新增 progress/restore_status 字段支持进度和恢复状态追踪
      
      前端:
      - 创建备份/恢复后轮询 GET /backups/:id 直到完成或失败
      - 标签页切换暂停/恢复轮询,组件卸载清理定时器
      - 正确处理 409(备份进行中)和轮询超时
      Co-Authored-By: default avatarClaude Opus 4.6 (1M context) <noreply@anthropic.com>
      c1fab7f8
    • kunish's avatar
      fix(antigravity): add stream keepalive to prevent connection drops · d7957343
      kunish authored
      Antigravity streaming handlers were missing the keepalive mechanism
      that exists in the standard gateway, causing proxy/CDN idle timeouts
      to break connections during long thinking phases (e.g. claude-opus-4-6).
      This resulted in truncated responses with missing tool calls.
      
      Add StreamKeepaliveInterval support to all three Antigravity streaming
      paths: Claude SSE, Gemini SSE, and upstream passthrough.
      d7957343
    • Ethan0x0000's avatar
      fix: always attach OpenAI 5h/7d window stats regardless of zero values · fa782e70
      Ethan0x0000 authored
      Removes hasMeaningfulWindowStats guard so the /usage endpoint consistently
      returns WindowStats for both time windows. The frontend now controls
      zero-value display filtering at the component level.
      fa782e70
    • Ethan0x0000's avatar
      fix: allow empty extra payload to clear account quota limits · afd72abc
      Ethan0x0000 authored
      UpdateAccount previously required len(input.Extra) > 0, causing explicit
      empty payloads (extra:{}) to be silently skipped. Change condition to
      input.Extra != nil so clearing quota keys actually persists.
      afd72abc
    • QTom's avatar
      fix(gateway): WS 连接池条件式 MarkBroken 防止跨请求串流 · 3741617e
      QTom authored
      正常终端事件(response.completed 等)退出后连接归还复用,
      仅异常路径(读写错误、error 事件、客户端断连)MarkBroken 销毁。
      
      Generate 模式:
      - 引入 cleanExit 标记,仅在 isTerminalEvent break 时设置 true
      - defer 中根据 cleanExit 决定是否 MarkBroken
      - 所有异常路径已在各自分支中提前调用 MarkBroken
      
      Ingress 模式:
      - 引入 lastTurnClean 标记,sendAndRelay 正常完成时设为 true
      - releaseSessionLease 根据 lastTurnClean 决定是否 MarkBroken
      - 错误路径重置 lastTurnClean = false
      - 客户端断连后 drain 仍保守 MarkBroken(L2916)
      3741617e
    • QTom's avatar
      fix(gateway): 防止 OpenAI Codex 跨用户串流 · ab4e8b2c
      QTom authored
      根因:多个用户共享同一 OAuth 账号时,conversation_id/session_id 头
      未做用户隔离,导致上游 chatgpt.com 将不同用户的请求关联到同一会话。
      
      HTTP SSE 修复:
      - 新增 isolateOpenAISessionID(apiKeyID, raw),将 API Key ID 混入
        session 标识符(xxhash),确保不同 Key 的用户产生不同上游会话
      - buildUpstreamRequest: OAuth 分支先 Del 客户端透传的 session 头,
        再用隔离值覆盖
      - buildUpstreamRequestOpenAIPassthrough: 透传路径同样隔离
      - ForwardAsAnthropic: Anthropic Messages 兼容路径同步修复
      - buildOpenAIWSHeaders: WS 路径的 OAuth session 头同步隔离
      ab4e8b2c
  4. 15 Mar, 2026 16 commits
  5. 14 Mar, 2026 6 commits
    • shaw's avatar
      fix: remove unused saveRecords method to pass lint · 39f8bd91
      shaw authored
      39f8bd91
    • erio's avatar
      fix(ops): tune aggregation constants to prevent PG overload · f59b66b7
      erio authored
      Increase MAX(bucket_start) query timeout from 3s to 5s to reduce
      timeout-induced fallbacks. Shrink backfill window from 30 days to
      1 hour so that fallback recomputation stays lightweight instead of
      scanning the entire retention range.
      f59b66b7
    • Rose Ding's avatar
      fix: 按 review 意见重构数据库备份服务(安全性 + 架构 + 健壮性) · 1047f973
      Rose Ding authored
      
      
      1. S3 凭证加密存储:使用 SecretEncryptor (AES-256-GCM) 加密 SecretAccessKey,
         防止备份文件中泄露 S3 凭证,兼容旧的未加密数据
      2. 修复 saveRecord 竞态条件:添加 recordsMu 互斥锁保护 records 的 load/save
      3. 恢复操作增加服务端验证:handler 层要求重新输入管理员密码,通过 bcrypt
         校验,前端弹出密码输入框
      4. pg_dump/psql/S3 操作抽象为接口:定义 DBDumper 和 BackupObjectStore 接口,
         实现放入 repository 层,遵循项目依赖注入架构规范
      5. 改为流式处理避免大数据库 OOM:备份时 pg_dump stdout -> gzip -> io.Pipe ->
         S3 upload;恢复时 S3 download -> gzip reader -> psql stdin,不再全量加载
      6. loadRecords 区分"无数据"和"数据损坏"场景:JSON 解析失败返回明确错误
      7. 添加 18 个核心逻辑单元测试:覆盖加密、并发、流式备份/恢复、错误处理等
      Co-Authored-By: default avatarClaude Opus 4.6 <noreply@anthropic.com>
      1047f973
    • wucm667's avatar
    • SsageParuders's avatar
      e0f290fd
    • SsageParuders's avatar
      refactor: merge bedrock-apikey into bedrock with auth_mode credential · 4644af2c
      SsageParuders authored
      Consolidate two separate channel types (bedrock + bedrock-apikey) into
      a single "AWS Bedrock" channel. Authentication mode is now distinguished
      by credentials.auth_mode ("sigv4" | "apikey") instead of separate types.
      
      Backend:
      - Remove AccountTypeBedrockAPIKey constant
      - IsBedrock() simplified; IsBedrockAPIKey() checks auth_mode
      - Add IsAPIKeyOrBedrock() helper to eliminate repeated type checks
      - Extend pool mode, quota scheduling, and billing to bedrock
      - Add RetryableOnSameAccount to handleBedrockUpstreamErrors
      - Add "bedrock" scope to Beta Policy for independent control
      
      Frontend:
      - Merge two buttons into one "AWS Bedrock" with auth mode radio
      - Badge displays "Anthropic | AWS"
      - Pool mode and quota limit UI available for bedrock
      - Quota display in account list (usage bars, capacity badges, reset)
      - Remove all bedrock-apikey type references
      4644af2c