dsh-context-usage
一个 DeepSeek Harness 的 Web 插件:把「这条对话到底把上下文烧到哪了」做成一屏可读的可视化面板 —— /context 斜杠命令、作曲器里的占用按钮、以及 composer 上方的用量总览。
对标 Claude Code 的 /context:同样的分段占用 + 容量占比,但补齐了它在 DSH 里缺失的部分 —— 累计计费用量、轮数/步数/输出速度、账户余额。
面板截图
它解决什么
DSH 原生的上下文信息散落在作曲器下方那条底栏里:一个圆环 + 三个计费药丸。你知道"用了多少",但不知道 用在哪(系统提示词?工具定义?对话历史?),也看不到本会话的累计消耗和速度。
这个插件把那些数字集中成一块面板,并把官方底栏整行隐藏、把纵向空间还给对话区(隐藏项全部有去处,见下)。
功能
/context 斜杠命令 —— 带插件自有的图标与中文简介,一键开合面板
- 占用按钮 —— 作曲器控件行(发送键与模型选择器之间)的
◔ 67%,实时跟随,点击开合
- 用量面板 —— 作曲器上方,四块信息并排:
- 总览:三段圆环 +
666.1K / 1M + 占比 + 轮数 · 步数 · tok/s
- 占用图:36×5 的方块阵列,按 系统 / 工具 / 消息 三类着色,其余为自由空间
- 本会话累计:未命中 / 命中 / 命中率 / 输出(provider 计费口径)
- 图例:系统提示词 / 工具定义 / 对话消息 / 自由空间 的色块与数值
- 余额药丸 —— 作曲器右侧显示账户余额,前台每 10 秒刷新,悬停显示取样时间;未登录/无钱包/接口异常都有明确状态
- 零依赖、无构建 —— 手写纯 JavaScript,只
require('react'),样式只用宿主主题 token。没有 src/、没有 pnpm install、没有 pnpm run build
安装
安装只能通过 DSH 的 plugin_manager 工具完成 —— 这是官方唯一支持的路径(官方技能明确禁止手改 profile 的 package.json / cordis.patch.yml,也禁止在 profile 里自己跑 pnpm)。
开发模式(文件夹链接,改代码即时生效):
plugin_manager { "action": "install_bundle", "target": "<本仓库的绝对路径>" }
发布模式(tarball 独立副本,本体可删可移):
powershell -File scripts\pack.ps1 # 生成 local-dsh-context-usage-<version>.tgz
plugin_manager { "action": "install_bundle", "target": "<tgz 的绝对路径>" }
装好后敲 /context,或点作曲器右下角(模型选择器与发送键之间)的 ◔ xx% 按钮。
完整的验证 / 升级 / 卸载 / 迁移步骤见 INSTALL.md(那份是写给 agent 读的)。
它隐藏了官方底栏,那些信息去哪了
挂载时本插件会整行隐藏作曲器下方那条官方底栏(原版占用圆环 + 轮/步/速度药丸 + 计费用量药丸),信息全部有去处:
| 官方底栏 | 去向 |
|---|
| 占用率圆环 | 面板总览 + 作曲器占用按钮 |
| 未命中 / 命中 / 输出 / 计费 | 面板「本会话累计」 |
| 轮数 / 步数 / 输出速度 | 面板总览第三行 |
| 账户余额 | 作曲器控件行(占用按钮右侧) |
官方没有可用的开关 —— ui-conversation 的 Config 只有 busyEnter 一项;conversation.input.activity 槽虽然能抑制圆环,但同一处 hidden: activity 会把模型选择器和本插件按钮一起藏掉。
所以实现方式是本插件自有的一张样式表,作用域由本插件放进该 dock 的锚点元素限定:
[class$="_dock"]:has([data-context-usage="composer-dock-anchor"]) { display: none !important }
- 只可能命中本插件锚点所在的那个 dock,不会波及其他面板
- 想恢复官方底栏:把
client.js 里的 HIDE_SHIPPED_DOCK 改成 false
- 依赖
_dock 这个 CSS Module 命名后缀,DSH 大版本升级后需要复核一次
数据来源与口径
数据全部来自宿主已有的投影,没有自算、没有埋点、不发额外请求:
| 面板元素 | 来源 | 口径 |
|---|
| 容量 / 占用 | contextPressure.contextWindow、pressureTokens | provider 每次请求上报,换模型自动跟随,包内不硬编码容量 |
| 系统 / 工具 / 消息 | contextBreakdown | 见下方说明 |
| 未命中 / 命中 / 命中率 / 输出 | tokenUsage | provider 上报的计费口径(本会话累计) |
| 轮数 / 步数 / 输出速度 | sessionStats | 宿主统计 |
| 余额 | ctx.remote.account.getBalance | 宿主直连 Platform,宿主侧无缓存 |
两点如实说明:
- 占用图的三段构成是估算:
contextBreakdown 给出三段 token 数,但方块按"每 token 约 4 字符"折算格数,与真实 token 边界不严格等价。占用率本身(pressureTokens / contextWindow)是精确上报值。
- "本会话累计"与"占用图"不同源:前者是计费口径的累计值,后者是当前请求的上下文构成。两者不该互相验算,这是有意保留的。
已知边界
- 只在 Web / 桌面 GUI 里有命令面(纯客户端命令),headless / CLI 没有该命令
- 上下文容量取自 provider 上报值,模型没上报时该行按缺失处理
- 余额药丸里的
CLIENT_VERSION 硬编码为 0.2.0-rc.2(客户端插件运行时读不到 shell 版本)。DSH 升级后若平台拒收,药丸会显示 余额 接口异常·<code>,改这一处常量即可
- 包名
@local/dsh-context-usage 里的 @local 是"只装进本机 profile、从不发布到 npm"的意思,不是真实的 npm scope;private: true 同理
目录结构
package.json # 包清单:dsh.bundle.patch(Host 行)+ dsh.client(浏览器半)+ icon + locale
cordis.patch.yml # 一行 insert,把本包挂进 profile 条目树
index.js # Host 半:空壳(不注册任何东西)
client.js # Client 半:全部逻辑(约 800 行手写 JS)
locale/zh.json # 插件页展示的标题与描述
locale/en.json
icon.svg # 插件页图标(三段圆环)
scripts/pack.ps1 # 打包成可独立安装的 tarball
INSTALL.md # 写给 agent 的安装/卸载/迁移说明
docs/ # README 配图
开发
改 client.js → 开发模式下页面自动热更;如果页面仍跑着旧 bundle(浏览器会按 id 去重注册),在插件管理里 disable → enable 再 Ctrl+R。Host 半(index.js)改动需要重启 DSH。
卸载
plugin_manager { "action": "remove_bundle", "target": "@local/dsh-context-usage" }
然后检查 ~/.dsh/profiles/<profile>/cordis.patch.yml,删掉 plugin_manager 追加的覆盖项:
- id: context-usage
disabled: false
开发模式下先卸载再删文件夹。详见 INSTALL.md。
License
MIT