model-sync 更新报告(最终版)

August 17, 2026 · View on GitHub

版本:0.1.6(2026-08-16) 范围:圆环语义互换(外环 = 5h,内环 = 7d)+ 设置页图标适配 基座@deepseek-ai/dsh 0.1.0-rc.6(未升级) 依赖:零新增(Node 内置 + DSH 自带)


〇、0.1.6 增量(圆环语义互换)

  1. 双层用量环语义交替:此前外环展示 7 天窗口、内环展示 5 小时窗口,现改为 外环 = 5h、内环 = 7d(与屏幕阅读顺序、视线焦点一致)。仅修改 DualRing 组件的 strokeDashoffset 绑定与 React key(避免 DOM 复用错位),win5h/win7d 字典键与 detail panel 行序不动。
  2. i18n 同步innerOuter 文案改为「内 7d / 外 5h」/「Inner 7d / outer 5h」(中英双语);悬浮提示与点击面板里的窗口行顺序保持原意。

〇、0.1.5 增量(重置倒计时 + 设置页 Icon)

  1. 重置倒计时:圆环 hover 详情(popup)重构为每窗口一行(7D/5H 各自独立行),显示「剩余 X% · 重置倒计时」;用量详情页窗口行把绝对时间改为倒计时(countdownTextX 天 X 小时后重置 / X 小时 X 分后重置 / X 分钟后重置 / 即将重置,中英双语键)。
  2. 设置页 nav Icon:settings-general 仅给内置 section id(models/agent-presets/plugins)配图标,第三方 section 一律回退齿轮——插件用 MutationObserver 按 nav label 文本匹配,重写 gear SVG 为 16px outline 图标(复制自 dsh-client-ui-primitives):模型同步 → IconRefreshOutline16(循环同步箭头)、用量详情 → IconListPenOutline16(明细清单),风格与内置 icon 一致;保留原 navIcon wrapper 类。

一、需求总览

#需求状态
1对话框用量增加 API 调用模型用量显示,剩余百分比 = 当前余额 ÷ 最后一次充值后的余额
2拓展全部可拓展供应商(按量余额 / 套餐窗口)
3套餐窗口与加量包并存的竞态规则:图标只显窗口,余额只在详情展开
4单额度画单环、双额度画双环;滑条颜色按剩余比例语义化
5设置页新建「用量详情」分页;重构「模型同步」页布局
6余额基准本地持久化(修复"每次重启重置"观感)
7圆环位置移动(模型名称右侧、上下文进度条左侧)+ 尺寸与配色调整

二、功能变更

2.1 API 按量模型用量显示

  • 对话框额度圆环新增按量模型(deepseek-official)余额显示。
  • 公式:剩余百分比 = 当前余额 / 最后一次充值后的余额(充值后归 100%,用掉 10 元 → 90%)。
  • 充值检测:平台无充值历史 API,插件自维护基准——轮询发现余额高于持久化基准即视为充值,基准重置为新余额(首次采集以当前余额为基准)。
  • 基准持久化.dsh/profiles/<profile>/model-sync.baseline.json(原子写 tmp+rename,写队列串行防并发竞态)。

2.2 全供应商覆盖(逐家真实凭据实测)

