dsh-client-ui-sidebar-perfmon
Verified@xmwengxing/dsh-client-ui-sidebar-perfmon · v0.3.2 · MIT · Web UI
Real-time host performance monitor for the DeepSeek Harness right Sidebar: CPU / memory / swap gauges plus a sortable process table — on Linux, macOS and Windows. · DSH 右侧栏实时性能监控:CPU / 内存 / 交换内存 仪表盘与可排序进程列表,支持 Linux / macOS / Windows。
Install
dsh plugin add @xmwengxing/dsh-client-ui-sidebar-perfmon Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Creators
Readme
@xmwengxing/dsh-client-ui-sidebar-perfmon
为 DeepSeek Harness 右侧栏提供实时主机性能监控: CPU / 内存 / 交换内存仪表盘、主机温度,以及可按 CPU、内存、进程名排序的进程列表。
English | 中文
┌─ 资源占用 ────────────────────── G2 · x64 · 已运行 5d 3h ─┐
│ ◜◝ ◜◝ ◜◝ │
│ 12.5% 39.1% 4.9% │
│ CPU 内存 交换内存 │
│ 4 核 · 负载 1.52 4.5 GB / 11.4 GB 0.4 GB / 8.0 GB │
├─ 温度 ── CPU 56.0°C · GPU — · 硬盘 39.9°C · 主板 27.8°C ─┤
├─ 进程列表 ───────────────────── 共 349 个进程 · 显示 60 行 ┤
│ CPU ↓ 内存 进程名 │
│ 筛选进程名或 PID ────────────────────────────────────── │
│ 99.9% 849 MB · 7% gnome-shell │
│ ▬▬▬▬ ▬▬ PID 147112 · 26 线程 · 运行 │
│ 35.0% 100 MB · 1% msedge │
│ ▬▬ ▬ PID 740756 · 14 线程 · 睡眠 │
└─────────────── 更新于 15:50:20 · 每 2 秒自动刷新 · 立即刷新 ┘
功能
插件向右侧栏贡献一个页面类型,并向会话顶栏贡献一个按钮:
- 性能监控页面 —— 同一时钟驱动的两个窗口:
- 资源占用:CPU、内存、交换内存三个环形仪表,各自显示百分比、一行辅助信息 (核心数与负载 / 已用与总量 / 本机未启用交换内存),标题栏显示主机名。
- 温度:每个传感器族一个读数——CPU、GPU、硬盘、主板——取该族最热的传感器,
并注明来源芯片与标签。读数 ≥60°C 变暖色,≥90°C 变警示色;主机没有某族的传感器
则显示
—,整机不暴露任何传感器时整张卡片隐藏而非显示四个破折号。行悬停提示 列出主机上报的每一个传感器。 - 进程列表:每行一个进程,显示 CPU 占用、常驻内存及其占物理内存的比例,
支持按进程名或 PID 筛选。三个标签就是列表的三列表头——
CPU、内存、进程名从左到右,各自正对它所排序的那一列。CPU与内存按该资源从高到低排列整机 进程;进程名切换为按名称排序。两个数值列宽度固定、永不压缩,名称列占用剩余宽度 并截断,因此侧边栏变窄时先牺牲进程名而不是数值,列表也永远不会出现横向滚动条。 列与行之间都有细线分隔;CPU与内存右侧的分隔线同时是拖拽把手——拖动即可 调整该列宽度,双击复位,也可聚焦后用方向键(Shift 加速、Home 复位)。宽度按浏览器记忆。
- 性能监控信息按钮 —— 位于会话顶栏的工具栏末位,紧邻右侧栏自身的展开按钮, 点击即打开(或聚焦)该页面。
两个窗口都按宿主上报的间隔刷新(默认 2 秒)。浏览器标签页隐藏时暂停轮询, 重新可见时立即拉取一次新数据。
环境要求
- Linux / macOS / Windows。每个平台各有专用读取器;各平台能提供哪些指标见 平台支持。
- DeepSeek Harness
0.2.0-rc.1或兼容版本。插件注册到右侧栏的 tab 类型注册表 与会话顶栏的工具栏席位,因此需要启动@deepseek-ai/dsh-web-app的 profile (webprofile 即是)。
无运行时依赖:宿主半边只用 node:os 与各平台自带工具,浏览器半边只用 GUI 已提供的 React。
安装
# 从 npm 安装
dsh plugin --profile web add @xmwengxing/dsh-client-ui-sidebar-perfmon
# 从本地检出安装
dsh plugin --profile web add /path/to/dsh-client-ui-sidebar-perfmon
# 从 git 安装(需要先允许 pnpm 执行构建脚本)
dsh plugin --profile web add github:xmwengxing/dsh-client-ui-sidebar-perfmon
然后重启 GUI。用 pm2 管理时:
pm2 restart deepseek-harness-webui
重启前可以先确认插件层已合成:
dsh --profile web --dump-config | grep -A2 perfmon
卸载:dsh plugin --profile web remove @xmwengxing/dsh-client-ui-sidebar-perfmon。
入口在哪里
打开右侧栏,引导页会列出 性能监控 卡片,点击即以 tab 形式打开该页面。 此后会话顶栏的 性能监控信息 按钮可打开或聚焦同一 tab;该 tab 与其它页面一样 支持分栏、拖动与浮出。
配置
默认值刻意保守:每两秒遍历一次 /proc,多个面板共享同一次读取结果。
需要调整时在 profile patch 中覆盖:
# ~/.dsh/profiles/web/cordis.patch.yml
- id: perfmon
name: '@xmwengxing/dsh-client-ui-sidebar-perfmon'
config:
refreshIntervalMs: 1000 # 500–60000,默认 Linux 2000 / macOS 3000 / Windows 4000
processLimit: 100 # 5–500,单次返回的进程行数
cacheMillis: 800 # 0–10000,该窗口内的轮询共享同一次读取
sampleMillis: 150 # 0–2000,首次读数的预热采样时长
projectDirEntryBudget: 50000 # 100–1000000,单个目录一次扫描的条目上限
projectDirMaxDirs: 12 # 1–100,一次扫描覆盖的 distinct 目录数
# projectDir: /srv/demo # 固定扫描某个目录,而不是跟随当前查看的会话
# projectDir: '' # 或完全隐藏目录大小行
平台支持
每个平台族一个读取器,各自读该平台自己的数据源。
| Linux | macOS | Windows | |
|---|---|---|---|
| CPU 占用 / 单核 | /proc/stat |
os.cpus() |
os.cpus() |
| 负载 | 有 | 有 | 无——Windows 没有这个概念,该段直接省略 |
| 内存 总量/已用/可用 | /proc/meminfo(MemAvailable) |
vm_stat(free + 可回收页) |
Win32_OperatingSystem + AvailableBytes |
| 缓存 / 缓冲 | Cached / Buffers |
文件页作为缓存;无缓冲项 | CacheBytes;无缓冲项 |
| 交换内存 | /proc/meminfo |
sysctl vm.swapusage |
页面文件(SizeStoredInPagingFiles) |
| 进程列表 | /proc/<pid>/stat,进程内读取 |
ps -Ao pid=,state=,time=,rss=,comm= |
一次 PowerShell 调用 |
| 进程状态 | 有 | 有 | 无——显示为 — |
| 线程数 | 有 | 无——BSD ps 没有可移植的线程数字段 |
有 |
| 温度 | /sys/class/hwmon(全部芯片),thermal zone 兜底 |
powermetrics(SMC)——不少机器需要 root,读不到时为 — |
暂不提供——WMI 温度类在多数机器上不受支持,故为 — |
| 项目目录大小 | 进程内遍历,三个平台一致 | 同左 | 同左 |
平台无法提供的字段一律上报 null 并在面板显示 —。任何字段都不会用 0 顶替——
因为 0 看起来像一次真实测量。对局部数值的说明(如项目目录的部分统计)就写在
数值旁边,而不是集中在单独的列表里。
开销:Linux 全部在进程内读 /proc,不启动任何子进程;macOS 与 Windows 每次采样
启动一个辅助进程,因此默认刷新间隔更保守——分别是 3 秒与 4 秒(Linux 为 2 秒),
可用 refreshIntervalMs 覆盖。
没有专用读取器的平台(FreeBSD、Solaris 等)回退到只用 node:os 的读取器:
真实的 CPU 读数与内存总量,交换内存与进程列表标记为不可用,而不是猜测。
数字是怎么来的
所有百分比都是同一累计计数器的两次采样之差,因此插件从不假设时钟节拍:
| 指标 | 规则 |
|---|---|
| CPU 占用 | 两次采样之间,忙时间占流逝时间的比例。 |
| 单核占用 | 同一规则,逐核心计算。 |
| 内存占用 | 已用 / 总量,其中“已用”指“不可用”——页缓存可回收,因此计入可用而非已用。 |
| 交换内存占用 | 已用 / 总量。 |
| 进程 CPU | 同一区间内该进程 CPU 时间的增量,按 100% = 一个核心 归一化——与 top 同一约定,因此 4 核机器上的 8 线程进程可能超过 100%。 |
| 进程内存 | 常驻集大小占总内存的比例。 |
读取器唯一必须遵守的规则是单位自洽:进程 CPU 时间必须与该读取器自己的 CPU 总量
同单位。Linux 两边都是 jiffies,macOS 与 Windows 两边都是毫秒——于是
忙Δ / 总Δ 与 进程Δ / 总Δ × 核心数 把单位约掉,任何地方都不需要假设 USER_HZ。
每次会话的第一次读数会用一次短采样预热,因此面板首帧显示的就是真实百分比而非 0。
有两种状态会如实呈现,而不是显示为 0:
- 本窗口内新出现的进程没有可作差的上一帧,其 CPU 单元格在下一次轮询前显示
—。 - 未启用交换内存的主机显示“未启用”,而不是一个 0% 的空环。
仪表盘下方的项目目录行按需统计:目录遍历是 CPU 与 IO 密集型工作——
停在用户主目录的会话可能有几十万条目——因此面板绝不隐式启动扫描。该行自带
一个按钮,统计当前正在查看的会话的工作目录:浏览器在启动请求里携带会话 id,
宿主经活跃会话存储解析 session.header.cwd;GUI 侧栏里“正在查看”的会话大多是
冷会话(其归属进程从未把它进入本进程的活跃存储),因此宿主会退回到
session-query 服务读取冷记录的 cwd。扫描进行中按钮变为“停止”,且停止落点在
单次文件系统调用之内,已统计的部分结果会带“已停止”说明保留显示。扫描完成后的
读数一直保留到下次扫描替换为止。常规轮询只读存储结果——面板开着在两次扫描之间
零开销。扫描有上限(单目录 5 万条目、单次 12 个目录)、符号链接既不跟随也不计入,
每一处省略都在数字旁说明,而不是默默夸大准确性。
接入方式
一个 bundle,两半:
- 宿主半边(
lib/index.js)在 Connection 共享且已鉴权的/api通道上注册一条 精确路由 ——POST /api/perfmon.snapshot—— 这正是官方 deliverables 与 session-log-export 包使用的同一接缝。注册在那里意味着该路由继承 GUI 的 Host/Origin 防护与浏览器会话鉴权,因此浏览器用同源fetch()即可访问, 插件自身不处理任何凭据。宿主侧带一个短缓存,多个面板共享同一次/proc遍历。 - 浏览器半边(
client/client.js)注册三个界面,全部是公开扩展席位:ctx.sidebarRightTabs.register()——perfmon页面类型及其引导页入口。ctx.slots.register(),席位sidebar.right.pane.tab,以该类型自身的id为键 —— 面板正文。ctx.slots.register(),席位conversation.session.header.utilities—— 顶栏按钮, 排序值最大,因此落在右侧栏展开按钮旁。
服务解析刻意延后:浏览器半边不声明 inject 列表,而是通过 ctx.inject([...])
逐个获取服务,因此缺少右侧栏或 Connection 的 profile 只会跳过对应贡献,
而不会让整个插件一直 pending。
样式只使用共享的 --dsw-* 设计令牌(字面色仅作为 var() 回退出现),
面板自带中英文案并按文档语言选择,因此不依赖 locale 服务。
隐私
插件读取本机内核计数器,只返回给发起请求的浏览器。它自身不发起任何网络请求, 不外发数据,不写文件。路由受与 GUI 其余部分相同的鉴权保护。
已知限制
- 没有进程属主、命令行与进程树。每行包含进程名、PID、状态、线程数、CPU 与 RSS。
- macOS 与 Windows 部分仅有解析器测试。这两个平台的读取器由「抓取的工具输出样本 + 注入的失败路径」覆盖,但作者未在真实 macOS / Windows 硬件上运行过。Windows 的进程状态、 macOS 的线程数是平台本身不提供,而非实现遗漏。
- 没有历史数据。面板只显示当前读数,没有迷你趋势图或留存采样。
- 轮询而非推流。刷新是按间隔请求,而非服务端推送。
- 顶栏按钮只负责打开,不负责切换。关闭面板由右侧栏自身的控件完成。
开发
npm install
npm run build # 生成 lib/index.js 与 client/client.js
npm run watch # 改动即重建
npm test # 先构建两半,再跑全部用例
npm test 覆盖:以手工构造的采样验证差值算法;通过 react-test-renderer 验证面板
行为(仪表、标签、排序、筛选、刷新、错误);已发布 bundle 的注册内容;以及一组
契约时效性用例——它们重新读取已安装的 dsh 包,确认本插件依赖的席位名、服务名
与路由规则仍然成立。
另有一个通过 DevTools 协议驱动真实 Chromium 的浏览器验证脚本:
# 另起一个实例,避免影响正在运行的 GUI
dsh --profile web --port 3099 --no-open
# 在 Chromium 监听 9222 的前提下
node scripts/verify-ui.mjs "http://127.0.0.1:3099/?token=<token>" /tmp/panel.png
许可证
MIT