Randark
41344c20ff
feat(monitor): wire quota fetcher & expose check_mode in handlers
...
- handler DTO: create/update 接收 check_mode/account_id,provider oneof 扩至 8 家,
endpoint/api_key 改为 omitempty(条件必填下沉 service 校验);
monitor/checkResult/historyItem 响应透传 check_mode/account_id/quota
- 用户端 latest_quota 由 channel_monitor_show_quota 控制,关闭时服务端剥离
- wire: NewChannelMonitorQuotaFetcher 以具体服务类型收参(窄接口包内保留供
stub),ProvideChannelMonitorRunner 注入后 SetQuotaFetcher
2026-08-18 04:14:15 +00:00
Randark
901a0439f1
feat: 国产供应商一等支持(Kimi/Zhipu/DeepSeek 多协议 + 配额/余额监控)
...
后端:
- 协议凭证维度 credentials[api_protocol] ∈ chat_completions(默认)/anthropic/responses(deepseek)
- /v1/messages 零转换直通原生 Anthropic 端点(kimi/zhipu/deepseek),CC/Responses
入站交叉组合走 apicompat 双向转换链(responses/chat_completions anthropic-native 转发器)
- count_tokens:anthropic 协议透传原生端点;其余 CN 协议本地 tiktoken 估算
- Coding Plan 额度探测(5h/weekly 滚动窗口)+ payg 余额探测(kimi/deepseek),
deepseek 双币种 CNY+USD 明细,任一币种达标不停调
- 周期任务 [CNBalance] 并发探测 + 预算随工作量放大;响应式 429 冷却到最早窗口
重置点;余额不足可恢复临时停调;智谱 CREDIT_LIMIT 不污染窗口解析
- CC→anthropic 流式客户端断开后继续排水上游保住 usage 计量
前端:
- 创建/编辑弹窗 account_mode + api_protocol + base_url 联动预设(含 watcher 竞态防护)
- 用量单元格:kimi/zhipu coding 显示 5h/weekly 窗口,kimi/deepseek payg 显示余额,
多币种并列展示;探测失败保留快照;挂载自动探测 5min 去抖
- 调度阈值设置面板补 kimi/zhipu 平台(对齐后端 AllowedSchedulingThresholdPlatforms)
2026-08-15 10:37:51 +00:00
Wesley Liddick
e803e3851c
Merge pull request #5559 from seng1e/fix/scheduled-backup-leader-lock
...
fix(backup): 定时备份加 leader 锁,避免多实例重复备份
2026-08-13 09:24:11 +08:00
seng1e and Claude Opus 4.8
bba6a55e0f
fix(backup): 定时备份加 leader 锁,避免多实例重复备份
...
仓库里所有周期任务都用 tryAcquireSingletonLeaderLock 选主、只让一个实例跑
(ops:*、dashboard:aggregation、subscription:expiry、payment:order:expiry 等),
唯独定时备份 runScheduledBackup 没接这套锁,每个实例都自己跑一遍。
多实例部署下同一时刻:
- 同一个库被 N 次 pg_dump;
- 内存峰值 ×N —— 归档整个读进内存再上传,内存吃紧的节点会直接 OOM;
- 上传的是同一个带时间戳的 key,N 份互相覆盖,白干一场连多余副本都留不下。
实测 3 节点:每天 backup_records 里三条一模一样的记录(同 key、同大小)。
改动:把 BackupService 接进和其它任务一样的 tryAcquireSingletonLeaderLock
(key=backup:scheduled:leader)。只锁定时备份,手动备份(CreateBackup/
StartBackup)不锁;无协调后端(cache/db 均 nil)时不加锁照常跑,单机/单测
行为不变;锁 TTL 35m > 备份自身 30m context 上限,防止大库 dump 中途锁过期。
wire_gen.go 由 wire 重新生成。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-08-12 21:36:41 +08:00
Lucky
814ecfba7c
fix(group): invalidate the channel cache when a group's platform changes
...
The channel cache holds a groupID -> platform map with a 10 minute TTL, and
only channel Create/Update/Delete call invalidateCache(). Changing a group's
platform through the admin API therefore leaves the cache pointing at the old
platform for up to 10 minutes.
Channel pricing, model mapping and the model whitelist are all matched per
platform, so during that window the lookups silently miss: pricing falls back
to the global LiteLLM price list, renames stop applying and the whitelist
stops restricting. Nothing is logged.
Inject a narrow ChannelCacheInvalidator into the admin service (same shape as
the existing APIKeyAuthCacheInvalidator) and call it from UpdateGroup only when
the platform actually changed. The dependency is optional -- when it is nil the
cache simply rebuilds on TTL expiry, as before.
2026-08-12 03:22:06 +00:00
shaw
d92edc01be
Merge origin/main into feat/channel-monitor-v2-ops-ui
...
Resolves three conflicts, all of the "both branches appended to the same
block" shape. Every one is resolved as a union of both sides; nothing from
either parent is dropped.
- handler/admin/setting_handler_update.go: keep ChannelMonitorHideThroughput
(V2) alongside GrokDefaultTextModel / GrokCrossClientModelMapEnabled /
GrokDefaultBaseURLMode (#5408 ). UpdateSettings writes every key on each
save, so dropping either side would reset those settings to zero values.
- service/domain_constants.go: keep SettingKeyChannelMonitorHideThroughput
and the three SettingKeyGrok* constants.
- repository/migrations_runner.go: keep the 195 checksum rule (V2) and the
218/219/220 rules (#5408 ).
2026-08-09 12:11:35 +08:00
IanShaw027
68faeac837
fix(grok): restore base URL resolution and operator settings wiring
...
Honor account GetGrokBaseURLOr policy for official vs custom endpoints,
and wire settings resolution used by responses/chat URL builders.
2026-08-08 01:07:19 +08:00
IanShaw027
ccf7ba3ba7
fix(grok): P2 分层清理、主对话 SearchCount 与调度 7d/30d
...
- DoGrokNativeResponsesJSON 去 gin.Context,UA 固定 CLI 身份
- GrokOAuthService 去掉 redis 直依赖,session store 由 wire 注入
- 主对话/流式响应统计 web_search_call/x_search/tool_search 写入 SearchCount
- Grok 调度阈值候选并入官方 weekly/monthly billing %
2026-08-07 17:21:01 +08:00
IanShaw027
25d2b03e90
fix(grok): 加固 OAuth 会话共享与一次性消费
2026-08-07 16:29:48 +08:00
IanShaw027
d0930c4bdb
fix(grok): 完善密码与SSO授权能力控制
2026-08-07 14:13:07 +08:00
IanShaw027
4a9459d607
fix(channel-monitor-v2): 修复 CI gofmt 与 public settings 注入契约
...
对齐 gofmt,并在 PublicSettingsInjectionPayload 补齐 channel_monitor_mode,
使 SSR 注入字段与 dto.PublicSettings 一致,修复 schema drift 单测失败。
2026-08-07 12:02:27 +08:00
IanShaw027
a5beecb92a
feat(channel-monitor-v2): 接入模式开关、路由门控与依赖注入
...
注册 admin/user 路由与 feature/mode 守卫,串联 Wire DI 与设置读写,
公开 channel_monitor_mode 与 hide_throughput 等运行时标志。
2026-08-07 11:05:32 +08:00
feeeei
26e0a89323
人机验证增加阿里云验证码 2.0
...
沿用腾讯天御验证码引入的多服务商模型:aliyun_captcha_enabled 作为独立
开关,与 Cloudflare Turnstile、腾讯天御三方互斥(保存校验 + 运行时
CAPTCHA_PROVIDER_CONFLICT)。后台「安全与认证」合并为单张人机验证卡片:
总开关 + 服务商单选(Turnstile / 腾讯天御 / 阿里云),选中即启用该家并
关闭其它,落库仍是三个独立开关键,由前端映射保证互斥。
阿里云侧同时支持 aliyun 中国站与国际站(alibabacloud.com):两站前端脚本、
region 取值与服务端 API 完全一致,仅账号与 AccessKey 相互独立,因此由
「服务地域」决定线路即可——中国内地走 captcha.cn-shanghai.aliyuncs.com,
非中国内地(新加坡)走 captcha.ap-southeast-1.aliyuncs.com,AccessKey
取自持有该实例的账号,无需在配置中区分站点。
- AliyunCaptchaService 对称 TencentCaptchaService:服务端校验走官方 SDK
VerifyIntelligentCaptcha,调用异常按 fail-closed 拦截,与 Turnstile
网络错误行为对称;保存设置时真实探测 AK/SK 有效性
- 保护面对齐腾讯扩展入口:VerifyTencentCaptchaIfEnabled 通用化为
VerifyActionCaptchaIfEnabled,OAuth 登录启动、passkey 登录在阿里云
启用时同样拦截;Turnstile 维持既有覆盖不扩大
- 前端 AliyunCaptchaWidget 为表单内预验证按钮(popup 模式),同时暴露
verify() 供 OAuth 启动、passkey 等动作入口程序化弹窗;未预验证直接
提交时弹窗兜底。SDK 按钮绑定异步完成,弹窗未出现前按 tick 重试触发,
并轮询弹窗可见性识别用户关闭
- captchaVerifyParam 复用 turnstile_token 请求字段提交;公开设置下发
aliyun_captcha_enabled / scene_id / prefix / region
- CSP 放行验证码 CDN:script-src/style-src 加 *.alicdn.com
2026-08-04 20:57:15 +08:00
Wesley Liddick
8b3fe664dc
Merge pull request #5261 from lyen1688/feat/tencent-captcha-gate
...
新增腾讯天御验证码认证门禁
2026-08-04 16:39:55 +08:00
lyen1688
e592c5f9e0
新增腾讯天御验证码认证门禁
2026-08-04 15:09:29 +08:00
zhiyu
2eb24814fe
fix(codex): 强制统一出站身份并让客户端版本号跟随官方发布
...
上游 /backend-api/codex 在容量紧张时按客户端身份分优先级降载,被降载的请求
HTTP 200 后立刻推流内 server_is_overloaded。此前网关对配不出官方身份的客户端
整体回退到硬编码的 codex_cli_rs/0.144.1(落后官方 4 个发布),这些请求稳定
落在被优先丢弃的一侧。
- 强制统一出口:所有 OAuth 出站的 User-Agent / originator / version 一律改写
为网关规范身份,客户端自报身份不参与构造;HTTP / 透传 / WS / alpha-search /
探针全覆盖。compat 桥接故意删除 originator 的路径保持 no-op。
- 版本号收敛为单一来源,运行时优先级为面板覆写 → 自动同步值 → 内置常量;
UA 与 version 头同源派生,不再各自硬编码。
- 新增 3 小时自动同步官方客户端最新稳定版,面板可关闭,无需为跟版本而发版。
- 流内 server_is_overloaded / slow_down 改为先在同账号有界重试再切号,并标记为
请求级瞬时故障,不再据此临时封禁账号。
- 移除被取代的降载身份黑名单、浏览器 UA 兜底及其辅助函数。
2026-08-03 20:14:58 +08:00
Zhixuan Jiang
cc62979aa7
feat: add passkey authentication
2026-07-26 09:50:28 -04:00
alfadb
5ac4a9fac2
feat(ollama): 支持 Cloud 官方用量自动刷新
2026-07-23 15:50:44 +08:00
Heatherm Huang
a008b63c16
Add composite group route registry
2026-07-23 09:20:18 +08:00
Wesley Liddick
bfabfe60c8
Merge pull request #4593 from StarryKira/fix/image-storage-env-unreachable
...
fix: 异步生图开关配了却不生效(环境变量被静默丢弃 + 迁移到后台开关)
2026-07-20 09:20:15 +08:00
Jlypx and Sisyphus
f72958d530
feat: 持久化客户端 IP 请求头设置
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai >
2026-07-20 00:09:11 +08:00
haruka and Claude Opus 4.8
b08cab91a9
feat(image-storage): 异步生图对象存储改为后台配置,保存即生效
...
此前开启异步生图必须改服务器上的 config.yaml 并重启容器(#4542),且若想
复用已配置的备份 S3,还得把同一套凭证再填一遍(#4458)。
- 新增 ImageStorageSettingService:配置存 settings 表,SecretAccessKey 经
SecretEncryptor 加密落库、读回脱敏、留空表示沿用旧值,与备份 S3 配置同一套做法。
- reuse_backup_s3(默认开)直接借用 backup_s3_config 的端点与密钥,只用自己的
bucket/prefix 区分对象,因此备份走 backups/、图片走 images/,且密钥不会在库里存两份。
- ImageTaskService 的启用状态改由 ImageStorageResolver 在运行时解析并缓存,
保存设置后 Invalidate 使下次请求重建客户端——不再需要重启。
- repository 侧由提供实例改为提供工厂,客户端才可能在运行期重建。
- 轮询接口的门控从 enabled() 放宽为 Pollable():关掉开关只拒绝新提交,
已受理的任务仍可取回结果,不再被中途吞掉。
- config.yaml 的 image_storage 保留为回落,后台从未保存过时沿用,
升级前已用配置文件开启的部署不受影响。
- 管理端 GET/PUT/POST /admin/backups/image-storage,PUT 与备份 S3 配置一样要求
step-up 2FA:改写存储目标同样能把生成内容导向外部账号。
注:go generate ./cmd/server 在当前 upstream 基线上即失败(securityaudit.
PromptAdminService 缺 provider),故 wire_gen.go 为手工同步。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01VHreE5pzCkSYz7J45fmd2Y
2026-07-19 00:56:21 -07:00
haruka and Claude Opus 4.8
37db8d031b
fix(config): 让环境变量能真正配置 image_storage 等凭证
...
viper.Unmarshal 只解码 AllKeys() 返回的键,而 AllKeys() 只汇总 SetDefault、
配置文件和显式 BindEnv 三个来源。AutomaticEnv 仅能覆盖已在其中的键,无法引入
新键;能兜底的 viper_bind_struct 又被 build tag 排除(我们只用 -tags embed)。
因此任何「没有注册默认值、且不在 config.yaml 里」的配置项,其环境变量会被静默
丢弃。image_storage 的 endpoint/bucket/access_key_id/secret_access_key/
public_base_url 正属此列,于是纯环境变量部署落到最坏组合:IMAGE_STORAGE_ENABLED
生效使 Enabled=true,四个凭证却为空 → Active()=false → 异步生图接口整体 404,
运维看到的却是"凭证不完整"。deploy/docker-compose.yml 默认就是纯环境变量驱动,
且自动生成的 config.yaml 从不写 image_storage 段,必然踩中(见 #4458、#4542)。
同类缺口不止于此:github_oauth、google_oauth、dingtalk_connect 三组第三方登录
配置(含 client_secret)同样完全无法用环境变量设置。
- 为这些键注册零值默认,使其进入 AllKeys() 而可被环境变量覆盖。零值与"键缺失"
时的解码结果一致,故行为不变。
- sticky_escape_enabled 例外:它的实际默认是 true(靠 IsSet 守卫在解码后补上),
注册 false 会让 IsSet 恒真而永久关闭该特性,故直接注册 true。
- 启动告警补上 missing_keys 字段,指明到底哪个凭证为空。
- 新增反射守卫测试:Config 结构体上每个可由环境变量表达的字段都必须已注册默认值。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01VHreE5pzCkSYz7J45fmd2Y
2026-07-18 05:24:32 -07:00
benjamin
b92bbf0299
fix: 过滤入口拒绝日志并强化鉴权边界
2026-07-18 00:11:18 +08:00
shaw
590efe29a5
Merge remote-tracking branch 'origin/main' into agent/fix-4326-async-image-object-storage
...
# Conflicts:
# backend/cmd/server/wire_gen.go
2026-07-16 15:32:38 +08:00
shaw
0ddd58aaf9
feat(security): 操作审计日志 + 会话IP/UA绑定 + 敏感操作 step-up 2FA
...
应对管理员访问凭证失守导致的数据外泄风险,新增三层防护:
审计日志(admin-only 可见,用户不可见)
- 新增 append-only audit_logs 表(migration 180)+ 异步批量写入 + 保留期清理
- 审计中间件挂在 admin/user/auth/admin-payment 组认证之后:记录所有变更类
请求 + 白名单敏感读取(账号/代理导出、备份下载、admin/user API key 读取)
- 请求头凭证首尾掩码;请求体 JSON 递归脱敏(api_key/password 等擦除,base_url
保留以便追责);非 JSON body 不入库
- 无单条删除;全量清空需现场 TOTP 校验、拒绝 admin API key、未启用 2FA 不允许,
清空后同步写入留痕记录
会话 IP/UA 绑定(默认开启,可在系统设置关闭)
- JWT 携带 session id + IP/UA 指纹哈希;IP 或 UA 任一变化即撤销会话家族并要求
重新登录;旧 token 无指纹时放行以平滑升级
敏感操作 step-up 2FA(sudo 窗口 15 分钟)
- 账号/代理导出、DB 备份创建/下载、S3 目标修改要求近期 TOTP 二次验证;admin API
key 一律拒绝;前端 useStepUp 组合式 + TotpStepUpDialog 弹码后自动重试
- API key 查看按需求暂不加强管控
前端:新增 /admin/audit-logs 操作日志页面(筛选/详情/2FA 清空)、侧边栏入口、
step-up 弹窗接入导出与备份流程、安全设置项(绑定开关 + 日志保留天数)、zh/en i18n
2026-07-16 13:47:50 +08:00
haruka and Claude Opus 4.8
0eb6e21aaa
feat: 异步图片任务结果落对象存储
...
为异步生图任务增加 S3 兼容对象存储支持,任务结果不再把大图内联存进 Redis:
- 新增可插拔接口 service.ImageStorage(Save -> url),适配别的厂商只需实现它
- S3 实现 S3ImageStorage(AWS S3 / R2 / 阿里云 OSS / MinIO),与备份共用 S3 客户端构造
- 新增 image_storage 配置(config.yaml + IMAGE_STORAGE_* 环境变量),默认关闭
- enabled 同时作为总开关:关闭或未配置对象存储时,异步生图接口返回 404 且不写
Redis,从根上避免几 MB 的 b64_json 结果撑爆 Redis
- 完成时把图片上传对象存储并把结果改写为短链接(公开直链或 presigned),
上传失败则任务标记为失败
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
Claude-Session: https://claude.ai/code/session_01SM1tf3CFVRzC7guuhBXvMd
2026-07-15 19:57:37 -07:00
haruka
1fb942dd77
feat: add async image generation tasks
2026-07-15 19:57:37 -07:00
Tian Lee
0765d10c1d
feat: 增加上游 Sub2API 计费倍率探测与账号展示
2026-07-15 23:58:46 +08:00
shaw
221581400b
feat(grok): 支持账号级自定义上游地址与请求头覆写
...
将账号级请求头覆写从 anthropic/openai 的 api_key 账号扩展到 Grok 的
api_key 与 oauth 账号,并放开 Grok OAuth 账号的自定义上游地址(仅作用于
转发端点,授权与 token 刷新链路不变)。
后端:
- IsHeaderOverrideEligible 扩展到 Grok(api_key+oauth),禁止名单新增
x-grok-conv-id(逐请求会话路由头)。
- 所有 Grok 上游请求路径接线 ApplyHeaderOverrides(Responses/Chat 桥/
媒体/配额探测/billing 探测/连通性测试),统一置于内置默认头之后。
- GetGrokBaseURL/GetGrokMediaBaseURL 放开 OAuth 自定义地址:官方地址
视同未定制回落官方网关,仅显式第三方 host 改发转发流量。
- 非官方 host 允许任意 path 前缀,官方 host 仍强制 /v1。
- OAuth base_url 校验按 host 判定官方/自定义,自定义 host 恒受运营方
URL 策略约束,不受 XAI_ALLOW_UNSAFE_URL_OVERRIDES 调试开关放宽。
- 给 GrokQuotaService 注入 config,使配额/billing 探测与转发共用同一
URL 策略。
前端:
- Edit 模态为 Grok OAuth 账号新增「自定义上游地址」开关。
- 请求头表单新增 JSON 快速导入与按 JSON 一键复制(复用 useClipboard,
兼容非安全上下文 HTTP 页面)。
- 门控改为平台×类型判定,Bulk 批量 base_url 增加格式校验,zh/en 文案同步。
2026-07-15 20:30:23 +08:00
Wesley Liddick
0de768e8be
Merge pull request #4221 from heathermhuang/codex/fix-grok-oauth-pool-health
...
fix(grok): refresh OAuth pools proactively
2026-07-15 16:07:09 +08:00
Wesley Liddick
4355861ef2
Merge pull request #4269 from catoncat/agent/sub2api-agent-identity
...
feat(openai): support Codex Agent Identity authentication
2026-07-15 09:47:00 +08:00
Heatherm Huang
6b25900403
fix(grok): refresh OAuth pools proactively
2026-07-15 09:40:08 +08:00
cat
d68a2aac1a
chore(openai): 同步上游并解决认证冲突
2026-07-14 19:04:04 +08:00
cat
f479a5d10c
fix(openai): 收紧 Agent Identity task 生命周期
2026-07-14 18:09:59 +08:00
Heatherm Huang
343390057d
fix(grok): fail over OAuth credential errors safely
2026-07-14 14:55:30 +08:00
superman2003
c896cacf6d
feat(grok): improve free quota probing and usage
2026-07-13 19:49:56 +08:00
Turtle_Li
1b07fe821a
merge: sync batch image branch with origin main
2026-07-07 03:27:11 +08:00
Turtle_Li
a994fbd77a
feat: add batch image MVP
2026-07-04 05:30:50 +08:00
Bestony@Homelab
089a7b7fae
feat(keys): add api key concurrency stats
2026-07-02 15:58:29 +08:00
DaydreamCoding and Claude Opus 4.8
819fda34d9
feat(codex-detect): codex_cli_only 检测加固 + 引擎指纹统一信号列表 + 账号级 app-server
...
将 codex_cli_only 客户端识别从「单一 strict 开关 + 固定 OR 头集合」重构为
可逐项管理的引擎指纹信号列表,加固整条判定链,并补齐账号级 app-server 控制、
对齐前端设置文案。
判定链(每步可短路):
- 账号未开 codex_cli_only → 不限制;gateway.force_codex_cli → 旁路放行
- 全局黑名单命中(OR 宽 deny)→ 立即拒
- 身份候选:官方 UA(strict,仅前缀)/ 官方 originator(OR)/ 全局白名单(双因子 AND)
/ 全局 app-server 开关 OR 账号 app-server 开关;均不命中 → 拒
- 版本门(仅官方候选):UA 须可解析引擎版本,再校验 [min,max] 区间
- 引擎指纹 AND 硬门:按信号列表逐条勾选 AND、每条行内变体 OR;无 Required 信号 → 放行
引擎指纹信号列表(唯一真源)
- 新增 openai.EngineFingerprintSignal 类型 + EvaluateEngineFingerprint 求值器
(勾选 AND / 行内变体 OR / 无勾选 → 放行)
- CodexRestrictionPolicy 增 EngineFingerprintSignals;信号列表单一决定是否启用指纹门,
不再保留独立「要求引擎指纹」总开关(与「信号全不选」语义重复)
- 新设置键 codex_cli_only_engine_fingerprint_signals(默认只勾 x-codex- 前缀);
旧 body 指纹开关幂等迁移并入信号列表;wire 接线
- 黑/白名单自由条目、命名预设、版本区间 全局设置管线
- gateway 缺 settingService(仅测试/误配可达)时指纹门回退默认种子信号、失败关闭,
不再因零值 policy(nil 信号)失败开放
账号级 Codex app-server(替换已失效的 ClaudeCode 放行机制)
- account.IsCodexCLIOnlyAppServerAllowed() 读 extra.codex_cli_only_allow_app_server,
仅在 codex_cli_only 开启时生效;候选身份门「全局 OR 账号」,与旧系统双层控制对齐
- 移除已无入口的 claude_code 预设机制(allowedClientRegistry / MatchAllowedClients /
账号 GetCodexCLIOnlyAllowedClients / reason);白名单 AllowedClientEntry / IsAllowedClientMatch 保留
门加固(反伪 + 写入校验)
- 官方 UA 访问门改 strict:IsCodexOfficialClientRequestStrict 仅前缀匹配,收窄「浏览器前缀 +
中段 codex token」伪造面(strict 仍保留 Codex 家族前缀与 UA 尾部兜底,故对「任意前缀 +
官方尾部 (name;ver)」仍放行——与 UA 可伪造、真正反伪靠引擎指纹门的设计一致)
- 官方客户端识别扩展:新增 codex-tui/、codex_vscode_copilot/ 前缀 + UA 尾部 (name;ver) 兜底
(恢复 CODEX_INTERNAL_ORIGINATOR_OVERRIDE 的真实 client,如 cccc→codex-tui),originator 改
精确集。该识别经 IsCodexOfficialClientByHeaders 被 passthrough 复用,故透传的官方判定一并
修正(codex-tui 等不再被误改写 UA)——非「行为不变」,属有意修正
- 白名单写入校验 ValidateCodexWhitelistEntriesJSON + AllowedClientEntry.IsWhitelistable:
双因子 AND 条目须可命中(非空 originator + 非空 ua_contains),拒绝写入会静默失效的死规则;
黑名单(OR 宽 deny,允许 originator-only)不受约束
管理端 / 前端
- handler / DTO / settings_view / 契约测试;gateway 接入判定链
- 信号列表编辑器(替换 body 开关)、api 类型、SettingsView;无勾选给常驻警告
- Create/Edit/Bulk 三弹窗「Codex Only」下新增 app-server 开关(OR 合并全局)
- 文案:UA/Originator → User-Agent/Originator;黑/白名单重命名为 User-Agent/Originator 黑/白名单;
「允许 App Server 第三方客户端」→「Codex app-server」+ 简介示例;i18n zh/en 同步
- 移除死代码 HasCodex*Fingerprint helper
测试:引擎指纹求值器 / 账号 app-server(OR 语义)/ detector(含 N1 strict、失败关闭)/
白名单写入校验 / BulkEdit spec 等;后端 build + service/openai/admin 单测全绿,前端 vue-tsc + vitest 全绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-26 16:19:41 +08:00
Heatherm Huang
44f502bab8
fix: address grok review feedback
2026-06-26 14:26:43 +08:00
Heatherm Huang
0d28642181
feat: add grok quota probe parity
2026-06-26 10:37:37 +08:00
Heatherm Huang
39be1ec97f
feat: add grok subscription support
2026-06-26 10:36:09 +08:00
shaw
b816949291
feat(openai-quota): query + reset rate-limit credits for OpenAI accounts
...
Adds an admin-side action that mirrors the Codex Desktop "rate-limit reset"
flow against chatgpt.com upstream for OpenAI OAuth accounts.
Backend
- OpenAIQuotaService.QueryUsage / ResetCredit hit /wham/usage and
/wham/rate-limit-reset-credits/consume with the Codex Desktop header set,
reusing OpenAITokenProvider for refreshed tokens and PrivacyClientFactory
for the impersonated Chrome TLS fingerprint.
- Honors the account's configured proxy by reading the eager-loaded
account.Proxy directly (falls back to proxyRepo only when missing).
- GET /api/v1/admin/openai/accounts/:id/quota
POST /api/v1/admin/openai/accounts/:id/reset-quota
- Wire DI for the new service + handler dependency.
Frontend
- OpenAIQuotaResetCell renders a single action row in AccountUsageCell's
OpenAI section: the existing local "查询" (active sampling) is injected
via #pre-actions, alongside a "次数 N" button that doubles as the
upstream query trigger and the available-credit indicator, and a "重置"
button that consumes one credit.
- No duplicate 5h/7d window display; the local UsageProgressBar owns those
bars to avoid confusion.
2026-06-16 16:55:07 +08:00
DaydreamCoding
af19d44327
feat(proxies): 代理有效期与失败回退
...
- schema/迁移: 代理有效期、提醒天数、失败回退配置 + 账号 fallback 来源字段
- service/repo/DTO/handler: CRUD 透传新字段 + 校验
- fallback 目标解析纯函数(链式解析 + 环检测 + 兜底)
- SweepExpiredProxies 到期改投账号 + outbox 失效
- ProxyExpiryService 后台到期扫描任务 + wire 注册
- 账号侧手动回切原代理 + fallback 来源徽章/按钮
- 前端: 创建/编辑表单、列表到期徽章、类型/API/i18n
- ops 告警: proxy_expired_count / proxy_expiring_soon_count 指标
- 导入导出携带有效期/回退字段(备用按 name 映射)
- 补全测试 stub + 集成测试 + review 问题修复
2026-06-08 00:01:30 +08:00
visa2 and Claude Opus 4.8
362f9e77bf
fix(service): gate periodic background jobs with a leader lock for multi-instance
...
Three periodic background jobs ran on every instance with no cross-instance
coordination, multiplying their cost (and side effects) by the replica count:
- DashboardAggregationService.runScheduledAggregation: N× heavy GROUP BY
aggregation queries every minute plus watermark write races.
- PaymentOrderExpiryService.runOnce: N× upstream payment-provider reconcile/
expiry API calls per pending order.
- SubscriptionExpiryService.sendExpiryReminders: N× full active-subscription
scans every minute and potential duplicate reminder emails.
Add a LeaderLockCache abstraction so only one instance runs each job per cycle:
- The interface lives in the service layer; the Redis-backed implementation
(SetNX + compare-and-delete release) lives in the repository layer, so the
service package keeps its depguard "must not import redis" boundary intact.
- tryAcquireSingletonLeaderLock prefers the cache and falls back to a Postgres
advisory lock when Redis errors, mirroring the Ops background services. When
neither backend is configured the job runs ungated, preserving single-instance
and test behavior (no self-lockout: the lock is released every cycle).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-05 22:47:24 +08:00
Wesley Liddick
418d09be56
Merge pull request #2881 from xiaoyiluck666/fix/openai-oauth-refresh-enrichment
...
修复 OpenAI OAuth 刷新未补全账号信息
2026-06-01 10:04:16 +08:00
DaydreamCoding and Claude Opus 4.8
f7f5e33830
feat(quota): user×platform 配额 DB 写聚合 flusher
...
Redis 同步权威 + DB 镜像,不在进程内维护 delta:
- 写入点 HasUserPlatformQuotaLimit 守卫:无 limit 跳过 Redis 写与持久化
- 累加 usage 的 Lua 在 flusher_enabled 时 SADD 脏集 billing:upq:dirty
- UserPlatformQuotaUsageFlusher 定时 SPOP 脏集 → 批量 HGETALL 读当前窗口 usage 快照
→ BatchSnapshotUsage 绝对值 UPSERT 覆盖 DB(去 SELECT FOR UPDATE 行锁)
→ 失败 SADD 回 / FK(23503)整批丢弃
- flusher 单批 clamp 到 ≤6000,保证一次 flush 只生成一条 UPSERT(单事务原子)
- flusher_enabled 默认 false(降级=旧异步直写 DB)
效果:DB 写连接从 O(QPS) 收敛到 O(副本)。
循环依赖:service 层独立 Snapshot/FK 类型,repository adapter 转换 + %w 映射 FK error。
admin reset/upsert 后失效 cache(脏残留被 flusher 当 MISS 跳过)。
健壮性与可观测性:
- flusher_enabled=false 时 Start 不注册定时器;flush_interval_ms 非法回退 2s
- Readd 回填失败单独计 dirty_lost(不再误记 dirty_readd)并 ALERT;脏集 Readd 补兜底 TTL
- 单 tick 达 max batches 上限仍有积压时记 log
- admin 失效 cache 失败升级为 ALERT(提示 enforcement 可能延迟至 sentinel TTL)
- BatchGet 单条命令失败 / usage 字段损坏均记 log,避免静默以 0 覆写 DB
三态 go vet + 单测/集成测全绿。
已知取舍(默认 flusher_enabled=false 不触发):
- FK 整批丢弃牵连同批正常 key(活跃 key 靠下次 SADD+绝对值快照自愈;Redis 仍权威)
- admin reset/upsert 直写 DB 与 flusher 异步刷存在覆盖竞态:flusher 持旧快照在途时可能覆盖
admin 刚写值(limit 列不受影响;usage 有 preflight windowExpired 兜底;低频)。彻底消除需 version OCC。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-05-29 17:19:15 +08:00
wucm667 and Claude Opus 4.7
c9caadb378
fix(account): address second-round review on quota auto-pause
...
- TopK initial filter now drops quota-paused accounts: fold the quota check
into isAccountRequestCompatible so session-hash, TopK pool, and per-candidate
rechecks all skip paused accounts. Previously the candidate pool was built
without the quota check, so paused accounts could fill TopK and leave the
scheduler returning "no available accounts" even with healthy ones available.
- Add per-account explicit disable flags auto_pause_5h_disabled /
auto_pause_7d_disabled with toggles in EditAccountModal. Without these,
leaving the account threshold blank silently falls back to the global default,
so admins could not exempt a single account once a global default existed.
Disable is per-window: an account can opt out of 5h auto-pause while still
honoring 7d. Schedule snapshot whitelist includes the new fields, i18n EN/ZH
updated, threshold-hint text revised to explain "blank = global default".
- Move quota auto-pause settings off the request hot path: replace the per-repo
TTL+singleflight sync DB read with a per-SettingService stale-while-revalidate
in-memory snapshot. Get is non-blocking (atomic.Pointer load + async refresh
on staleness); writes via UpdateOpsAdvancedSettings push directly into the
cache through an injected sink; wire warms the cache at startup. Adds Warm
(sync) for tests/init and SetOpenAIQuotaAutoPauseSettings (sink target).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-05-29 14:32:45 +08:00