Commit Graph
402 Commits
Author SHA1 Message Date
erio 6fa385255d chore: bump version to 0.1.105.4 2026-03-30 02:25:23 +08:00
erio e87ed88090 chore: bump version to 0.1.105.3 2026-03-30 02:14:30 +08:00
erio 3fd0361542 chore: bump version to 0.1.105.2 2026-03-30 02:06:07 +08:00
erio 9e9285c25a Merge remote-tracking branch 'origin/feature/channel' into release/custom-0.1.105
# Conflicts:
#	backend/cmd/server/wire_gen.go
#	backend/internal/handler/handler.go
#	backend/internal/handler/wire.go
2026-03-30 02:05:59 +08:00
erio a9117600a5 feat(channel): 渠道管理系统 — 多模式定价 + 统一计费解析
新增渠道管理功能,支持三种计费模式(Token 区间/按次/图片),
统一定价解析链(Channel → LiteLLM → Fallback),
无渠道配置时保持原有计费逻辑不变。

Backend:
- 新增 channels/channel_groups/channel_model_pricing/channel_pricing_intervals 表
- ChannelService: atomic.Value + singleflight 缓存,通配符模型匹配
- ModelPricingResolver: 统一定价解析器
- BillingService: CalculateCostUnified 统一计费入口
- 完整输入验证(BillingMode/价格非负/名称长度)
- 33 个单元测试覆盖核心路径

Frontend:
- ChannelsView.vue: 渠道 CRUD 列表页
- PricingEntryCard.vue + IntervalRow.vue: 定价编辑组件
- 支持三种计费模式切换 + 区间编辑
2026-03-30 02:03:06 +08:00
erio 0393981397 merge: integrate upstream v0.1.105 into release/custom-0.1.105
Merge upstream v0.1.105 (94 commits) with our customizations from
release/custom-0.1.104. Key upstream additions:
- TLS fingerprint profile management
- OpenAI→Anthropic endpoint compatibility routing
- Privacy mode for OpenAI/Antigravity accounts
- Requested model tracking in usage logs
- Error observability enhancements
- Various bug fixes

Conflict resolutions (all "keep both sides"):
- handler.go/wire.go: added both TLSFingerprintProfile and GDriveOAuth
- wire_gen.go: combined internal500CounterCache with TLS fingerprint objects
- accounts.ts: kept setPrivacy + affinity functions
- BulkEditAccountModal.vue: kept OpenAI WS mode + Allow Overages sections

Additional fixes:
- gateway_handler_chat_completions.go, gateway_handler_responses.go:
  added missing sub2apiUserID parameter to SelectAccountWithLoadAwareness
- antigravity_internal500_penalty.go: gofmt fix
2026-03-27 18:23:39 +08:00
shaw 1854050df3 feat(tls-fingerprint): 新增 TLS 指纹 Profile 数据库管理及代码质量优化
新增功能:
- 新增 TLS 指纹 Profile CRUD 管理(Ent schema + 迁移 + Admin API + 前端管理界面)
- 支持账号绑定数据库中的自定义 TLS Profile,或随机选择(profile_id=-1)
- HTTPUpstream.DoWithTLS 接口从 bool 改为 *tlsfingerprint.Profile,支持按账号指定 Profile
- AccountUsageService 注入 TLSFingerprintProfileService,统一 usage 场景与网关的 Profile 解析逻辑

