Skip to content
dsh.fish
Bundle

dsh-process-board

DSH 服务面板:查看由哪个对话(Agent 会话)启动了哪些服务——PEB 环境块读取 DSH_SESSION_ID 归属(含分离进程),三态健康探测 + HTTP 码,支持礼貌停止、日志实时查看与启动参数重放。Host scans agent-started services with session attribution; client renders a fullscreen table panel with tri-state health, graceful stop, live logs and restart replay.

Source
cyanTao
License
MIT
Updated
Updated 6 days ago

Readme

# dsh-process-board

DSH(DeepSeek Harness)服务面板插件——在 Web GUI 侧边栏查看**由哪个对话(Agent 会话)启动了哪些服务**,支持一键停止、日志实时查看、启动参数登记与重放。

**English**: A DSH service panel plugin — see which conversation (agent session) started which services, with tri-state health probes, graceful stop, live log tail and restart replay. Zero runtime dependencies, pure-DOM client.

[![npm version](https://img.shields.io/npm/v/dsh-process-board)](https://www.npmjs.com/package/dsh-process-board) [![npm downloads](https://img.shields.io/npm/dt/dsh-process-board)](https://www.npmjs.com/package/dsh-process-board) [![DSH Market](https://raw.githubusercontent.com/2BingLing/dsh-market/master/assets/readme/badge-listed-zh.svg)](https://dsh.market/) [![status](https://img.shields.io/badge/status-stable-brightgreen)]() [![平台](https://img.shields.io/badge/平台-Windows%20%7C%20macOS%20%2A-brightgreen)]() [![依赖](https://img.shields.io/badge/依赖-零运行时依赖-success)]() [![license](https://img.shields.io/badge/license-MIT-blue)]()

<!-- 评分 ≥ 80 后换金色精选徽章:
[![DSH Market](https://raw.githubusercontent.com/2BingLing/dsh-market/master/assets/readme/badge-top-rated.svg)](https://dsh.market/)
-->

## 效果预览

**服务面板**——按会话分组、三态健康点、HTTP 探测码、端口徽章,一行一服务:

![服务面板](docs/images/panel-services.jpg)

**日志分栏**——左侧服务列表 + 右侧选中进程的实时日志流(WARN/ERROR 高亮、4s 自动刷新、可全屏):

![日志分栏](docs/images/panel-logs.jpg)

## 功能一览

| 能力 | 说明 |
|---|---|
| **会话归属** | 通过 DSH 宿主注入的 `DSH_SESSION_ID` 环境变量(Windows 经 PEB 环境块读取,**含 Start-Process 分离进程**)+ 宿主进程树血缘双通道,把每个服务归属到启动它的对话,面板按会话中文标题分组 |
| **服务视图** | 三道过滤(端口/日志标记闸门 → npm/cross-env 启动器壳剔除 → nginx master-worker 合并),面板只展示真正的服务,不刷屏子进程 |
| **三态探测** | 🟢 running(端口监听)/ 🟡 pid-alive(进程在、端口未监听,如 java 冷启动)/ ⚫ stopped;附 **HTTP 探测响应码列**(200/404 都算可达显绿,✗ 红) |
| **启停管理** | 停止走礼貌终止 → 宽限 → 进程树强杀;stopped 行出现「启动」按钮可重放 |
| **日志查看** | 启动时注入 `DSH_PB_LOG` 环境标记,面板分栏实时 tail(ERROR 红 / WARN 黄高亮,4s 自动刷新,滚动吸底) |
| **全屏** | 面板 ⛶ 铺满视口;日志 ⛶ 覆盖整个面板;Esc 逐级退出 |

## 安装

> 前置:已安装 DSH(`dsh` 命令可用)。`dsh plugin` 底层是 pnpm,以下任一方式均可。

```bash
# 方式 A(推荐):npm 安装——版本语义化,升级方便
dsh plugin --profile web add dsh-process-board

# 方式 B:git 仓库直装(GitHub 或 Gitee 均可,锁定分支最新提交)
dsh plugin --profile web add https://github.com/cyanTao/dsh-process-board.git
# dsh plugin --profile web add https://gitee.com/mr-liangjx/dsh-process-board.git

# 方式 C:clone 后本地链接(可改代码、随改随生效)
git clone https://github.com/cyanTao/dsh-process-board.git ~/dsh-process-board
dsh plugin --profile web add link:~/dsh-process-board
```

升级(npm 方式):

```bash
dsh plugin --profile web update dsh-process-board
```

安装后**重启 DSH 宿主**(重新 `dsh web`),浏览器刷新页面 → 侧边栏出现「进程面板」入口。

> ⚠️ 注意 `link:` 只接受**本地目录路径**。写 `link:https://...` 会被当本地链接解析失败,插件卡片显示「未安装」。

卸载:

```bash
dsh plugin --profile web remove dsh-process-board
```

## 使用

### 面板

侧边栏「进程面板」→ 全屏居中面板(见上方「效果预览」截图):

- **停止**:confirm 后礼貌终止进程树(SIGTERM/taskkill → 10s 宽限 → 强杀);同名 master-worker 已合并为一条(从 master 停止整组,不会被"拉起复活")
- **启动**:stopped 行出现;重放登记表中的启动参数(detached + 自动注入日志标记)
- **日志**:仅对带 `DSH_PB_LOG` 标记的进程可用;点 ⛶ 日志区覆盖整个面板
- **全屏**:面板 ⛶ 铺满视口;Esc 逐级退出(日志全屏 → 面板全屏 → 关闭)

### Agent / 智能体起服务的推荐姿势

让面板"看得见"你起的服务(日志可查、可归属、可停止、可重启):

```bash
# 1. 带日志标记启动(stdout 合流到文件)
export DSH_PB_LOG=/tmp/my-service.log
java -jar app.jar >> /tmp/my-service.log 2>&1 &

# 2. 或直接登记(之后面板「启动」按钮可重放)
curl -X POST http://127.0.0.1:3080/api/plugins/process-board/start \
  -H 'content-type: application/json' \
  -d '{"name":"my-svc","argv":["java","-jar","app.jar"],"cwd":"/path/to/app","port":8080,"logFile":"/tmp/my-svc.log"}'
```

PowerShell(Windows):

```powershell
$env:DSH_PB_LOG = "$env:TEMP\my-service.log"
Start-Process java -ArgumentList '-jar','app.jar' -RedirectStandardOutput $env:DSH_PB_LOG -WindowStyle Hidden
```

## API(loopback + 浏览器同源标记防护,防 CSRF/DNS rebinding)

| 路由 | 方法 | 入参 | 说明 |
|---|---|---|---|
| `/api/plugins/process-board/state` | GET | — | 扫描快照 + 逐服务三态探测 + HTTP 码 |
| `/api/plugins/process-board/kill` | POST | `{pid}` | 礼貌停止进程树 |
| `/api/plugins/process-board/log` | POST | `{pid, lines?}` | tail 日志(≤500 行;仅 `DSH_PB_LOG` 标记路径,防任意文件读取) |
| `/api/plugins/process-board/start` | POST | `{name}` 或 `{name, argv, cwd, port, logFile}` | 重放登记 / 显式登记并启动 |

## 平台支持

| 层 | Windows | macOS |
|---|---|---|
| 服务面板 UI / API / 登记表 | ✅ | ✅ |
| 端口/HTTP 探测、礼貌停止 | ✅ | ✅(POSIX 信号 + 进程组) |
| **进程扫描 + 会话归属** | ✅(WMI + PEB 环境块读取) | 🚧 **待实现**(方案:`ps` + `lsof -i` + 读 `/proc/<pid>/environ`,比 Windows PEB 简单;欢迎 PR) |

> Mac 当前安装后插件可加载,但扫描器返回空(面板无数据)——`scanner.js` 中 `process.platform !== 'win32'` 提前返回。探测/停止层已跨平台就绪,补 POSIX 扫描器即完整可用。

## 结构

```
src/host/          # 宿主侧(node,DSH host 进程内)
  scanner.js       #   进程扫描:PEB 环境块读 DSH_SESSION_ID + 三道服务过滤
  probe.js         #   跨平台探测(端口/HTTP/pid)+ 礼貌停止(SIGTERM→SIGKILL / taskkill)
  registry.js      #   服务登记表 ~/.dsh/gate/process-board/services.json(mkdir 锁 + 原子写)
  index.js         #   路由:state / kill / log / start + 周期扫描
src/client/index.js  # 浏览器侧:侧边栏入口 + 全屏表格面板 + 日志分栏(纯 DOM,零 React)
cordis.patch.yml     # web profile 插件行注册
```

## 工作原理(会话归属双通道)

```
DSH 宿主
  └─ shell 工具(注入 DSH_SESSION_ID=<session-uuid>)
       ├─ 直接子进程 ────────────┐
       └─ Start-Process 分离进程 ─┤ env 继承标记
                                  ▼
              scanner 读每个候选进程的环境块
              (Windows: PEB→ProcessParameters→Environment 分页读取)
              命中 DSH_SESSION_ID → 归属该会话(面板显示会话中文标题)
              未命中但在宿主进程树内 → 归属「宿主进程」组(MCP 子进程等)
```

## License

MIT

Install

dsh plugin --profile web add github:cyanTao/dsh-process-board#befa53958221ebed0a3ffd0083d3c5b1f152c8ea

Profile: web

Source