# dsh-step-clock 中文 | [English](README.md) 一个给 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 网页版用的**单步耗时实时秒表**。它回答内建计时器回答不了的那个问题:**正在跑的这一小步,已经跑了多久?** ``` ● 正在执行 bash,已运行 1 分 12 秒 第 12 步 [bash] 1:12 ``` 那一步跑完之后,它会继续把结果留在屏幕上: ``` ● 上一步(第 12 步)已完成,用时 3 分 45 秒 3:45 ``` 状态条位于输入框上方的那一条(和 todo、goal 条同排),并在输入框**下方**另有一处,这样目标条再高也挤不掉它。 ## 为什么需要它 Harness 本身已在对话底部显示一个轮次(turn)级时钟,但它**要等 15 秒才出现**,而且计的是**整轮**的时间。当你盯着一个长时间的 `bash` 调用时,你无法判断它是刚开始两秒,还是已经卡了四分钟——那个轮次时钟也回答不了。 本插件计量的是**当前这一小步**,并且从它真正开始活动的时刻起算: - **工具步骤**锚定在该工具调用自身的开始时间上。运行中的调用只在其运行期间存在于实时快照里,所以 `0:47` 表示**这次调用本身**已跑了 47 秒,而不是从轮次推算出来的估计值。 - **思考步骤**回退到步骤边界,这是模型耗时最诚实的锚点。 - 秒表**从 `0:00` 就开始跳,没有任何延迟门槛**。 ## 它会说什么 它用直白的中文句子描述当前状况,而不是丢一个光秃秃的数字: | 状态 | 文案 | | --- | --- | | 正在执行工具 | `正在执行 <工具名>,已运行 47 秒` | | 多个工具并行 | `正在执行 bash,另有 2 个工具并行,本步已运行 5 秒` | | 模型流式输出中 | `模型正在思考,本步已耗时 23 秒` | | 已提交、还没输出 | `已提交,正在等待模型响应,已等待 3 秒` | | 上一步已完成 | `上一步(第 12 步)已完成,用时 3 分 45 秒` | | 什么都没跑 | `空闲,等待下一步` | 旁边还有:步号、正在执行的工具名标签(最多 4 个,超出 `+N`,悬停看全部)、以及最右侧一个紧凑的 `m:ss` 数字。 时长按中文习惯换算——`47 秒`、`1 分 12 秒`、`2 分钟`、`1 小时 3 分`——所以`0:03` 不会产生"3 秒还是 3 分钟"的歧义。 ### 为什么完成后还要留着 一个步骤经常在一秒内就结束了,只在"运行期间"存在的状态条极易被错过。把上一步的用时留到下一步开始前,你就能**事后**发现某个慢步骤——比如一个跑了四分钟的 `bash`。只有在该步骤自己的 `start` 与 `end` 时间戳**都存在**时才记录;不存在时它会老老实实显示"空闲",而不是编一个看起来像真的耗时。 ## 安装 ```sh dsh plugin --profile web add @climber47/dsh-step-clock ``` 然后重启 `dsh web`。下一次有步骤运行时,状态条就会出现在输入框上方。 ## 实现方式 这是一个 dsh bundle,以单条 insert 行挂载: - `package.json` 声明 `dsh.bundle.patch`(这是它能被安装的关键)与 `dsh.client`(`platform: web`,这是浏览器半边被加载的关键)。 - `cordis.patch.yml` 插入 `step-clock` 行。 - `lib/index.js` 是(有意为空的)宿主半边。bundle 的 insert 行会解析包根,所以包必须可被导入;本插件没有宿主行为。 - `lib/client.js` 是浏览器半边,采用客户端 bundle 必须的 `window.__ModuleLoader__.load({ id, factory })` 注册形状。React 通过 `require('react')` 从模块加载器取得,不打包进产物。 - 它只注册**一个纯新增**条目:输入框上方的 `conversation.input.dock`(`replaceRisk: none`,不会动自带的 todo / goal / queue 条目)。样式通过创建一个带标记的 `