代码优化:
- 删除已被 TLSFingerprintProfileService 完全取代的 registry.go 死代码(418 行)
- 提取 3 个 dialer 的重复 TLS 握手逻辑为 performTLSHandshake() 共用函数
- 修复 GetTLSFingerprintProfileID 缺少 json.Number 处理的 bug
- gateway_service.Forward 中 ResolveTLSProfile 从重试循环内重复调用改为预解析局部变量
- 删除冗余的 buildClientHelloSpec() 单行 wrapper 和 int64(e.ID) 无效转换
- tls_fingerprint_profile_cache.go 日志从 log.Printf 改为 slog 结构化日志
- dialer_capture_test.go 添加 //go:build integration 标签,防止 CI 失败
- 去重 TestProfileExpectation 类型至共享 test_types_test.go
- 修复 9 个测试文件缺少 tlsfingerprint import 的编译错误
- 修复 error_policy_integration_test.go 中 handleError 回调签名被错误替换的问题
2026-03-27 14:33:05 +08:00
erio ed98145154 chore: bump version to 0.1.104.5 2026-03-24 20:41:04 +08:00
erio c668b96e15 feat(antigravity): progressive penalty for consecutive INTERNAL 500 errors
When an antigravity account returns 500 "Internal error encountered."
on all 3 retry attempts, increment a Redis counter and apply escalating
penalties:
- 1st round: temp unschedulable 10 minutes
- 2nd round: temp unschedulable 10 hours
- 3rd round: permanently mark as error

Counter resets on any successful response (< 400).
2026-03-24 20:18:49 +08:00
erio 21fd129dcc chore: bump version to 0.1.104.4 2026-03-24 17:53:08 +08:00
erio c7168c1abc chore: bump version to 0.1.104.3 2026-03-24 16:47:20 +08:00
QTomandClaude Opus 4.6 91b1d812ce feat(openai): Mobile RT 补全 plan_type、精确匹配账号、刷新时自动设置隐私
1. accounts/check 补全 plan_type:当 id_token 缺少 plan_type(如 Mobile RT),
   自动调用 accounts/check 端点获取订阅类型
2. orgID 精确匹配账号:从 JWT 提取 poid 匹配正确账号,避免 Go map
   遍历顺序随机导致 plan_type 不稳定
3. RT 刷新时设置隐私:调用 disableOpenAITraining 关闭训练数据共享,
   结果存入 extra.privacy_mode,后续跳过重复设置

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 14:50:03 +08:00
erio 90bd7d28ce chore: bump version to 0.1.104.2 2026-03-23 19:39:09 +08:00
erio 8cbfe9dcc6 chore: bump version to 0.1.104.1 2026-03-22 06:03:34 +08:00
github-actions[bot] 94bba415b1 chore: sync VERSION to 0.1.104 [skip ci] 2026-03-20 01:31:30 +00:00
erio 528ff5d28c fix(antigravity): fast-fail on proxy unavailable, temp-unschedule account
## Problem

When a proxy is unreachable, token refresh retries up to 4 times with
30s timeout each, causing requests to hang for ~2 minutes before
failing with a generic 502 error. The failed account is not marked,
so subsequent requests keep hitting it.

## Changes

### Proxy connection fast-fail
- Set TCP dial timeout to 5s and TLS handshake timeout to 5s on
  antigravity client, so proxy connectivity issues fail within 5s
  instead of 30s
- Reduce overall HTTP client timeout from 30s to 10s
- Export `IsConnectionError` for service-layer use
- Detect proxy connection errors in `RefreshToken` and return
  immediately with "proxy unavailable" error (no retries)

### Token refresh temp-unschedulable
- Add 8s context timeout for token refresh on request path
- Mark account as temp-unschedulable for 10min when refresh fails
  (both background `TokenRefreshService` and request-path
  `GetAccessToken`)
- Sync temp-unschedulable state to Redis cache for immediate
  scheduler effect
- Inject `TempUnschedCache` into `AntigravityTokenProvider`

### Account failover
- Return `UpstreamFailoverError` on `GetAccessToken` failure in
  `Forward`/`ForwardGemini` to trigger handler-level account switch
  instead of returning 502 directly

### Proxy probe alignment
- Apply same 5s dial/TLS timeout to shared `httpclient` pool
- Reduce proxy probe timeout from 30s to 10s
2026-03-19 23:48:37 +08:00
erio 0667cf3cac fix(antigravity): fast-fail on proxy unavailable, temp-unschedule account
- Set proxy TCP dial timeout to 5s and TLS handshake timeout to 5s
  for quick failure detection instead of waiting 30s
- Reduce overall HTTP client timeout from 30s to 10s
- Detect proxy connection errors (IsConnectionError) and skip retries
  immediately with clear "proxy unavailable" error
- Add 8s context timeout for token refresh on request path to cap
  total wait time
