Commit Graph

163 Commits

Author SHA1 Message Date
erio
ba98243cc2 feat(channel-monitor): gate UI by feature switch + polish form UX
- AppSidebar 三处菜单项(管理端渠道监控、用户端/个人页渠道状态)按
  channel_monitor_enabled 条件展开,关闭时隐藏
- ChannelStatusView setInterval 随开关启停:关闭 clearInterval,
  开启/未知态自动启动,避免禁用功能后仍在轮询
- MonitorFormDialog provider Select 改为 3 色单选按钮
  (openai=emerald / anthropic=orange / gemini=sky),i18n 文案
  供应商 → 平台 / Provider → Platform
- MonitorKeyPickerDialog 按钮列表改为 name/key/group 三列表格 +
  搜索框,按 key.group.platform === provider 过滤,避免跨平台误选
- form.provider 变化时清空 api_key,修复切换平台仍保留旧 key 的
  错配 bug
- providerPickerClass 抽取到 useChannelMonitorFormat composable,
  统一 emerald/orange/sky 颜色语义,消除硬编码 Tailwind class 重复
- maskApiKey 工具函数统一(utils/maskApiKey.ts),KeysView 与
  MonitorKeyPickerDialog 共用 slice(0,6)...slice(-4) 策略
- bump version to 0.1.114.27
2026-04-21 01:42:58 +08:00
erio
7da5124067 feat(channel-monitor): add feature switch settings + fix extra_models save
Settings:
- New "功能开关" tab between 通用设置 and 安全与认证
- ChannelMonitorEnabled toggle: runner skips scheduling when false,
  user-facing list returns empty
- ChannelMonitorDefaultIntervalSeconds (15-3600): pre-fills interval
  when creating a new monitor; each monitor can still override

Bug fix:
- ModelTagInput now commits pending input on blur, not just Enter/Tab.
  Previously clicking "save" with an un-Enter'd extra model would drop
  the value (DB stored extra_models=[] even when user typed entries).

Backend:
- domain_constants: SettingKeyChannelMonitor{Enabled,DefaultIntervalSeconds}
- SettingService.GetChannelMonitorRuntime: lightweight getter used by
  runner tick + user handler per-request (fail-open on DB error)
- Runner tickDueChecks: bails early when feature disabled
- ChannelMonitorUserHandler: checks feature flag before serving
- Comment on runner doc: scheduler state is implicit (every tick re-reads
  ListEnabled from DB), so CRUD ops on monitors self-maintain the schedule

Bump VERSION to 0.1.114.25
2026-04-21 00:21:29 +08:00
erio
20a4e41872 feat(monitor): admin channel monitor MVP with SSRF protection and batch aggregation
新增 admin「渠道监控」模块(参考 BingZi-233/check-cx),独立于现有 Channel 体系。
admin 配置 + 后台定时调用上游 LLM chat completions 健康检查 + 所有登录用户只读可见。

后端:
- ent: channel_monitor + channel_monitor_history(AES-256-GCM 加密 api_key)
- service 按职责拆分:service/aggregator/validate/checker/runner/ssrf
- provider strategy map 替代 switch(openai/anthropic/gemini)
- repository batch 聚合(ListLatestForMonitorIDs + ComputeAvailabilityForMonitors)消除 N+1
- runner: ticker(5s) + pond worker pool(5) + inFlight 防并发 + TrySubmit 防雪崩
  + 凌晨 3 点 cron 清理 30 天历史
- SSRF 防护:强制 https + 私网/loopback/云元数据 IP 拒绝(127/8、10/8、172.16/12、
  192.168/16、169.254/16、100.64/10、::1、fc00::/7、fe80::/10)+ DialContext
  在 socket 层防 DNS rebinding
- API key sanitize:擦除 url.Error 与上游响应 body 中的 sk-/sk-ant-/AIza/JWT 模式
- APIKeyDecryptFailed 标志位 + 单 monitor 路径检测,避免空 key 调用上游

handler:
- admin: CRUD + 手动触发 + 历史接口(api_key 脱敏)
- user: 只读列表 + 状态详情(去除 api_key/endpoint)
- ParseChannelMonitorID 共用 + dto.ChannelMonitorExtraModelStatus 共用

前端:
- 路由 /admin/channels/{pricing,monitor} + /monitor(用户只读)
- AppSidebar 父项 expandOnly 支持
- ChannelMonitorView 拆为 8 个子组件 + ChannelStatusView 拆出 detail dialog
- composables/useChannelMonitorFormat + constants/channelMonitor 共享
- i18n monitorCommon namespace 消除 admin/user 两 view 重复

