Commit Graph
2136 Commits
Author SHA1 Message Date
erio 896fb2b0b4 feat: add client affinity scheduling for Anthropic/Antigravity accounts
新增客户端亲和调度功能,新会话优先调度到客户端之前使用过的账号,减少账号频繁切换。

- 调度层 Layer 1.6:粘性会话未命中时,从 Redis Sorted Set 按最近使用时间降序
  查找亲和账号,通过全部可调度检查后尝试获取槽位
- 账号级 opt-in:通过 Extra 字段 client_affinity_enabled 控制,未启用的账号
  既不写入亲和关系也不被亲和选中
- Redis 数据结构:ZSET client_affinity:{groupID}:{clientID},Lua 脚本原子清理
  过期成员 + 查询/更新,per-member TTL 通过 score 实现
- 仅 Claude Code/Console 客户端生效(通过 metadata.user_id 格式识别)
- DTO/前端:新增开关 UI,支持 Anthropic OAuth/SetupToken 和 Antigravity 平台
2026-03-06 12:43:22 +08:00
erio 95fcb02fe2 fix: restore SimulateClaudeMaxEnabled and ResetAccountQuota lost during merge 2026-03-06 05:34:03 +08:00
erio e74270f8eb chore: bump version to 0.1.91.4 2026-03-06 05:29:07 +08:00
erio 3c204c1862 Merge branch 'feature/account-load-factor' into release/custom-0.1.91 2026-03-06 05:25:32 +08:00
erio c87e6526c1 fix: use real Concurrency instead of LoadFactor for metrics and monitoring
LoadFactor should only affect scheduling weight, not load rate reporting.
2026-03-06 05:18:45 +08:00
erio af3a5076d6 fix: add load_factor upper bound validation to BulkUpdateAccounts 2026-03-06 05:17:52 +08:00
erio 18f2e21414 fix: use HTML-safe expressions for @input handlers in Vue templates
Replace `<` comparisons with Math.max/ternary+>= to avoid Vue template
parser treating `<` as HTML tag start in attribute values.
2026-03-06 05:07:52 +08:00
erio 8a8cdeebb4 fix: prevent negative values for concurrency and load_factor inputs 2026-03-06 05:07:52 +08:00
erio 12b33f4ea4 fix: address load_factor code review findings
- Fix bulk edit: send 0 instead of null/NaN to clear load_factor
- Fix edit modal: explicit NaN check instead of implicit falsy
- Fix create modal: use ?? instead of || for load_factor
- Add load_factor upper limit validation (max 10000)
- Add //go:build unit tag and self-contained intPtrHelper in test
- Add design intent comments on WaitPlan.MaxConcurrency
2026-03-06 05:07:52 +08:00
erio 01b3a09d7d fix: validate account status before update and update load factor hint
- Normalize non-standard status (e.g. "error") to "active" on edit load
- Add pre-submit validation for status field to prevent 400 errors
- Update load factor hint: "提高负载因子可以提高对账号的调度频率"
2026-03-06 05:07:40 +08:00
erio 0d6c1c7790 feat: add independent load_factor field for scheduling load calculation 2026-03-06 05:07:10 +08:00
erio 14dc1d4421 Merge branch 'feature/apikey-quota-limit' into release/custom-0.1.91 2026-03-06 05:04:45 +08:00
erio 95e366b6c6 fix: add missing IncrementQuotaUsed and ResetQuotaUsed to stubAccountRepo in api_contract_test 2026-03-06 04:37:56 +08:00
erio 02b78950c9 fix: use HTML-safe expressions for @input handlers in Vue templates
Replace `<` comparisons with Math.max/ternary+>= to avoid Vue template
parser treating `<` as HTML tag start in attribute values.
2026-03-06 04:33:55 +08:00
erio dbe94847de fix: prevent negative values for concurrency and load_factor inputs 2026-03-06 04:30:30 +08:00
erio ee7d6bc19f fix: address load_factor code review findings
- Fix bulk edit: send 0 instead of null/NaN to clear load_factor
- Fix edit modal: explicit NaN check instead of implicit falsy
- Fix create modal: use ?? instead of || for load_factor
- Add load_factor upper limit validation (max 10000)
- Add //go:build unit tag and self-contained intPtrHelper in test
- Add design intent comments on WaitPlan.MaxConcurrency
2026-03-06 04:27:41 +08:00
erio 3d93a29b35 fix: validate account status before update and update load factor hint
- Normalize non-standard status (e.g. "error") to "active" on edit load
- Add pre-submit validation for status field to prevent 400 errors
- Update load factor hint: "提高负载因子可以提高对账号的调度频率"
2026-03-06 04:16:47 +08:00
erio a9ecd7bcc6 chore: bump version to 0.1.91.1 2026-03-06 04:08:37 +08:00
erio f89465fb39 Merge branch 'main' into release/custom-0.1.91
# Conflicts:
#	frontend/src/components/admin/account/AccountActionMenu.vue
#	frontend/src/views/admin/AccountsView.vue
2026-03-06 04:08:14 +08:00
erio 440c3f46a7 feat: add independent load_factor field for scheduling load calculation
- Separate load factor from concurrency: concurrency controls actual
  slot acquisition, load_factor controls load rate calculation