- Mark account as temp-unschedulable for 10min when token refresh
  fails (both background and request path)
- Sync temp-unschedulable state to Redis cache for immediate
  scheduler effect
- Return UpstreamFailoverError on GetAccessToken failure to trigger
  account failover instead of returning 502 directly
- Apply same 5s dial timeout to httpclient pool (proxy probe/test)
- Reduce proxy probe timeout from 30s to 10s
2026-03-19 23:20:14 +08:00
erio 26da801d29 chore: bump version to 0.1.103.4 2026-03-19 20:58:19 +08:00
erio 602a0c1cbd chore: bump version to 0.1.103.3 2026-03-19 20:29:15 +08:00
erio 10e302a5d0 chore: bump version to 0.1.103.2 2026-03-18 23:14:32 +08:00
erio e3dbae9ad4 chore: bump version to 0.1.103.1 2026-03-18 23:00:22 +08:00
erio 305f673634 chore: bump version to 0.1.102.5 2026-03-18 22:29:05 +08:00
erio 5eb6f190bd chore: bump version to 0.1.102.4 2026-03-18 19:27:58 +08:00
erio ca1e7c8959 chore: bump version to 0.1.102.3 2026-03-18 19:04:12 +08:00
erio 9587eaeed9 chore: bump version to 0.1.102.2 2026-03-18 15:53:00 +08:00
erio 1d946b3847 Merge upstream v0.1.102 into release/custom-0.1.102 2026-03-18 12:11:03 +08:00
QTomandClaude Opus 4.6 d4cc9871c4 feat(admin): 分组管理新增容量列(并发/会话/RPM 实时聚合)
复用 GroupCapacityService,在 admin 分组列表中添加容量列,
显示每个分组的实时并发/会话/RPM 使用量和上限。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:06:35 +08:00
QTomandClaude Opus 4.6 961c30e7c0 feat(admin): 分组管理列表新增用量列与账号数分类
分组管理列表增强:

1. 今日/累计用量列:
   - 新增独立端点 GET /admin/groups/usage-summary
   - 一次查询返回所有分组的今日费用和累计费用(actual_cost)
   - 前端异步加载后合并显示在分组列表中

2. 账号数区分可用/限流/总量:
   - 将账号数列从单一总量改为 badge 内多行展示
   - 可用: active + schedulable 的账号数(绿色)
   - 限流: rate_limit/overload/temp_unschedulable 的账号数(橙色,无限流时隐藏)
   - 总量: 全部关联账号数

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 10:06:35 +08:00
erio 44ec2626cf feat: add affinity scheduling controls 2026-03-18 04:08:45 +08:00
erio 338e3df8d9 chore: bump version to 0.1.101.3 2026-03-17 01:17:07 +08:00
erio d79ec88d9c chore: bump version to 0.1.101.2 2026-03-16 22:12:54 +08:00
erio 5fd19b856b chore: bump version to 0.1.101.1 2026-03-16 18:19:43 +08:00
erio 897c93528d feat: optimize Antigravity AI Credits scheduling - use AICredits rate limit key
Replace sync.Map + per-model runtime state with a single AICredits key in
model_rate_limits. Rate-limited accounts with available credits are now
scheduled directly and credits injected without a 429 round trip.