合规:所有文件符合 CLAUDE.md(Go ≤ 500 行 / Vue ≤ 300 行 / 函数 ≤ 30 行)
CI: go build / gofmt / golangci-lint(0 issues) / make test-unit / pnpm build 全绿
2026-04-20 20:21:02 +08:00
shaw
4d0483f5b8 feat: 补充gpt生图模型测试功能 2026-04-22 18:12:03 +08:00
erio
df57d2776b fix(billing): reject rate_multiplier <= 0 on save; clamp negatives to 0 in compute
分组倍率和用户专属倍率在保存时没有校验,0 会触发计费层的 `<=0 → 1.0`
防御条款,结果订阅/余额分组按标准价扣费;完全是沉默地绕过了业务规则。

- 保存校验(admin_service):CreateGroup / UpdateGroup / BatchSetGroupRateMultipliers /
  UpdateUser.SyncUserGroupRates 全部要求 > 0
- 计算层(billing_service):三处 `<=0 → 1.0` 改为 `<0 → 0`;负数按 0 结算,
  避免配置异常被静默按 1x 收费
- 前端:分组倍率 / 用户专属倍率输入 min 统一到 0.001
- 删除未使用的 IsFreeSubscription 方法

测试:新增 billing_service_rate_multiplier_test.go 端到端验证;更新原有锁定
旧 `<=0 → 1.0` 行为的测试。
2026-04-17 22:06:32 +08:00
Wesley Liddick
1db32d692b Merge pull request #1666 from touwaeriol/feat/account-cost-display
feat(usage): add account cost display to admin dashboard and usage pages
2026-04-15 16:43:07 +08:00
Wesley Liddick
8fd29082c0 Merge pull request #1663 from touwaeriol/fix/test-dialog-close-during-stream
fix(ui): allow closing test dialog during active SSE stream
2026-04-15 16:40:40 +08:00
erio
e180dd0710 fix(usage): remove label text from inline account cost, keep orange color 2026-04-15 16:09:58 +08:00
erio
a7dd535d47 fix(usage): show account cost inline under cost column, remove separate column
- Cost cell: change gray "A $xxx" to orange "成本 $xxx" with i18n
- Remove standalone account_cost column from column settings (redundant)
2026-04-15 15:59:51 +08:00
erio
db27e8f000 feat(usage): add account cost to breakdown sub-table and admin usage log
- UserBreakdownItem: add AccountCost field + SQL aggregation
- UserBreakdownSubTable: add orange account cost column
- Admin usage table: add account_cost column (after cost, default visible)
- Column settings: add account_cost toggle option
2026-04-15 15:40:40 +08:00
erio
e0b12b7512 fix(usage): put cost label before value in usage stats card 2026-04-15 15:02:21 +08:00
erio
6ade6d30a8 feat(usage): add account cost display to admin dashboard and usage pages
- Add account_cost column to dashboard aggregation tables (migration 107)
- DashboardStats: add TotalAccountCost/TodayAccountCost fields
- ModelStat/GroupStat: add AccountCost field with SQL aggregation
- GetStatsWithFilters: always return TotalAccountCost (remove accountID filter)
- Dashboard Token cards: show user(green)/cost(orange)/standard(gray)
- Usage stats card: show account cost and standard below main value
- Model/Group distribution tables: add orange cost column
2026-04-15 15:02:21 +08: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
e761d38fd1 fix(payment): integrate recharge fee rate in order flow and fix UI display
Backend:
- Use cfg.RechargeFeeRate in order creation instead of hardcoded 0
- Remove dead getFeeRate stub method
- All amounts computed server-side: order_amount, pay_amount, fee_rate

Frontend - PaymentView:
- Read recharge_fee_rate from checkout-info API (not per-method)
- Show fee breakdown only when fee_rate > 0
- Show credited amount only when multiplier ≠ 1

Frontend - Order display (user + admin):
- Fix fee_rate * 100 bug (fee_rate is already a percentage)
- OrderTable: show pay_amount as primary, fee/credited as sub-lines
- AdminOrderDetail: full breakdown (base/fee/paid/credited)
- AdminRefundDialog: label "到账金额" for clarity
- PaymentResultView: show pay_amount with fee info