- Add EffectiveLoadFactor() method: LoadFactor > Concurrency > 1
- Add load_factor field to Create/Edit/BulkEdit account forms
- Fix RPM default value: auto-fill 15 when RPM enabled but not set
- Fix stale test compilation errors in server and handler packages
2026-03-06 03:42:24 +08:00
erio c746964936 chore: bump version to 0.1.90.8 2026-03-06 01:16:40 +08:00
erio 77701143bf fix: use range assertion for time-sensitive ExpiresInDays test
The test could flake depending on exact execution time near midnight
boundaries. Use a range check (29 or 30) instead of exact equality.
2026-03-06 01:07:28 +08:00
erio b2d6879b3f refactor: unify post-usage billing logic and fix account quota calculation
- Extract postUsageBilling() to consolidate billing logic across
  GatewayService.RecordUsage, RecordUsageWithLongContext, and
  OpenAIGatewayService.RecordUsage, eliminating ~120 lines of
  duplicated code
- Fix account quota to use TotalCost × accountRateMultiplier
  (was using raw TotalCost, inconsistent with account cost stats)
- Fix RecordUsageWithLongContext API Key quota only updating in
  balance mode (now updates regardless of billing type)
- Fix WebSocket client disconnect detection on Windows by adding
  "an established connection was aborted" to known disconnect errors
2026-03-06 00:54:48 +08:00
erio 02dea7b09b refactor: unify post-usage billing logic and fix account quota calculation
- Extract postUsageBilling() to consolidate billing logic across
  GatewayService.RecordUsage, RecordUsageWithLongContext, and
  OpenAIGatewayService.RecordUsage, eliminating ~120 lines of
  duplicated code
- Fix account quota to use TotalCost × accountRateMultiplier
  (was using raw TotalCost, inconsistent with account cost stats)
- Fix RecordUsageWithLongContext API Key quota only updating in
  balance mode (now updates regardless of billing type)
- Fix WebSocket client disconnect detection on Windows by adding
  "an established connection was aborted" to known disconnect errors
2026-03-06 00:54:17 +08:00
erio c26f93c4a0 fix: route antigravity apikey account test to native protocol
Antigravity APIKey accounts were incorrectly routed to
testAntigravityAccountConnection which calls AntigravityTokenProvider,
but the token provider only handles OAuth and Upstream types, causing
"not an antigravity oauth account" error.

