READMESource: main@a424f1da
DSH-Terminal
VSCode 风格的 终端模拟器 + 文件管理器 动态 Cordis 插件,运行在 DeepSeek Harness(DSH)WebUI 中:在宿主机(设备端)启动真实 PTY,投射到浏览器页面,让你边和 Harness 对话边用本地终端。
MIT License · 零运行时依赖(不使用 xterm.js,ANSI 引擎为纯 JS 自研)
功能
终端
- 真实 PTY(DSH
subprocess.spawnTerminal/ node-pty),自动探测用户登录 shell($SHELL,bash 兜底),不写死 bash - 自研 ANSI/VT100 渲染引擎:SGR 16/256/truecolor、光标寻址、滚动区域、备用屏幕缓冲、DA/DSR/CPR 应答、括号粘贴、光标显隐、宽字符(CJK)对齐、虚拟化渲染
- 多会话标签(
+新建 /×关闭 / 状态点),页面刷新后会话自动恢复 - PTY 尺寸跟随面板(原生
resize+ 实测字符宽度),面板可拖动调高 - 键盘:Ctrl+C 中断(有选区时复制)、完整 Ctrl 映射(tmux 前缀 Ctrl+B、nano 退出 Ctrl+X 等)、粘贴、中文输入法
- 注入
TERM=xterm-256color(绕开 node-pty 的dumb覆盖)——tmux/nano/htop/clear/ 彩色输出均可工作
文件管理器
- 工作区目录树(懒加载展开)、面包屑导航、文本预览(二进制/超大文件拦截)、「在终端中打开」(自动
cd)
主题
- 面板全部使用 DSH 主题令牌(
--dsw-alias-*),明暗主题自动跟随;ANSI 调色板按colorScheme切换 - 无衬线等宽字体栈(JetBrains Mono / Fira Code / Cascadia Code / Noto Sans Mono / DejaVu Sans Mono…)
架构
┌─ Host(DSH Node 进程)──────────────────────────────┐
│ subprocess.spawnTerminal ──→ 真实 PTY(bash/zsh/fish)│
│ 输出按块缓存(512KB) · term.* / files.* / state RPC │
└──────────────▲──────────────────────────────────────┘
│ host.call(JSON RPC,66ms 增量轮询)
┌──────────────┴──────────────────────────────────────┐
│ Client(浏览器) │
│ ANSI 屏幕模型 · 虚拟化渲染 · 输入捕获 · 文件树 │
│ 插槽:conversation.input.left(>_ 开关) │
│ conversation.input.dock(底部面板) │
└─────────────────────────────────────────────────────┘
- 会话隔离:插件的运行实例按 DSH 会话隔离,每个会话拥有独立的 PTY 集合;插件停止/更新时
ctx.effect自动终止全部 PTY。 - RPC 协议(全部为无损 JSON):
| 方法 | 方向 | 说明 |
|---|---|---|
state |
C→H | 工作区根目录 |
term.list |
C→H | 会话快照列表(恢复用) |
term.spawn |
C→H | 新建 PTY(cols/rows/cwd) |
term.resize |
C→H | 原生 PTY resize(handle.terminal.resize 后门,带特性探测) |
term.write |
C→H | 原始 UTF-8 输入 |
term.poll |
C→H | 增量输出(偏移量续读) |
term.signal / term.kill |
C→H | 前台进程组信号 / 终止会话 |
files.list / files.read |
C→H | 目录列表 / 文本预览(1MB 上限,256KB 切片) |
仓库结构
├── src/
│ ├── host.js # Host 端源码(PTY 会话管理 + RPC)
│ └── client.js # Client 端源码(ANSI 引擎 + UI + 插槽注册)
├── scripts/
│ └── build-payload.js # 语法自检 + 生成 cordis_define 载荷
├── dist/ # 可直接粘贴部署的 JSON 载荷(由脚本生成)
│ ├── host.json
│ ├── client.json
│ └── define.json
├── BOOTSTRAP.md # 在任意 DSH 实例中部署的完整教程
├── LICENSE # MIT
└── README.md
动态插件没有「导入」通道:部署必须通过 DSH Agent 的
cordis_define工具以内联字符串提交,因此dist/提供 JSON 转义、1500 字符折行的粘贴即用载荷(避免手工转义 ~60KB 代码出错)。
快速开始(本机)
- 让 DSH Agent 按
BOOTSTRAP.md的步骤调用cordis_define(载荷取自dist/)。 cordis_run→ 在 Run 卡片上批准(单勾=本次版本,双勾=后续更新免审批)。- 刷新页面 → 输入框左侧出现
>_按钮 → 点击打开面板。 cordis_inspect_self(<pluginId>)检查宿主/客户端诊断。
改代码后更新:编辑 src/ → node scripts/build-payload.js → cordis_define(kind: existing + 原 pluginId,得到新 packageId)→ cordis_run(mode: update)。
兼容性
| 能力 | 状态 |
|---|---|
| bash / zsh / fish 交互 | ✅ |
彩色输出、clear |
✅ |
tmux(含 Ctrl+B 前缀、状态栏滚动区域) |
✅ |
nano(含 Ctrl+X 退出) |
✅ |
htop(备用屏幕缓冲) |
✅(无鼠标支持) |
vim / less |
✅ 基本可用(无鼠标/剪贴板增强) |
| 鼠标事件(X10/SGR) | ❌ 未实现 |
| XTGETTCAP 终端能力探测 | ❌ 未实现(tmux 容忍) |
| 终端内拖拽选取(自定义选区高亮) | ❌ 用原生 DOM 选区 + 右键复制代替 |
已知限制
- 输出经 66ms 轮询传输,非 WebSocket 推送(DSH 插件 RPC 只有 Client→Host 请求-响应通道)。
- 宿主端运行于 Node vm 沙箱,无法
require任意模块;PTY 能力以 DSH 服务为准。 term.resize依赖handle.terminal这一私有实现细节(dsh-subprocess-local的 node-pty 对象),后端更换时会优雅降级为固定尺寸。
版本历史
- pkg-1:初版(pid 字段缺失 + DockPanel hooks 顺序错误)。
- pkg-2:修复上述两处。
- pkg-3:修复输出覆盖当前行(lf/wrap 光标推进)、clear 无效(清滚动缓冲 + contentEnd 锚定滚动)、原生 PTY resize、DSH 主题令牌换肤。
- pkg-4:默认 shell 探测、注入 TERM 修复 tmux/clear、TUI 支持(备用屏幕/滚动区域/查询应答/括号粘贴)、无衬线等宽字体 + 实测字符宽度。
- pkg-5(仓库基线):屏幕恒为
rows行(修复 nano/tmux/htop 单行渲染)、Ctrl 映射补全、IME 输入兜底、空会话保留「+ 新建」。
License
MIT © 2025 lanshuye
No comments yet. Be the first to write one.