Types + i18n:
- Add recharge_fee_rate to CheckoutInfoResponse
- Add fee_rate to CreateOrderResult
- Add translations: creditedAmount, fee, baseAmount, includedInPayAmount
2026-04-15 01:27:24 +08:00
erio
60a4b9316b feat(payment): balance recharge multiplier and refund amount separation
- Add balance_recharge_multiplier system setting (e.g. 1.2 = charge 100 get 120)
- Separate order_amount (credited balance) from pay_amount (actual payment)
- Refund calculates gateway amount proportionally from pay_amount
- Frontend shows both amounts in order details, payment status, refund dialog
- Admin settings UI for configuring recharge multiplier
2026-04-15 01:27:24 +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
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
a68df457d8 fix: address audit findings across websearch, notify, and channel pricing
Backend fixes:
- Fix balance notify ignoring percentage threshold type (was treating
  percentage value as fixed USD amount)
- Remove dead code parseJSONStringArray
- Add ImageOutputTokens to tryModelFilePricing calculation
- Unify zero-value check: cost == 0 → cost <= 0 in calculateTokenStatsCost
- Use MarshalNotifyEmails instead of json.Marshal for consistency
- Rename quotaDim.oldUsed → currentUsed for clarity
- Extract HTML email templates to const variables (function ≤30 lines)

Test fixes:
- Rewrite account_websearch_test.go for GetWebSearchEmulationMode tri-state
- Add 6 tryModelFilePricing test cases

Frontend fixes:
- Replace hardcoded '未命名' with i18n key
- Extract getBillingModeLabel/getBillingModeBadgeClass to shared utils
- Replace inline type with imported NotifyEmailEntry
- Pass platform to AccountStats pricing rules via inferRulePlatform()
- Add billing mode constants (BILLING_MODE_TOKEN/PER_REQUEST/IMAGE)
2026-04-14 09:26:08 +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
fa833f7684 Merge remote-tracking branch 'upstream/main' into feat/payment-system-v2
# Conflicts:
#	frontend/src/api/admin/settings.ts
#	frontend/src/stores/app.ts
#	frontend/src/types/index.ts
#	frontend/src/views/admin/SettingsView.vue
2026-04-11 18:25:06 +08:00
erio
e3a000e0d4 refactor(payment): code standards fixes and regression repairs
Backend:
- Split payment_order.go (546→314 lines) into payment_order_lifecycle.go
- Replace magic strings with constants in factory, easypay, webhook handler
- Add rate limit/validity unit constants in payment_order_lifecycle, payment_service
- Fix critical regression: add PaymentEnabled to GetPublicSettings response
- Add missing migration 099_fix_migrated_purchase_menu_label_icon.sql

Frontend:
- Fix StripePopupView.vue: replace `as any` with typed interface, use extractApiErrorMessage
- Fix AdminOrderTable.vue: replace hardcoded column labels with i18n t() calls
- Fix SubscriptionsView.vue: replace hardcoded Today/Tomorrow with i18n
- Extract duplicate statusBadgeClass/canRefund/formatOrderDateTime to orderUtils.ts
- Add missing i18n keys: common.today, common.tomorrow, payment.orders.orderType/actions
- Remove dead PurchaseSubscriptionView.vue (replaced by PaymentView)
2026-04-11 13:16:35 +08:00
erio
63d1860dc0 feat(payment): add complete payment system with multi-provider support
Add a full payment and subscription system supporting EasyPay (Alipay/WeChat),
Stripe, and direct Alipay/WeChat Pay providers with multi-instance load balancing.
2026-04-11 13:16:35 +08:00
IanShaw027
5f8e60a1b7 feat(table): 表格排序与搜索改为后端处理 2026-04-09 18:14:28 +08:00
IanShaw027
d8fa38d55a fix(account): 修复账号管理中的状态筛选 2026-04-09 18:14:28 +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
62e80c602d revert: completely remove all Sora functionality 2026-04-05 17:11:01 +08:00
erio
71f61bbc47 fix: resolve 5 audit findings in channel/credits/scheduling
P0-1: Credits degraded response retry + fail-open
- Add isAntigravityDegradedResponse() to detect transient API failures
- Retry up to 3 times with exponential backoff (500ms/1s/2s)
- Invalidate singleflight cache between retries
- Fail-open after exhausting retries instead of 5h circuit break

P1-1: Fix channel restriction pre-check timing conflict
- Swap checkClaudeCodeRestriction before checkChannelPricingRestriction
- Ensures channel restriction is checked against final fallback groupID

