@dsh-external/dsh-ui-progress
DSH Web UI 会话进度插件:为 DeepSeek Harness 的 Web GUI 的输入框停靠区提供常驻会话进度条,零核心改动(纯 client 插件,不触碰 agent-loop)。
你的 DSH 版本决定装哪个插件版本(装错会崩:常见症状 useConversation is not a function)
- DSH 0.1.2-alpha.1 ~ 0.2.1-alpha.1:装新版(下方默认命令;各 DSH 版本对应的插件 tag 见版本对应表)
- 更旧的 DSH(0.1.1-rc.2 及以前):无可用版本
安装
安装方式(v0.11.4 起自动挂载):本包自 v0.11.4 起自带 cordis.patch.yml 并声明 dsh.bundle.patch——dsh plugin --profile web add 安装后自动注册 profile 层并挂载,不再需要手写 insert 配置行(固定旧 tag 的部署仍需)。GUI 注意:插件页「添加插件」只接受注册表包名或本地目录路径;name@github:owner/repo#tag 是 pnpm 别名规格(CLI 专用),粘进 GUI 会报 ERR_PNPM_INVALID_PACKAGE_NAME——GUI 请克隆后用本地目录路径,或等 npm 发布后用包名。
# 方式一:git 依赖固定 tag(公开镜像,推荐;也可用 github:omdsh-dev/dsh-ui-progress)
dsh plugin --profile web add '@dsh-external/dsh-ui-progress@github:omdsh-dev/dsh-ui-progress#v0.11.8'
# 方式二:本地 link(开发)
git clone https://github.com/omdsh-dev/dsh-ui-progress.git
cd dsh-ui-progress && pnpm install && pnpm run build
dsh plugin --profile web add link:/path/to/dsh-ui-progress
配置行($DSH_HOME/profiles/web/cordis.patch.yml,热重载,无需重启):
- insert:
- id: dsh-ui-progress
name: '@dsh-external/dsh-ui-progress'
安装提示:pnpm 11 首次安装可能拦截 node-pty 等构建脚本——在 ~/.dsh/profiles/web 下执行 pnpm approve-builds --all 放行后重跑安装命令;装完硬刷新浏览器(Ctrl/Cmd+Shift+R)。
提示词安装(让 DSH 自己装)
把下面这段提示词发给任意一个 DSH 会话,模型会替你完成安装:
帮我安装 dsh-ui-progress 插件(DSH 会话进度条:输入框常驻会话进度条/todos 真实进度/中断橘红态),步骤:
- 执行
dsh plugin --profile web add '@dsh-external/dsh-ui-progress@github:omdsh-dev/dsh-ui-progress#v0.11.8'(首次可能被 pnpm 11 拦截 node-pty 构建脚本而失败)
- 在
~/.dsh/profiles/web 下执行 pnpm approve-builds --all(放行构建脚本)
- 再执行一次第 1 步的安装命令
- 完成后提醒我硬刷新浏览器(Ctrl/Cmd+Shift+R)
遇到报错先查 https://github.com/omdsh-dev/dsh-ui-progress README 的常见问题/已知限制。
版本对应 / Version compatibility
智能版本门控更新提示 / DSH-gated update chip
更新浮标会结合当前运行的 DSH 版本(宿主端从 dsh 安装清单读取,随 /dsh-ui-progress/latest 一并返回)与仓库根的 compatibility.json(版本→支持的 DSH 列表,精确匹配)判定提示形态:
- 最新版支持当前 DSH → 正常「新版本 vX 可用,点击更新」;
- 最新版需要更高 DSH、但存在支持当前 DSH 的中间新版 → 提示更新到中间版,并注明「另有 vX 需更高 DSH」;
- 最新版需要更高 DSH、且当前 DSH 无任何可用新版 → 琥珀色信息条:「新版本 vX 支持更高 DSH 版本,当前 DSH vY 暂不可用」,不提供直接升级。
兼容数据拉取失败或无该版本条目时,自动回退为旧的普通升级提示(离线安全)。发版时需同步维护 compatibility.json(与下表同一步骤新增一行)。
版本对应 / Version compatibility
构建产物随 DSH 快照版本更新,安装时按快照选择对应版本:
| 插件版本 | DSH 快照 | 说明 |
|---|
v0.11.8(默认) | 与上一版相同 | 修复工具执行期 token 速率冻结:短思考→工具调用的切换中,实时 token 速率会带着旧值冻结显示整个工具执行期(根因:滑动窗口只在有新 token 时更新读数、空窗口永远保留旧值,而 tool-call 步的 partial 在参数流完后 tokens 恒定);现在连续两个空窗口(约 2 秒)自动清空读数、token 恢复流动即重新显示,单窗口间隙仍保留旧值不闪零。新增 5 个 hook 测试,全量 62 测试通过 |
v0.11.7 | 与上一版相同 | 声明支持 dsh-v0.2.1-alpha.5(升级实机验证:web profile --dump-config 全插件行加载零错误;运行时只读探测 file-trace mermaid/katex 路由 200、better-sidebar fence 活;宿主保留 webStartup 服务、无插件面破坏性变更——新增的 conversation.input.model.label Slot 为并列新增键,与本插件既有注入面(conversation.input.for / conversation.input.dock 等)无冲突;零适配改动);双 bundle node --check 通过 |
v0.11.6 | 与上一版相同 | 声明支持 dsh-v0.2.1-alpha.4(升级实机验证:web profile --dump-config 全插件行加载零错误;宿主保留 webStartup 服务、无插件面破坏性变更——新引入的 engines.dsh 兼容判定仅对声明者生效,本插件未声明故沿用原有规则;六插件零适配改动);双 bundle node --check 通过 |
v0.11.5 | 与上一版相同 | 声明支持 dsh-v0.2.1-alpha.3(升级实机验证:web profile --dump-config 全插件行加载零错误;运行时只读探测 file-trace mermaid/katex 路由 200、better-sidebar fence 活;宿主保留 webStartup 服务,六插件零适配改动);双 bundle node --check 通过 |
v0.11.4 | 与上一版相同 | 自带 bundle 声明:补齐 cordis.patch.yml 并声明 dsh.bundle.patch——dsh plugin --profile web add 装完自动注册并挂载 profile 层,不再需要手写 insert 行(社区反馈「GUI 安装后不生效」的根因);双 bundle node --check 通过 |
v0.11.3 | dsh-v0.1.2-alpha.1 ~ alpha.5、rc.1、0.1.3-alpha.1 ~ 0.1.7-alpha.2、0.1.7-rc.1、0.1.7-rc.2、0.2.0-rc.1、0.2.0-rc.2、0.2.1-alpha.1、0.2.1-alpha.2 | 声明支持 dsh-v0.2.1-alpha.2(升级实机验证:web profile --dump-config 全插件行加载、peer 校验零错误,宿主启动监听正常,零适配改动);双 bundle node --check 通过 |
v0.11.2 | dsh-v0.1.2-alpha.1 ~ alpha.5、rc.1、0.1.3-alpha.1 ~ 0.1.7-alpha.2、0.1.7-rc.1、0.1.7-rc.2、0.2.0-rc.1、0.2.0-rc.2、0.2.1-alpha.1 | 声明支持 dsh-v0.2.1-alpha.1(升级实机验证:web 宿主七插件挂载激活正常,零适配改动);typecheck/57 单测/构建全绿 |
兼容性说明:当前版本为 v0.9.12(面向 dsh-v0.1.2-rc.1);以下为历史快照兼容记录。v0.8.0 构建基于 snapshot0808 开发,同时兼容 snapshot0809(snapshots/20260809T140917Z),实机验证通过;v0.9.0 为原生 snapshot0809 构建;v0.9.1 面向 snapshot0810(snapshots/20260810T155924Z,默认版本),同时兼容 snapshot0811(snapshots/20260811T152241Z)与最终快照 snapshot0812(snapshots/20260812T172954Z-final)——0811 与 0812 实机 boot 验证通过(见下)。
npm 发版兼容:兼容 DSH npm 发版 @deepseek-ai/dsh@0.1.1-rc.1(v0.9.2 实机 boot 验证通过:dsh --profile web 启动后 boot 清单包含 @dsh-external/dsh-ui-progress,/plugins/@dsh-external/dsh-ui-progress/client.js 返回 200;conversation.input.dock 槽位与 locale/invariants 服务在 0.1.1-rc.1 上保持不变),同时兼容 @deepseek-ai/dsh@0.0.1-rc.5(dist-tag next,即最终快照 snapshot0812 的 npm 发版;npm exec -p @deepseek-ai/dsh@0.0.1-rc.5 -- dsh --profile web --port <port> 可访问指定版本并启动,lib 生产模式),同时保持兼容 @deepseek-ai/dsh@0.0.1-rc.2(snapshot0811 的 npm 发版)。实测(npm rc.5 基线):dsh web 启动后 window.__DSH_BOOT__ 清单包含 @dsh-external/dsh-ui-progress(inject: dsh-client-locale/dsh-client-runtime/dsh-client-ui-conversation),/plugins/@dsh-external/dsh-ui-progress/client.js 返回 200;src 对 rc.5 基线构建产物 typecheck 全绿(本插件已把 cordis 类型导入与 peer 迁移至 @deepseek-ai/cordis,见下)。注意:0811 起 vendored cordis 更名为 @deepseek-ai/cordis(npm 发版不再发布 cordis 名义的 vendored 包),本插件已迁移(peer 声明 @deepseek-ai/cordis: ^4.0.1-rc.1,npm rc.5 基线上为 4.0.1-rc.4),纯 npm install 不再报 ERESOLVE。
alpha 发版兼容:兼容 dsh-v0.1.2-alpha.1(GitHub tag dsh-v0.1.2-alpha.1,源码构建安装,不发布 npm;v0.9.4 迁移并验证:0.1.2-alpha.1 移除了 @deepseek-ai/dsh-client-runtime 客户端包,ClientContext 改从 @deepseek-ai/cordis 导入、ConversationSnapshot 重构为 views 架构(旧 nodes/turnTimings/turnEnds/partial/runningCalls 全部移到 ChatSnapshot.legacy 兼容投影,turn 时间线在 ChatSnapshot.timeline)。本插件已在 0.1.2-alpha.1 源码基线上重写状态推导(session-state.ts 改为读取 Chat legacy 切片 + 新 SessionSnapshot 的 lastAgentError),typecheck、39 个单测与构建全绿,注册改用 ctx.slots.inject('conversation.input.dock', …) 新范式)。
本插件 v0.9.7 起内置兼容性自诊断:apply 时探测所需客户端 API,不满足时不再崩溃,而是在页面右下角渲染修复指引横幅(点击可关闭),提示升级 DSH 或更新插件。
git 依赖方式固定 tag(公开镜像,推荐):pnpm add '@dsh-external/dsh-ui-progress@github:omdsh-dev/dsh-ui-progress#v0.11.8'(或 github:omdsh-dev/dsh-ui-progress;历史版本:0809 用户用 #v0.9.0,0808 用户用 #v0.8.0,0807 用户用 #v0.6.0,0805 用户用 #v0.1.0)。
0809 兼容要点(snapshot0809,实机验证)
- 0809 运行中的
dsh web 的 window.__DSH_BOOT__ 清单包含 @dsh-external/dsh-ui-progress,conversation.input.dock 进度条正常渲染——运行中加载圈旋转、todos 真实比例填充、完成浅绿、中断橘红、待办琥珀各态实测正常。
- 加载机制变化:0809 重构了客户端插件机制——旧的
dsh.plugin.json 清单 + resolveClientPath(packages/plugin/plugin)已删除,改为 package.json 的 dshClient 声明(platform: 'web',可选 inject/immediately)+ exports["./client"] 指向构建产物;宿主扫描 loader 条目组成 boot 图,Web 端从 /plugins/<id>/client.js 拉取。本插件 package.json 已满足该声明,无需改动。
- 本插件使用的槽位
conversation.input.dock(list/session)与 keyed tool.call.toolview 在 0809 上仍由官方客户端声明(tool.call.toolview 的 owner 类型与 0808 一致);useSession 快照与 todos 投影契约未变。
- 构建要求:0809 宿主在激活时校验
dshClient 包的构建产物,缺失会抛 ClientPackageCompositionError 并拒绝启动 dsh web——升级快照或改源码后必须重新 pnpm run build 再启动,否则浏览器拉到的是旧 lib/client.js。
0810 兼容要点(snapshot0810,实机验证)
- 元数据发现变化:0810 的 ClientModuleHostService 在启动时扫描已加载插件的 package.json,但只读嵌套
dsh.client(packages/client/modules/src/index.ts 的 resolveMeta,pkg.dsh.client);顶层 dshClient 字段读不到会静默丢出 boot 图——无日志、无报错,"启动顺利但插件全没"。本插件已从顶层 dshClient 迁移为嵌套 dsh.client(inject/platform 原样保留),0810 实机验证 window.__DSH_BOOT__ 清单包含本插件、进度条各态正常。
- 无需重构建:
lib/client.js 构建产物不变,package.json 不参与编译;symlink 安装改源仓库即生效,无需重装。
0811 兼容要点(snapshot0811,实机验证)
- cordis 更名(本快照唯一影响本插件的官方变化):0811 将 vendored cordis 由
cordis@4.0.0-rc.7 更名为 @deepseek-ai/cordis@4.0.1-rc.1(官方 client 包随之全部改从 @deepseek-ai/cordis 导入)。本插件对 cordis 只有 type-only 导入(src/invariant.ts 的 import type { Context } from 'cordis'),构建产物(lib/*.js)零 cordis 运行时导入——更名不影响已构建 bundle 的运行时加载;但源码对 npm rc.2 基线 typecheck 时 cordis 裸导入报 TS2307(仅此一处),将类型导入迁移为 from '@deepseek-ai/cordis' 后全绿。建议同步把 peerDependencies.cordis 迁移为 @deepseek-ai/cordis: ^4.0.1-rc.1。
- 实机 boot 验证:snapshot0811(
snapshots/20260811T152241Z)web 启动后 window.__DSH_BOOT__ 清单包含 @dsh-external/dsh-ui-progress(inject: dsh-client-locale/dsh-client-runtime/dsh-client-ui-conversation),/plugins/@dsh-external/dsh-ui-progress/client.js 返回 200。本插件使用的槽位 conversation.input.dock(list/session)、useSession 快照与 todos 投影契约在 0811 上均保持声明。
- 测试 fixture 漂移:typecheck 的 src 全绿;
tests/session-progress-bar.spec.tsx 有两处 fixture 未跟上 0811 新增字段——ConversationSnapshot.views(0811 新增视图快照存储)与 InputState.imageIds(0811 新增草稿图片附件)——源码与构建产物不受影响(fixture 已在 v0.9.1 最终快照适配中补齐,见下)。
0812/最终快照 兼容要点(snapshots/20260812T172954Z-final,实机验证)
- cordis 更名落地:本插件已把 type-only 导入(
src/invariant.ts 的 import type { Context } from '@deepseek-ai/cordis')与 peerDependencies/devDependencies 迁移至 @deepseek-ai/cordis(^4.0.1-rc.1;npm rc.5 基线上为 @deepseek-ai/cordis@4.0.1-rc.4)——构建产物(lib/*.js)零 cordis 运行时导入,npm rc.5 消费者 typecheck 全绿,npm install 无需 --legacy-peer-deps。
- invariants 源码包迁移(仅影响本地 typecheck):最终快照将
@deepseek-ai/dsh-invariants 源码包由 packages/support/invariants 移至 packages/runtime-diagnostics/invariants,devDependencies 路径已同步更新;服务名 invariants 与注册协议未变,运行不受影响。
- 测试 fixture 补齐:
tests/session-progress-bar.spec.tsx 的 fixture 已补齐 0811 起新增的 ConversationSnapshot.views(空视图快照 { get: () => undefined })与 InputState.imageIds(空数组)字段——typecheck(含 tests)与 27 个单测对最终快照基线通过。
- 实机 boot 验证:最终快照(
snapshots/20260812T172954Z-final)web 启动后 window.__DSH_BOOT__ 清单包含 @dsh-external/dsh-ui-progress,/plugins/@dsh-external/dsh-ui-progress/client.js 返回 200;npm rc.5 consumer dsh web 启动后 boot 清单同样包含本插件。本插件使用的槽位 conversation.input.dock(list/session)、useSession 快照与 todos 投影契约在最终快照与 rc.5 上均保持声明。typecheck、build 与 27 个单测对最终快照基线通过。
功能
- 常驻会话进度条(
conversation.input.dock,输入框停靠区):读取框架 useSession 快照渲染真实执行状态——运行中/空闲、当前在飞的工具名、当前窗口已结算的工具结果数、当前轮次。运行中左侧加载圈旋转,进度条 shimmer 扫光 + 品牌色光环脉冲,填充宽度缓动。填充宽度:有 todos 投影时按真实完成比例((已完成+进行中)/总数,进行中任务计入进度);无 todos 时固定默认 100%——会话整体进度没有专门投影,不展示伪百分比(v0.8.0 起移除旧的"每个已结算工具结果进一格、窗口上限 10"分段填充)。运行中额外显示实时已耗时(自当前回合开始,0.1s 步进跳动,满一分钟折叠为 XmYs 后按秒递增)与 ETA 预计剩余时间(仅当模型在最近的 report_progress 上报里给出 eta 估计——不做线性外推,模型没报就不显示);空闲时显示上一回合耗时。会话完成(跑过至少一轮后空闲)进度条切换为浅绿色,从未运行过的会话保持中性蓝灰。
- 中断橘红态(v0.8.0 新增):本会话最近一个已结束回合被中断/停止——手动打断、API 故障或其他意外原因——进度条切换为橘红色(浅橘背景 + 橘红填充/图标/百分比 + 慢速脉冲),标签显示"已中断",优先于运行中/完成态的常规配色。只按最近一个回合判定:中断后继续发送并正常完成的新回合会让进度条恢复正常配色(中断遗留标记仍保留在窗口内但不再触发)。注意态(琥珀,见下)仍优先于中断态。
- 实时 token 生成速率(v0.9.0 新增):运行中模型正在生成时(有流式 partial 内容、且无待处理的人机交互),进度条在已耗时旁显示实时速率(如
12.3 tok/s,斜体品牌色,固定最小宽度保持进度条右侧稳定)。流式 chunk 不携带 token 计数(核心端只有回合结束后的 provider usage),因此该值是自校准估算值:初始按 CJK 感知字符密度折算当前 partial 的 token 数(中日韩宽字符 1 字符 ≈ 1 token,其余按核心 token-meter 同款 4 字符 ≈ 1 token);一旦窗口内任何已结算 step 上报了真实 output tokens,就用其「真实 tokens ÷ 加权字符数」密度缩放当前流式估算——数字会贴近所用模型 tokenizer 的真实密度,而非固定字符启发式。速率按滑动窗口平均(默认 1s 窗口)计算:每 ~1s 刷新一次、只统计最近窗口内新增的 token,消除逐 chunk 闪动;空窗口保持上次读数不归零。速率除以窗口时长(排除 TTFT)——与核心端回合结束后显示的结算 tokens/s(outputTokens/decodeMs)口径一致,运行中数值可直接与结算值对比。每个新 step 重新起算;工具执行/等待人机交互/回合结束时不显示(结算后的精确速率由核心 StatsLine 呈现,避免重复展示同一事实)。
- 待办提醒(attention):本会话或其后代 subagent 会话存在等待人处理的交互(沙箱命令审批 / 选项选择 / 计划审阅)时,进度条切换为琥珀色警告态(浅琥珀背景 + 琥珀填充/图标 + 慢速脉冲),文字提示来源与类型——
等待审批 / 需要选择(本会话)、子代理等待审批 / 子代理需要选择(subagent)、等待审批 · 子代理 2 项待处理(并存时)。subagent 会话被官方侧边栏隐藏,其 pending 状态从全局会话列表(origin: 'subagent' 行的 pendingInteraction)读取——这是主 agent 感知子代理等待的主要出口。优先级:pending(琥珀) > running(蓝) > interrupted(橘红) > done(绿) > idle(中性)。
Model Experience
v0.8.0 起本插件不再注入任何模型可见输入:report_progress 工具与上报引导段落已移除(宿主 half 为空),插件只做浏览器端呈现。若其他宿主插件注册 report_progress 工具,会话进度条的 ETA 行仍会读取其上报的 eta 字段(见上文)。
不注入任何用户消息内容;会话文本与上下文注入不受影响。
安装
见 INSTALL.md(组织内成员)。
配置
无配置键。安装后只需在配置树里插入一行:
- insert:
- id: dsh-ui-progress
name: '@dsh-external/dsh-ui-progress'
Export shape
浏览器半 ./client(apply/inject 命名空间插件)、空 Node half ./index、标准 invariant companion ./invariant。
Known Limitations and Deferred Work
- 会话整体进度无专门投影:无 todos 时填充固定 100%,不展示伪百分比;todos 比例只反映当前 todos 列表,不代表会话全程进度。
- 中断检测按当前窗口 + 最新回合判定(v0.9.3 起以
turn/end reason 为主信号,停止即检出,不再依赖节点痕迹);分页/压缩后旧标记被截断,中断态随之消退;窗口内没有 turn/end 事件(如会话被强杀且未修复)时回退到节点痕迹,仍可能漏检。处于重试路径(model-retry)的回合不显示中断态。
- ETA 完全依赖模型在
report_progress 的 eta 字段上报:模型不报或报错(非字符串/非正数)就不显示;进度条取窗口内最近一次上报的 eta,若最近一次未带 eta 则隐藏(即使更早的上报带过)。
- 浏览器 half 刷新页面即生效(宿主 half 为空,升级安装无需重启
dsh web)。
- CSS 动效常量(时长/缓动)为本地字面量(当前样式体系尚无 motion token 族);中断橘红色为 warn/error token 的
color-mix(样式体系无独立橘色 token)。
- 实时 token 速率为估算值(流式 chunk 无 token 计数):先按 CJK 感知字符密度起算,一旦有已结算 step 的真实 provider usage 即按密度自校准(首个校准 step 之前的首个回合仍为字符启发式);推理/正文/工具参数一并计入;显示为 1s 滑动窗口平均(本地字面量
TOKEN_RATE_WINDOW_MS),非 provider 报告值,回合结束后以核心 StatsLine 的结算 tokens/s 为准。