dsh-ui-web/packages/dsh-full-stats

34Star2Fork0Issue0Watching

覆盖 DSH 官方会话统计行:完整展示轮/步/耗时/缓存/token,加运行状态指示点,并允许自定义思考中/工作中/完成时三种状态文本。

语言
TypeScript
License
Apache-2.0
分支
main
dsh-plugindsh-plugin-marketdsh-plugins

安装

$ dsh plugin --profile web add github:CAPTAIN1275/dsh-ui-web/packages/dsh-full-stats

在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程

一句话定位

dsh-full-stats 覆盖 DSH Web GUI 官方那条会被截断的会话统计行,把它替换成一整行可换行展示的轮/步/耗时/首 token/速度/缓存命中/输入输出 token 数字串,并在行首加一颗琥珀色或绿色的运行状态点。它在「Web UI 插件」分组里提供一张可折叠配置卡,让你自定义「思考中 / 工作中 / 完成时」三种状态的提示文字,并替换官方硬编码的「Deep diving...」。

核心能力

  • 完整展示会话统计:会话级插槽组件(id=stats,priority=-1)输出 ${turns} 轮 · ${steps} 步 | LLM ${llmMs} · 工具调用 ${toolMs} | 首 token 平均 ${ttftMs/steps} | ${decodeTokens/秒} tok/s | 缓存命中 % | 输入 tok · 输出 tok,整行 whiteSpace:normal 不省略(src/client/index.ts:121-160)。
  • 运行状态指示点:行首渲染 8px 圆点,会话运行中为琥珀色(#f59e0b 带 6px 阴影)、空闲为绿色(#4ade80),点击会话切换有 0.15s 过渡(src/client/index.ts:163-196)。
  • 三种状态自定义文本:配置卡提供「思考中 / 工作中 / 完成时」三段输入框,留空即退回原始内容;填了之后按会话状态显示对应前缀,文本后仍接完整统计(src/client/index.ts:152-159、src/client/FullStatsSettingsCard.tsx:104-137)。
  • 覆盖官方「Deep diving...」占位文本:MutationObserver 监听 [class*="turnStatus"] 节点,遇到官方硬编码的「Deep diving...」文本节点即原位替换为 thinkingText,保留时钟 span(src/client/index.ts:74-91)。
  • 跨进程配置持久化:宿主页注册 GET / PUT /api/full-stats/config,写入 ~/.dsh/full-stats.json$DSH_HOME 优先,否则 ~/.dsh),浏览器配置卡保存后即派发 dshc-full-stats-config 事件,统计行即时刷新(src/index.ts:69-92、src/client/FullStatsSettingsCard.tsx:73-85)。
  • WebUI 设置卡接入:在 web-ui.plugin.item 插槽注册 id=full-stats(order=120),与任务看板、皮肤中心同级出现在 DSH Web 设置页(src/client/index.ts:218-226)。