Provider按量余额套餐窗口落地
deepseek-officialGET /user/balance余额(充值基准本地追踪 + baselineAt
kimi-codingboosterWallet.balance(平台自带 amount/amountLeft 基准)✅ 5h/7d加量包余额 + 窗口 + 累计用量
xai (grok)❌ 无公开 REST✅ gRPC-web GetGrokCreditsConfig7 天窗口(替换"尚未接入")
zai / minimax-cn❌ 无公开端点(探测 404)✅ 5h/7d窗口 + zai 累计用量
xiaomi❌ 无公开端点无数据
openai-codex✅ wham/usage窗口
  • Grok gRPC-web 移植:从 CC Switch(farion1231/cc-switch subscription_grok.rs)移植——空帧 POST + 通用 protobuf 扫描启发式(路径末段=1 的 [0,100] float 为用量百分比、[1,5,1] varint 为重置时间)。实测 used 52%。
  • Kimi 加量包amount(总充值 25 亿点)/ amountLeft(剩余 15.85 亿点)→ 剩余 63.4%;平台自带基准,无需本地追踪。
  • 累计用量QuotaWindow.usedRaw/limitRaw/rawUnit 承载原始计数(kimi 56/100 次、zai 5150/10000 次)。

2.3 渲染规则(图标 / 详情 / 颜色 / 尺寸)

  1. 竞态规则:有套餐窗口的 provider 图标只显窗口(如 kimi 加量包只在 hover 详情展开);纯余额 provider(deepseek)余额上图标。

  2. 单/双环:单额度(仅 1 窗口或仅余额)画单环;5h+7d 双额度才画双环。

  3. 滑条颜色(HSL 插值,色相主导、明度协调;双主题色板,检测 body[data-ds-dark-theme]):

    剩余暗色主题亮色主题(深色锚点保 ≥3:1 对比)
    0%hsl(0, 65%, 42%) 暗红hsl(0, 70%, 38%) 深红(3.79:1)
    50%hsl(80, 62%, 47%) 黄绿—(插值)
    75%hsl(120, 60%, 50%) 绿色hsl(145, 72%, 22%) 深墨绿(3.02:1,原 1.4:1)
    100%hsl(205, 50%, 65%) 天蓝hsl(215, 70%, 35%) 深蓝(3.12:1)
  4. 位置:输入栏 模型名称(model seat)右侧、上下文进度条(ContextMeter)左侧——CSS order 重排。坑:SlotOutlet 锚点是 display:contents div(非 flex item),order 必须作用于锚点内部元素([data-slot="conversation.input.model"] > ._7KE1Ra_root order 1 / [data-slot="conversation.input.right"] > .msync-wrap order 2 / .JObwrW_root order 3;trailing 容器哈希类 uV2eYG_trailing,rc.6 产物,DSH 升级需复核)。

  5. 尺寸:单环 14.4px(基准 12px,略小于 ContextMeter 14px,整体 ×1.2),双环 21.6px(= 单环 × 1.5)。

  6. popup 详情:窗口行(含累计用量/剩余%/重置时间,标签随窗口数动态)、加量包/余额行(剩余 X% · 当前 / 基准)、title 悬停提示。

2.4 设置页(原生分页)

settings.section 是 list slot,多注册一条目即左侧导航新分页(源码核实 dsh-client-ui-settings-general):

  • 「模型同步」(order 16):供应商模型管理(名称 + baseURL + 应用新模型 + chips 横向滚动 + 错误行)+ 折叠「插件启停」(details 默认收起)。额度杂项全部移出。
  • 「用量详情」(order 17,新):每供应商额度表格——窗口(累计用量/剩余%/重置时间 + quotaColor 进度条)、加量包、API 余额(含「基准记录于 …」时间戳);顶部更新时间 + 刷新,60s 自动轮询;余额 provider 提供「以当前余额为基准」手动校正按钮。

2.5 基准持久化加固(0.1.2 修复)

  • 诊断结论:持久化机制本身工作正常(基准文件已落盘,运行中 current: 39.56, lastRecharge: 39.59 跨进程保持;dsh 启动不清理 profile 目录)。"每次重启重置"观感来自首采锚点——功能首次启用时无历史基准,只能以当时余额为基准,此后显示 ≈100%;且 persistBaseline.catch(() => {}) 静默吞掉一切写入错误。
  • 修复:① 持久化失败记 model-sync baseline persist failed 日志(读写均记录);② QuotaBalance.baselineAt 透出基准设定时间;③ 新增 POST /baseline-reset + 详情页「以当前余额为基准」按钮(覆盖启用前已充值的首采失真场景)。

三、文件变更清单

文件变更
src/domain.tsQuotaWindow.usedRaw/limitRaw/rawUnitQuotaBalance.label/baselineAt
src/quota.tsDeepSeek 余额 + 充值基准(日志化持久化、collectBalance/resetBaseline);Kimi 加量包 + 累计用量;Grok gRPC-web 移植(~150 行);zai 累计用量
src/http.ts补充 deepseek-official provider;deepseekApiKeyEnv 提取;/baseline-reset 路由
client/client.jsquotaColor(HSL 锚点插值);单/双环三态渲染 + 尺寸(14.4/21.6);findBalance 竞态规则;UsagePage + section 分页注册;SettingsPage 布局重构;compactNum/动态 label;trailing 区 CSS order 重排
AGENTS.md已完成插件表:model-sync 能力与渲染约定(含哈希类复核提示、基准文件语义)
CHANGELOG.md本报告

四、关键设计决策

  1. 充值基准本地持久化(DeepSeek):平台无充值历史 API → 本地 JSON 快照,余额跳升 = 充值重置;原子写 + 串行队列防竞态;失败日志化不静默。
  2. 平台基准优先(Kimi):BalanceReading.lastRecharge? 可选——平台给总量(加量包 amount)直接复用,跳过本地追踪。
  3. Grok 账单走 gRPC-web 移植:无公开 REST 端点;移植 CC Switch 已验证的 protobuf 启发式,不自研逆向。
  4. 分页用原生 list slotsettings.section 多注册一条目即左侧导航新分页,无需 fallback。
  5. 职责分离:模型管理(模型同步页)与额度信息(用量详情页)彻底分开;图标/详情两级信息密度(图标只表达主额度,详情承载全部)。
  6. 纯 CSS 布局重排:额度环位置移动零运行时开销;data-slot 契约属性做锚点,哈希类仅 trailing 容器一处(rc.6 锁定下稳定)。

五、实测结果(真实凭据)

deepseek-official → balance { current: 39.55, lastRecharge: 39.59, unit: 'CNY', baselineAt }(基准跨进程保持)
kimi-coding       → 5h 累计 0/100 次 · 7d 累计 56/100 次 · 加量包 15.85亿/25亿 点(剩余 63.4%)
zai               → 7d 累计 5150/10000 次(percentage=51 吻合)· 5h 0/2000 次
xai (grok)        → 7d 窗口 used 52% / 剩余 48%,重置 7 天后

六、验证状态

  • pnpm build(tsc strict)+ node --check 通过
  • ✅ Host 采集器 mock-ctx 实测(余额保持、raw 透出、resetBaseline {ok:true}、写失败日志捕获)
  • ✅ client 渲染逻辑模拟(颜色锚点、单/双环模式与尺寸、累计用量文本、trailing order 重排对照真实 DOM)
  • ⏳ 运行态 UI 验收:重启 dsh web 后核对输入栏布局、两页内容与接口

七、验收步骤(重启后)

  1. 重启 dsh web
  2. Invoke-RestMethod http://127.0.0.1:3080/agentteam/model-sync/state
    • deepseek-official → quota.balance(含 baselineAt)
    • kimi-coding → windows 带 usedRaw/limitRaw + balance(加量包)
    • xai → windows 含 7d(used≈52)
  3. 浏览器:输入栏顺序 [模型名称] [额度环] [上下文进度条] [发送];单环 14.4px / 双环 21.6px;设置页「模型同步」精简布局 +「用量详情」表格正确

八、已知限制

  • xiaomi / minimax 无公开余额端点;zai / xai 余额不可得(仅窗口)——collectQuota 已留分支,平台开放后即插即用。
  • Grok 账单为逆向协议,平台改版可能失效(失败仅显示 reason,不影响其它 provider)。
  • kimi/zai 的 rawUnit 暂按「次」展示;若平台口径为 token/点数,后续调整文案。
  • 圆环位置依赖 trailing 容器哈希类 uV2eYG_trailing(rc.6 产物)——DSH 升级需复核;类名变化只会让环回到原位,不影响功能。
  • 基准文件首采=启用时余额;启用前已充值可用详情页「以当前余额为基准」校正或手改 model-sync.baseline.jsonlastRecharge