- Scheduler: rate-limited + overages + credits available = allow scheduling
- Forwarding: inject credits proactively when model rate limited
- Storage: credits exhaustion stored as model_rate_limits["AICredits"]
- Frontend: show credits_active (yellow ⚡) vs credits_exhausted states
- Bump version to 0.1.100.4
2026-03-16 03:51:34 +08:00
erio 0158cb8aa8 chore: bump version to 0.1.100.3 2026-03-16 02:11:09 +08:00
erio 1fc9dd7b68 feat: unified OAuth token refresh API with distributed locking
Introduce OAuthRefreshAPI as the single entry point for all OAuth token
refresh operations, eliminating the race condition where background
refresh and inline refresh could simultaneously use the same
refresh_token (fixes #1035).

Key changes:
- Add OAuthRefreshExecutor interface extending TokenRefresher with CacheKey
- Add OAuthRefreshAPI.RefreshIfNeeded with lock → DB re-read → double-check flow
- Add ProviderRefreshPolicy / BackgroundRefreshPolicy strategy types
- Simplify all 4 TokenProviders to delegate to OAuthRefreshAPI
- Rewrite TokenRefreshService.refreshWithRetry to use unified API path
- Add MergeCredentials and BuildClaudeAccountCredentials helpers
- Add 40 unit tests covering all new and modified code paths
2026-03-16 01:31:54 +08:00
erio d844f3b6b5 feat: unified OAuth token refresh API to fix refresh_token race condition (#1035)
Introduce OAuthRefreshAPI as the single entry point for all OAuth token
refresh operations (both background TokenRefreshService and inline
TokenProvider), eliminating the race condition where two independent
refresh paths consume the same one-time-use refresh_token.

Key changes:
- New OAuthRefreshAPI with distributed lock + DB re-read + double-check
- All 4 platform refreshers implement OAuthRefreshExecutor (CacheKey)
- TokenRefreshService and TokenProviders share the same lock key
- Add errRefreshSkipped sentinel for accurate refresh statistics
- 7 new Path A unit tests covering all RefreshIfNeeded branches

chore: bump version to 0.1.100.2
2026-03-16 01:00:20 +08:00
erio fa7d5be25b chore: bump version to 0.1.100.1 2026-03-15 20:08:25 +08:00
erio 8688e4b78e chore: bump version to 0.1.99.7 2026-03-15 19:26:04 +08:00
erio ccffa0640a chore: bump version to 0.1.99.6 2026-03-15 19:05:13 +08:00
erio 3caa91985c chore: bump version to 0.1.99.5 2026-03-15 18:44:38 +08:00
erio 9f573fed55 chore: bump version to 0.1.99.4 2026-03-15 17:42:18 +08:00
erio 77a9b4f420 chore: bump version to 0.1.99.3 2026-03-15 17:35:10 +08:00
erio 7a5b9cffe5 chore: bump version to 0.1.99.2 2026-03-14 22:51:41 +08:00
erio 085c0d7e17 chore: bump version to 0.1.99.1 2026-03-14 21:03:20 +08:00
erio 25a0030450 Merge branch 'main' into release/custom-0.1.99
# Conflicts:
#	backend/cmd/server/wire_gen.go
#	backend/cmd/server/wire_gen_test.go
#	backend/internal/handler/dto/mappers.go
#	backend/internal/service/ratelimit_service.go
#	backend/internal/service/ratelimit_service_401_db_fallback_test.go
#	backend/internal/service/ratelimit_service_401_test.go
#	frontend/src/components/account/AccountCapacityCell.vue
#	frontend/src/components/account/CreateAccountModal.vue
#	frontend/src/components/account/EditAccountModal.vue
#	frontend/src/views/admin/DataManagementView.vue
2026-03-14 21:03:09 +08:00
Wesley Liddick aa4e37d085 Merge pull request #966 from GuangYiDing/feat/db-backup-restore
feat: 数据库定时备份与恢复(S3 兼容存储,支持 Cloudflare R2)
2026-03-14 18:58:56 +08:00
Rose DingandClaude Opus 4.6 1047f973d5 fix: 按 review 意见重构数据库备份服务(安全性 + 架构 + 健壮性)
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: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 17:48:21 +08:00
erio 11cb34e56e chore: bump version to 0.1.98.1 2026-03-14 14:10:40 +08:00
erio 4e149109de chore: bump version to 0.1.97.1 2026-03-14 14:07:42 +08:00
erio 5e0a508eca Merge branch 'main' into release/custom-0.1.97
# Conflicts:
#	README.md
#	README_CN.md
#	backend/internal/handler/gateway_handler.go
#	backend/internal/repository/user_group_rate_repo.go
#	backend/internal/service/admin_service_group_rate_test.go
#	backend/internal/service/gateway_service.go
#	frontend/src/components/account/CreateAccountModal.vue
#	frontend/src/views/admin/AccountsView.vue
2026-03-14 14:07:05 +08:00