Extract routeAntigravityTest to route APIKey accounts to native
Claude/Gemini test paths based on model prefix, matching the
gateway_handler routing logic for normal requests.
2026-03-06 00:36:13 +08:00
erio c826ac28ef refactor: extract QuotaLimitCard component for reuse in create and edit modals
- Extract quota limit card/toggle UI into QuotaLimitCard.vue component
- Use v-model pattern for clean parent-child data flow
- Integrate into both EditAccountModal and CreateAccountModal
- All apikey accounts (all platforms) now support quota limit on creation
- Bump version to 0.1.90.6
2026-03-06 00:36:00 +08:00
erio 1893b0eb30 feat: restyle API Key quota limit UI to card/toggle format
- Redesign quota limit section with card layout and toggle switch
- Add watch to clear quota value when toggle is disabled
- Add i18n keys for toggle labels and hints (zh/en)
- Bump version to 0.1.90.5
2026-03-06 00:35:35 +08:00
erio 05527b13db feat: add quota limit for API key accounts
- Add configurable spending limit (quota_limit) for apikey-type accounts
- Atomic quota accumulation via PostgreSQL JSONB operations on TotalCost
- Scheduler filters out over-quota accounts with outbox-triggered snapshot refresh
- Display quota usage ($used / $limit) in account capacity column
- Add "Reset Quota" action in account menu to reset usage to zero
- Editing account settings preserves quota_used (no accidental reset)
- Covers all 3 billing paths: Anthropic, Gemini, OpenAI RecordUsage

chore: bump version to 0.1.90.4
2026-03-06 00:35:09 +08:00
erio ce4095904e chore: bump version to 0.1.90.7 2026-03-05 22:56:20 +08:00
erio 0d2dcbff11 fix: route antigravity apikey account test to native protocol
Antigravity APIKey accounts were incorrectly routed to
testAntigravityAccountConnection which calls AntigravityTokenProvider,
but the token provider only handles OAuth and Upstream types, causing
"not an antigravity oauth account" error.

Extract routeAntigravityTest to route APIKey accounts to native
Claude/Gemini test paths based on model prefix, matching the
gateway_handler routing logic for normal requests.
2026-03-05 22:44:21 +08:00
erio 02dca78dbe refactor: extract QuotaLimitCard component for reuse in create and edit modals
- Extract quota limit card/toggle UI into QuotaLimitCard.vue component
- Use v-model pattern for clean parent-child data flow
- Integrate into both EditAccountModal and CreateAccountModal
- All apikey accounts (all platforms) now support quota limit on creation
- Bump version to 0.1.90.6
2026-03-05 22:13:56 +08:00
Wesley Liddick ae5d9c8bfc Merge pull request #788 from touwaeriol/fix/usage-error-passthrough
fix: pass through upstream HTTP status in usage API errors
2026-03-05 22:05:36 +08:00
erio 8df299b767 feat: restyle API Key quota limit UI to card/toggle format
- Redesign quota limit section with card layout and toggle switch
- Add watch to clear quota value when toggle is disabled
- Add i18n keys for toggle labels and hints (zh/en)
- Bump version to 0.1.90.5
2026-03-05 22:01:40 +08:00
erio 95cf59b2f6 feat: add quota limit for API key accounts
- Add configurable spending limit (quota_limit) for apikey-type accounts
- Atomic quota accumulation via PostgreSQL JSONB operations on TotalCost
- Scheduler filters out over-quota accounts with outbox-triggered snapshot refresh
- Display quota usage ($used / $limit) in account capacity column
- Add "Reset Quota" action in account menu to reset usage to zero
- Editing account settings preserves quota_used (no accidental reset)
- Covers all 3 billing paths: Anthropic, Gemini, OpenAI RecordUsage

