1. 05 Feb, 2026 11 commits
    • yangjianbo's avatar
      9e1535e2
    • shaw's avatar
      fix: 修复管理页面活跃会话数始终显示为0的问题 · ae1934f7
      shaw authored
      问题原因:Redis Pipeline 执行 Lua 脚本时出现 NOSCRIPT 错误,
      因为 redis.NewScript 使用 EVALSHA 执行脚本,当 Redis 重启或
      脚本未被缓存时,Pipeline 模式无法自动回退到 EVAL。
      
      解决方案:在 NewSessionLimitCache 初始化时预加载所有 Lua 脚本
      到 Redis,确保后续 Pipeline 执行时脚本已被缓存。
      ae1934f7
    • shaw's avatar
      feat: 新增全局错误透传规则功能 · 39e05a2d
      shaw authored
      支持管理员配置上游错误如何返回给客户端:
      - 新增 ErrorPassthroughRule 数据模型和 Ent Schema
      - 实现规则的 CRUD API(/admin/error-passthrough-rules)
      - 支持按错误码、关键词匹配,支持 any/all 匹配模式
      - 支持按平台过滤(anthropic/openai/gemini/antigravity)
      - 支持透传或自定义响应状态码和错误消息
      - 实现两级缓存(Redis + 本地内存)和多实例同步
      - 集成到 gateway_handler 的错误处理流程
      - 新增前端管理界面组件
      - 新增单元测试覆盖核心匹配逻辑
      
      优化:
      - 移除 refreshLocalCache 中的冗余排序(数据库已排序)
      - 后端 Validate() 增加匹配条件非空校验
      39e05a2d
    • ianshaw's avatar
      7b46bbb6
    • ianshaw's avatar
      feat(gemini): 增强 API 授权错误处理,自动提取并显示激活 URL · d2527e36
      ianshaw authored
      当 Gemini for Google Cloud API 未启用时(SERVICE_DISABLED 错误),
      系统现在会:
      - 自动检测 403 PERMISSION_DENIED 错误
      - 从错误响应中提取 API 激活 URL
      - 向用户显示清晰的错误消息和可点击的激活链接
      - 提供操作指引(启用后等待几分钟)
      
      新增文件:
      - internal/pkg/googleapi/error.go: Google API 错误解析器
      - internal/pkg/googleapi/error_test.go: 完整的测试覆盖
      - GEMINI_API_ERROR_HANDLING.md: 实现文档
      
      修改文件:
      - internal/repository/geminicli_codeassist_client.go:
        在 LoadCodeAssist 和 OnboardUser 中增强错误处理
      
      这大大改善了用户体验,用户不再需要手动从错误日志中查找激活 URL。
      d2527e36
    • shaw's avatar
      feat: 支持用户专属分组倍率配置 · 2b192f7d
      shaw authored
      2b192f7d
    • IanShaw027's avatar
      fix(gemini): 修复已注册用户 OAuth 授权时错误调用 onboardUser 的问题 · 979114db
      IanShaw027 authored
      问题:Google One Ultra 等已注册用户在 OAuth 授权时,如果 LoadCodeAssist
      返回了 currentTier/paidTier 但没有返回 cloudaicompanionProject,之前的
      逻辑会继续调用 onboardUser,导致 INVALID_ARGUMENT 错误。
      
      修复:对齐 Gemini CLI 的处理逻辑:
      - 当检测到用户已注册(有 currentTier/paidTier)时,不再调用 onboardUser
      - 先尝试从 Cloud Resource Manager 获取可用项目
      - 如果仍无法获取,返回友好的错误提示,引导用户手动填写 Project ID
      
      这个修复解决了 Google One 订阅用户无法正常授权的问题。
      979114db
    • Lemon's avatar
      39a0359d
    • shaw's avatar
      feat(auth): 实现 Refresh Token 机制 · 49a3c437
      shaw authored
      - 新增 Access Token + Refresh Token 双令牌认证
      - 支持 Token 自动刷新和轮转
      - 添加登出和撤销所有会话接口
      - 前端实现无感刷新和主动刷新定时器
      49a3c437
    • JIA-ss's avatar
      feat(gateway): filter /v1/usage stats by API Key instead of UserID · fa3ea5ee
      JIA-ss authored
      
      
      Previously the /v1/usage endpoint aggregated usage stats (today/total
      tokens, cost, RPM/TPM) across all API Keys belonging to the user.
      This made it impossible to distinguish usage from different API Keys
      (e.g. balance vs subscription keys).
      
      Now the usage stats are filtered by the current request's API Key ID,
      so each key only sees its own usage data. The balance/remaining fields
      are unaffected and still reflect the user-level wallet balance.
      
      Changes:
      - Add GetAPIKeyDashboardStats to repository interface and implementation
      - Add getPerformanceStatsByAPIKey helper (also fixes TPM to include
        cache_creation_tokens and cache_read_tokens)
      - Add GetAPIKeyDashboardStats to UsageService
      - Update Usage handler to call GetAPIKeyDashboardStats(apiKey.ID)
      Co-Authored-By: default avatarClaude Opus 4.5 <noreply@anthropic.com>
      fa3ea5ee
    • shaw's avatar
      fix(gateway): 修复工具名转换破坏 Anthropic 特殊工具的问题 · 05af95da
      shaw authored
      未知工具名不再进行 PascalCase/snake_case 转换,保持原样透传。
      修复 text_editor_20250728 等 Anthropic 特殊工具被错误转换的问题。
      05af95da
  2. 04 Feb, 2026 4 commits
  3. 03 Feb, 2026 25 commits
    • shaw's avatar
      chore: fix gofmt formatting · df1c2383
      shaw authored
      df1c2383
    • liuxiongfeng's avatar
      fix(gemini): 导出 DummyThoughtSignature 常量并修复跨账号签名验证 · 6baf8108
      liuxiongfeng authored
      - 将 dummyThoughtSignature 改为导出的 DummyThoughtSignature 常量,供跨包使用
      - 修改 gemini_native_signature_cleaner.go 将删除签名改为替换为 dummy 签名
        这样可以跳过 Gemini 3 的签名验证,解决粘性会话切换账号时的验证失败问题
      - 更新相关测试文件
      
      Fixes: 粘性会话切换账号时 thoughtSignature 验证失败导致 400 错误
      6baf8108
    • liuxiongfeng's avatar
      fix(openai): 统一 OAuth instructions 处理逻辑,修复 Codex CLI 400 错误 · 9a48b2e9
      liuxiongfeng authored
      - 修改 applyCodexOAuthTransform 函数签名,增加 isCodexCLI 参数
      - 移除 && !isCodexCLI 条件,对所有 OAuth 请求统一处理
      - 新增 applyInstructions/applyCodexCLIInstructions/applyOpenCodeInstructions 辅助函数
      - 新增 isInstructionsEmpty 函数检查 instructions 字段是否为空
      - 添加 Codex CLI 和非 Codex CLI 场景的测试用例
      
      逻辑说明:
      - Codex CLI + 有 instructions: 保持不变
      - Codex CLI + 无 instructions: 补充 opencode 指令
      - 非 Codex CLI: 使用 opencode 指令覆盖
      9a48b2e9
    • bayma888's avatar
      fix(lint): format gateway_service.go with gofmt · 3fed478e
      bayma888 authored
      3fed478e
    • bayma888's avatar
      fix(test): update API contract tests for new quota fields · 0afc5d0b
      bayma888 authored
      Add quota, quota_used, expires_at fields to expected JSON responses
      in POST /api/v1/keys and GET /api/v1/keys test cases.
      0afc5d0b
    • bayma888's avatar
      fix(test): add IncrementQuotaUsed to all APIKeyRepository test stubs · be7bc658
      bayma888 authored
      - Add missing IncrementQuotaUsed method to stubApiKeyRepo in api_contract_test.go
      - Fix gofmt formatting issues in api_key_service.go, dto/types.go, api_key_handler.go
      be7bc658
    • bayma888's avatar
      fix(test): add IncrementQuotaUsed to all APIKeyRepository test stubs · e59e3a9f
      bayma888 authored
      Add the missing IncrementQuotaUsed method to:
      - fakeAPIKeyRepo (api_key_auth_google_test.go)
      - stubApiKeyRepo (api_key_auth_test.go)
      - apiKeyRepoStub (api_key_service_delete_test.go)
      - authRepoStub (api_key_service_cache_test.go)
      e59e3a9f
    • bayma888's avatar
      feat(api-key): add independent quota and expiration support · 6146be14
      bayma888 authored
      This feature allows API Keys to have their own quota limits and expiration
      times, independent of the user's balance.
      
      Backend:
      - Add quota, quota_used, expires_at fields to api_key schema
      - Implement IsExpired() and IsQuotaExhausted() checks in middleware
      - Add ResetQuota and ClearExpiration API endpoints
      - Integrate quota billing in gateway handlers (OpenAI, Anthropic, Gemini)
      - Include quota/expiration fields in auth cache for performance
      - Expiration check returns 403, quota exhausted returns 429
      
      Frontend:
      - Add quota and expiration inputs to key create/edit dialog
      - Add quick-select buttons for expiration (+7, +30, +90 days)
      - Add reset quota confirmation dialog
      - Add expires_at column to keys list
      - Add i18n translations for new features (en/zh)
      
      Migration:
      - Add 045_add_api_key_quota.sql for new columns
      6146be14
    • bayma888's avatar
      fix(test): add missing stub methods to stubRedeemCodeRepo in api_contract_test · 730d2a9a
      bayma888 authored
      Add ListByUserPaginated and SumPositiveBalanceByUser methods
      730d2a9a
    • bayma888's avatar
      fix(test): add missing stub methods for RedeemCodeRepository and AdminService · d008941c
      bayma888 authored
      Add ListByUserPaginated and SumPositiveBalanceByUser to redeemRepoStub
      Add GetUserBalanceHistory to stubAdminService
      
      Fixes CI test compilation errors
      d008941c
    • JIA-ss's avatar
      fix(proxy): 增加代理探测的多 URL 回退机制 · df7a3e65
      JIA-ss authored
      
      
      某些 AI API 专用代理只允许访问特定域名(如 anthropic.com、openai.com),
      会拦截对 ip-api.com 的请求。本次修改增加了多 URL 回退机制:
      
      1. 优先使用 ip-api.com(可获取详细地理信息:城市、地区、国家)
      2. 若失败则回退到 httpbin.org/ip(仅获取 IP 地址,速度快)
      
      主要变更:
      - 新增 probeURLs 列表支持多个探测 URL
      - 重构 ProbeProxy() 实现回退逻辑
      - 新增 parseHTTPBin() 解析 httpbin.org 响应
      - 优化错误信息,JSON 解析失败时显示响应体前 200 字符
      Co-Authored-By: default avatarClaude <noreply@anthropic.com>
      df7a3e65
    • song's avatar
      chore: gofmt · 0707f3d9
      song authored
      0707f3d9
    • song's avatar
      chore: gofmt · f1aafbc0
      song authored
      f1aafbc0
    • song's avatar
      fix: update tests for group fallback · 7cb5444d
      song authored
      7cb5444d
    • JIA-ss's avatar
      fix(api): 修复 thinking 块被意外修改导致的 400 错误 · ad90bb46
      JIA-ss authored
      
      
      问题描述:
      使用扩展思考功能时,偶现以下错误:
      "thinking or redacted_thinking blocks in the latest assistant message cannot be modified"
      
      根因分析:
      当代理服务修改请求体中的某些字段时(如 metadata.user_id、model),
      使用 map[string]any 解析整个 JSON 后重新序列化,导致:
      1. 字段顺序改变(Go map 序列化按字母排序)
      2. 数字格式变化(如 1.0 → 1)
      3. Unicode 转义变化
      
      Claude API 对 thinking 块进行字节级验证,任何变化都会触发错误。
      
      修复内容:
      1. identity_service.go - RewriteUserID/RewriteUserIDWithMasking
         使用 json.RawMessage 保留其他字段的原始字节
      
      2. gateway_service.go - replaceModelInBody
         使用 json.RawMessage 保留其他字段的原始字节
      
      3. gateway_service.go - normalizeClaudeOAuthRequestBody
         保留 messages 的原始字节,跳过包含 thinking 块的消息修改
      
      4. gateway_service.go - isThinkingBlockSignatureError
         添加 "cannot be modified" 错误检测,触发自动重试
      
      5. antigravity_gateway_service.go - isSignatureRelatedError
         添加 "cannot be modified" 错误检测
      Co-Authored-By: default avatarClaude Opus 4.5 <noreply@anthropic.com>
      ad90bb46
    • ducky's avatar
      feat(usage): add reasoning effort column · 53ee6383
      ducky authored
      53ee6383
    • liuxiongfeng's avatar
      feat(accounts): 账号列表显示 Antigravity scope 级别限流状态 · 8824400c
      liuxiongfeng authored
      - 后端 DTO 新增 scope_rate_limits 字段,从 extra 提取限流信息
      - 前端状态列显示 scope 级限流徽章(Claude/Gemini/Image)
      - 清除速率限制时同时清除账号级和 scope 级限流(已有实现)
      
      Cherry-picked from slovx2/sub2api: 66f49b67
      8824400c
    • liuxiongfeng's avatar
      feat(ops): 运维界面展示 Antigravity 账号 scope 级别限流统计 · 6e8eff9b
      liuxiongfeng authored
      在运维监控的并发/排队卡片中,为 Antigravity 平台账号显示各 scope
      (claude/gemini_text/gemini_image) 的限流数量统计,便于管理员了解
      哪些 scope 正在被限流。
      
      Cherry-picked from slovx2/sub2api: 08d6dc52
      6e8eff9b
    • liuxiongfeng's avatar
      fix: jsonb_set 嵌套路径无法创建多层 key 的问题 · f5884d16
      liuxiongfeng authored
      PostgreSQL jsonb_set 在 create_if_missing=true 时无法一次性创建多层嵌套路径。
      例如设置 {antigravity_quota_scopes,gemini_image} 时,如果 antigravity_quota_scopes 不存在,
      jsonb_set 不会自动创建外层 key,导致更新静默失败(affected=1 但数据未变)。
      
      修复方案:嵌套两次 jsonb_set,先确保外层 key 存在,再设置内层值。
      同时在设置限流时更新 last_used_at,使刚触发 429 的账号调度优先级降低。
      
      Cherry-picked from slovx2/sub2api: 4b57e80e
      f5884d16
    • liuxiongfeng's avatar
      feat(antigravity): 默认开启按配额域限流,避免整个账号被锁定 · 56949a58
      liuxiongfeng authored
      将 GATEWAY_ANTIGRAVITY_429_SCOPE_LIMIT 的默认值从关闭改为开启。
      当 Gemini 模型触发 429 限流时,只会限制对应的配额域(gemini_text),
      而 Claude 和 gemini_image 仍可继续使用,提高账号利用率。
      56949a58
    • liuxiongfeng's avatar
      feat(antigravity): map all gemini-2.5 to gemini-3 series · 7d256879
      liuxiongfeng authored
      Antigravity 上游不再支持 gemini-2.5 系列,统一映射到 gemini-3:
      - gemini-2.5-flash → gemini-3-flash
      - gemini-2.5-flash-lite → gemini-3-flash
      - gemini-2.5-flash-thinking → gemini-3-flash
      - gemini-2.5-flash-image → gemini-3-pro-image
      - gemini-2.5-pro → gemini-3-pro-high
      - gemini-2.5-pro-preview → gemini-3-pro-high
      - gemini-2.5-pro-exp → gemini-3-pro-high
      7d256879
    • liuxiongfeng's avatar
      test: update gemini-2.5-pro mapping test case · f9512fda
      liuxiongfeng authored
      Update test expectation to reflect new mapping:
      gemini-2.5-pro -> gemini-3-pro-high
      f9512fda
    • liuxiongfeng's avatar
      feat(antigravity): map gemini-2.5-pro to gemini-3-pro-high · beb63cb1
      liuxiongfeng authored
      Add prefix mapping rules for gemini-2.5-pro variants:
      - gemini-2.5-pro -> gemini-3-pro-high
      - gemini-2.5-pro-preview -> gemini-3-pro-high
      - gemini-2.5-pro-exp -> gemini-3-pro-high
      beb63cb1
    • song's avatar
      fix: align migration checksum and import formatTime · 11ff73b5
      song authored
      11ff73b5
    • shuike's avatar