Oliver
6d11f9ed77
Add Vertex service account support
2026-04-25 20:39:58 -04:00
Oliver
489a4d934e
Show today stats for Vertex usage window
2026-04-25 19:46:32 -04:00
shaw
095f457c57
feat(openai): port /responses/compact account support flow (PR #1555 )
...
将 vansour/sub2api#1555 的 OpenAI compact 能力建模手工移植到当前 main:账号
级 compact 状态/auto-force_on-force_off 模式、compact-only 模型映射、调度器
tier 分层(已支持 > 未知 > 已知不支持)、管理后台 compact 主动探测,以及对应
i18n/状态徽章。普通 /responses 流量行为不变,无数据库迁移。
2026-04-25 14:52:58 +08:00
shaw
4d0483f5b8
feat: 补充gpt生图模型测试功能
2026-04-22 18:12:03 +08:00
erio
258fd145ff
fix(account): prevent quota-exceeded API key/Bedrock accounts from being scheduled
...
Add quota exceeded check to IsSchedulable() and refactor
shouldClearStickySession to delegate to IsSchedulable(), eliminating
duplicated logic and fixing missed overload/rate-limit/expired checks.
Frontend displays quota exceeded status independently via quota fields.
2026-04-19 18:45:04 +08:00
erio
948d8e6d02
fix(admin): prevent browser password manager from autofilling account API key
...
Chrome's password manager matched the apikey-type account's Base URL + API Key
inputs as a login form and autofilled the last saved password by domain, so
editing a Gemini account could overwrite its apikey with a Claude key that
shared the same Base URL. Add autocomplete="new-password" plus data-*-ignore
attributes for 1Password / LastPass / Bitwarden to opt the field out of every
major password manager's autofill.
2026-04-17 22:06:32 +08:00
Wesley Liddick
e6e73b4f52
Merge pull request #1690 from KnowSky404/fix/ws-codex-scheduler-cache-1662
...
fix: preserve openai ws flags in scheduler cache
2026-04-16 17:21:32 +08:00
KnowSky404
836092a666
fix: restore ctx pool ws mode option in account ui
2026-04-16 02:13:04 +00:00
erio
38c00872e1
fix(ui): allow closing test dialog during active SSE stream
...
Replace dead EventSource variable with AbortController to enable
cancelling fetch streams. Remove close-button disable during connecting
status so users can dismiss the dialog at any time.
2026-04-15 11:34:31 +08:00
erio
3fa5b8bca5
fix: flaky WebSocket test, usage request queue, and test improvements
...
- Fix flaky WebSocket passthrough test: allow StatusNormalClosure after
client close instead of requiring NoError (race condition fix)
- Fix ratelimit 401 test: use PlatformOpenAI instead of PlatformGemini
for OAuth token cache invalidation scenario (more accurate)
- Add usageLoadQueue: Anthropic OAuth/setup-token accounts sharing the
same proxy exit are serialized with 1-2s jitter to prevent upstream 429
- AccountUsageCell: add module-level usage cache (5min TTL), unmounted
safety guard, and integrate enqueueUsageRequest for throttled fetching
2026-04-14 20:13:59 +08:00
erio
a56151fec9
refactor: extract CapacityBadge component from AccountCapacityCell
...
Extract repeated badge template (SVG icon + current/max display) into
a reusable CapacityBadge component. Reduces AccountCapacityCell from
~300 lines to ~180 lines with identical behavior.
2026-04-14 19:39:22 +08:00
erio
63f539b382
fix: merge general improvements from release branch
...
Backend:
- gateway_handler: pass subject.UserID instead of int64(0) for user-level routing
- setting_handler: add missing BalanceLowNotifyRechargeURL to UpdateSettings response
- openai_gateway_service: use applyAccountStatsCost for account stats pricing integration
- embed_on: add local file override (data/public/) for embedded frontend assets
Frontend:
- useTableSelection: add batchUpdate method for batch operations
- AccountsView: virtual scrolling params, Set-based isSelected, swipe virtualization
- ProxiesView: add batchUpdate to selection and swipe-select
- BulkEditAccountModal: fix submit handler to prevent event object as argument
- SettingsView: move payload construction outside try block
- i18n: add general translation keys (saved, deleted, view, validation, allowUserRefund)
- api/client: reorder error fields for consistency
- stores/payment: clarify pollOrderStatus JSDoc
2026-04-14 19:29:37 +08:00
erio
a9880ee7b9
fix: round-2 audit fixes — security, code quality, and UI improvements
...
Security (HIGH):
- Normalize all Redis cache keys to lowercase (verifyCode, passwordReset)
- Fix verify code TTL renewal on failed attempts: use remaining TTL via
ExpiresAt field instead of resetting to full 15-minute window
- Add 3 missing fields to diffSettings audit log (promo_code, invitation_code,
custom_endpoints)
Code quality (MEDIUM):
- Extract filterVerifiedEmails shared helper (balance_notify_service.go)
- Add Pricing array non-empty validation for channel pricing rules
- Add platform token semantics comment in gateway_service.go
- Complete validatePlanPatch test coverage (+10 test cases)
- Replace string types with QuotaThresholdType/QuotaResetMode across frontend
- Remove duplicate getPlatformTextColor/getRateBadgeClass in ChannelsView
- Return EMAIL_NOT_FOUND error on RemoveNotifyEmail miss
UI improvements:
- Reorder cost tooltip: user billing above separator, account billing below
- Add NaN guard to accountBilled function
- Move timezone selector inline into reset-mode row (no longer standalone)
2026-04-14 09:35:05 +08:00
erio
1b7c295199
refactor: M5 useQuotaNotifyState composable + H14 Vue file splits
...
M5: New composable frontend/src/composables/useQuotaNotifyState.ts
- Replaces 9 individual refs in both Create/Edit modals with reactive state
- Provides loadFromExtra/writeToExtra/reset helpers
- Eliminates ~120 lines of duplicated code across the two modals
H14: Vue file length violations fixed
- AdminPaymentPlansView.vue: 325 → 183 lines (extracted PlanEditDialog.vue)
- QuotaLimitCard.vue: 327 → 268 lines (extracted QuotaDimensionRow.vue)
- PlanEditDialog.vue: 181 lines (new, plan create/edit form)
- QuotaDimensionRow.vue: 108 lines (new, single quota dimension row)
2026-04-14 09:33:39 +08:00
erio
9d319cfa2d
fix: batch 2 audit fixes — diffSettings notify fields, slog migration, frontend constants
...
H5: diffSettings now tracks 5 balance/quota notify fields in audit log
M15: log.Printf audit log migrated to slog.Info, removed "log" import
M14: New frontend/src/constants/account.ts with shared constants
QuotaNotifyToggle.vue uses QUOTA_THRESHOLD_TYPE_FIXED/PERCENTAGE
L2: UsageTable.vue uses BILLING_MODE_TOKEN/IMAGE from billingMode.ts
2026-04-14 09:32:24 +08:00
erio
ed8a9d975b
fix: batch 1 audit fixes — quota SQL fixed mode, public recharge URL, WebSearch bool fallback, UpdatePlan validation
...
H1: incrementUsageBillingAccountQuota now uses shared dailyExpiredExpr/weeklyExpiredExpr
constants (supporting fixed reset mode) instead of hardcoded '24 hours'/'168 hours'
H4: public settings endpoint now maps balance_low_notify_recharge_url
H6: GetWebSearchEmulationMode tolerates legacy bool values (true→enabled)
H7: UpdatePlan validates non-nil patch fields (rejects negative price, empty name, etc.)
H8: UsageTable accountBilled() helper with total_cost ?? 0 null guard
H9: AdminUsageLog TS type adds channel_id + billing_tier
M2: account.go "fixed" literals replaced with thresholdTypeFixed constant
M13: SystemSettings TS type adds web_search_emulation_enabled
UI: QuotaLimitCard title labels now use flex-1 to align with flex-1 input boxes
2026-04-14 09:32:11 +08:00
erio
a43da62254
fix(accounts): unify modal width, add notify props to create, fix quota layout
...
- EditAccountModal width changed from "normal" to "wide" (match CreateAccountModal)
- CreateAccountModal now passes all quota notify props to QuotaLimitCard
- QuotaLimitCard: when global notify disabled, hide title row, input takes full width
- Quota alert email: show remaining quota + threshold (fixed/$, percentage/%) instead of usage trigger point
2026-04-14 09:31:32 +08:00
erio
e27335acdd
fix(ui): widen notify type dropdown to show % fully, align quota input widths
2026-04-14 09:30:02 +08:00
erio
216bda58da
fix: change quota notify threshold semantics to "remaining quota"
...
Threshold now represents remaining quota instead of usage amount:
- Fixed ($): threshold=400, limit=1000 → alert when remaining drops to $400
(i.e., usage reaches $600)
- Percentage (%): threshold=30%, limit=1000 → alert when remaining drops
to 30% (i.e., usage reaches $700)
Also:
- Rename 告警阈值 → 提醒阈值 in i18n
- Widen type dropdown to w-16 for proper $ / % display
2026-04-14 09:29:25 +08:00
erio
7141dceee2
fix(frontend): place quota notify toggle inline with limit input
...
Move QuotaNotifyToggle to the same row as the limit $ input for all
three dimensions (daily/weekly/total), significantly reducing card height.
2026-04-14 09:29:01 +08:00
erio
ac55443278
fix(frontend): collapsible quota card and compact notify layout
...
- QuotaLimitCard: add collapse/expand toggle (chevron icon + click header)
- QuotaNotifyToggle: show $ or % suffix in threshold input
- Reduce vertical spacing between reset mode hint and notify toggle
2026-04-14 09:28:48 +08:00
erio
2066c478ab
fix(frontend): quota notify UI improvements
...
- QuotaNotifyToggle: add $ or % suffix to threshold input based on type
- QuotaLimitCard: combine reset mode and notify toggle on same row
to reduce vertical height for daily/weekly sections
- Remove redundant ml-4 indentation from QuotaNotifyToggle
2026-04-14 09:28:24 +08:00
erio
245f47cebb
fix(frontend): simplify websearch select labels and reduce width
...
- "默认(跟随渠道)" → "默认", "Default (follow channel)" → "Default"
- Move "follows channel config" info to description text
- Reduce select width from w-32 to w-24 in both Edit and Create modals
2026-04-14 09:27:46 +08:00
erio
48e8efe3e8
fix(frontend): hide quota notify toggle when global setting is disabled
...
QuotaLimitCard now requires quotaNotifyGlobalEnabled prop to control
visibility of QuotaNotifyToggle components. When the global account
quota notification is disabled in admin settings, per-account threshold
toggles are hidden in both Edit and Create account modals.
2026-04-14 09:27:33 +08:00
erio
1262654d97
feat: WebSearch tri-state, account stats pricing fix, quota cache fix, usage tooltip
...
WebSearch tri-state switch:
- Account-level web_search_emulation changed from bool to tri-state
string: "default" (follow channel) / "enabled" / "disabled"
- shouldEmulateWebSearch checks channel config when account is "default"
- SQL migration converts old bool values
- Frontend select replaces toggle in Edit/CreateAccountModal
Account stats pricing:
- resolveAccountStatsCost uses upstream model (post-mapping) for matching
- Priority: custom rules → model pricing file (when toggle on) → default
- Custom rules always configurable, independent of toggle
- Account ID field changed to searchable selector filtered by platform
- Description updated to reflect new behavior
Quota notification cache fix:
- CheckAccountQuotaAfterIncrement fetches real-time account from DB
- Reconstructs pre-increment usage for accurate threshold crossing detection
- New AccountQuotaReader interface (minimal: GetByID only)
Usage tooltip:
- Per-request/image billing shows per-request price instead of $0 token price
- Token billing continues to show input/output price per million tokens
2026-04-14 09:26:08 +08:00
erio
eba289a7ff
feat(notify): add global toggles, percentage threshold, and visibility control
...
- Add global toggle for account quota notification in admin settings
- Add percentage-based threshold type for per-account quota alerts
- Hide balance notify card on user profile when global toggle is off
- Expose balance_low_notify_enabled and account_quota_notify_enabled in PublicSettings
- Add threshold type (fixed/percentage) to QuotaNotifyToggle with $ / % switcher
2026-04-14 09:25:49 +08:00
erio
889b5b4f3b
fix(websearch): improve settings UI and hide config when globally disabled
...
- API Key show/copy buttons moved inside input field (inline icons)
- Proxy selector and test button on same row to save vertical space
- Test opens a dialog modal instead of inline display
- Hide all websearch config in channels/accounts when global toggle is off
2026-04-14 09:25:36 +08:00
erio
c3812ce1e3
fix(notify): address review findings - accountCost formula, dedup, refactor
...
- Fix accountCost calculation in finalizePostUsageBilling to match
postUsageBilling (always multiply by AccountRateMultiplier)
- Use strings.EqualFold for email dedup in collectBalanceNotifyRecipients
- Extract CheckAccountQuotaAfterIncrement into smaller functions:
buildQuotaDims + asyncSendQuotaAlert (< 30 lines each)
- Add "not splittable" comments for HTML template functions
- Extract QuotaNotifyToggle.vue sub-component to reduce
QuotaLimitCard.vue from 404 to 339 lines
2026-04-14 09:23:16 +08:00
erio
b32d1a2c9f
feat(notify): add balance low & account quota notification system
...
- User balance low notification: email alert when balance drops below
configurable threshold (user email + verified extra emails)
- Account quota notification: broadcast email to admin-configured
recipients when daily/weekly/total quota usage exceeds alert threshold
- Admin settings: global enable/disable, default threshold, quota
notification email list (Email Settings tab)
- User profile: enable/disable, custom threshold, add/remove extra
notification emails with verification code flow
- Account quota: per-dimension alert toggle and threshold in quota
control card
- Trigger logic: first-crossing only (old >= threshold && new < threshold
for balance; old < threshold && new >= threshold for quota), naturally
prevents duplicate notifications without Redis dedup
2026-04-14 09:23:02 +08:00
erio
1b53ffcac7
feat(gateway): add web search emulation for Anthropic API Key accounts
...
Inject web search capability for Claude Console (API Key) accounts that
don't natively support Anthropic's web_search tool. When a pure
web_search request is detected, the gateway calls Brave Search or Tavily
API directly and constructs an Anthropic-protocol-compliant SSE/JSON
response without forwarding to upstream.
Backend:
- New `pkg/websearch/` SDK: Brave and Tavily provider implementations
with io.LimitReader, proxy support, and Redis-based quota tracking
(Lua atomic INCR + TTL, DECR rollback on failure)
- Global config via `settings.web_search_emulation_config` (JSON) with
in-process cache + singleflight, input validation, API key merge on
save, and sanitized API responses
- Channel-level toggle via `channels.features_config` JSONB column
(DB migration 101)
- Account-level toggle via `accounts.extra.web_search_emulation`
- Request interception in `Forward()` with SSE streaming response
construction using json.Marshal (no manual string concatenation)
- Manager hot-reload: `RebuildWebSearchManager()` called on config save
and startup via `SetWebSearchRedisClient()`
- 70 unit tests covering providers, manager, config validation,
sanitization, tool detection, query extraction, and response building
Frontend:
- Settings → Gateway tab: Web Search Emulation config card with global
toggle, provider list (add/remove, API key, priority, quota, proxy)
- Channels → Anthropic tab: web search emulation toggle with global
state linkage (disabled when global off)
- Account Create/Edit modals: web search emulation toggle for API Key
type with Toggle component
- Full i18n coverage (zh + en)
2026-04-14 09:20:39 +08:00
qingyuzhang
abe4267553
fix(frontend): lazy load mobile account usage cells
2026-04-13 07:34:07 +08:00
erio
ff86154a03
refactor: remove unused OpenAIOAuthOptions after Sora platform removal
...
The options parameter only served to switch between 'openai' and 'sora'
platforms. With Sora removed, the parameter is unnecessary.
2026-04-05 17:19:27 +08:00
erio
fcee67e317
fix: remove remaining unused Sora variables causing TypeScript build failure
...
- Remove unused accessTokenInput ref from OAuthAuthorizationFlow
- Remove unused parsedSessionToken* computed and handleValidateSessionToken
- Prefix unused options parameter in useOpenAIOAuth
2026-04-05 17:19:27 +08:00
erio
155900e62f
fix: remove unused Sora references causing TypeScript build failure
...
- Remove handleImportAccessToken event binding from CreateAccountModal
- Remove unused imports/variables from OAuthAuthorizationFlow (useAppStore,
parsedAccessToken*, handleImportAccessToken)
- Remove unused oauthPlatform variable from useOpenAIOAuth composable
2026-04-05 17:19:27 +08:00
erio
62e80c602d
revert: completely remove all Sora functionality
2026-04-05 17:11:01 +08:00
shaw
b65275235f
feat: Anthropic oauth/setup-token账号支持自定义转发URL
2026-03-30 09:10:57 +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
Wang Lvyuan
bb399e56b0
merge: resolve upstream main conflicts for bulk OpenAI passthrough
2026-03-24 19:27:51 +08:00
Wesley Liddick
7537dce0f0
Merge pull request #1230 from LvyuanW/bulk-openai-oauth-ws-mode-pr
...
Add bulk OpenAI OAuth WS mode editing
2026-03-24 15:17:13 +08:00
QTom and Claude Opus 4.6
9f8cffe887
feat(openai): 新增"手动输入 Mobile RT"入口,使用 SoraClientID 刷新
...
在 OpenAI 平台添加独立的"手动输入 Mobile RT"选项,使用
client_id=app_LlGpXReQgckcGGUo2JrYvtJK 刷新 token,与现有
"手动输入 RT"(Codex CLI client_id)互不影响。
共享同一 UI 和批量创建逻辑,通过 clientId 参数区分。
同时修复空名称触发 ent NotEmpty() 校验导致 500 的问题。
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-03-24 14:50:03 +08:00
Wang Lvyuan
73d72651b4
feat: support bulk OpenAI passthrough toggle
2026-03-23 17:17:42 +08:00
Wang Lvyuan
adbedd488c
Add bulk OpenAI OAuth WS mode editing
2026-03-23 17:11:01 +08:00
Wesley Liddick
4015f31f28
Merge pull request #1157 from LvyuanW/fix-bulk-model-restriction-empty
...
fix: allow clearing model restriction in bulk edit when whitelist is empty
2026-03-20 09:13:44 +08:00
shaw
525cdb8830
feat: Anthropic 账号被动用量采样,页面默认展示被动数据
...
从上游 /v1/messages 响应头被动采集 5h/7d utilization 并存储到
Account.Extra,页面加载时直接读取本地数据而非调用外部 Usage API。
用户可点击"查询"按钮主动拉取最新数据,主动查询结果自动回写被动缓存。
后端:
- UpdateSessionWindow 合并采集 5h + 7d headers 为单次 DB 写入
- 新增 GetPassiveUsage 从 Extra 构建 UsageInfo (复用 estimateSetupTokenUsage)
- GetUsage 主动查询后 syncActiveToPassive 回写被动缓存
- passive_usage_ 前缀注册为 scheduler-neutral
前端:
- Anthropic 账号 mount/refresh 默认 source=passive
- 新增"被动采样"标签和"查询"按钮 (带 loading 动画)
2026-03-19 17:42:59 +08:00
Wang Lvyuan
1de18b89dd
merge: sync upstream/main before PR
2026-03-19 16:37:28 +08:00
Wang Lvyuan
882518c111
fix(frontend): allow clearing model restriction in bulk edit
2026-03-19 16:32:13 +08:00
Wesley Liddick
21f349c032
Merge pull request #1095 from LvyuanW/lvyuan/dev
...
fix(admin/accounts): reset edit modal state on reopen
2026-03-18 11:37:07 +08:00
Ethan0x0000
2005fc97a8
fix(ui): show 'now' for idle OpenAI usage windows
...
Use utilization-based idle detection instead of local request counts so newly imported OAuth accounts keep countdowns when usage is non-zero.
2026-03-17 19:23:35 +08:00
Wang Lvyuan
0772d9250e
fix(admin/accounts): reset edit modal state on reopen
2026-03-17 18:44:10 +08:00
Wesley Liddick
c521117b99
Merge pull request #1074 from StarryKira/fix/session-window-reset-from-header
...
fix(usage): use real reset header for 5h session window countdown fix issue #1064 #1065
2026-03-17 14:48:16 +08:00