dsh-task-timer:对话底部工作时长 pill 与侧边栏合计

前言

在 DeepSeek Harness(DSH)里跑 agent,仪表盘已经能拆出模型时间、工具时间和 token,但「这条对话 agent 实际干了多久」和「从首条消息到最后一动过了多久」仍是两个不同问题。若把 ask_user_question 等你回答的整段都算进工具时间,挂机越久读数越大,和直觉里的「工作时长」对不上。侧边栏会话行右侧若只显示 55分钟,也容易被读成「跑了 55 分钟」,而不是「55 分钟前有过活动」。

下面介绍社区插件 dsh-task-timer(维护者 ShuaihuiMou,分类:客户端)。它在对话底部 composer dock 增加带时钟图标的工作时长 pill,在弹窗里补充创建对话至今;在左侧边栏 Settings/用户名行上方汇总全部对话合计使用时长与合计 token,并把工作区每条会话的时间补成与悬停卡一致的「N 前」读法。插件以 MIT 许可证发布,当前 npm 包版本 1.6.0,要求宿主 dsh >= 0.2.1-rc.5。

这是什么

dsh-task-timer 是 DSH 的客户端插件:宿主侧注册 taskTimer 会话投影,浏览器侧向 conversation.composer.dock 与 sidebar.footer.action 注入 UI,不另开 RPC、不为合计时长解压全量历史日志。

社区目录为独立站点,与 DeepSeek/幻方无官方从属关系;安装前请自行查看仓库源码与许可证。插件随当前 DSH 进程权限运行。

核心功能

对话底部:工作时长 pill

pill 排在官方 activity(TPS)与 usage(Token)之后,主标签格式为「数值在前、名称在后」,例如 51分24秒 · 工作时长。时长显示规则:不足 1 分钟显示到 0.1 秒;不足 1 小时显示分秒;满 1 小时后显示「X小时Y分」且不再显示秒,分钟不会溢出为 60 分等写法。

工作时长口径与仪表盘 sessionStats 对齐,不再自行折叠整份事件日志:

工作时长 = llmMs + toolMs - awaitMs

llmMs、toolMs 直接取自仪表盘已在用的 sessionStats 投影。插件唯一自行累计的是 awaitMs:对 ask_user_question、request_user_input、exit_plan_mode(含 mcp__<server>__ask_user_question 等带 MCP 前缀的副本)在 tool/call 到 tool/result 之间的跨度配对记账,再从读数中扣除。未结算的等待不扣;turn/end 时未结算的等待丢弃,与 sessionStats 一致。用户输入间隙、轮次间空闲本就不在 llmMs/toolMs 里,无需再减。

早于 1.4.0 的版本曾把「等你回答」的时间算进工作时长;README 说明口径修正后 pill 与侧边栏合计同步生效。工具审批弹窗在日志中无对应事件,仍按工具时间计,为已知边界。

点击 pill 打开弹窗:展示仪表盘没有的 创建对话至今,以及仅在确有扣减时显示的 已扣除等待回答。模型时间、工具时间不在弹窗重复——「N轮N步」pill 已分开列出。弹窗样式优先复用 ui-chat 的 stat-dialog.module.css 类名,底色使用仪表盘卡片同款 bg-layer-2。

创建对话至今是墙钟跨度:最后一次对话活动 - 对话内容起点。起点为第一条承载对话内容的事件(非 header 的 createdAt;无内容事件时退回 createdAt);终点为日志里最新一条推进对话的事件,不是 Date.now(),对话空闲时该数停住,有新活动再前移。打开弹窗时立即刷新,打开期间每秒 tick;收起后每分钟轮询,对话已空闲且追上终点时不启秒级定时器。

侧边栏:合计时长与 token

在用户名行上方注入两行(纵向叠放,非并排):

  • 1小时29分 · 对话总时长
  • 3.3M · 对话总token

数据来源为侧边栏已有的 sessions.list 快照与各会话投影:每行时长为 sessionStats.llmMs + sessionStats.toolMs - taskTimer.awaitMs,逐行先减 awaitMs 再求和。已连接会话优先用 projectionsBySession 实时值;冷会话用投影检查点缓存。origin === "subagent" 的子会话行不计入,避免与父会话工具时间重复。没有任何工作时长记录时不渲染时长行;侧边栏折叠为 56px 轨道时整段隐藏。

token 合计读 tokenUsage 投影四桶(uncachedInputTokens、cacheReadTokens、cacheWriteTokens、outputTokens),口径与 ui-chat UsagePill 整份日志 token 总量一致,紧凑格式与内置 usage pill 相同。无 token 记录时不渲染 token 行;仅有 token 无时长时 token 行仍可单独显示。

工作区会话行:「N 前」

ui-workspace 的 timeLabel 无对外 slot,也无法二次注册 workspace locale。插件在浏览器可用 MutationObserver 时,仅匹配会话行内带 _sessionRow/_time 后缀的节点,按 time.ago 模板(如 {t}前)幂等改写文本节点,避免误伤聊天消息上的 _time;刚刚、待回答、待审批 等状态词不改。

安装与启用

DSH 安装目录下 CLI 为 resources/runtime/cli/bin/dsh.cmd(已加入 PATH 时可写 dsh)。从公开仓库安装到 desktop profile:

& "<dsh>" plugin --profile desktop add github:ShuaihuiMou/dsh-task-timer

将 <dsh> 替换为本机实际路径。安装后按 DSH 桌面端惯例在设置中启用插件 bundle;具体启用入口以当前 DSH 版本 UI 为准。不要使用未在文档中出现的臆造安装命令。

典型用法

安装并启用后无需额外配置文件:

  1. 打开任意对话,在底部 composer dock 查看 工作时长 pill,数值随 agent 的 llm/工具活动更新,等你回答的段落会从读数中扣除。
  2. 点击 pill,查看 创建对话至今 与可选的 已扣除等待回答;对话无人操作时「创建对话至今」不会随挂窗时间上涨。
  3. 在左侧边栏用户名上方查看全部对话(不含 subagent 子会话)的合计时长与 token。
  4. 在工作区列表中,会话右侧时间应读成「55分钟前」一类表述,与悬停卡一致。

适用场景与注意

适合需要区分 agent 净工作秒数 与 对话从首条内容到最后活动的墙钟跨度、并在侧边栏一眼看到多对话合计时长与 token 的 DSH 桌面用户。

使用时请注意:

  • 工作时长依赖宿主 sessionStats 与自研 awaitMs 配对规则一致;问句类工具未返回前,await 未结算,读数与仪表盘工具时间 temporarily 可能看起来「还没扣完」。
  • 侧边栏合计不读盘解压历史,依赖列表与投影缓存;极冷会话以检查点为准。
  • 非浏览器装配(如 SSR 冒烟)无 MutationObserver 时会话行「前」后缀装饰不会挂载,其余 pill 行为以该环境是否注入 client 为准。

结尾

dsh-task-timer 在不大改宿主的前提下,用 taskTimer 投影和 composer/sidebar 注入,把「扣掉等你回答的时间」的工作时长、 capped 的「创建对话至今」、多对话合计时长与 token、以及工作区时间读法统一到一套可核对的口径。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