技术实现

  • 语言: TypeScript(ESM,TSX + CSS Modules;tsdown 编译,target es2024、jsx react-jsx)
  • 关键依赖: @deepseek-ai/cordis(host 插件运行时,注册 webServer 路由)、@deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-ui-conversation(browser 半区被注入目标)、react ^18.2.0(memo 化 FullStatsLine 与 FullStatsSettingsCard 渲染)
  • 架构模式: Cordis 双半区插件 — src/index.ts 是 host 半区(ctx.inject(['webServer'], ...) 注册 /api/full-stats/config GET/PUT 路由 + 读写 ~/.dsh/full-stats.json,无 webServer 服务时为空操作),src/client/index.ts 是 browser 半区(ctx.slots.inject 覆盖 conversation.composer.dock#stats 插槽 + 注册 web-ui.plugin.item#full-stats 配置卡 + 监听宿主路由与 dshc-full-stats-config 事件);cordis.patch.yml 注册插件 id=ui-full-statspackage.json#dsh.client 声明 platform: "web"inject: [dsh-client-runtime, dsh-client-ui-conversation]
  • 入口文件: src/index.ts(host 半区入口,apply 注册配置路由)、src/client/index.ts(browser 半区入口,覆盖统计行 + MutationObserver 替换 Deep diving + 注册配置卡)、src/client/FullStatsSettingsCard.tsx(可折叠配置卡 UI)、src/client/card.module.css(卡片样式,复用官方 ui-plugin-config token)

适用场景

已经在 DSH Web GUI 里跑项目会话、想要一眼看清本轮「跑了多少步、LLM 与工具各花了多久、首 token 多快、缓存命中几成」的数字党;以及想把官方「Deep diving...」改成自己人格化文案(如「大肥鱼正在吃白饭」)的玩家。

前置依赖与兼容性

依赖最低版本说明
DSH0.1.0-rc.6devDependencies 锁定 @deepseek-ai/dsh-client-runtime@deepseek-ai/dsh-client-ui-conversation^0.1.0-rc.6@deepseek-ai/cordis^4.0.1(package.json:33-42)
客户端 profilewebcordis.patch.yml 注册 id: ui-full-statsname: '@captain1275/dsh-full-stats'package.json#dsh.client.platformwebinject 含 dsh-client-runtime + dsh-client-ui-conversation;headless / CLI profile 下浏览器半区不会加载(cordis.patch.yml:1-4、package.json:13-23)
React^18.2.0浏览器半区 React 18 渲染(package.json:42)
Node.js未声明仓库根 package.json 与本包 package.json 均无 engines 字段;host 半区仅用 node:fs / node:path / node:os / node:http 标准库(src/index.ts:11-13)
平台跨平台(macOS / Windows / Linux)仅依赖 Node 标准库,无原生绑定;host 半区路径处理由 path.join 自动适配 win32
原生模块没有 koffi / node-pty / node:sqlite 等原生绑定;测试用 jsdom@29.1.1(package.json:34-42)

安装方式

dsh plugin --profile web add github:CAPTAIN1275/dsh-ui-web/packages/dsh-full-stats

安装后重启 DSH Web,进入任意项目会话即可看到对话框下方的完整统计行与行首状态点;DSH Web 设置页 → Web UI 插件分组里也会出现「完整统计行(状态文本)」可折叠配置卡。

配置项

配置类型说明默认值
思考中状态文本(替换 Deep diving...)字符串会话思考阶段替换官方硬编码「Deep diving...」占位文本,留空则显示原文本
工作中状态文本字符串会话正在生成回复时显示在统计行前的自定义前缀,留空则只显示统计行
完成时状态文本字符串会话空闲且非空白时显示在统计行前的自定义前缀,留空则只显示统计行

以上三项文本在浏览器侧的「完整统计行(状态文本)」卡片填写后,PUT 到 /api/full-stats/config 持久化到 ~/.dsh/full-stats.json,并发 dshc-full-stats-config 事件让统计行即时刷新。

常见问题

Q: 安装后能在哪里看到它?

A: 进入 DSH Web GUI 任意项目会话,对话框下方会多出一行不省略的统计行(轮/步/LLM 与工具耗时/首 token/速度/缓存命中/输入输出 token),行首带琥珀色或绿色状态点;DSH Web 设置页的「Web UI 插件」分组里也会出现一张「完整统计行(状态文本)」可折叠配置卡。

Q: 配置保存到哪?卸载或换机器会丢吗?

A: 三项文本字段写到宿主进程侧的 ~/.dsh/full-stats.json(默认读取 $DSH_HOME 环境变量,回退 ~/.dsh),PUT 接口在写入前会校验字段类型并覆盖式写回。换机器需要手动迁移这个 JSON 文件;卸载插件不会删除该文件。

Q: 「思考中状态文本」是覆盖官方哪段话?

A: 覆盖官方 ChatView 内联 JSX 硬编码的「Deep diving...」占位文本。客户端用 MutationObserver 监听 [class*="turnStatus"] 节点,匹配到该字符串后原位替换为用户配置;保留时钟 span,仅替换文本节点。

Q: 三种状态文本要怎么触发显示?

A: 会话运行中 + workingText 非空时显示「工作中」前缀;会话空闲且非空白 + doneText 非空时显示「完成时」前缀;任意一种配置为空串就退回原始统计行,不显示自定义前缀。

Q: 它会替代 DSH 官方的统计行吗?其他类似插件冲突怎么办?

A: 是覆盖而非并存。浏览器半区以同 id=stats、更低 priority=-1 在 conversation.composer.dock 插槽里重新注册;DSH 自带的官方组件与本插件组件的渲染顺序由 priority 决定。本插件源码中未对 dsh-live-stats 等同类插件做特殊互斥处理。

Q: 配置接口有大小限制吗?

A: 有。PUT /api/full-stats/config 的请求体超过 100,000 字节会被服务端直接拒绝并销毁请求(reject(new Error('body too large')));三个文本字段加起来远低于该阈值,常规输入不会触发。

Q: 必须 DSH Web 才能用吗?

A: 是。package.json#dsh.client.platform 字段为 web,浏览器半区依赖 DSH 客户端运行时;宿主路由 /api/full-stats/config 同样挂在 DSH Web 的 webServer 上,headless / CLI 模式不会加载。

Q: 卸载后统计行会自动恢复成官方样式吗?

A: 会。本插件以 priority=-1 顶替官方 id=stats,移除插件后该覆盖项随插件卸载消失,DSH Web 自带的统计行即恢复显示——但官方原始样式仍是会被截断的 whiteSpace:nowrap 行。

上手难度

入门 — 装好插件、重启 DSH Web 即可看到效果;想要自定义状态文本时进入设置页 → Web UI 插件分组展开「完整统计行(状态文本)」填写三项文本即可,无需手写配置或命令行。

已知问题与限制

  • 配置接口请求体上限 100,000 字节:PUT /api/full-stats/configreadBody 中对超过该阈值的请求直接 reject(new Error('body too large'))req.destroy();当前三个文本字段不可能触发,但若未来扩展字段需注意(src/index.ts:54-67)。
  • 自定义状态文本前缀只在「非空配置」下生效:thinkingText 为空时 mountThinkingTextReplacer 直接 return,workingText / doneText 为空时跳过对应分支退回原始统计行——三段文本必须都填才有完整效果(src/client/index.ts:76、src/client/index.ts:152-159)。
  • cachedConfig 是模块级单例:src/client/index.ts:46let cachedConfig 在多次实例化插件或 HMR 场景下可能残留旧值;保存配置后通过 dshc-full-stats-config 事件刷新,但事件未触达时仍可能读到陈旧数据(src/client/index.ts:46-63、src/client/index.ts:200-203)。
  • 强依赖官方 DOM 选择器与硬编码文本:mountThinkingTextReplacer[class*="turnStatus"] 与文本「Deep diving...」匹配官方节点;若官方 ChatView 重构(class 名变更或文本 i18n 化)将直接失效(src/client/index.ts:74-91)。
  • 聚合包 dsh-web-ui-all 不会自动加载本插件:aggregate.yml 把 dsh-full-stats 放在 deps: 但未列入 patchFrom:,所以仅依赖安装不会把 ui-full-stats 注入 profile 名册——通过聚合包使用者需手动将 @captain1275/dsh-full-stats 加入 dsh.profile.bundles(packages/dsh-web-ui-all/aggregate.yml:21-31、README.md:97-110)。