Commit Graph
1537 Commits
Author SHA1 Message Date
erio 064a70db29 fix: update wire_gen.go to pass gatewayCache to NewAccountHandler 2026-03-06 15:55:23 +08:00
erio c616284890 chore: bump version to 0.1.92.3 2026-03-06 15:49:11 +08:00
erio 60f050d184 feat: add account affinity client count indicator
Add reverse Redis index (account_affinity:{accountID}) to track which
clients are bound to each account via affinity scheduling. Display a
blue badge with client count in the admin account list, with a hover
tooltip showing client details (groupID:clientID + TTL).

Backend: reverse index in Lua scripts, batch query methods, new
GET /accounts/:id/affinity-clients endpoint.
Frontend: blue badge + lazy-loaded tooltip in AccountStatusIndicator.
2026-03-06 15:48:58 +08:00
erio 63dff62673 fix: restrict client affinity to Anthropic OAuth/SetupToken accounts only
客户端亲和仅对 Claude Code 账号(Anthropic OAuth/SetupToken)生效,
移除 Antigravity 平台支持。UI toggle 移动到拦截预热请求下方。
2026-03-06 14:46:47 +08:00
erio c1816f39f2 revert: remove passthrough check from isModelSupportedByAccount
该函数不被 OpenAI 调度路径调用,透传短路应只加在
openai_account_scheduler.go 中。
2026-03-06 14:30:44 +08:00
erio 69abdff732 chore: bump version to 0.1.92.2 2026-03-06 14:24:58 +08:00
erio 489a6d4839 fix: OpenAI scheduler also bypass model check for passthrough accounts
之前只在 gateway_service.isModelSupportedByAccount 中添加了透传短路,
但 OpenAI 调度器 (openai_account_scheduler.go) 直接调用
account.IsModelSupported(),未经过该函数,导致 gpt-5.4 仍然 503。
2026-03-06 14:20:08 +08:00
erio 312f2ecb8d fix: OpenAI passthrough accounts bypass model mapping check
透传模式账号仅替换认证,应允许所有模型通过。之前调度阶段的
isModelSupportedByAccount 不感知透传模式,导致 model_mapping
中未配置的新模型(如 gpt-5.4)被拒绝返回 503。
2026-03-06 13:54:25 +08:00
erio 75f1faea14 chore: bump version to 0.1.92.1 2026-03-06 13:08:32 +08:00
erio b4005aa7b2 Merge branch 'release/custom-0.1.91' into release/custom-0.1.92 2026-03-06 13:06:17 +08:00
erio 180c515f9a fix: race condition in TestOpsSystemLogSink_StartStopAndFlushSuccess
done 信号在 BatchInsertSystemLogsFn 内发出,但 writtenCount 在函数返回后
才原子递增,导致测试主 goroutine 收到信号后立即检查 WrittenCount 时可能为 0。
改用短轮询等待 WrittenCount > 0,消除竞态。
2026-03-06 13:02:04 +08:00
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
Wesley Liddick fb7d1346b5 Merge pull request #800 from mt21625457/pr/gpt54-support-upstream
feat(openai): 增加 GPT-5.4 支持并修复长上下文计费与白名单回归
2026-03-06 10:42:01 +08:00
shaw 491a744481 fix: 修复账号列表首次加载窗口费用显示 $0.00
lite 模式下从快照缓存读取窗口费用,非 lite 模式查询后写入缓存
2026-03-06 10:23:22 +08:00
yangjianbo f366026435 fix(openai): 修复 gpt-5.4 长上下文计费与快照白名单
补齐 gpt-5.4 fallback 的长上下文计费元信息,\n确保超过 272000 输入 token 时对整次会话应用\n2x 输入与 1.5x 输出计费规则。\n\n同时将官方快照 gpt-5.4-2026-03-05 加入前端\n白名单候选与回归测试,避免 whitelist 模式误拦截。\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

(cherry picked from commit d95497af87f608c6dadcbe7d6e851de9413ae147)
2026-03-06 10:16:23 +08:00
yangjianbo 1a0d4ed668 feat(openai): 增加 gpt-5.4 模型支持与定价配置
- 接入 gpt-5.4 模型识别与规范化,补充默认模型列表
- 增加 gpt-5.4 输入/缓存命中/输出价格与计费兜底逻辑
- 同步前端模型白名单与 OpenCode 上下文窗口(1050000/128000)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit 924476dcac6181cd0f3ee731ec7b73672ff03793)
2026-03-06 10:16:23 +08:00
Wesley Liddick 63a8c76946 Merge pull request #798 from touwaeriol/feature/account-load-factor
feat: add account load_factor for scheduling load calculation
2026-03-06 09:42:10 +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 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 0d6c1c7790 feat: add independent load_factor field for scheduling load calculation 2026-03-06 05:07:10 +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 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 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
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 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
程序猿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