packages/dsh-task-board
zhu1090093659/dsh-web侧边栏多列任务看板:卡片交给真实 DSH 智能体会话执行,支持 cron 定时(Host 侧到点执行,关浏览器也生效)。
侧边栏系统监控:实时查看宿主机概览(CPU/内存/网络/磁盘)、进程列表与 Docker 容器状态,全程只读。
A read-only system monitor for DeepSeek Harness (DSH) Web: a “System Monitor” entry in the left sidebar footer opens a right-side monitor drawer that shows live host (the machine DSH runs on) overview, process list, and Docker container status.
Read-only by design: no docker restart/stop, no process kill, no exec, no shell. Built for quick resource checks, troubleshooting, and container observation.
/info and /version, read-only).history and dockerInfo; meta.capabilities gains swap, perCpu, diskIo, temperature, history, dockerInfo. Still read-only.sidebar.panellist seat as the context-insight plugin. The old footer trigger is gone.main slot, key dsh-side-monitor) instead of a right-side drawer. Page header, tabs (Overview / Processes / Docker), scrollable body and responsive cards follow the context-insight layout. The width drag handle and drawer animation were removed.t("monitorTitle")), so it follows the panel language without re-registration.sidebar.footer.action slot (ctx.slots.inject + ctx.slots.register), the ctx.connection.rpc.call browser contract and the Host route-mount registration all match the 0.2 runtime (the /side-monitor endpoints were driven end-to-end against a live boot: token exchange, session cookie, meta / overview responses).shell.overlay slot entry instead of a second React root appended to document.body. The 0.2 UI guide forbids a plugin-owned app root; the shell's frame-wide floating layer gives the drawer the host theme, light/dark switching and stacking for free, and it is click-through until the drawer's own box (which opts back into pointer events) is hit — the rest of the app stays usable while the monitor is open.dsh-host-open-in-app is the live proof of how 0.2 plugins serve browser routes. Reaching the carrier through connection.rpc.handle() (the 0.1.x way) does not work: the facade mounts its route through owner.webServer, and cordis 4 refuses that read on the shadow-bound context the facade ends up with (even when the plugin declares it), so the channel silently never mounted and the drawer reported 'transport failure ... HTTP 405'. v0.4.0 instead declares inject = ['connection', 'webServer'] and registers its own POST /side-monitor/<endpoint> prefix route, fenced by connection.requestRejection before anything is reachable, speaking the exact 0.2 client wire (client-request / server-response envelopes).dsh.client.inject and peerDependencies dropped @deepseek-ai/dsh-client-runtime (it stopped publishing at 0.1.1-rc.2). inject now names the modules whose seats and services the panel uses — @deepseek-ai/dsh-client-connection, @deepseek-ai/dsh-client-ui-layout (declares shell.overlay), @deepseek-ai/dsh-client-ui-renderer (provides the slots service) and @deepseek-ai/dsh-client-ui-sidebar (declares sidebar.footer.action); peerDependencies pin @deepseek-ai/dsh-client-connection and @deepseek-ai/dsh-client-ui-renderer to the ^0.2.0-rc.2 line and @deepseek-ai/cordis to ~4.0.4.--dsw-specific-surface-fill is replaced by --dsw-specific-menu (dropdown, port menu, modal) and the dedicated --dsw-alias-toast-bg / --dsw-alias-toast-label pair; the drawer shadow uses --dsw-elevation-panel instead of a literal.shell.overlay registration and the absence of a document.body React root.The panel still ships its own zh-CN / en-US dictionary and language switcher (
dsh-side-monitor:language) rather than the 0.2 Client locale service. Migrating toctx.locale— so the panel follows Settings → General and registers in the language catalog — is planned for a later release.
sidebar.footer.action slot (ctx.slots.inject + ctx.slots.register), the ctx.connection.rpc.call browser contract and the Host connection.rpc.handle channel registration all match the 0.1.1-rc.2 runtime (live-tested: /side-monitor overview / processes / containers / meta return current data).@deepseek-ai/dsh-client-ui-slots reference: the package no longer ships in DSH 0.1.1-rc.2 (its slot runtime merged into @deepseek-ai/dsh-client-runtime). Removed it from dsh.client.inject and from peerDependencies so fresh dsh plugin installs resolve cleanly instead of pulling the rc.6-era package.--net=host netns probe now runs at most every 15s (was 5s) and never blocks the overview poll — stale snapshots are reused while the refresh happens in the background, with a baseline guard so the container-netns fallback never diffs against host-netns counters.lib/client.js's CLIENT_VERSION is regenerated from package.json by tools/sync-generated.mjs (replaces tools/convert-i18n.mjs), which also regenerates the inline i18n dictionary and lints for the no-concatenation rule; npm run check:gen verifies there is no drift.t("a") + t("b") splicing anywhere in the client, enforced by the generator's lint.Received/Sent -> RX/TX; DSH Container -> DSH running in container (DSH on host -> DSH running on host); the status line under the header no longer repeats the data source (it was duplicated with the header badge) and the view label is properly spaced (Host view, never Hostview).meta endpoint reports fine-grained status (mode, per-source state, network probe, consistency) and Host capabilities (Host Mount mode, Docker socket, host-netns probe, process aggregation, container stats) — shown in new Status / Capabilities sections of the About dialog.dsh-side-monitor:language. Every header / tab / card / process / docker / toast / error / tooltip / diagnostics string is translated (dictionary in lib/i18n.js, regenerated into the client bundle by tools/sync-generated.mjs).Host Data / 宿主数据) with the runtime note in the subtitle (PC9527-fnOS · DSH Container); About reports Browser / Host / RPC / Runtime / System / Process / Docker sources./proc/net is net-namespace scoped, so a /host/proc bind still shows the container's interfaces — v0.2.3 reads the host netns through a short-lived --net=host read-only probe (cached, falls back gracefully) and curates veth/br/docker noise. Disk dedup now uses st_dev and surfaces host data volumes (/vol1 on fnOS).🌐 host → container, plain TCP = neutral 📋, loopback = yellow 🔒 + Host only, unpublished = gray 🔒 + Container only; IPv4+IPv6 dual-stack renders once with an IPv4 + IPv6 tag.host:port; right-click menu offers HTTP/HTTPS open / copy address.127.0.0.1 / 0.0.0.0 / explicit hostIp (IPv6 auto-bracketed); unpublished ports show 🔒 and cannot be opened; containers with failed stats show a ⚠ tooltip.sidebar.footer.action slot — shows text when expanded, icon only when collapsed, highlighted while open.100dvh + safe-area insets.protocolVersion (v3) + pluginVersion; a mismatch shows a “version mismatch” banner and an About panel (Browser / Host / RPC versions, fine-grained status and capabilities) instead of undefined fields.# install from a local directory
dsh plugin --profile web add /path/to/dsh-side-monitor
After installing, refresh the page — a “System Monitor” entry appears at the bottom of the left sidebar.
When DSH runs inside a container, the collectors read the container's own /proc (container view). To monitor the real host, add read-only mounts that expose the host's proc / sys / root filesystem at fixed paths:
services:
deepseek-harness:
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/host/root:ro
- /var/run/docker.sock:/var/run/docker.sock
The collector auto-detects these paths (host view wins when present, container view otherwise); you can also set them explicitly via plugin config:
procRoot: /host/proc
sysRoot: /host/sys
fsRoot: /host/root
Once mounted, overview / processes read host resources and the source label switches to “host view”. Note: /proc, /sys, and / must be mounted read-only.
| Data | Interval |
|---|---|
| CPU / memory / network / load / uptime | 2s |
| Disk | 10s (Host-side cache) |
| Process list | 3s (Host-side snapshot cache) |
| Docker list + stats | 5s (stats 3s cache) |
Client UI (Sidebar Row + Monitor Main-Panel Page + 3 Tabs)
│ RPC: connection.rpc.call('/side-monitor', ...)
▼
Host Service (lib/collectors.js + lib/rpc.js)
├─ Environment (mode / systemSource / processSource / dockerSource / hostname)
├─ Overview Collector (procRoot/stat|meminfo|loadavg|uptime|cpuinfo|sys/kernel/osrelease + fsRoot/etc/os-release + net/dev|net/route + mounts/statfs)
├─ Process Collector (procRoot/<pid>/stat|status|cmdline, host-side search/sort/pagination, PPID included)
├─ Network Collector (procRoot/net/dev sampled diff + procRoot/net/route default route + fib_trie/if_inet6 interface IPs)
├─ Disk Collector (procRoot/mounts + statfs multi-mount, mountinfo major:minor dedup, 10s cache)
└─ Docker Collector (/var/run/docker.sock read-only Engine API, health + structured ports)
/side-monitor with three read-only endpoints: overview / processes / containers. Every request is fenced by connection.requestRejection — DSH Connection's Host/Origin trust fence (loopback plus configured --trusted-host authorities) and its browser-session authentication — before anything is reachable./host/proc, /host/sys, and /host/root must be mounted read-only.npm run check # syntax check
npm test # node:test unit tests (test/fixtures/proc are real /proc snapshots)
pid: host but is not forced by default; enabling it makes the consistency self-check report that the PID namespace is not isolated.shell.overlay slot (no document.body app root), Host handle(channel, handler) arity, manifest peer deps / dsh.client.inject retargeted to the 0.2 line, current theme tokens./proc/net/dev as source of truth (interfaces/traffic kept even when IP resolution fails); CPU distinguishes physical cores / logical CPUs; Docker port refinements (loopback locking, hostIp dedup, localized uptime); RPC version handshake; process aggregate view; mobile 100dvh + safe areas; fixture unit tests and CI./proc/net/fib_trie and if_inet6; disk dedup via mountinfo major:minor; source self-check.MIT