P1-2: Add interval pricing validation (frontend + backend)
- Backend: ValidateIntervals() with boundary, price, overlap checks
- Frontend: validateIntervals() with Chinese error messages
- Rules: MinTokens>=0, MaxTokens>MinTokens, prices>=0, no overlap

P2: Fix cross-platform same-model pricing/mapping override
- Store cache keys using original platform instead of group platform
- Lookup across matching platforms (antigravity→anthropic→gemini)
- Prevents anthropic/gemini same-name models from overwriting each other
2026-04-04 11:25:01 +08:00
erio
6c718578a5 refactor(ui): extract formatCacheTokens and formatMultiplier to shared utils 2026-04-04 11:21:11 +08:00
erio
212eaa3a05 fix(ui): show token breakdown when image model uses token billing
Only display image count format when billing_mode is "image".
When channel has token pricing, show input/output/cache token details.
2026-04-04 11:19:55 +08:00
erio
1b2ea7a1df fix(ui): also fix floating point precision in mTokToPerToken 2026-04-04 11:17:49 +08:00
erio
a9e5fc8539 fix(ui): floating point precision in perTokenToMTok conversion 2026-04-04 11:17:49 +08:00
erio
9b213115e7 fix: address audit findings - cache sync, validation, consistency
- clearCreditsExhausted: sync Redis scheduler cache after DB update
- Image billing mode UI: write to per_request_price instead of image_output_price
- OpenAI RecordUsage: use BillingModelSourceRequested constant, add s.cfg nil guard
- Fix i18n key path: admin.channels.perRequestPriceRequired → admin.channels.form.perRequestPriceRequired
2026-04-04 11:17:49 +08:00
erio
2355029dc1 fix: validate empty intervals + antigravity platform pricing match
- Backend: reject intervals with all-null price fields on save
- Backend: filterValidIntervals skips empty intervals in pricing resolver
- Frontend: red border + asterisk on empty interval rows
- Backend: antigravity groups now match anthropic/gemini channel pricing
2026-04-04 11:17:49 +08:00
erio
c0b5900a37 feat(ui): display three-level model mapping chain in usage logs
- Show channel + account mapping steps using model_mapping_chain field
- Add model_mapping_chain to AdminUsageLog TypeScript type
- Fallback to two-level display when chain is not available
- Fix cost nil guard in Anthropic/Antigravity RecordUsage paths
- Bump version to 0.1.105.31
2026-04-04 11:17:48 +08:00
erio
d72ac92694 feat: image output token billing, channel-mapped billing source, credits balance precheck
- Parse candidatesTokensDetails from Gemini API to separate image/text output tokens
- Add image_output_tokens and image_output_cost to usage_log (migration 089)
- Support per-image-token pricing via output_cost_per_image_token from model pricing data
- Channel pricing ImageOutputPrice override works in token billing mode
- Auto-fill image_output_price in channel pricing form from model defaults
- Add "channel_mapped" billing model source as new default (migration 088)
- Bills by model name after channel mapping, before account mapping
- Fix channel cache error TTL sign error (115s → 5s)
- Fix Update channel only invalidating new groups, not removed groups
- Fix frontend model_mapping clearing sending undefined instead of {}
- Credits balance precheck via shared AccountUsageService cache before injection
- Skip credits injection for accounts with insufficient balance
- Don't mark credits exhausted for "exhausted your capacity on this model" 429s
2026-04-04 11:15:59 +08:00
erio
2555951be4 feat(channel): 渠道管理全链路集成 — 模型映射、定价、限制、用量统计
- 渠道模型映射:支持精确匹配和通配符映射,按平台隔离
- 渠道模型定价:支持 token/按次/图片三种计费模式,区间分层定价
- 模型限制:渠道可限制仅允许定价列表中的模型
- 计费模型来源:支持 requested/upstream 两种计费模型选择
- 用量统计:usage_logs 新增 channel_id/model_mapping_chain/billing_tier/billing_mode 字段
- Dashboard 支持 model_source 维度(requested/upstream/mapping)查看模型统计
- 全部 gateway handler 统一接入 ResolveChannelMappingAndRestrict
- 修复测试:同步 SoraGenerationRepository 接口、SQL INSERT 参数、scan 字段
2026-04-04 11:13:58 +08:00
erio
669bff78c4 fix(ui): 模型映射改用平台色字体,删除多余的边框色函数 2026-04-04 11:13:57 +08:00
erio
40cebc250f feat(ui): 渠道表单模型标签和映射输入框显示平台对应颜色
- PricingEntryCard 折叠态模型 tag 按平台着色
- ModelTagInput 模型标签按平台着色
- 模型映射输入框边框按平台着色
2026-04-04 11:13:57 +08:00
erio
58f2044637 fix(ui): 渠道定价折叠态模型名完整展示,不再截断
去掉 max-w-[120px] truncate 限制,改用 flex-wrap 允许换行,
充分利用空白区域展示完整模型名。
2026-04-04 11:13:57 +08:00
erio
a51e0047b7 feat(usage): 使用记录增加计费模式字段 — 记录/展示/筛选 token/按次/图片
- DB: usage_logs 表新增 billing_mode VARCHAR(20) 列
- 后端: RecordUsage 写入时根据 image_count 判定计费模式
- 前端: 使用记录表格新增计费模式 badge 列 + 筛选下拉
2026-04-04 11:11:06 +08:00
erio
12d03e4030 feat(channel): 模型价格自动填充 + 默认定价 API
- 新增 GET /admin/channels/model-pricing?model=xxx API
- 从 BillingService 查询 LiteLLM/Fallback 默认定价
- 前端添加模型时自动查询并填充价格($/MTok)
- 仅在所有价格字段为空时才自动填充,不覆盖手动配置
2026-04-04 11:09:28 +08:00
erio
ebac0dc628 feat(channel): 缓存扁平化 + 网关映射集成 + 计费模式统一 + 模型限制
- 缓存重构为 O(1) 哈希结构 (pricingByGroupModel, mappingByGroupModel)
- 渠道模型映射接入网关流程 (Forward 前应用, a→b→c 映射链)
- 新增 billing_model_source 配置 (请求模型/最终模型计费)
- usage_logs 新增 channel_id, model_mapping_chain, billing_tier 字段
- 每种计费模式统一支持默认价格 + 区间定价
- 渠道模型限制开关 (restrict_models)
- 分组按平台分类展示 + 彩色图标
- 必填字段红色星号 + 模型映射 UI
- 去除模型通配符支持
2026-04-04 11:09:01 +08:00
erio
29d58f2414 feat(channel): 模型映射 + 分组搜索 + 卡片折叠 + 冲突校验
- 渠道模型映射:新增 model_mapping JSONB 字段,在账号映射之前执行
- 分组选择:添加搜索过滤 + 平台图标
- 定价卡片:支持折叠/展开,已有数据默认折叠
- 模型冲突校验:前后端均禁止同一渠道内重复模型
- 迁移 083: channels 表添加 model_mapping 列
2026-04-04 11:06:36 +08:00
erio
dca0054e93 feat(channel): 模型标签输入 + $/MTok 价格单位 + 左开右闭区间 + i18n
- 模型输入改为标签列表(输入回车添加,支持粘贴批量导入)
- 价格显示单位改为 $/MTok(每百万 token),提交时自动转换
- Token 模式增加图片输出价格字段(适配 Gemini 图片模型按 token 计费)
- 区间边界改为左开右闭 (min, max],右边界包含
- 默认价格作为未命中区间时的回退价格
- 添加完整中英文 i18n 翻译
2026-04-04 11:01:22 +08:00
erio
91c9b8d062 feat(channel): 渠道管理系统 — 多模式定价 + 统一计费解析
Cherry-picked from release/custom-0.1.106: a9117600
2026-04-04 11:00:55 +08:00
QTom
c13c81f09d feat(privacy): 为 OpenAI OAuth 账号添加前端手动设置隐私按钮
复用已有的 set-privacy API 端点,Handler 通过 platform 分发到
ForceOpenAIPrivacy / ForceAntigravityPrivacy,前端 AccountActionMenu
扩展隐私按钮支持 OpenAI OAuth 账号。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 14:51:36 +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
QTom
c2965c0fb0 feat(antigravity): 自动设置隐私并支持后台手动重试
新增 Antigravity OAuth 隐私设置能力,在账号创建、刷新、导入和后台
Token 刷新路径自动调用 setUserSettings + fetchUserInfo 关闭遥测;
持久化后同步内存 Extra,错误处理改为日志记录。

Made-with: Cursor
2026-03-25 17:38:41 +08:00
weak-fox
4838ab74b3 feat(admin): add account privacy mode filter 2026-03-23 10:16:52 +08:00