Repository navigation
Releases: ChinRinhan/dsh-token-wall
Release list
v0.2.1 — 修复拖桌宠变成拖整个窗口
修复:拖桌宠会把整个窗口拖走(Windows)
桌宠拖到窗口顶部时,拖它反而把整个窗口拖走了。这个版本修掉它。只动了一处 CSS,没有功能变化。
根因
桌面端在 Windows 下用一个 ::before 伪元素铺满窗口顶部当作系统拖动区:
[data-windows-titlebar] .frame:before {
height: var(--dsh-windows-titlebar-height);
-webkit-app-region: drag; /* ← 系统拖动区 */
position: absolute; inset: 0 0 auto;
}桌宠是 document.body 的直接子元素、position: fixed。拖到那块区域上方时,指针事件被系统当成窗口拖动吞掉——pointerdown 根本到不了 JS,所以桌宠自己的拖动逻辑(setPointerCapture + 改 left/top)一次都没跑。
macOS 侧宿主对 body 里不在 #root 内的元素统一兜底成 no-drag,Windows 没有这条兜底,所以这是 Windows 专有的坑。
修法
#dsh-tu-pet,
#dsh-tu-pet * {
-webkit-app-region: no-drag;
app-region: no-drag;
}子树必须单独声明:-webkit-app-region 不是继承属性,Electron 的拖动区判定按「指针下那个元素」自己的样式算——只写根上的话,落在标题栏文字或工作区 chip 上的按下仍会被当成拖窗口。
验证
- 自动化:
client.smoke.mjs加三条源码级断言(根规则有-webkit-app-region: no-drag、有标准名app-region: no-drag、子树规则存在)。 ⚠️ 这三条只锁「声明存在」这个必要前提——无头环境没有真实的窗口拖动行为,拿不到现象本身。真机要手工验:把桌宠拖到窗口顶边再拖一次,窗口不应移动。- 全量 15 个测试文件 + 3 个自检工具全绿。
升级
cd ~/.dsh/profiles/<profile>/node_modules
rm -rf dsh-token-wall
git clone https://github.com/ChinRinhan/dsh-token-wall.git dsh-token-wall
cd dsh-token-wall && git checkout v0.2.1如果你用 link: 指向本地 clone,git pull 后刷新页面即可(只改了 client.js,走客户端 HMR,不需要重启 DSH)。
路由前缀(/dsh-token-usage)、存储目录、localStorage key 都没有变,升级不会丢历史数据。
完整变更:CHANGELOG.md · 上一版 v0.2.0
v0.2.0 — 桌宠显示当前会话用量
桌宠从「只讲全时累计」变成「也讲这次对话」
这个版本让桌宠回答一个它以前答不出的问题:这次对话花了多少、上下文还剩多少。同时修掉一处统计口径分叉。
桌宠(截图右下角)现在显示四类读数:
- 本会话:当前会话的累计用量,是大数字。
- 进度条 + 池:进度条是当前这个 10M 方块填了多少,池是全时累计的块数——两者同一个量纲。
- 本轮:进行中这一轮的用量,实时在涨;悬停可看「上一轮」作参照。
- 补充读数:上下文占用、缓存命中率、今日总量。
新增
- 本会话:当前会话的累计用量。宿主投影(权威、含整份日志)优先,退到我们自己增量折的结果。
- 本轮:进行中这一轮的用量,实时在涨。DSH 自带的「本轮用量」只在轮次结束后才出现,这一点是它做不到的。
- 上一轮:进「本轮」的 tooltip——它是「本轮这个数算大还是算小」的参照。
- 上下文:
projectedTokens / contextWindow。唯一有后果的读数(快满会被压缩),60% 起转黄、85% 起转红。 - 缓存命中率:缓存读取 / 计费输入。成本的主要驱动——实测单个会话 119.89M 里 118.63M 是缓存读取,而这个数以前只藏在 harness 的详情弹窗里。
- 今日:今天的总量,给一个节奏参照。
- 折叠态自适应:接近压缩(≥ 80%)时显示上下文百分比,平时显示本会话量。
改进
- 逐轮折叠是容错的:DSH 自己那套是「全有全无」——任一生命周期异常(缺
step/end、attempt 未闭合)就让整轮读数消失。我们的实现缺边界也能从任意一条带 usage 的消息起算,读数可能偏低,但不会消失。 - 重启后读旧会话,「本轮 / 上一轮」立刻有值:冷读时顺手把同一份日志折一遍播种,不用等下一次实时采样。
- 新增
tools/cross-validate-turns.mjs:拿真实会话日志把折叠结果与宿主自己持久化的tokenUsage投影比对。本机实测 116 个会话全部一致。
修复
/workspaces未使用运行时统计口径:它读的是部署期 config,而/today与/summary走运行时 prefs。后果是设置页关掉「含子会话」后,方块墙/桌宠的累计立刻变小,而旁边的工作区分布纹丝不动——同一块界面两个矛盾的数字。- 「读不到」不再被画成 0:宿主投影字段一旦改名,旧写法会让 NaN 一路流成「0」。现在任一桶不是有限数就显示
—。 - 零值语义两个方向都修正:今日真为 0 时显示
0(不是—);只有 live 的 0 不再被当成本会话用量。 - 逐会话状态表从 FIFO 修正为 LRU——此前长期活跃的会话会被后来的会话挤掉,导致「本轮」突然归零。
升级
registry.npmjs.org/dsh-token-wall 返回 404),所以目前只能从源码安装:
cd ~/.dsh/profiles/<profile>/node_modules
git clone https://github.com/ChinRinhan/dsh-token-wall.git dsh-token-wall
cd dsh-token-wall && git checkout v0.2.0或者用 link: 指向本地 clone,便于继续开发(profile 的 package.json 里已有这种先例):
"dsh-token-wall": "link:F:/path/to/dsh-token-wall"路由前缀(/dsh-token-usage)、存储目录、localStorage key 都没有变,升级不会丢历史数据。
打包体积说明:
package.json的files白名单里已包含docs/,所以从源码安装得到的目录也能直接跑node tools/pet-tree.mjs、node tools/cross-validate-turns.mjs这些自检工具。
注意
- 本版的桌宠读数依赖宿主的两个服务:
sessionProjections(活会话投影)与sessionQuery(冷会话读盘)。两者缺失时会显示—而不是 0,并在/today?session=的projectedUnavailable里说明原因。 /today新增可选的?session=<id>参数;不带该参数时响应与旧版完全一致。- 桌宠的进度条表达的是当前 10M 方块的填充进度,不是上下文占用。这不是疏忽:进度条这个形状对应的量纲就是「还差多少攒满一块」,和旁边的「N 块」是同一件事。上下文是独立读数。
已知限制
- 逐轮状态只在内存里(有界 Map,最近 64 个会话),不持久化——新会话本来就该从零起算。重启后旧会话靠冷读播种补上。
- 标题生成的开销仍然不可见(日志里只有
session/title-llm-request,不带 usage)。
完整变更:CHANGELOG.md · 手工验收清单:docs/ACCEPTANCE.md · 设计取舍:docs/DESIGN.md
dsh-token-wall v0.1.3
修复了一个会让整个 Web 界面起不来的缺陷,并加上防止它复发的自动检查。
修复:注册 id 与包名不一致导致 Web boot 整体失败
package.json 的 name 从 dsh-token-usage 改为 dsh-token-wall 时(b29fcac,因 npm 上重名),client.js 里的
window.__ModuleLoader__.load({ id: 'dsh-token-usage', ... })没跟着改。宿主的 client-modules 模块表按包名索引,浏览器按包名 dsh-token-wall 去取 bundle,脚本执行后却注册成 dsh-token-usage:
- 这一行永远解析不到 → 宿主按「缺失行单独重试」再请求一次同一脚本
- 第二次执行触发
duplicate factory registration for "dsh-token-usage" - Web boot 自检把它算作「1 entry did not activate」,整个启动判失败
实际日志:
Error: web boot: 1 entry did not activate
dsh-token-wall: import failed (see console for the import error)
Uncaught Error: client-modules: duplicate factory registration for "dsh-token-usage"
这个缺陷延迟了约 25 小时才暴露:改名当时宿主进程没重启,模块图早已组合好,统计照常记录;10/24 02:00 重启才是第一次重新扫描包名。
修法:注册 id 改为 dsh-token-wall。路由前缀 /dsh-token-usage、存储目录、localStorage key、PKG_NAME 全部不变,已有数据不受影响。
新增 tools/check-boot-identity.mjs
把「宿主启动时用来索引插件的名字」对齐检查,挂进 npm run check(因而也挂在 prepublishOnly 上):
client.js注册 id ===package.json的nameclient.js在files白名单内(不在白名单 = 用户装下来没有 browser 半,症状与本故障一模一样)exports["./client"]、exports["."]、dsh.bundle.patch指向的文件存在- 带
--profile <dir>时扫描该 profile 里所有已安装的客户端插件,第三方插件写错也能拦住
测试修正
test/client.smoke.mjs 原先硬编码 'dsh-token-usage' 去断言,改包名时会和源码一起漂移,等于没测。现在从 package.json 读 name 作为唯一真源。
验证
npm test全绿(退出码 0)- 反向验证:临时把注册 id 改回旧值 → 工具报
注册=dsh-token-usage 包名=dsh-token-wall,退出码 1 - 真实 profile 扫描:
desktop下 4 个 web 客户端插件全部一致 npm pack --dry-run:23 个文件,client.js在包内
升级注意
- 改包名时:
client.js的注册 id 必须一起改;index.js的export const name和路由前缀不要改,否则已有用户的历史数据会找不到。 - 升级后需要重启 DSH(模块图在启动时组合并缓存)。
npm install dsh-token-wall@0.1.3
dsh-token-wall v0.1.2
v0.1.2 — first public release Token usage dashboard for DSH. This release: - block wall, one block per 10M tokens, 100 blocks per page - floating pet: charging block + pool of completed blocks - spend breakdown by workspace / model / vendor, with model-name normalization so the same model across providers merges into one row - history backfill from existing session logs, then live capture - runtime toggles persisted outside the Cordis config Since 0.1.1: - npm package renamed to dsh-token-wall (dsh-token-usage was taken) - repository renamed to match - support for both generations of sessionPersistence; unrecognised interfaces now report degraded instead of silently returning zero - /today and /summary share one filter definition - retention prunes the in-memory table too - fixtures use neutral workspace names; no real project names remain - README rewritten for users, with screenshots
