DeepSeek Harness Hub
← 返回列表

Zhen-WushuiLingchun/dsh-tui

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

面向 DeepSeek Harness 的交互式终端界面。它把 Harness 已有的…

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/24 · 已提供中文文档
综合分
28.3
GitHub 分
28.3
用户评分
★ Stars
1
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add Zhen-WushuiLingchun/dsh-tui
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/17(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-tui

面向 DeepSeek Harness 的交互式终端界面。它把 Harness 已有的 Agent、模型路由、工具、会话持久化、审批和提问能力放进一个长期存在的 TUI 工作区中:无需启动浏览器,也不另造一套后端。

界面使用 OpenTUI 与 SolidJS 渲染,重点不是做一张“终端海报”,而是让日常工作中的输入框、对话、工具活动、上下文占用和会话恢复始终清楚可见。

dsh-tui 首页:倾斜黑洞开屏、常驻输入框和运行时状态

图中 552k/1.0m 来自 Harness 的 contextPressure 投影。TUI 不写死 1M:容量和占用都以当前模型路由实际报告的数据为准。

它解决什么问题

DeepSeek Harness 已经拥有完整的 Agent 与工具运行时,但纯命令行输出很难同时回答下面这些问题:

- 我现在在哪个目录、哪个会话里?
- 当前使用的模型是什么,上下文还剩多少?
- 模型是在回复、思考,还是运行 Shell / 其他工具?
- 哪条工具指令失败了,完整参数和输出在哪里?
- Agent 正在等审批,还是在等一个选项答案?
- 终端变窄后,关键信息是否仍然看得见?

dsh-tui 提供一个单会话、常驻输入框的终端工作区:

- 模型回复始终以 Markdown 展示,不折叠最终答案。
- Reasoning 与工具活动默认压成一行,可单独展开,也可用 Ctrl+O 全部展开。
- 输入框始终固定在底部;审批或提问到来时,它会切换为 APPROVE / ANSWER 状态。
- 模型、上下文、MCP 和插件数量来自 Harness 运行时,不使用猜测值。
- 会话继续写入标准 $DSH_HOME/sessions,可以在 TUI、Web 或其他 Harness 界面之间复用。
- 80×24 到超宽终端使用同一套响应式布局;空间不足时按优先级减信息,不截断关键字段。

界面概览

1. 首页

空会话显示一张由真彩色半块字符绘制的倾斜黑洞。它有四档完整资源,而不是把一张大图强行裁切:220×60、160×45、100×34 和 80×24 都有对应尺寸。第一条消息出现后,开屏立即让位给对话。

首页下方的三行输入区从上到下分别是:

1. 当前输入状态和辅助操作;
2. 永久存在的输入行;
3. 模式、模型、上下文、MCP 与插件状态。

2. 对话与折叠活动

聊天界面:最终回复常驻,思考和 Shell 活动折叠为状态行

用户消息、模型回复、Reasoning、工具调用和系统消息是不同的语义行。折叠后的活动行仍保留最有用的信息:

- thought:Reasoning 的开头摘要与词数;
- shell:解析后的命令与 running / ok / failed 状态;
- 其他工具:工具名、代表性参数与状态;
- 模型回复:完整 Markdown,不参与折叠。

按 Ctrl+O 后,会展开当前对话中的 Reasoning、Shell 命令、工具参数和捕获输出:

展开后的模型思考和 Shell 输出

TUI 只展示模型适配器真实发出的 reasoning 块。若提供方没有公开 Reasoning,就不会伪造“思考过程”。

3. 会话选择

在有历史会话的目录运行 dsh-tui 时,会先出现当前目录专属的恢复面板:

当前目录的会话选择面板

它只列出创建于当前工作目录的会话。这样可以保持“先 cd 到项目,再继续这个项目的对话”的使用习惯,不会把其他目录的历史混在一起。

4. 窄终端

80×24 下的紧凑布局

80×24 是设计和测试覆盖的紧凑基线。此时仍保留输入框、模型与上下文;MCP、插件、会话 ID、提示项和黑洞尺寸会按可用空间逐级缩减。更窄的终端会继续隐藏低优先级装饰,但不保证拥有完整的视觉层级。

快速开始

环境要求

| 依赖 | 要求 | 原因 |
| --- | --- | --- |
| DeepSeek Harness | dsh 命令可在 PATH 中找到 | dsh-tui 是 Harness profile,不是独立 Agent 后端 |
| Node.js | 26.1 或更高 | OpenTUI 原生渲染依赖实验性的 node:ffi |
| pnpm | 可在 PATH 中找到 | dsh plugin 使用 pnpm 管理 profile 依赖 |
| 终端 | 真实 TTY;建议支持 True Color、Unicode 和鼠标 | 交互输入、半块图像和真彩色状态依赖终端能力 |

Node 26 启用 --experimental-ffi 时会打印一条 ExperimentalWarning,这是当前 OpenTUI 启动的正常提示。

安装到 tui profile

从 GitHub 安装:

~~~sh
dsh plugin --profile tui add github:Zhen-WushuiLingchun/dsh-tui
~~~

建议在正式环境固定提交:

~~~sh
dsh plugin --profile tui add github:Zhen-WushuiLingchun/dsh-tui#
~~~

从本地 checkout 安装:

~~~sh
cd dsh-tui
dsh plugin --profile tui add .
~~~

也可以安装已经打包、包含 lib/ 的 tarball:

~~~sh
dsh plugin --profile tui add ./dsh-tui-0.4.0.tgz
~~~

dsh plugin 会在 profile 不存在时创建 $DSH_HOME/profiles/tui,加入 @deepseek-ai/dsh-base,再把本包声明的 bundle patch 叠加进去。它不会修改 Harness 的 Web 或 headless profile。

Git 安装被 allowBuilds 拦截
Git 依赖需要在安装阶段运行 prepare 生成 lib/。pnpm 10 默认可能阻止依赖执行构建脚本,并在错误中指出 profile 的 pnpm-workspace.yaml。确认源码可信后,在该文件中允许本包:

~~~yaml
allowBuilds:
dsh-tui: true
~~~

然后重新执行安装命令。allowBuilds 是“允许安装时执行代码”的授权;请审查源码并固定提交。若不希望开放安装脚本,可以改用预构建 tarball 或未来发布的 npm 包。

启动方式

推荐使用随包提供的 dsh-tui 启动器,因为它会自动给子进程注入 --experimental-ffi:

~~~sh
dsh-tui
dsh-tui --resume
dsh-tui --list
dsh-tui --help
~~~

把 bundle 安装进 profile 并不会自动把 profile 内的 bin 加进系统 PATH。在源码 checkout 中可以显式建立全局链接:

~~~sh
pnpm link --global
dsh-tui
~~~

如果不想建立全局链接,也可以直接启动 profile。

PowerShell:

~~~powershell
$env:NODE_OPTIONS = '--experimental-ffi'
dsh --profile tui
~~~

Bash / Zsh:

~~~sh
NODE_OPTIONS=--experimental-ffi dsh --profile tui
~~~

dsh-tui 启动器本质上只做两件事:添加 FFI 标志,然后执行 dsh --profile tui 。因此所有模型、凭据、工具和会话配置仍由 Harness 管理。

日常使用

启动参数

| 命令 | 作用 |
| --- | --- |
| dsh-tui | 当前目录有历史会话时打开选择器,否则新建会话 |
| dsh-tui --resume  | 跳过选择器,直接恢复指定会话 |
| dsh-tui --list | 列出持久化会话后退出,不挂载交互界面 |
| dsh-tui --help | 显示本应用参数 |

会话选择器

| 按键 | 作用 |
| --- | --- |
| ↑ / ↓ | 移动选中项,首尾循环 |
| Ctrl+P / Ctrl+N | 上移 / 下移 |
| Enter | 恢复选中会话 |
| n | 新建会话 |
| q / Esc | 退出 |

对话快捷键

| 按键或操作 | 作用 |
| --- | --- |
| Enter | 发送当前输入 |
| Ctrl+O | 展开或折叠全部 Reasoning 与工具活动 |
| 鼠标点击活动行 | 只展开或折叠这一行 |
| PageUp / PageDown | 每次滚动半个视口 |
| 鼠标滚轮 | 滚动对话 |
| Ctrl+D | 结束输入并退出 |
| Ctrl+C | 终止当前 TUI 进程 |

新的流式输出会让视图回到最新消息。输入框始终保留焦点,方向键不会被对话滚动抢走。

斜杠命令

| 命令 | 作用 |
| --- | --- |
| /exit、/quit、/q | 保存并退出 |
| /list、/sessions | 在终端输出持久化会话列表 |
| /new | 新建并切换到一个会话 |
| /resume  | 切换到指定持久化会话 |
| /help、/h | 在对话中显示帮助 |

其他内容都按普通用户消息提交,包括无法识别的斜杠文本。

审批与问题

当工具请求审批时,输入框会变为 APPROVE:

- y / yes:仅允许这一次;
- c / cancel:取消请求;
- 其他输入或空输入:拒绝。

当 Agent 调用 Harness 的 Ask User 能力时,输入框会变为 ANSWER:

- 单选:输入选项编号,例如 2;
- 多选:用空格或逗号分隔,例如 1 3 或 1,3;
- 自由文本题:直接输入文字。

根 Agent 和其拥有的子 Agent 共用这个终端回答者,因此它们的审批和问题都会回到同一个输入框。

如何理解底部状态区

示例:

~~~text
▌  MESSAGE                                               ctrl+o details
▌  › ask anything · /help for commands
▌  chat · deepseek-v4-pro · 55% ctx · 552k/1.0m · ⊙ 2 mcp · ⚙ 47 plugins
~~~

| 字段 | 数据来源 | 行为 |
| --- | --- | --- |
| chat / working… / needs you | TUI 当前阶段 | 请求运行、等待用户时立即变化 |
| 模型名 | agentDefaultModel.currentSelection() | 宽终端显示 provider/model,窄终端显示短名 |
| 上下文 | contextPressure 投影 | 优先 projectedTokens,否则使用 pressureTokens;contextWindow 是分母 |
| MCP 数量 | Loader 中启用的 @deepseek-ai/dsh-mcp-client 实例 | 已知为零时明确显示 0 mcp |
| 插件数量 | Loader 中启用且非分组的条目 | Loader 不可读时省略,不伪造零 |

以 Harness 当前内置的 deepseek-official/deepseek-v4-pro 为例,路由报告 1,000,000 token 上下文,因此会显示 …/1.0m。如果其他模型报告 128K、256K 或没有公开容量,TUI 会分别显示真实容量或 ctx pending,不会把 DeepSeek 的 1M 套到其他模型上。

上下文颜色分段:

- 低于 70%:绿色;
- 70%–89%:琥珀色;
- 90% 及以上:红色;
- 请求尚未产生用量或服务不可用:ctx pending / ctx —。

架构

它在 Harness 中的位置

dsh-tui 是一个外部 bundle layer。它复用 @deepseek-ai/dsh-base,只新增终端入口与终端渲染,不启动浏览器、HTTP Host 或 Web Runtime。

~~~mermaid
flowchart TD
Launcher["dsh-tui 启动器注入 --experimental-ffi"] --> CLI["dsh --profile tui"]
CLI --> Profile["Profile 组合"]
Base["@deepseek-ai/dsh-baseAgent · 模型 · 工具 · 会话"] --> Profile
Bundle["dsh-tui/cordis.patch.ymlstartup + runner"] --> Profile
UserPatch["profile / home / --patch 覆盖层"] --> Profile
Profile --> Startup["tui-startup解析 --resume / --list"]
Startup --> Runner["tui-runner创建或恢复一个 Agent"]
Runner --> Harness["Harness 服务sessions · approvals · questions · projections · loader"]
Harness --> Events["session/event"]
Events --> Fold["foldEvent事件折叠为语义行"]
Fold --> Host["响应式 UiState Host"]
Host --> OpenTUI["SolidJS + OpenTUI真实终端渲染"]
~~~

Profile 的生效顺序由 Harness 管理:bundle 按 dsh.profile.bundles 顺序应用,然后是 profile patch、home 级 patch 和命令行 --patch。后面的层可以覆盖前面的配置。Harness 的 patch 对目标行的 config 是整体替换,不是深度合并;自定义配置时需要写完整的目标配置值。

一条消息如何到达屏幕

~~~mermaid
sequenceDiagram
participant U as 用户
participant T as dsh-tui
participant A as Harness Agent
participant S as Session / Projection
participant V as OpenTUI

U->>T: Enter 提交输入
T->>T: parseCommand
alt 斜杠命令
T->>S: 新建、恢复、列出或退出
else 普通消息
T->>A: createUserMessage + followup
A-->>S: assistant/chunk、tool/call、tool/result...
S-->>T: session/event
T->>T: foldEvent 更新语义行
T->>S: 读取 contextPressure
T->>V: 更新 UiState
V-->>U: 增量重绘终端
end
~~~

TUI 不修改系统提示词之外的请求结构,不给每轮增加额外前缀,也不实现独立 Token 估算。因此它本身不会改变 KV Cache 命中方式;上下文数字由 Harness 的 token-meter 和模型路由负责。

源码分层

| 文件 | 职责 |
| --- | --- |
| bin/dsh-tui.js | 跨 Windows / POSIX 启动 dsh,注入 FFI 标志并透传参数 |
| cordis.patch.yml | 在 dsh-base 之上插入启动参数提供者、Code Runtime 与 TUI Runner |
| src/startup.ts | 用 Commander 解析 --resume、--list 和帮助 |
| src/index.ts | 会话生命周期、输入命令、Agent 提交、审批、问题和 Harness 事件订阅 |
| src/stream.ts | 将持久化会话事件折叠为 user / assistant / thinking / tool / system 行 |
| src/telemetry.ts | 从 projection 与 loader 读取上下文、MCP、插件数量并格式化 |
| src/ui.tsx | SolidJS/OpenTUI 组件、输入框、Markdown、折叠行为和响应式布局 |
| src/hole.ts | 四档内嵌真彩色半块黑洞资源;运行时不依赖外部图片 |
| scripts/preview.mjs | 用真实测试渲染器输出空白、聊天、展开、审批等场景 |

为什么使用 SolidJS 变换

OpenTUI 的 Solid 渲染依赖响应式属性 getter,不能把 TSX 当成普通 React JSX 编译。tsdown.config.ts 使用 Babel:

- babel-preset-solid 以 generate: universal、moduleName: @opentui/solid 编译 TSX;
- 将 solid-js 与 solid-js/store 映射到客户端构建;
- 把 @deepseek-ai/ 标记为运行时外部依赖,由当前 dsh 安装提供。

这样 Git / tarball 安装只构建本包的 lib/.mjs,Harness 核心 API 则始终跟随实际启动它的安装,而不是把另一份 Harness 复制进 profile。

兼容性

Harness 兼容

- 模型:不限制为 DeepSeek 模型。只要模型通过 Harness Adapter 运行,回复、工具和状态都走同一事件流;Reasoning 与上下文容量按 Adapter 是否提供对应数据决定。
- 工具与 Skills:继承 dsh-base 的工具面,包括 Shell、文件、Skills、工作流、目标和子 Agent。TUI 不维护第二份工具注册表。
- MCP:MCP 仍由 Harness profile 配置。TUI 只显示启用实例数量,不私自启动服务器。
- 会话:使用标准 Session 与 SessionPersistence 服务,--resume 不依赖 TUI 私有格式。
- 审批与提问:实现 Harness 的 approval 事件和 userQuestions provider;所有决定仍由 Harness 写入会话。
- 配置覆盖:profile 自己的 cordis.patch.yml、home patch 和 --patch 仍可覆盖 bundle。
终端与平台兼容

| 场景 | 状态 |
| --- | --- |
| Windows PowerShell / Windows Terminal | 已验证;启动器通过 cmd.exe /d /s /c 调用 dsh |
| Linux / macOS | 启动器走标准 dsh 子进程;受 Node 26 与 OpenTUI 对该平台的支持约束 |
| 80×24 | 自动化布局与视觉测试覆盖的紧凑基线 |
| 100×34、160×45、220×60 | 自动化截图与布局测试覆盖 |
| 非 TTY / CI 管道 | --list、--help 可用;交互界面需要真实 TTY |
| 非 True Color 终端 | 可以启动,但终端可能量化黑洞和状态色 |
| 不完整 Unicode 字体 | 半块图形、图标或框线可能显示异常;建议 Cascadia Mono、JetBrains Mono 等 |

已知限制

- 同一时刻只展示一个会话;/new 和 /resume 会切换当前会话,不提供多窗格。
- 根 Agent 与子 Agent 的审批/问题共用同一个终端输入框,没有按子会话拆分的提示路由。
- Reasoning 完全取决于提供方;无法显示提供方没有发送的私有思考。
- OpenTUI 当前要求 Node 26 的实验性 FFI,启动警告暂时无法消除。
- DeepSeek Harness 仍处于快速演进阶段;若 Harness 升级后插件无法挂载,应重新安装本 bundle,使依赖解析和构建产物与新版本对齐。

配置与扩展

安装后的 profile 位于:

~~~text
$DSH_HOME/profiles/tui/
├── package.json
├── cordis.yml
├── cordis.patch.yml
└── node_modules/
~~~

如果没有设置 DSH_HOME,Harness 默认使用 ~/.dsh。应把个人覆盖写入 profile 自己的 cordis.patch.yml,不要直接编辑 node_modules/dsh-tui/cordis.patch.yml;后者在更新包时会被替换。

本 bundle 默认:

- 复用 @deepseek-ai/dsh-base;
- 使用 coding persona;
- 保留 Harness Code Mode 的 DSH_TOOLS_MODE 开关;
- 插入 Code Runtime、tui-startup 和 tui-runner;
- 关闭共享 HMR 行;
- 不插入 Web Host、HTTP Server 或浏览器插件。

开发与验证

~~~sh
pnpm install
pnpm run prepare
pnpm test
~~~

测试覆盖:

- 参数解析与启动选择器;
- Harness 会话事件折叠;
- 上下文、插件与 MCP 遥测;
- 80 / 100 / 160 / 220 列布局;
- Markdown、Reasoning、工具折叠、审批与问题;
- 首页黑洞在各档尺寸下的颜色、暗区和延伸结构;
- 有消息后首页图消失、输入框持续存在。

输出实际终端字符帧:

~~~sh
pnpm preview
pnpm preview chat
pnpm preview expanded
pnpm preview picker
pnpm preview approval
pnpm preview question
pnpm preview working
~~~

prepare 在独立 checkout 中可能提示无法解析 @deepseek-ai/dsh-。这些包被有意保留为运行时外部依赖,由 Harness 的 profile module fallback 提供;只要构建完成且在实际 dsh profile 中启动成功,这些 warning 不代表产物缺失。

发布前建议至少执行:

~~~sh
pnpm run prepare
pnpm test
npm pack --dry-run --json
~~~

并在 80×24、100×34 与一个宽终端中分别检查空会话、普通聊天和 Ctrl+O 展开状态。

常见问题

dsh-tui:command not found

Bundle 已经安装进 profile,但启动器不一定在系统 PATH。可在 checkout 中执行 pnpm link --global,或者使用带 NODE_OPTIONS=--experimental-ffi 的 dsh --profile tui。

Cannot find module node:ffi

Node 版本过低,或者直接运行 dsh --profile tui 时没有添加 --experimental-ffi。确认:

~~~sh
node --version
~~~

版本应为 26.1 或更高。优先使用 dsh-tui 启动器。

为什么显示 ctx pending

新会话在第一次模型请求前没有用量样本,这是正常状态。若完成请求后仍然 pending,检查 profile 是否挂载 token-meter / session projection,以及当前模型路由是否报告 contextWindow。

为什么没有 thought 行

当前模型适配器没有发出 reasoning 块。TUI 不会根据最终回答反推或编造思考内容。

黑洞颜色不对或字符错位

确认终端启用了 True Color,并使用等宽、包含 ▀ / ▝ 等 Unicode 字形的字体。终端强制 16 色、字体 fallback 或非 1:2 字符比例都会改变图像观感。

更新 Harness 后启动失败

先确认当前 dsh 版本和 profile 实际安装的 bundle,再重新解析:

~~~sh
dsh plugin --profile tui update dsh-tui
~~~

如果使用 Git 提交固定版本,改为新的已验证提交后重新执行 add。不要通过复制另一份 @deepseek-ai/ 到本包来绕过模块错误,这会造成同一进程中存在两套 Harness 服务类型。

安全说明

- Git 安装的 prepare 会执行本仓库代码;仅对可信来源启用 allowBuilds。
- MCP 服务器是 profile 配置的外部进程,可能在 Agent 沙箱之外运行;启用前应审查命令与权限。
- TUI 的批准输入 y 只产生 allowed-once,不会自行创建永久授权。
- API Key、模型端点和凭据继续由 Harness 管理,本包不读取或保存独立凭据文件。

License
MIT

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群