wucm667
e4c7927eff
feat(payment): 支持强制移动端统一使用二维码支付
2026-05-19 18:22:12 +08:00
Wesley Liddick
a84bf3fab9
Merge pull request #2521 from Brisbanehuang/codex/fix-subscription-model-scopes
...
fix: hide model scopes for non-antigravity plans
2026-05-19 17:15:15 +08:00
Wesley Liddick
21ae52c01f
Merge pull request #2571 from sherlockwhite/fix/openai-account-email-and-usage-refresh
...
fix(accounts): show email and fix usage refresh for OpenAI OAuth accounts
2026-05-19 16:56:26 +08:00
Wesley Liddick
2a242aec0f
Merge pull request #2573 from wucm667/feat/redeem-code-expiry
...
feat(redeem): 兑换码支持设置使用有效期
2026-05-19 16:25:12 +08:00
wucm667
e4aaf0af29
feat(redeem): 兑换码支持设置使用有效期
2026-05-19 15:53:28 +08:00
chenjian
6db02f0069
fix(accounts): show email and add usage refresh button for OpenAI OAuth
...
- AccountsView: display email under account name by checking extra.email
and credentials.email in addition to extra.email_address; OpenAI OAuth
stores email under the 'email' key while Anthropic uses 'email_address'
- AccountUsageCell: add per-account refresh button to the OpenAI OAuth
usage section, identical to the existing Anthropic OAuth pattern;
reuses loadActiveUsage, activeQueryLoading, and the activeQuery i18n key
2026-05-19 15:43:13 +08:00
Wesley Liddick
089582d0c7
Merge pull request #2501 from Agoniedi/fix-ops-deeplink-tdz
...
fix: avoid ops deep link initialization error
2026-05-19 15:37:26 +08:00
Wesley Liddick
1b6ed24c33
Merge pull request #2492 from DaydreamCoding/feat/dingtalk-login
...
feat(dingtalk): 钉钉 OAuth 登录接入 + internal_only 用户属性同步
2026-05-19 15:36:13 +08:00
DaydreamCoding
b19da9c7fe
feat(dingtalk): 钉钉 OAuth 登录接入与 internal_only 用户属性同步
...
⚠️ 应用类型约束:当前实现仅支持「钉钉登录-企业内部应用」(DingTalk 开放平台
internal_app 类型)。第三方个人应用、第三方企业应用类型暂不支持——OAuth 流程
相同但 corp 校验、跨企业行为不同。backend 通过 DingTalkAppKind 校验对非
internal_app 类型 fail-closed(硬约束)。
钉钉 OAuth 登录主链
- 4 步 OAuth 链:ExchangeCodeForUserToken / GetUnionIdByUserToken /
GetUserIdByUnionId / GetStaffInfoByUserId;app token 缓存
- pending session 机制持久化 OAuth 中间态;cookie-only token 持久化
- 三种分流:bind_login_required / email_completion / choose_account_action
- corp_restriction_policy 支持 none + internal_only;stale "whitelist" 在
加载层与写入层均静默 coerce 为 none + slog.Warn
- bypass_registration 开关:企业内部模式豁免全局 REGISTRATION_DISABLED
- isReservedEmail / signup_source / canUnbindProvider / OAuth pending flow
等横切点支持 dingtalk provider
- migration 136:4 表 CHECK 约束加入 'dingtalk' provider 值
internal_only 模式同步企业邮箱/姓名/部门到用户属性
- SyncCorpEmail / SyncDisplayName / SyncDept 三个独立开关 + 对应
SyncXxxAttrKey 目标属性 key(默认 dingtalk_email / dingtalk_name /
dingtalk_department);非 internal_only policy 在写入层与加载层均
coerce 为 false,admin handler 与 setting_service 双层兜底
- 同步语义:首次注册写 users.username(昵称优先 → 企业姓名 fallback),
之后每次登录刷新 3 个属性;空值也写入以覆盖旧值
- 邮箱三级 fallback:org_email > email > extension["企业邮箱"]
(钉钉自定义字段 JSON)
- 部门路径递归向上拼接,跳过 dept_id=1 选首个真实子部门,剥离根组织名
- GetUnionIdByUserToken 同时返回 OIDC /contact/users/me 的 nick 字段;
新增 GetDeptInfo 调用 OAPI /topapi/v2/department/get
- AuthHandler 注入 UserAttributeService;OAuth pending flow 在
createPendingOAuthAccount / bindPendingOAuthLogin 分别派发到
AfterRegistration(syncUsername=true)/ AfterLogin
- migration 137 seed dingtalk_email/name/department 三个用户属性定义
附带修复(同集成路径暴露的两个 OAuth 注册回归)
- LoginOrRegisterOAuthWithTokenPair 新建用户分支用 inferLegacySignupSource
覆写 caller 显式传入的 signupSource,导致 dingtalk/linuxdo/oidc/wechat
渠道授权按 email 渠道读取;改为只在 caller 未显式传入时回退邮箱推断
- mergeProviderDefaultGrantSettings 把 parse fallback 默认值
(Concurrency=5 / Balance=0) 当作"未配置"哨兵,admin 显式设 5 时被误判
退回全局默认(复现:全局默认 1 + 渠道默认并发 5 + grant_on_signup → 新
用户实际 concurrency=1);去掉哨兵,admin 任何 >=0 值都覆盖 globalDefaults
前端
- DingTalk Login / Callback / EmailCompletion / ChoiceAccount / Error
视图;router + auth API client
- admin SettingsView:corp policy radio(none / internal_only)+ bypass
注册开关 + i18n;internal_only 下展示三同步开关 + 目标 attr key 下拉
(拉取 user attribute definitions),展示 fieldEmail /
qyapi_get_department_list 钉钉权限申请提示
- Profile:S1 主动绑定 / S5 解绑钉钉按钮 + 合成邮箱防自锁
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 15:27:47 +08:00
DaydreamCoding
664e9fdcd4
feat(usage): 用户用量按平台拆分 + UsersView 列设置可配置 + 用量列排序
...
后端
- BatchUserUsageStats / UserDashboardStats 新增 ByPlatform 字段
复用 ops 路径 COALESCE(g.platform, a.platform) 语义,不冗余 DB 字段
- 抽出 usageLogEffectivePlatformExpr 常量供管理员与用户两路径共用
- GetBatchUsersUsage cacheKey 加 v=2 + 当日日期,修复跨午夜旧缓存兼容新字段
前端
- 新建 PlatformUsageBreakdown:管理员用量列 hover tooltip 展示各平台 today/total
- 新建 PlatformCostCell:单平台 today/total 紧凑单元格
- UsersView 列设置新增 Claude/OpenAI/Gemini/Antigravity 四个平台子列,默认隐藏可手动启用
- 普通用户 Dashboard 新增 Row 3 平台拆分卡片,受 isSimple 控制
- 平台之和 < 总值时显式展示"其他"行,避免数字对不齐
- last_active_at 从 FORCED_VISIBLE_COLUMNS 移除,允许用户隐藏并持久化
- 列设置加 schema 版本号 + 迁移机制,老用户升级时新增默认隐藏列自动应用
- UsersView 用量列(汇总 + 4 平台子列)加入前端单页排序:列头单按钮 + 弹出菜单
切换"今日 / 近30天",三态循环 desc → asc → off;菜单底部备注"仅对本页数据排序"
- sortedUsers computed 在 server-side-sort 结果之上叠加本地排序,缺失值按 0 处理;
usageSort 状态独立 localStorage 持久化,互不干扰后端 sort_by
- i18n 新增 admin.users.sortBy / sortCurrentPageOnly
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 15:25:34 +08:00
Wesley Liddick
548c71c8bb
Merge pull request #2557 from Arron196/fix/issue-2542-daily-card-expiry-mode
...
fix: 修复日卡跨日重复刷新额度
2026-05-19 14:53:22 +08:00
Wesley Liddick
9f1a2c234d
Merge pull request #2448 from wucm667/codex/issue-2334-copy-all
...
fix: 修复兑换码生成后复制全部报错
2026-05-19 14:45:38 +08:00
Wesley Liddick
c65522641d
Merge pull request #2473 from is7Qin/fix/image-tier-validation
...
fix(channels): 按次/图片计费模式下区间校验跳过 token 上下文重叠规则
2026-05-19 14:28:33 +08:00
Wesley Liddick
082216befc
Merge pull request #2508 from honue/main
...
fix: 修复管理后台分组页可用账号数显示错误
2026-05-19 14:08:00 +08:00
name
ddab7de916
Merge branch 'main' into fix/image-tier-validation
2026-05-19 11:06:17 +08:00
Wesley Liddick
8584b8f7cf
Merge pull request #2504 from yetone/fix-admin-settings-darkmode
...
fix(admin/settings): make tab shell readable in dark mode
2026-05-19 09:55:01 +08:00
benjamin
f1cc83e0ee
fix(admin): 修正管理端日卡额度提示
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 21:09:11 +08:00
benjamin
5dae745e86
test: 避免 Ops 图表测试使用保留组件名
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 17:12:41 +08:00
benjamin
09cec311e8
fix: 统一 Ops 请求错误图表 SLA 口径
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-18 16:52:44 +08:00
Brisbanehuang
26ca73a4cd
fix: hide model scopes for non-antigravity plans
2026-05-17 02:20:41 +08:00
honue
360f8dec1a
fix: 修复管理后台分组页可用账号数显示错误
2026-05-16 11:16:56 +08:00
yetone
b0c7723393
fix(admin/settings): make tab shell readable in dark mode
...
Vue's scoped-CSS compiler was dropping the `:global(.dark) .settings-tabs-shell`
rules in the production build, so the tab strip kept its light-mode white
background and the inactive tab labels (text-gray-300) showed at ~1.6:1
contrast — effectively unreadable.
Hoist the three dark-mode overrides into an unscoped `<style>` block so they
survive the scoped-CSS transform.
2026-05-16 01:00:03 +08:00
Agoniedi
e46d2c2112
fix: avoid ops deep link initialization error
2026-05-15 23:59:51 +08:00
name
b936925c8a
fix(channels): 按次/图片计费模式跳过 token 区间重叠校验
...
image 与 per_request 模式的层级按 tier_label (1K/2K/4K) 匹配,
不依赖 min/max token 范围, 多个层级共用 min=0/max=null 是预期形态。
原校验器一律按 token 上下文分段处理, 新增第二条图片层级时会被
"无上限区间只能是最后一个" 误拦, 导致 OpenAI gpt-image 等模型
无法保存按次定价。
validateIntervals 新增 mode 参数, image / per_request 模式跳过
区间重叠与 last-unlimited 检查, 保留单条 min/max 自洽与价格非负
校验。token 模式行为不变。
2026-05-14 23:48:47 +08:00
wucm667
4d51e53d20
fix(redeem): 修复批量复制兑换码兼容性
2026-05-14 11:35:00 +08:00
shaw
a07a0dac63
feat: add configurable Antigravity user agent version
2026-05-11 22:25:20 +08:00
shaw
9377c96746
fix: 让消息 cache_control 改写默认关闭
2026-05-11 21:26:41 +08:00
shaw
18cc4691e6
优化系统设置页标签导航
2026-05-11 16:10:40 +08:00
shaw
b23055af5b
feat: add Airwallex payments and multi-currency support
2026-05-11 11:17:26 +08:00
shaw
fda1ed459d
feat: 优化 OAuth 账号导入流程
2026-05-08 11:36:09 +08:00
shaw
e872cbec0b
feat: 添加登录注册条款确认
2026-05-07 17:35:05 +08:00
shaw
0eca600ffa
fix moderation key handling and key UI
2026-05-07 14:31:19 +08:00
shaw
7a9c1d7edd
feat(frontend): add account Codex image bridge control
2026-05-07 11:07:33 +08:00
Wesley Liddick
45b1e6ae41
Merge pull request #2233 from Arron196/fix/codex-image-generation-bridge-switch
...
fix(openai): 增加 Codex 图片生成桥接显式开关
2026-05-07 10:30:26 +08:00
Wesley Liddick
e69319e747
Merge pull request #2224 from lyen1688/feat-email-oauth-github-google
...
feat: 增加 GitHub 和 Google 邮箱快捷登录
2026-05-07 10:07:28 +08:00
shaw
fff4a300c6
feat(risk-control): add content moderation audit
2026-05-07 09:14:47 +08:00
Jlypx
246e48215d
feat(frontend): add Codex image bridge toggle
...
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent )
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-05-07 00:10:20 +08:00
lyen1688
af550fa64e
feat: 增加 GitHub 和 Google 邮箱快捷登录
2026-05-06 16:06:11 +08:00
Wesley Liddick
37f7c7128c
Merge pull request #2120 from gaoren002/fix/rate-limit-429-cooldown-config
...
fix(rate-limit): make 429 fallback cooldown configurable
2026-05-05 19:46:11 +08:00
2ue
6faa344916
feat: add OpenAI image generation controls
2026-05-05 03:26:54 +08:00
shaw
0b84d12dbb
fix: correct affiliate audit record sources
2026-05-03 22:12:57 +08:00
lyen1688
650ddb2e39
fix: make affiliate record users clickable
2026-05-03 20:33:14 +08:00
lyen1688
6a41cf6a51
feat: add admin affiliate record pages
2026-05-03 20:33:13 +08:00
shaw
73b872998e
feat: 添加 Anthropic 缓存 TTL 注入开关
2026-04-30 13:38:22 +08:00
gaoren002
4b904c887c
fix(rate-limit): make 429 fallback cooldown configurable
2026-04-30 03:01:39 +00:00
Wesley Liddick
27cad10d30
Merge pull request #2030 from KnowSky404/feature/account-bulk-edit-scope-and-compact
...
feat: support filtered account bulk edit and align compact OpenAI bulk fields
2026-04-29 20:56:43 +08:00
erio
4b6954f9f0
feat(ops): allow retention days = 0 to wipe table on each scheduled cleanup
...
Background / 背景
The ops cleanup task currently rejects retention days < 1 in both validate
and normalize, so operators who want minimal-history setups (e.g. high
churn deployments that prefer near-realtime cleanup) cannot express that
intent through the UI. The only options are 1+ days, which keeps at least
24h of history regardless of cron frequency.
ops 清理任务目前在 validate 和 normalize 两处都拒绝小于 1 的保留天数,
让希望尽量不留历史的运维场景(高吞吐部署 + 想用近实时清理)无法通过 UI
表达。最低只能配 1,等于不管 cron 多频繁,至少都会保留 24 小时的历史。
Purpose / 目的
Let admins set retention days to 0, meaning "every scheduled cleanup
run wipes the corresponding table(s) entirely". Combined with a more
frequent cron (e.g. `0 * * * *`) this yields effectively rolling cleanup.
允许管理员把保留天数设为 0,语义为"每次定时清理时把对应表全部清空"。
搭配更频繁的 cron(比如每小时整点)即可获得近似滚动清理的效果。
Changes / 改动内容
Backend
- service/ops_settings.go: validate accepts [0, 365]; normalize only
refills default 30 when value is < 0 (negative is treated as legacy
bad data, 0 is honoured)
- service/ops_cleanup_service.go: introduce `opsCleanupPlan(now, days)`
returning `(cutoff, truncate, ok)`. days==0 returns truncate=true and
short-circuits to a new `truncateOpsTable` helper that uses
`TRUNCATE TABLE` (O(1), no WAL, no VACUUM pressure). days>0 keeps
the existing batched DELETE path unchanged. Empty tables skip
TRUNCATE to avoid the ACCESS EXCLUSIVE lock entirely
- Extract `isMissingRelationError` helper to dedupe the "table not
yet created" tolerance shared by both delete and truncate paths
- Add unit tests for `opsCleanupPlan` (three branches) and
`isMissingRelationError`
后端
- service/ops_settings.go: validate 接受 [0, 365];normalize 仅在 < 0
时回填默认 30(负数视为脏数据,0 被尊重)
- service/ops_cleanup_service.go: 抽 `opsCleanupPlan(now, days)` 返回
`(cutoff, truncate, ok)`。days==0 → truncate=true,走新增
`truncateOpsTable`(TRUNCATE TABLE,O(1),无 WAL、无 VACUUM 压力);
days>0 仍走原批量 DELETE 路径,行为完全不变。空表跳过 TRUNCATE,
避免无意义的 ACCESS EXCLUSIVE 锁
- 抽 `isMissingRelationError` helper 复用 delete / truncate 两处的
"表不存在"宽容判断
- 补 `opsCleanupPlan` 三分支 + `isMissingRelationError` 单元测试
Frontend
- OpsSettingsDialog.vue: validation accepts [0, 365]; input min=0
- i18n (zh/en): hint mentions "0 = wipe all on every cleanup",
validation message updated to 0-365 range
前端
- OpsSettingsDialog.vue: 校验放宽到 [0, 365],input min 改 0
- i18n(zh/en):hint 补"0 = 每次清理时清空所有",错误提示改 0-365
Trade-offs / 取舍
- TRUNCATE requires ACCESS EXCLUSIVE lock briefly, but ops tables only
have the cleanup task as a writer, so the lock is invisible to other
workloads
- Empty-table guard avoids the lock when there is nothing to clean
- Negative values are still treated as legacy bad data and replaced
with default 30 to preserve compatibility
2026-04-29 15:01:02 +08:00
DaydreamCoding
30f55a1f72
feat(openai): OpenAI Fast/Flex Policy 完整实现(HTTP + WebSocket + Admin)
...
对称参照 Claude BetaPolicy 的 fast-mode 过滤实现,新增针对 OpenAI 上游
service_tier 字段(priority / flex,含客户端 "fast" → "priority" 归一化)的
pass / filter / block 三态策略,覆盖全部 OpenAI 入口 + admin 配置入口。
后端核心
- 新增 SettingKeyOpenAIFastPolicySettings、OpenAIFastPolicyRule、
OpenAIFastPolicySettings 配置模型,含规则的 service_tier × action × scope
× 模型白名单 × fallback action 维度。
- SettingService.Get/SetOpenAIFastPolicySettings;缺失时返回内置默认策略
(所有模型的 priority 走 filter,whitelist 为空,fallback=pass)。设计
依据:service_tier=fast 是用户级开关,与 model 字段正交,默认锁定特定
model slug 会留下"用 gpt-4 + fast 透传 priority 上游"的绕过路径。JSON
解析失败不再静默 fallback,slog.Warn 记录脏数据,便于运维定位。
- service_tier 归一化(trim + ToLower + fast→priority + 白名单 priority/flex)
与策略评估(evaluateOpenAIFastPolicy)作为唯一真实来源,HTTP / WS 共用。
抽出纯函数 evaluateOpenAIFastPolicyWithSettings,配合 ctx-bound settings
快照(withOpenAIFastPolicyContext / openAIFastPolicySettingsFromContext),
WS 长会话入口预取一次后所有帧复用,避免每帧打到 settingService。
HTTP 入口(4 个)
- Chat Completions、Anthropic 兼容(Messages,含 BetaFastMode→priority 二次
命中)、原生 Responses、Passthrough Responses 全部接入
applyOpenAIFastPolicyToBody,filter 走 sjson 顶层删除 service_tier,block
返回 403 forbidden_error JSON。
- 4 入口统一使用 upstream 视角的 model(GetMappedModel +
normalizeOpenAIModelForUpstream + Codex OAuth normalize 后的 slug),
避免 chat/messages/native /responses/passthrough 因为 model 维度不同
造成 whitelist 命中差异。
- 在 pass 路径也把客户端 "fast" 别名归一化为 "priority" 写回 body,
否则 native /responses 与 passthrough 入口会把 "fast" 原样透传给上游
导致 400/拒绝(chat-completions 入口的 normalizeResponsesBodyServiceTier
此前已具备同等行为)。
WebSocket 入口
- 新增 applyOpenAIFastPolicyToWSResponseCreate:严格匹配
type="response.create",仅处理顶层 service_tier;filter 用 sjson 删字段,
block 返回 typed *OpenAIFastBlockedError。
- ingress 路径在 parseClientPayload 内调用,block 命中先 Write Realtime
风格 error event 再返回 OpenAIWSClientCloseError(StatusPolicyViolation
=1008),依赖底层 WebSocket Conn.Write 的同步 flush 保证 error 先于
close。
- passthrough 路径在 RunEntry 前对 firstClientMessage 应用策略,并通过
openAIWSPolicyEnforcingFrameConn 包装 ReadFrame 对每个 client→upstream
帧执行策略;后续帧无 model 字段时回退到 capturedSessionModel。
filter 闭包内同时侦测 session.update / session.created 帧的 session.model
字段刷新 capturedSessionModel,封堵"首帧 model=gpt-4o(pass)→
session.update 改为 gpt-5.5 → 不带 model 的 response.create fallback
到 gpt-4o"的 mid-session 绕过路径。
- passthrough billing:requestServiceTier 在策略 filter 之后再从
firstClientMessage 提取,filter 命中时 OpenAIForwardResult.ServiceTier
上报 nil(default tier),与 HTTP 入口(reqBody 来自 post-filter map)
/ WS ingress(payload 来自 post-filter bytes)的语义一致。
- 错误事件 schema:{event_id: "evt_<32hex>", type: "error",
error: {type: "forbidden_error", code: "policy_violation", message}},
与 OpenAI codex 客户端 error event 解析兼容。
Admin / Frontend
- dto.SystemSettings / UpdateSettingsRequest 新增
openai_fast_policy_settings 字段(omitempty),bulk GET/PUT 接入。
- Settings 页 Gateway 页签新增 Fast/Flex Policy 表单卡片:
service_tier × action × scope × 模型白名单 × fallback action 全字段配置。
- 前端守门:openaiFastPolicyLoaded 标志仅在 GET 真带回字段时才允许回写,
避免 rollout/错误把默认规则覆盖成空;saveSettings 回写循环 skip 该字段,
由专用刷新逻辑处理;仅 action=block 时发送 error_message,匹配后端
omitempty 行为。
测试
- HTTP 路径:openai_fast_policy_test.go 覆盖默认配置(whitelist=[],所有
模型 priority filter)/ block 自定义错误 / scope 区分 / filter 删字段 /
block 不改 body / block 短路上游 / Anthropic BetaFastMode 触发 OpenAI
fast policy 等场景。
- WebSocket 路径:openai_fast_policy_ws_test.go 覆盖
helper 单元(filter / fast→priority 归一化 / flex 透传 / block typed
error / 无 service_tier 字节不变 / 非 response.create 帧不动 / 空 type
帧不动 / event_id+code 字段断言 / 非字符串 service_tier 容错)+
pass 路径 fast 别名归一化回归 +
ingress 端到端(filter 后上游不含 service_tier / block 后客户端先收
error event 再收 close 1008 且上游 0 写)+
passthrough capturedSessionModel fallback 用例(whitelist 策略下首帧
建立、缺 model 命中 fallback、缺少 fallback 时的 leak 文档化)+
passthrough session.update / session.created 旋转 capturedSessionModel
的 mid-session 绕过回归 +
passthrough billing post-filter ServiceTier 与 idempotent filter 回归。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 11:15:09 +08:00
KnowSky404
53b24bc2d8
fix: tighten account bulk edit target typing
2026-04-27 18:20:36 +08:00
KnowSky404
2ab6b34fd1
feat: add filtered-result account bulk edit
2026-04-27 18:12:24 +08:00