Commit Graph
80 Commits
Author SHA1 Message Date
tbphp 9d38793dd0 fix(affinity): 统一缓存标识亲和并补齐 Codex 缓存分组 (#635) 2026-09-13 01:25:45 +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 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 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 d518b06acc refactor: 统一错误决策与执行链路 (#466)
* refactor: 统一错误决策与执行链路

* fix(gateway): 修正错误来源与候选预算
2026-08-24 23:26:22 +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
tbphp 03ee3048a3 feat(access-key): 增加估算费用额度限制 (#439)
* feat(access-key): 增加估算费用额度限制

* fix(storage): 修正 MySQL 迁移恢复断言

* fix(access-key): 修复额度并发与恢复边界

* fix(access-key): 修复额度发布与周期收敛

* test(requestlog): 稳定额度恢复状态断言

* fix(control): 保持健康额度快照一致
2026-08-20 17:19:32 +08:00
tbphp f80c768180 Merge branch 'v2' into fix/claude-channel-hardening
# Conflicts:
#	internal/control/route_inspect.go
#	internal/control/route_inspect_test.go
#	web/src/features/monitor/InspectorTab.vue
2026-08-17 16:12:07 +08:00
tbphp f63777aced fix(subscription): 完善局部观察与本地计数归属 2026-08-17 15:00:14 +08:00
tbphp f56d9bb413 fix(pricing): 优先匹配档位计价 2026-08-17 12:05:32 +08:00
tbphp 47482dd2a6 fix(usage): 调整聚合数据保留策略 2026-08-17 10:52:33 +08:00
tbphp 141819c632 test(ci): 优化测试夹具与并行门禁 2026-08-16 12:38:26 +08:00
tbphp a48ad669ea feat(pricing): 支持 Fast 模式计价与日志标识 2026-08-16 12:00:07 +08:00
tbphp 9907adf4e0 Merge branch 'v2' into refactor/protocol-channel-architecture
# Conflicts:
#	internal/control/service.go
#	internal/storage/db_test.go
2026-08-15 15:46:33 +08:00
tbphp 4c00eed40b refactor(channel): 统一渠道架构与协议契约 2026-08-15 15:37:50 +08:00
tbphp 90507600cc fix(subscription): 修正账号卡片统计口径 2026-08-15 15:36:34 +08:00
tbphp 25424d61c4 feat(codex): 完善订阅额度与调度体验 2026-08-14 23:16:21 +08:00
tbphp 334e1336f1 feat(monitor): 扩展消耗分布统计维度 2026-08-12 22:46:08 +08:00
tbphp 1df1d02e2d fix(monitor): 优化消耗分布切换与分组展示 2026-08-12 22:15:59 +08:00
tbphp 94b8e7e2dc feat(monitor): 使用消耗分布替换路由明细 2026-08-12 21:05:21 +08:00
tbphp a285d0fe39 refactor(storage): 统一数据库迁移链 2026-08-12 10:00:40 +08:00
tbphp 59d07c9b6b feat: 日志协议优化 2026-08-12 08:37:53 +08:00
tbphp e7de10ec73 feat(route): 支持有损协议转换与参数追踪 2026-08-11 17:42:10 +08:00
tbphp 3e948eedbe test(ci): 稳定远端 race 门禁 2026-08-11 16:32:43 +08:00
tbphp d6be4272d1 feat(console): 完善日志诊断与模型视图 2026-08-11 08:18:45 +08:00
tbphp 2100ac69d5 feat(logs): 优化路由与协议转换提示 2026-08-10 22:45:11 +08:00
tbphp c13906f001 fix(logs): 展示脱敏后的上游错误消息 2026-08-10 22:11:52 +08:00
tbphp 61b763b96b fix(channel): 收口渠道执行与终局迁移 2026-08-10 10:31:08 +08:00
tbphp 6f6f7c3efc refactor(channel): 切换为 Bifrost 渠道执行架构 2026-08-10 08:22:15 +08:00
tbphp 8ae02d4053 feat(monitor): 优化用量趋势与时间粒度 2026-08-09 12:04:21 +08:00
tbphp d5b4e3261e feat(auth): 支持访问密钥登录只读后台 2026-08-08 23:33:29 +08:00
tbphp a9ef5edd39 fix(requestlog): 排除零尝试请求统计 2026-08-08 15:53:55 +08:00
tbphp dc7510a879 feat(requestlog): 增加返回模型一致性提示 2026-08-08 12:47:31 +08:00
tbphp 295d7724ab fix(v2): 收紧外部数据库与运行设置合同 2026-08-07 19:04:33 +08:00
tbphp 59a3c58c4f feat(models): 优化全局模型价格管理 2026-08-07 17:16:29 +08:00
tbphp e789feffb4 feat(storage): 支持 SQLite、MySQL、PostgreSQL 2026-08-07 07:49:11 +08:00
tbphp ad362cddfb test(logging): 对齐精简事件名称 2026-08-06 23:15:01 +08:00
tbphp bae6d65e29 feat(monitor): 记录并展示请求思考配置 2026-08-06 19:59:44 +08:00
tbphp 2d8a160473 docs: 修改日志 2026-08-06 17:57:43 +08:00
tbphp fadf9303bf fix(monitor): 修复监控数据与页面交互 2026-08-06 12:10:28 +08:00
tbphp f89cbd59fc feat(monitor): 完善用量与路由检查页面 2026-08-06 08:10:44 +08:00
tbphp 6141cf85ef feat(monitor): 完成监控页面请求日志实现 2026-08-05 23:01:42 +08:00
tbphp 1f7687e413 fix(log): 调整请求日志字段顺序 2026-08-05 22:19:20 +08:00
tbphp 0e7f50edc2 fix(log): 保留上游 Key ID 日志字段 2026-08-05 21:11:21 +08:00
tbphp 5abfb3d663 fix(log): 精简请求完成日志字段 2026-08-05 20:04:45 +08:00
tbphp ca8016f92f fix(log): 精简运行日志并保留级别颜色 2026-08-05 19:40:53 +08:00