chore: bump version to 0.1.90.4
2026-03-05 21:48:37 +08:00
erio a0f643da0e fix: keep 500 status for upstream errors, pass details in response body
Upstream errors like 401/429 must not be passed through as HTTP status
codes because the frontend routes on status (401 triggers JWT logout).
Keep HTTP 500 but include upstream error details in the message.
2026-03-05 21:03:08 +08:00
erio 9117c2a4ec fix: include upstream error details in usage API error response
When FetchUsageWithOptions receives a non-200 response from the
Anthropic API (e.g. 429 Rate Limited, 401 Unauthorized), the error
was wrapped with fmt.Errorf which infraerrors.FromError cannot
recognize, causing a generic "internal error" message with no details.

Replace fmt.Errorf with infraerrors.New(500, "UPSTREAM_ERROR", msg)
so the upstream error details (status code + body) are included in
the 500 response message. The HTTP status remains 500 to avoid
interfering with frontend auth routing (e.g. 401 would trigger
JWT expiry redirect).
2026-03-05 21:02:11 +08:00
erio 99331a5285 fix: throttle Anthropic usage queries and pass through upstream HTTP errors
- Frontend: queue Anthropic OAuth/setup-token usage requests by proxy
  with random 1-1.5s interval to prevent upstream 429
- Backend: return ApplicationError with actual upstream status code
  instead of wrapping all errors as 500
- Handle component unmount to skip stale updates on page navigation
2026-03-05 19:12:49 +08:00
shaw bab4bb9904 chore: 更新openai、claude使用秘钥教程部分 2026-03-05 18:58:10 +08:00
shaw 33bae6f49b fix: Cache Token拆分为缓存创建和缓存读取 2026-03-05 18:32:17 +08:00
Wesley Liddick 32d619a56b Merge pull request #780 from mt21625457/feat/codex-remote-compact-outcome-logging
feat(openai-handler): support codex remote compact outcome logging
2026-03-05 16:59:02 +08:00
Wesley Liddick 642432cf2a Merge pull request #777 from guoyongchang/feature-schedule-test-support
feat: 支持基于 crontab 的定时账号测试
2026-03-05 16:57:23 +08:00
程序猿MT 61e9598b08 fix(lint): remove redundant context type in compact outcome logger 2026-03-05 16:51:46 +08:00
guoyongchangandClaude Opus 4.6 d4e34c7514 fix: 修复空结果导致定时测试模态框崩溃的问题
后端返回 null (Go nil slice) 时前端访问 .length 抛出 TypeError,
在 API 层对 listByAccount 和 listResults 加 ?? [] 兜底。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:47:01 +08:00
程序猿MT bfe7a5e452 test(openai-handler): add codex remote compact outcome coverage 2026-03-05 16:46:14 +08:00
程序猿MT 77d916ffec feat(openai-handler): support codex remote compact outcome logging 2026-03-05 16:46:12 +08:00
guoyongchangandClaude Opus 4.6 831abf7977 refactor: 移除冗余中间类型和不必要代码
- 移除 ScheduledTestOutcome 中间类型,RunTestBackground 直接返回 *ScheduledTestResult
- 简化 SaveResult 直接接受 *ScheduledTestResult
- 移除 handler 中不必要的 nil 检查
- 移除前端 ScheduledTestsPanel 中多余的 String() 转换

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:37:07 +08:00
guoyongchangandClaude Opus 4.6 817a491087 simplify: 移除 leader lock,单实例无需分布式锁
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:31:27 +08:00
guoyongchangandClaude Opus 4.6 9a8dacc514 fix: 修复 golangci-lint depguard 和 gofmt 错误
将 redis leader lock 逻辑从 service 层抽取为 LeaderLocker 接口,
实现移至 repository 层,消除 service 层对 redis 的直接依赖。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:28:48 +08:00
guoyongchangandClaude Opus 4.6 8adf80d98b fix: wire_gen_test 补充 scheduledTestRunner 参数
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:23:41 +08:00
guoyongchangandClaude Opus 4.6 62686a6213 revert: 还原 docker-compose.local.yml 的本地测试改动
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:17:33 +08:00