O
|
f06ead40dd
|
feat: 优化日期时间范围选择器 (#660)
* feat: 优化日期时间范围选择器
* feat(web): 添加主页智能模型选择
|
2026-09-16 10:03:02 +08:00 |
|
tbphp
|
9605ed208b
|
fix(subscription): 修正 Codex 与 Claude 凭据身份判重 (#639)
* fix(subscription): 修正订阅凭据身份与刷新校验
* docs: 撤回 README 中的凭据身份说明
* fix(subscription): 校验令牌身份冲突并补齐刷新后判重
* fix(subscription): 防止刷新丢失已确认身份
* fix(subscription): 延后批量导入身份判重
|
2026-09-13 12:26:46 +08:00 |
|
tbphp
|
9d38793dd0
|
fix(affinity): 统一缓存标识亲和并补齐 Codex 缓存分组 (#635)
|
2026-09-13 01:25:45 +08:00 |
|
tbphp
|
b64a389823
|
feat(ultrafast): 支持请求层级转发与独立计价 (#624)
* fix(codex): 统一快速模式出站参数为 fast
* feat(ultrafast): 支持请求层级转发与独立计价
|
2026-09-11 13:10:29 +08:00 |
|
tbphp
|
c55312e155
|
feat(groups): 支持选择测试协议和模型并修复禁用分组测试 (#623)
* feat(groups): 支持配置和选择密钥测试协议
* fix(groups): 完善测试模型选择并遵循渠道协议声明
* fix(groups): 修复禁用分组测试并统一测试设置布局
* fix(groups): 统一测试控件样式并复用模型输入
|
2026-09-11 12:59:01 +08:00 |
|
tbphp
|
f091528bdb
|
feat(gateway): 接入原生 Responses WebSocket 与逐轮治理 (#616)
* feat(gateway): 接入原生 Responses WebSocket 与逐轮治理
* feat(gateway): 增加 WS 分层开关并修复连接治理
* fix(gateway): 关闭停用或删除分组的 WS 连接
|
2026-09-10 21:18:41 +08:00 |
|
tbphp
|
0c9d188892
|
fix(codex): 修正请求身份头覆盖与会话兼容 (#617)
* fix(codex): 修正请求身份头覆盖与会话兼容
* fix(codex): 保留显式空值身份请求头
|
2026-09-10 20:04:23 +08:00 |
|
tbphp
|
7cbd2e672d
|
feat(responses): 实现响应状态续接路由 (#609)
* feat(responses): 实现响应状态续接路由
* fix(responses): 限制响应 ID 长度并兼容缺失字段删除
* fix(responses): 按协议存储能力匹配续接路由
|
2026-09-09 23:13:41 +08:00 |
|
tbphp
|
de6d2d44fc
|
feat(access-keys): 支持自定义密钥并统一编辑与生成交互 (#611)
* feat(access-keys): 支持自定义密钥与强度提示
* fix(access-keys): 恢复默认掩码并按密钥长度分档
* feat(access-keys): 统一密钥编辑与随机生成交互
* style(access-keys): 改用骰子图标生成密钥
* fix(access-keys): 修复筛选幂等判定与恢复状态提示
* fix(access-keys): 统一编辑请求的幂等摘要
|
2026-09-09 23:05:09 +08:00 |
|
tbphp
|
fb18dc9e87
|
refactor(cooldown): 精简模型冷却展示与管理接口 (#606)
* fix(web): 精调模型冷却展示与筛选样式
* refactor(cooldown): 精简模型冷却展示与管理接口
|
2026-09-09 15:50:02 +08:00 |
|
tbphp
|
fe4b6ac159
|
feat(gateway): 接入原生文本重排序协议 (#607)
|
2026-09-09 15:06:50 +08:00 |
|
tbphp
|
7ed01e668b
|
feat(images): 支持 Antigravity 与 Gemini 共享生图转换 (#605)
* feat(antigravity): 支持 Images 单向生图转换
* feat(images): 复用转换并支持 Gemini 渠道生图
* fix(images): 修正生图转换失败分类并恢复候选回退
|
2026-09-09 13:20:10 +08:00 |
|
tbphp
|
d4699dd2b1
|
feat(health): 支持凭据按模型冷却与统一恢复 (#599)
* feat(health): 支持凭据按模型冷却与统一恢复
* fix(health): 修复模型冷却的错误契约与恢复边界
* fix(web): 修复模型冷却展示与重置反馈
* fix(web): 保持分组健康与恢复反馈一致
* fix(health): 修复停用分组的模型冷却身份展示
|
2026-09-09 08:05:43 +08:00 |
|
tbphp
|
a42555469a
|
feat(gateway): 统一全局请求重试预算 (#598)
|
2026-09-08 20:43:25 +08:00 |
|
tbphp
|
96d3e0d5c7
|
feat(subscription): 支持多格式订阅凭据导入 (#596)
* feat(subscription): 支持多格式订阅凭据导入
* fix(subscription): 修复批量导入请求边界
* fix(subscription): 保留批量导入超时语义
|
2026-09-08 20:05:22 +08:00 |
|
 Oandtbphp
|
6da82242d8
|
feat(subscription): support custom upstream URLs (#579)
* feat(codex): support custom base URL
* fix(codex): require HTTPS for custom base URL
* docs: document changed subscription functions
* fix(groups): 展示并区分详情中的默认与自定义地址
* fix(groups): 统一上游地址配置交互与图标位置
* fix(subscription): 绑定额度重置操作的上游地址
* fix(gateway): 隔离旧上游请求的健康状态更新
---------
Co-authored-by: tbphp <tangb7420@gmail.com>
|
2026-09-08 19:44:39 +08:00 |
|
tbphp
|
e0bfa07ec4
|
feat(scheduler): 统一凭据权重并调整模型错误重试 (#597)
* feat(scheduler): 统一凭据权重并调整错误重试
* docs: 更新三语配置权重说明
|
2026-09-08 17:18:08 +08:00 |
|
tbphp
|
175949e20a
|
feat(usage): 支持自定义时间统计并统一时间筛选 (#594)
* feat(usage): 统一时间区间统计与快捷筛选
* fix(usage): 精简时间筛选与趋势提示布局
* fix(usage): 保留未修改时间端点的原始时刻
|
2026-09-08 13:33:06 +08:00 |
|
tbphp
|
a97578fe9b
|
feat(access-keys): 完善访问密钥分发与用量管理 (#590)
* feat(access-keys): 完善访问密钥分发与用量管理
* fix(web): 保留监控上下文并同步复制草稿
* fix(web): 补全发放联系信息并保留排行密钥标识
* fix(monitor): 修复日志入口与用量时间边界
* feat(access-keys): 优化分发界面并精简发放流程
* fix(access-keys): 收紧列表排版并精简发放弹窗
|
2026-09-08 12:52:42 +08:00 |
|
tbphp
|
e888fe6035
|
feat(credentials): 统一全量操作并支持五千条密钥导入 (#587)
* feat(credentials): 统一全量操作并支持五千条密钥导入
* fix(web): 明确恢复全部的凭据范围
* fix(web): 同步密钥导入错误位置上限
* test(requestlog): 修正延迟刷盘测试的同步时序
|
2026-09-07 21:21:16 +08:00 |
|
tbphp
|
33fb54bfe6
|
fix(monitor): 修正最近一小时用量与成本统计 (#588)
|
2026-09-07 20:20:06 +08:00 |
|
tbphp
|
25061d6579
|
feat(pricing): 支持分组与访问密钥价格倍率 (#584)
* feat(pricing): 增加分组与访问密钥价格倍率
* fix(pricing): 在原始总费用计算后应用倍率
|
2026-09-07 12:41:48 +08:00 |
|
tbphp
|
16be863ea5
|
fix(subscription): 允许手动刷新恢复异常订阅凭据 (#580)
* fix(subscription): 允许手动刷新恢复异常订阅凭据
订阅凭据刷新遇到网络故障后落入 outcome_unknown,此后所有刷新入口
全部关闭,重启也不恢复,只能重新连接账号或重新导入。
新增 RefreshForManualRecovery 作为唯一允许恢复异常认证状态的入口,
仅由管理面「刷新凭据」使用;数据面自动刷新、模型发现与额度观测继续
沿用原有门禁。放开后原代码「只有 ready 能进入刷新」的前提失效,同步
修正三处连带问题:
- 临时失败与启动失败不再无条件写回 ready,改为写回进锁时的原状态,
避免一次 503 把状态未知的凭据洗白并放回调度
- 残留 refreshing 归一为 outcome_unknown 再参与恢复,避免界面长期
显示正在刷新
- 版本复用分支增加认证状态与运行时一致性确认,版本变大不再单独作为
刷新成功的依据
调度排除、状态展示、失败分类与额度同步入口均保持不变。
Closes #571
* fix(subscription): 修正手动恢复的运行时确认与错误归属
Review 发现放开人工恢复后遗留两处边界:
- ensureRuntimeMatchesDurableSecret 依赖 ReconcileGroup 修复运行时,
但后者只比较持久化配置,不含 auth_state。运行时版本已是最新、仅
认证状态落后时会被判定为无需变更并返回成功,账号实际仍不可调度。
改为先定向同步认证状态,并在返回成功前重新确认版本与状态一致
- 失败分支把用于持久化的历史错误码直接用于 API evidence,异常账号
重试遇到网络失败时会报告旧的认证问题,残留 refreshing 的
refresh_interrupted 还会落到需要重新授权的兜底映射。持久化继续
沿用原状态与原错误码,evidence 改为依据本次失败分类生成
新增两个用例:版本相同仅认证状态落后时经真实 ReconcileGroup 修复;
原状态明确失效或残留 refreshing 时本次网络失败报告为结果未知。
|
2026-09-07 09:49:55 +08:00 |
|
tbphp
|
18079996f0
|
refactor(settings): 重构设置页分区并统一分组设置的覆盖交互 (#576)
* refactor(settings): 按业务语义重排配置分区,收敛默认态展示密度
- 路由策略并入亲和分区(路由与调度),validation_interval 移出超时分组并入重试/凭据健康,
models_dev_auto_sync_enabled 从请求转发移至数据与维护,header_rules 与 inject_usage_options
合并为上游请求改写;6 个分区拆为 7 个语义更清晰的分区。
- 新增 SettingRow 承载默认态单行展示、覆盖态才展开控件与说明文字,默认态徽标与操作按钮收敛,
避免逐字段重复常驻的说明文案。
* refactor(settings): 抽取 SettingRow 为共享组件并同步分组设置页展示密度
- SettingRow 从设置页移至 components/config,替换分组设置页运行时区块里的
RuntimeOverrideRow,行为对齐:默认态收敛徽标/按钮、覆盖态才展开控件与说明。
- RuntimeOverrideRow 无剩余引用,一并删除。
- 顺带修正分组页 inject_usage_options 折叠态展示 help 文案而非当前值的问题,
改为展示已启用/已禁用,说明文字移入 help 提示。
- 请求亲和沿用原有 SegmentedControl 三态控件,未纳入本次迁移。
* fix(settings): 按反馈调整 SettingRow 交互细节
- 提示统一用已有 AppTooltip 组件,替换原生 title;且不论是否覆盖,说明都只在
标签旁以 tooltip 展示,不再于覆盖态额外常驻一份。
- 覆盖/恢复默认按钮从行尾移到值后面,改回可见的按钮样式,不再靠悬停淡入。
- 覆盖态不再叠加“显式覆盖”徽标,仅保留左侧强调色与底色区分;待恢复/环境变量
锁定两种状态的徽标保留。
- 路由策略改用 SegmentedControl 二选一切换,替换下拉选择,和代理等控件观感一致。
- 各分区行列表之间补上小间距,避免行与行贴在一起。
* fix(settings): 覆盖/恢复默认按钮改为图标 + tooltip
文字按钮换成小方形图标按钮:覆盖用 PencilLine,恢复默认用 RotateCcw,配色沿用
原有 action/warning 两种 tone;按钮不再显示文字,改为 hover/聚焦时通过
AppTooltip 展示对应文案,无障碍上保留 aria-label。
* fix(settings): 覆盖/恢复默认图标去掉按钮底色,仅悬停反馈
去掉常驻边框和背景色,图标默认裸露显示,与旁边的说明提示图标风格保持一致;
悬停/聚焦时才出现对应 tone 的浅色背景。
* fix(settings): 覆盖图标恢复悬停显示
未覆盖态(含待恢复默认)的“覆盖”图标恢复为鼠标悬停/键盘聚焦到该行才显示,
平时隐藏;已覆盖态的“恢复默认”图标保持常驻可见,因为该行本身已有强调色和
底色区分,不需要靠图标常驻来提示。窄屏和纯触屏环境下始终显示,避免无法触发。
* refactor(settings): 移除 inject_usage_options 并统一设置页控件尺寸
移除 inject_usage_options 配置,改为始终注入:
- 该开关只在「OpenAI Completions + 原生透传 + 流式」这一条路径生效(转换路径的
usage 来自 SDK,Anthropic/Gemini 原生流自带 usage),默认即为开启,暴露为用户
配置的收益远低于理解成本。
- 后端删除设置键、分组覆盖与渠道约束校验,IncludeUsage 固定为 ObserveUsage;
新增迁移 0008 清理 system_settings 行与分组 overrides 中的历史键,否则解析器
会以 "unknown runtime setting" 拒绝整份配置。
- 前端删除两处设置行、资源投影字段与三语文案。
设置页与分组设置页的控件:
- 新增 --setting-control-height,并在 .setting-row/.setting-block 上覆盖
--control-compact/xs/sm,让输入框、切换控件、下拉统一小一档;变量继承进子组件,
不需要和组件自身 scoped 样式比优先级。
- 固定行内容高度,折叠态与覆盖态不再有高度差,点开编辑时行不会跳动。
- 块级说明(CORS 策略、下游响应头规则)从常驻小字改为标签旁 tooltip,与设置行一致。
分组设置页删除只读的渠道展示:顶部已有渠道信息,此处重复且不可编辑。
* fix(storage): 修复迁移 0008 在 PostgreSQL 上的两处方言问题
- 反引号是 MySQL/SQLite 语法,PostgreSQL 解析 `key` = ? 直接报 syntax error,
导致启动中断。改用 GORM 结构体条件,由驱动按方言自行加引号。
- 往 json 列写 []byte 时 PostgreSQL 驱动按 bytea 处理,报 invalid input syntax
for type json。改为写字符串。
已在 SQLite / PostgreSQL 16 / MySQL 8 三种方言上实跑升级路径:注入历史的
system_settings 行与分组 overrides 后启动,确认键被清除、分组只剩其余覆盖、
迁移正常记账。
* refactor(settings): 合并上游 Header 到跨域分区,统一控件尺寸与请求头/响应头命名
- 分组页控件尺寸未跟着变小,是因为上一轮的尺寸变量覆盖只挂在 .setting-row/
.setting-block 上;分组页的姓名/验活模型输入框、权重与请求亲和的 SegmentedControl
都不在这两个类名内。改为挂在 .settings__content/.group-settings__content 内容区
(不含侧边导航与保存栏),覆盖 --control-compact/xs/sm/md 四个尺寸变量,让设置页
和分组页的所有交互控件统一收敛到 26px。
- "上游请求改写"分区被删除,header_rules 合并进浏览器访问分区,与 CORS、
下游响应头规则放在一起(顺序:CORS → 上游请求头规则 → 下游响应头规则);
该分区原本只剩 header_rules 一项(inject_usage_options 上一轮已删除),
单独占一个侧边菜单已经没有意义。
- 请求头/响应头命名统一:全局设置页"全局 Header Rules"改名"上游请求头规则",
与已有的"下游响应头规则"对称;分组页"HeaderRules"同步改名"上游请求头规则"。
新分区标题定为"Header 与跨域"。
- 清理合并后失效的 settings.headers.* 键(title/currentPublishedRuleCount/
defaultSource/overrideSource/pendingRestoreSource/override/restoreDefault/
inherited/resetPending/replacementWarning/securityNotice),改用已有的
settings.runtime.* 通用状态词汇,与 CORS、下游响应头规则保持一致。
已用真实浏览器验证:分区合并后的顺序与文案、校验横幅跳转到正确分区并定位到
非法输入框、分组页控件高度与设置页一致。
* refactor(group-settings): 统一请求亲和与上游请求头规则的覆盖交互
请求亲和由三态 SegmentedControl 改为 SettingRow 覆盖/恢复默认模式;
上游请求头规则由 details 折叠改为 SettingBlock,并补上独立的覆盖开关,
与设置页的交互模式完全一致;同步移除废弃的展开态路由状态与文案。
* fix(group-settings): 恢复默认时不再回显未保存的旧覆盖值
分组已保存覆盖值后,草稿中点击恢复默认会读到仍是旧覆盖值的 effective
快照,导致视觉上"看起来没变"。为出站代理、超时/次数类、请求亲和、
上游请求头规则补充待恢复态:展示占位文案与徽标,保存后才回填真实的
全局生效值,与设置页面的重置反馈保持一致。
* feat(group-settings): 验活模型改为可搜索候选输入
复用参数覆盖规则里模型输入的 datalist 模式,把分组当前模型作为候选,
输入即过滤;候选取上游模型 ID(验活按该值请求上游),别名作为副标题
展示。后端不限制该值,仍保留自由输入。
* fix(settings): 按 review 处理迁移账本断言与三处设置项细节
- 外部数据库契约里的迁移账本断言硬编码到 0007,只在 PostgreSQL/MySQL 下
执行,本地 SQLite 会跳过,导致 0008 落库后仅 CI 报错
- 下游响应头规则的待恢复态未取草稿值,取消覆盖后仍回显旧规则,与同区的
上游请求头规则表现不一致
- 连接与可靠性分区的数字输入清空后写入 0,其中重试次数与拉黑阈值的 0 合法,
会被静默保存;改为与路由分区一致按 NaN 处理
- 修正 pendingRestoreSource 的英文文案
|
2026-09-06 22:54:21 +08:00 |
|
tbphp
|
2aa5002a45
|
fix(subscription): 按来源和周期匹配 Codex 被动额度窗口 (#574)
* fix(subscription): 拒绝跨周期的被动额度覆盖
被动额度合并前校验已有窗口与样本的周期;同 ID 但周期冲突时丢弃整个窗口补丁,避免 7d 被改成 5h,同时污染用量、重置时间及健康摘要。
保留兼容窗口与缺少周期字段的增量更新行为;补充合并与持久化回归测试,不改变限流、额度池或路由调度。
* fix(subscription): 按来源和周期匹配 Codex 被动额度
主动同步保留 metered_feature,响应头按命名空间生成相同来源标识;不依赖模型名称或 Limit-Name。
按同一账号内的来源与实际周期唯一匹配已有窗口,允许 primary/secondary 槽位变化,但保留卡片 ID 与展示元数据。缺少来源/周期或存在歧义时不覆盖;其他渠道继续使用原有 ID 匹配。
补充解析、跨槽位合并、来源隔离、控制面序列化及持久化健康投影测试。无 429、路由或调度改动;旧快照需主动同步一次补齐来源。
* docs(subscription): 修正被动额度快照合并的注释说明
明确无变化时保持原始字节,仅在窗口数据变化时重新编码;不修改任何运行逻辑。
|
2026-09-06 09:29:35 +08:00 |
|
tbphp
|
2b23d8a62a
|
feat(ui): 补齐权重、分组启停与日志路由入口 (#572)
* feat(ui): 补齐权重、分组启停与日志路由入口
订阅账号卡片支持调度权重(#535):徽章行只在手动权重时露出 chip,
点击一次完成展开并进入编辑;权重面板落在展开区代理面板之上,两块上下堆叠。
自动权重等同代理的继承态,不在折叠态制造视觉噪音。
代理模式改用分段控件,三个模式直接可见;表单不再折行,地址栏独自吸收
剩余宽度。分段控件新增 xs 尺寸,与同排输入框、按钮统一 26px,
顺带修掉密钥列表权重编辑器原本 30px 与 26px 不齐的问题。
分组列表支持快速启停(#554):开关并入状态列,与徽章相邻以区分
「我关的」和「凭据不可用」。集合项新增 enabled 字段——status 还叠加了
weight_manual 为 0 的历史数据,拿它当开关会出现点击后状态不变的假故障。
追加凭据改为纯图标,省下的宽度抵掉状态列扩宽,总表宽反而更窄。
模型列表展示归属分组(#555):上游行挂分组 chip,最多两枚、其余折叠为 +N,
数据本就随列表返回,此前未被消费。
请求日志路由拆成访问密钥与路由两列(#555):路由列首行渠道图标加分组名、
次行凭据编号,分组名可点击就地筛选。按各列实际内容重算宽度,
压出的空间正好装下新列,总宽与拆列前持平。
* fix(ui): 修正开关反馈延迟、按钮内边距与列举分隔符
分组开关此前绑查询数据,而 AppSwitch 是纯受控组件,点击后要等请求与
refetch 走完才翻转,看起来是个卡住的开关。改为本地乐观置位,请求结束
(成功交还 refetch 结果、失败回滚原值)后再交还查询数据。
代理指示器的按钮形态补上 padding/font 复位:容器是固定 22×22 的
border-box,UA 默认内边距会把 13px 图标挤变形。
模型分组折叠提示原先硬编码中文顿号,会漏进英文与日文界面,改用
Intl.ListFormat 按当前语言格式化。实测须用 conjunction + narrow:
narrow 去掉「和 / and」只留分隔符,而 unit 类型在中日文下根本不插
分隔符,会把名字连成一串。
* fix(monitor): 修正日志骨架屏列数
路由列拆成访问密钥与路由两列后,非访问密钥视图的列头与 grid 都是 9 列,
骨架屏仍按 8 列渲染,加载时与表头错位。两处 SkeletonSurface 一并修正。
* refactor(ui): 撤除分组集合 enabled 字段并精简注释
开关改由 status 派生:weight_manual 为 0 虽然也判定 disabled,但该值经
接口限定在 1~100,只有直接改库才能触发,为此新增响应字段与两个测试
超出了本次 UI 补齐的范围。后端与测试恢复原状,本 PR 回到纯前端改动。
同时精简全部新增注释,只保留解释非显然决策的部分,去掉代码本身已经
说清楚的描述。
* feat(monitor): 日志显示凭据掩码并补齐交互细节
日志响应新增 credential_name:按 ID 从凭据注册表取密文解密后算掩码,
订阅账号给邮箱掩码、API 密钥给密钥掩码。密文常驻内存,整个过程不读
数据库,一页内重复出现的凭据只解密一次;注册表里没有的凭据留空,
前端据此显示「已删除 · #id」,与访问密钥、分组共用同一套回退。
分组开关改走设置页同一条缓存失效链路,切换后进入详情页不再需要刷新。
日志中可点击就地筛选的值扩展到访问密钥、分组、凭据、模型四处,样式
提取为全局 filterable-value,此前两个组件各维护一套雷同规则。
订阅卡片的权重徽标与代理徽标统一改用 AppTooltip 并提示可点击编辑;
模型页的分组 chip 直达该分组的模型 tab;日志详情的凭据后增加复制按钮,
与 request_id 的复制控件同尺寸同图标。
* fix(models): 详情抽屉的分组链接直达模型 tab
与模型列表的分组 chip 保持一致,从模型上下文点进分组不再落到凭据 tab。
* fix: 修复样式
* fix: 访问密钥模型页面修复
|
2026-09-05 21:41:41 +08:00 |
|
tbphp
|
c86a9ad1da
|
feat(scheduler): 支持原生与转换路由混合权重调度 (#570)
* feat(scheduler): 支持原生与转换路由混合权重调度
* fix(settings): 补齐路由策略当前有效值提示
|
2026-09-05 12:58:22 +08:00 |
|
tbphp
|
ad8be749e3
|
feat(gateway): 增加分组参数覆盖规则 (#546)
* feat(gateway): 增加分组参数覆盖规则
* fix(gateway): 收紧参数覆盖安全边界
* refactor(web): 优化参数覆盖编辑器样式
* fix(web): 修正参数覆盖编辑器实现
* fix: 修正参数覆盖空键与输入推断
* fix: 拒绝参数覆盖中的负零
* fix(gateway): 纳入覆盖后兼容的候选
* fix(gateway): 固定参数覆盖前的路由上下文
* fix(control): 保留参数覆盖数字字面量
* fix(gateway): 统一参数覆盖请求体限制
* fix(gateway): 避免参数覆盖的 HTML 转义膨胀
* fix(gateway): 限制请求内参数覆盖缓存
* fix(parameteroverride): 避免请求整树解码膨胀
* fix(parameteroverride): 避免深层请求重复扫描
|
2026-09-05 12:09:14 +08:00 |
|
tbphp
|
559ed2dc88
|
feat(gateway): 支持数据面 CORS 与响应头规则 (#568)
* feat(gateway): 支持数据面 CORS 与响应头规则
* fix(cors): 修正来源缓存与禁用校验
* fix(cors): 规范化允许来源
|
2026-09-05 10:34:47 +08:00 |
|
tbphp
|
14e8e98c4f
|
fix(settings): 移除 ETag 并简化保存流程 (#530)
|
2026-09-02 16:29:59 +08:00 |
|
tbphp
|
d7d28370da
|
feat(channel): 增加 New API 多协议渠道 (#524)
|
2026-09-01 19:56:40 +08:00 |
|
tbphp
|
a7d11adf96
|
重做首页常用订阅账号卡片视觉设计 (#515)
* feat(home): 重做首页常用订阅账号卡片视觉设计
* fix(home): 常用订阅账号容器改为换行网格,去掉横向滚动
* fix(home): 首页常用订阅账号上限改回 4 个,PC 默认单行不换行
* fix(home): 修复 mini card 焦点窗口选择与标签周期丢失问题
* fix(home): 修复迷你订阅卡额度与可用状态显示
* fix(home): 优先展示已耗尽额度窗口
|
2026-09-01 06:50:29 +08:00 |
|
tbphp
|
70fdd862f2
|
fix(security): 收紧 OAuth 与数值边界 (#513)
|
2026-08-31 18:51:59 +08:00 |
|
tbphp
|
bba3a4a493
|
fix(home): 实时刷新常用订阅账号 (#505)
|
2026-08-31 15:27:59 +08:00 |
|
tbphp
|
2ea86cd8dc
|
feat(home): 展示常用订阅账号 (#504)
* feat(home): 展示常用订阅账号
* fix(home): 修正英文分组数量文案
|
2026-08-31 14:24:35 +08:00 |
|
tbphp
|
922c6e055c
|
fix(subscription): 避免临时刷新失败锁死凭据 (#499)
|
2026-08-30 18:20:28 +08:00 |
|
tbphp
|
aee2111290
|
feat(gateway): 支持 OpenAI Embeddings API (#496)
新增原生 OpenAI Embeddings 端点,覆盖首期 API Key 渠道,并复用现有路由、健康、用量、日志与管理流程。
|
2026-08-30 00:45:19 +08:00 |
|
tbphp
|
a58de8b1b2
|
feat(credentials): 增加 API Key 手动测试 (#495)
|
2026-08-29 22:25:09 +08:00 |
|
tbphp
|
eb7e54cf1d
|
feat(access-key): 增加有效期来源限制和密钥轮换 (#494)
* feat(access-key): 增加有效期来源限制和密钥轮换
* fix(access-key): 提交前重新校验有效期
* fix(access-key): 恢复过期提交错误反馈
|
2026-08-29 21:26:32 +08:00 |
|
tbphp
|
515c958dd1
|
feat(config): 支持运行策略与数据库连接池配置 (#492)
* feat(config): 增加重试拉黑及数据库连接池配置
* fix(settings): 恢复已提交配置快照
|
2026-08-29 18:23:34 +08:00 |
|
tbphp
|
6947edf190
|
fix(subscription): 跳过并标记重复账号 (#488)
* fix(subscription): 跳过并标记重复账号
* fix(subscription): 修复混合状态连接检查
* fix(subscription): 修复重复账号重新授权
|
2026-08-28 21:43:43 +08:00 |
|
tbphp
|
1a6e454475
|
feat(subscription): 接入 Codex/Claude 被动额度信号观察 (#487)
* feat(subscription): 接入 Codex/Claude 被动额度信号观察
从 Codex/Claude 订阅请求的响应 Header 中安全采集额度信号,归一化为与主动观察一致的账号级窗口,
经内存 pending map 合并后由 RequestLog worker 复用现有 quotaWake 异步落库,
自动刷新账号卡的额度窗口与同步时间;额度仅用于管理面展示,不参与路由、调度或健康判定。
同时修复 recordCredentialObservationFailure / invalidateCredentialObservationAfterReset
整行 Save 覆盖并发写入 snapshot_json 的既有问题,改为按列更新。
* fix(subscription): 修正被动额度合并的两处数据错误
丢弃比已存记录更旧的被动采样:手动刷新在 pending 落库前完成时,
旧采样会让 observed_at_ms 倒退并用旧额度覆盖新值;updated_at_ms
条件更新只能拦截读取之后的写入,拦不住这种时间倒退。
MergeQuotaWindow 不再用空字符串覆盖 Label/LabelKey/Scope/Unit:
这些是快照必填字段,被清空后 ApplyQuotaWindows 会跳过该窗口并
清除管理面低额度提示。
* fix(subscription): 落库确认后清空 pending 窗口缓存
ack 此前只清 dirty 标记,不清 entry.windows;下一次响应即使只带
部分字段,也会把已经落库的陈旧字段当作当前观察重新合并进去,
可能覆盖同一时间发生的主动刷新写入的更新值。
现在版本匹配时一并清空窗口缓存,配合已有的 MergeQuotaWindow
字段级保护,落空字段的响应不会再用零值或陈旧值覆盖数据库现值。
* fix(subscription): 通用化 Codex 被动额度解析并修正三处数据错误
Codex 被动解析改为从 Header 自动发现限额命名空间,不再写死
primary/secondary 两个账号级窗口。带 Limit-Name 的附加限额
(如 GPT 5.3 Codex Spark)现在也能被动更新,且窗口 ID 与主动
JSON 路径一致;将来新增的限额类型无需改代码即可识别。缺少
Limit-Name 的命名空间跳过,因为无法生成可匹配的稳定 ID。
同时修正:
- 越界 used-percent、非正或溢出的 reset/window 一律丢弃,
不再用 0 或回绕值覆盖快照中的有效字段;
- 被动不再输出 Label/LabelKey,避免只带使用率的响应把 7d 窗口
的标签改写成 Session,与 window_seconds 自相矛盾;
- 主动成功的 observed_at_ms/updated_at_ms 改用响应完成时间
(last_attempt_at_ms 仍为尝试开始时间),慢速手动刷新不再被
刷新期间捕获的被动样本反向覆盖,CAS token 也不再可能不变;
- 窗口值未变化但确实观察到时推进 observed_at_ms,低频账号不再
长期显示数小时前同步。
* refactor(subscription): pending 只保留最新一次响应,不再跨响应合并
pending 条目此前会把多次响应的窗口字段按 ID 合并,却只记录一个
观察时间。混在一起的字段因此可能带着较晚的时间戳落库,反过来
盖掉这期间提交的主动刷新结果。上一轮给 ack 加清缓存只堵住了
"已落库后残留"这一半,尚未落库前合并的那一半仍然存在。
改为每次记录整体替换:一个 pending 条目只承载一次响应,窗口与
观察时间始终描述同一时刻,这类时序覆盖从根上不再可能,ack 也
不需要再清缓存。被丢弃的旧响应不构成数据丢失——快照中该窗口
保持原值,下一次带该窗口的响应会刷新它。
生产代码净减 19 行。
* fix(subscription): 用 observation_version 做被动写入的并发令牌
时间戳不能充当 CAS 令牌:两次写入可能落在同一毫秒,updated_at_ms
数值不变会让已过期的被动写入通过条件更新,盖掉刚提交的主动刷新。
改用 observation_version(主动成功本就递增),并保留 updated_at_ms
比对以覆盖主动失败与重置这两条只改元数据、不动版本的路径。
同时收敛三处局部合同:
- 绝对 reset 无效时继续尝试同一响应中的相对 reset,不再因一个坏
Header 丢掉可用值;
- 被动输出不再携带 Scope / Unit / IsPrimary(此前只清了 Label),
贯彻「自动更新只改额度数值与状态」,Codex 与 Claude 两侧一致;
- pending 深拷贝窗口的指针字段,调用方后续修改不会改变待落库内容。
* fix(subscription): ACK 时移除 pending 条目并让同毫秒判给主动结果
ACK 此前只清 dirty 标记,条目连同克隆的窗口一直留在 map 里。凭据
删除后也不会释放,长期运行且凭据有增删的实例会持续增长。改为版本
匹配时直接移除条目——凭据删除本就走「registry 查不到 → ACK」这条
路径,因此不需要再给删除流程挂额外的清理钩子。
被动样本与行内 observed_at_ms 相同时改为丢弃(原为严格小于才丢)。
被动 Header 先捕获、主动刷新稍后完成,两者截断到同一毫秒时,旧的
被动结果会盖掉权威的主动结果,且此时 CAS 不冲突。相同毫秒判给主动
结果即可,不引入更高精度时间戳。该判断收紧后,落库处基于
alreadyObservedAt 的分支成为死代码,一并删除。
顺带移除无生产调用方的 AckPassiveQuotaObservation 导出方法。
|
2026-08-28 18:26:00 +08:00 |
|
tbphp
|
e9e88dce99
|
feat(images): 接入 OpenAI 图片生成与编辑 (#476)
* feat(images): 接入 OpenAI 图片生成与编辑
* fix(images): 补齐响应容量与边界处理
* fix(images): 修正协议观测与响应上限覆盖
* fix(stream): 保证取消优先于流关闭
* fix(images): 修正空 SSE 错误对象判定
* fix(images): 避免媒体数据触发凭据误判
* fix(images): 阻止流式响应泄漏凭据
* fix(images): 校验完整流事件后再转发
* fix(images): 修正响应模型观测
|
2026-08-27 15:11:52 +08:00 |
|
tbphp
|
d518b06acc
|
refactor: 统一错误决策与执行链路 (#466)
* refactor: 统一错误决策与执行链路
* fix(gateway): 修正错误来源与候选预算
|
2026-08-24 23:26:22 +08:00 |
|
tbphp
|
bd539713da
|
perf: 优化测试性能与 CI/发布流水线耗时 (#465)
* test(control): 消除测试 fixture 中的重复密钥派生
- internal/control:fixture 构造中 388 次重复执行 PBKDF2(10 万轮
SHA256)密钥派生,改为共享单例,仅派生一次
- 新增 internal/testutil/encryptiontest,提供按 key material 值
memoize 的共享 encryption.Service,横向覆盖 gateway、subscription、
execution/cpa 中同样存在的重复派生(PBKDF2 占比最高达 79%)
- aesService 构造后只读,跨 fixture(含并行测试)共享安全;container
包同类调用经排查确认属于被测装配流程本身,不适用本次改造
* test(state): 迁移测试改用共享 schema 模板
state/loader 中 openMigratedDatabase 被 21 次调用,每次都完整走一遍
迁移注册表;改为复用 sqlitetest.OpenMigrated 的模板缓存,与 control、
requestlog 部分测试已采用的方式一致。app、container、requestlog 中同
类调用点经逐点排查,均属被测对象本身或依赖真实文件/账本状态,不适用。
* ci(release): 消除 CI 与发布流水线中的耗时浪费
- race-tests 独立 setup-go 缓存命名空间,避免与 test/database-contract
共用 key 导致 race-instrumented GOCACHE 永远无法写回
- 移除 publish-images 中零命中的 GHA buildx image cache,同时消除其
失败会拖累发布状态判定为 partial/blocked 的关联风险
- 三个只读 job(仅用 buildx imagetools 查询)移除多余的 buildx 初始化
- native-artifact-smoke 改为按需下载单个 binary + 独立 checksums,
不再下载完整 release-assets
* test(control): 第一批测试标记 t.Parallel(35 个文件)
internal/control 651 个顶层测试里只有 5.8% 标了 t.Parallel(),其余
在包内是排队串行执行的;race-tests 总耗时现在完全由该包的最长执行时
间决定(213s),是唯一剩余的瓶颈。
本批覆盖 35 个文件、299 个函数。排除 18 个不适用的函数:
- 16 个直接操作全局 logrus 状态的测试(catalog_sync_test.go 等 8 个
文件),继续保持串行;Go 的 t.Parallel() 调度语义保证未标记的测试
会在所有并行测试开始前完整跑完,两者不会交叉执行
- external_database_integration_test.go 的 2 个测试依赖
GPT_LOAD_DATABASE_TEST_DSN:race-tests 中因未设置而被 t.Skip,标记
并行无收益;database-contract job 中会共享同一个外部数据库实例真
实执行,标记并行有正确性风险(唯一索引冲突/断言假设独占)
已排查确认安全:t.Setenv/os.Setenv 均为 0 处,无硬编码端口占用,每个
fixture 走独立 :memory: 数据库;本地 -count=3 重复验证无 flaky。
剩余约 297 个函数(36 个文件)作为第二批,待本批 CI 实测确认收益后
再决定是否推进。
* test(control): 第二批测试标记 t.Parallel,补齐排除说明(36 个文件)
覆盖剩余 297 个函数、36 个文件,加上第一批的 299 个,internal/control
除 18 个明确排除的函数外全部标记 t.Parallel()。
为 18 个排除函数逐一补充一行注释说明原因,避免日后被误认为遗漏而被
顺手加上 t.Parallel():
- 16 个劫持全局 logrus 状态的测试
- 2 个依赖 GPT_LOAD_DATABASE_TEST_DSN 共享外部数据库的测试
本地 -count=3 重复验证、全量 go test -count=1 . ./internal/...(58
包 ok)均通过。
* fix(release): 采纳 Review 反馈,修正文档措辞与产物保留期
- encryptiontest.Service 的文档注释修正为明确说明缓存仅在单个包的
测试二进制内有效,不跨包共享(每个包的 go test 是独立进程)
- native-artifact-smoke 依赖的 binary-*、release-checksums 保留期
从 1 天提高到与 release-assets 一致的 14 天:失败的 release run
若延迟超过 1 天才重试,此前较短的保留期会导致产物过期、下载失败,
阻塞发布流程
以下反馈经核实判定为不成立,未采纳:
- validation_test.go 中两个测试被指"竞争全局并发槽位"——经查
newValidationWorkerForTest 每次调用构造全新独立实例(worker、
channel、mutation coordinator 等),validationConcurrency 只是
编译期常量,两个测试之间不存在任何运行时共享状态
|
2026-08-24 20:07:11 +08:00 |
|
tbphp
|
4f9eba5802
|
feat(proxy): 完成数据面代理与渠道约束 (#459)
* feat(proxy): 实现第一阶段数据面代理
* feat(proxy): 收敛渠道与代理协议支持
* fix(proxy): 修复环境检测与迁移验证
* fix(proxy): 回收旧代理运行时并校验地址
* fix(proxy): 补齐创建链路与前端校验
* fix(proxy): 收口订阅代理与迁移兼容
* fix(proxy): 修复环境代理与运行时回收
* fix(proxy): 为系统外部请求应用全局代理
* docs(config): 精简环境配置说明
* feat(proxy): 重构代理设置的前端交互与样式
设置页与分组设置页:
- 代理设置接入页面统一的草稿态与保存栏,不再独立即时提交
- 计入页面 dirty/valid,参与未保存离开拦截与并发冲突推迟
- 新增 ProxyOverrideRow,用分段控件替代原独立编辑弹层
账号卡片与密钥行:
- ProxyConfigEditor 新增 card 外观:标题在白底面板外,与相邻小节同级
- 修掉按视口宽度判断断点的问题,窄容器内不再挤压错乱
- 编辑态下拉固定宽度,不随所选模式伸缩;整体收进两行
- 新增 ProxyScopeIndicator,凭据配置了独立代理时给出标识与悬停提示
密钥行交互:
- 操作列收成「更多操作」菜单与展开图标,与账号卡片同构
- 折叠区分为权重、出站代理、运行诊断三个带标题小节,设置与诊断不再混放
- 权重编辑从弹层迁入折叠区,权重列的值可点击直达
- 释放的列宽还给凭据、权重与最近调用列
文案精简为继承、直连、自定义,并清理两处无引用的死键
* refactor(proxy): 统一代理设置的覆盖交互并消除样式重复
设置页与分组设置页:
- 代理行改用 RuntimeOverrideRow,与超时等设置项共用同一组件
- inherit 映射为“未覆盖”,direct/custom 映射为“显式覆盖”,因此补齐了
覆盖/恢复默认按钮、覆盖状态徽章、当前有效值与待恢复默认态
- 分段控件只保留直连与自定义,继承由外层覆盖开关表达
- 删除自造的 ProxyOverrideRow,新增只含编辑控件的 ProxyOverrideControl
已保存的自定义地址:
- 输入框不做回填,统一由 placeholder 展示已存地址
- 同模式下留空或与已存地址逐字相同均视为未改动,顺带挡住掩码被当作
新密码存回;无改动时保存按钮禁用
- 重新开启覆盖时回到基线已存的覆盖模式,使恢复默认可原路撤销
代码质量:
- 面板外壳(标题 + 白底面板 + 标签/值/编辑图标/操作)抽为全局
.setting-panel,代理、权重、诊断三处共用,不再各写一份
- 删除 ProxyConfigEditor 已无调用方的 row 外观及随之失效的 props、
徽章分支与始终隐藏的文案
- 占位地址推导与覆盖开关规则收敛为 proxy.ts 中的共享函数
- 移除代理输入提示文案及其失去引用的 i18n 键
密钥行折叠区诊断值字号对齐上方面板。重构以构建产物 CSS 逐条比对验证,
差异均为已论证的等价改写。
* fix(proxy): 修复代理传输与校验边界
|
2026-08-24 11:11:22 +08:00 |
|
tbphp
|
414679ef49
|
feat(group): 默认按最近调用排序 (#460)
* feat(group): 默认按最近调用排序
* fix(group): 优化最近调用排序查询
* fix(group): 兼容 MySQL 分组活动查询
|
2026-08-23 12:09:03 +08:00 |
|
tbphp
|
7f64cbbd9e
|
fix(health): 限制异常上游凭据提示数量 (#458)
|
2026-08-22 17:58:41 +08:00 |
|
tbphp
|
92c52ec265
|
feat(subscription): 增加账号批量操作 (#455)
* feat(subscription): 增加账号批量操作
* fix(subscription): 统一账号文件导入导出
* fix(subscription): 独立展示批量同步状态
* fix(groups): 优化凭据批量操作交互
* fix(groups): 优化凭据批量操作布局
* feat(groups): 增加凭据全量操作
* fix(groups): 修复凭据批量操作反馈
|
2026-08-22 13:30:03 +08:00 |
|
tbphp
|
ed5622f9bd
|
fix(subscription): 移除额度快照时间失效 (#454)
* fix(subscription): 移除额度快照时间失效
* fix(subscription): 完善额度快照与重置卡展示
* fix(subscription): 修复迁移与到期提示
* fix(storage): 修复额度快照迁移恢复
* fix(control): 修复重置卡到期告警
* fix(web): 限制重置卡详情数量
|
2026-08-22 02:00:23 +08:00 |
|