omdsh-tui
by omdsh-plugins
DeepSeek Harness工作区根目录:TUI界面、配置包和终端UI库。
Workspace root for the DeepSeek Harness interactive terminal: the TUI surface, its profile bundle, and the vendored terminal UI library.
安装
dsh plugin --profile web add github:omdsh-plugins/omdsh-tuiGitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试
安装与环境配置指引、插件开发教程见 DSH 中文社区文档 ↗
安装即在你的机器上以你的权限运行第三方代码——它可读写文件、使用凭据、访问网络,DSH 的工具审批不会为插件代码加沙箱。「检测到 manifest」仅代表发现 dsh.bundle / dsh.plugin 清单,不构成兼容性或安全审查;安装前请审阅源码,不熟悉的插件先在不含密钥的环境试用。
README
English | 中文
DeepSeek Harness 的交互式终端,以可安装的 profile bundle 形式提供。
上游删掉了自己的 TUI 包。这个仓库自己带一个,而且是对着一个已发布的 harness 版本构建的,不是对着它的某个 fork——所以这个终端跟进 harness 新版本,只需要改一个版本号,而不是合并一整个 monorepo。
包
| 包 | 是什么 |
|---|---|
packages/tui |
@omdsh-plugins/omdsh-tui —— 终端表层:对话渲染、编辑器、自动补全、工具卡片、状态行 |
packages/tui-app |
@omdsh-plugins/omdsh-tui-app —— profile bundle:cordis.patch.yml、命令行、会话身份,以及 /resume 的进程接力 |
vendor/tui |
@deepseek-ai/tui —— 以源码形式 vendor 进来的终端 UI 库;出处和本地改动见它自己的 README |
模式
每个会话都由一个 agent preset 组合而成——这套插件组合决定了模型有哪些工具、人设说什么、能看到哪些提示词段落——而 /mode 就是架在 dsh 自带那四个 preset 之上的界面:
| 模式 | Preset id | 模型拿到什么 |
|---|---|---|
| Standard mode | standard |
完整的编码智能体:文件编辑、shell、文件与网页搜索、skill、计划、目标、子智能体、workflow |
| Code mode | code |
Standard 的能力经由 Code Mode SDK 呈现,原本五次调用的序列变成一段 TypeScript 程序 |
| Minimal mode | minimal |
常驻的 bash 和 str_replace_editor,一句话的人设,别的什么都没有 |
| Creator mode | cordis |
Standard 加上自指的 Cordis 工具集和一个写 preset 的 skill,可以让一个智能体替你写出另一个智能体 |
/mode 打开一个选择器;/mode <id> 直接选中一个。已经说过话的会话也可以切。harness 把"只能在空白会话切"这条限制称为"一条产品规则,不是机械规则";而在终端里,敲键盘的人就是会话的主人。所以这个界面接受这个判断,只把唯一真实的后果说清楚:新模式重放不了哪些先前的工具调用。只有正在跑的一轮会挡住切换,因为工具目录在这一轮进行期间必须保持稳定。/mode default <id> 是另一回事:它指定新会话从哪个模式开始,写的是 Web 界面「通用」设置那一行所写的同一个 agent-presets 用户设置。切换一旦提交就会记进日志,所以 /resume 会按这段历史当初产生时的那套组合重建会话。
让这个选择真实成立、而不只是个标签的,是 bundle patch:它关掉了 base 的 host 侧工具行,所以 preset 说移除某个工具,就是真的移除了。这条线画在哪里,见 bundle 的 README;/mode 到底做了什么,见前端那份。
它构建时依赖的 harness 版本
pnpm-workspace.yaml 的 catalog 一次性给每个 harness 包钉死同一个版本。dsh-* 条目跟着这个终端对应的发布线走;cordis 和 schemastery 取的是那个版本自己依赖的稳定版。跟进一个新的 harness 版本,就是挪动 catalog——包的版本号跟着它走——再跑测试。
pnpm run check:harness-pin 证明两件事:catalog 只指向一个版本——一份钉了两个版本的 catalog,会用两半从未一起发布过的东西拼出一个运行时,而 pnpm 会一声不吭地把它装上——以及 packages/ 里的每个包都把那个版本当作自己的版本号。这里的包版本号不是终端自己记的账:它标明这个终端构建时对应哪个 DeepSeek Harness 版本。所以在 catalog 钉着 0.1.0-rc.8 的时候写 0.1.0-rc.9,等于声称一个根本不存在的版本,检查会直接失败。版本号只能跟着 catalog 一起动。
启动横幅读的是 @deepseek-ai/dsh-agent 的 manifest(它是一个 peer 依赖,所以在运行时它就是这个 profile 真正组合出来的那个 harness),然后把结果打印成 DeepSeek Harness v<version>:它和版本号字段说的是同一句话,只是直接读自 harness 本身,而不是本仓库发布的某个 manifest。
安装
需要 PATH 上有一个全局的 dsh——下面每一步都要外调它——外加 Node ^22.19.0 || >=24.0.0 和 pnpm 11.7.0,正如 engines 和 packageManager 所写。macOS、Linux、Windows 的交互式终端全都支持;Windows 走的是 pi-tui 自带的原生控制台 VT 输入处理。
一个 bundle 就是一个声明了 "dsh": { "bundle": { "patch": "./cordis.patch.yml" } } 的 npm 包,profile 会把它作为一层 patch 叠在 dsh-base 上。这里的东西都没有发布,所以 profile 要从检出安装:
pnpm install
pnpm run install:profile # 构建、装进 `omdsh-tui` profile、验证它能组合出来
dsh --profile omdsh-tui
那个脚本就是手动步骤,外加"这几步确实成了"的检查:
pnpm run build
dsh plugin --profile omdsh-tui add "$PWD/packages/tui" "$PWD/packages/tui-app"
dsh --profile omdsh-tui --dump-config # 组合出来的层栈,不启动
两个包都要,不是只要 bundle。 Loader 解析某一行的模块 specifier 时,是从 profile 目录出发的,而 bundle patch 有两行点名 @omdsh-plugins/omdsh-tui。已发布的 bundle 会把前端那个包当作普通依赖一起拉进来;从检出安装做不到这一点,原因有二——pnpm 不会安装 link: 依赖自己的依赖,而且 bundle 是通过 workspace:^ 指向它的,workspace:^ 出了这个工作区就没有任何意义。装它的时候会打印 declares no dsh.bundle — installed as a plain dependency:对一个被 bundle import 的库来说,这正是应有的结果,不是问题。
组合得出来,不等于启动得起来:--dump-config 只读 patch 文件,从不 import 任何模块,所以一棵树 dump 得再完美,启动时仍可能因为某一行点名了 profile 解析不到的包,死于 ERR_MODULE_NOT_FOUND。install:profile 两样都查。
profile 名字随你起(pnpm run install:profile -- --profile <name>);终端里没有任何东西绑死在某一个名字上,因为退出提示、帮助文本、原地进行的 /resume 接力,读的都是本进程启动时 argv 里的那个名字。
omdsh-codemode 需要这个 profile。 它的会话列就是一个跑着 dsh --profile omdsh-tui 的终端。一个装了 Code 模式、却没装这个 profile 的 Web profile,会在那一列里渲染出 dsh: profile "omdsh-tui" does not exist,别的什么都没有。两者是两次独立的安装,装进两个独立的 profile——终端本身永远不进 Web profile,理由见 ## 已知限制。
卸载时点名安装时装进去的那两个包:
dsh plugin --profile omdsh-tui remove @omdsh-plugins/omdsh-tui-app @omdsh-plugins/omdsh-tui
剩下的只是一个没有任何表层的 dsh-base profile,没法拿来启动;rm -rf ~/.dsh/profiles/omdsh-tui 会把 profile 本身也带走。
从内置终端的旧版本升级
omdsh-tui 这个名字是刻意的。在 TUI 还随包发布的年代,tui 属于 harness 安装本身,而升级 dsh 时 ~/.dsh 并不迁移——所以跑过那种版本的机器上,至今都留着一个 ~/.dsh/profiles/tui,里面点名的那个 bundle,当前的 dsh 已经解析不了:
Error: dsh: cannot resolve profile bundle "@deepseek-ai/dsh-tui-app" from the dsh installation or ~/.dsh/profiles/tui; run 'dsh plugin --profile tui install' if its dependencies are not installed.
dsh plugin add 不会清掉那一条。它只调和它作为依赖管理的那些 bundle——这正是 @deepseek-ai/dsh-base 不会被误删的原因——但这也意味着陈旧条目永远不会被重新检查:add 成功了,失败的是下一次启动。错误信息里给的建议也帮不上忙:那个包根本没地方可装。
装在 omdsh-tui 底下就避开了这次撞名。想继续用 tui 这个名字,就把安装脚本指过去——它会丢掉所有已经解析不了的 bundle,并打印丢掉了什么:
pnpm run install:profile -- --profile tui
命令
pnpm install
pnpm run build # tsc 按 project 产出 lib/types,tsdown 打包每个成员
pnpm run install:profile # 构建,然后把 bundle 装进一个 dsh profile 并验证
pnpm run check:harness-pin # catalog 只指向一个 harness 版本,每个包都带着它
pnpm run typecheck # 源码、测试和脚本;vendor 进来的库保留它自己那套宽松开关
pnpm run test # 单元测试
pnpm run test:snapshot # 终端帧重放,与录下来的输出比对(DSH_SNAPSHOT=refresh 重新录制)
pnpm run clean # 删掉每个成员的 lib/(含 vendor 那个)和那些 tsbuildinfo
install:profile 在 -- 后面接受 --profile <name> 和 --skip-build。vendor 进来的那个库是按宽松编译设置持有的上游源码,所以 checks 这个 project 读的是它产出的声明文件,而不是拿本仓库的开关再把它查一遍。
它从哪里来
从 harness monorepo 的一个 fork 里拆出来,在那边它是 packages/tui/tui、packages/bundle/tui-app 和 vendor/tui。设计理由在 docs/ 里:TUI profile 前端,以及底部锚定的表层。docs/tui.zh.md(English)不是决策记录,而是写给读者的那一份——这个表层是什么、ctx.tui 为想要屏幕的插件提供了什么、启动器能控制什么。
有一个函数也跟着过来了,上游并不发布它:resolveHarnessCheckout,就是那段"一路向上找到 harness 检出根目录"的逻辑——harness-source 那个提示词段落要写得诚实就得靠它。它住在 packages/tui-app/src/checkout.ts;哪天某个 harness 版本把它导出了,这份就可以删掉。
已知限制
- 一个 profile 只组合一个表层,而这就是一个。 这个 bundle 的 patch 和
dsh-web-app的 patch 打的是同一批 base 行——system-prompt、tools,还有二十多个——所以同时装了两者的 profile 不会得到两扇前门,只会逐行看"谁最后叠上去算谁"。它得待在自己的 profile 里——这正是它不在本集合 registry 里、install:profile也新建一个 profile 而不是往web里加的原因。TUI profile 是建出来的,不是加进一个正在运行的 Web profile 里的。 - 它需要一个真的终端。 stdin 和 stdout 都必须是 TTY。脚本和 Loader 管道要的是一次性的
@deepseek-ai/dsh-headless;这一个没有地方可画。 - 这里的东西都没有发布。 每一次安装都是检出安装,也就是说
dsh plugin记下的是一条link:,装进去的文件就是这棵工作树——改完记得重新构建,也别指望插件中心报版本,它报的是linked。 - 没有
harness:local/harness:npm开关。 和那些插件仓库不同,这里没有脚本化的办法对着一个 harness 检出构建:要跟进尚未发布的 harness 改动,得手改 catalog 里那些dsh-*行,事后再改回去。 - vendor 进来的那个库是一个归你维护的 fork。
vendor/tui带着上游没有实现的本地改动,所以上游出了新的pi-tui,在这里是一次合并,不是一次版本号升级。
原始 README: https://github.com/omdsh-plugins/omdsh-tui/blob/main/README.zh.md ↗
同类插件
查看全部 →
k8e
k8e.sh — 开源 Agentic AI 沙箱矩阵

hol-guard
开源AI代理防病毒:运行时拦截风险工具、秘密访问、提示注入、恶意软件包、MCP服务器、插件和技能。

anolisa
ANOLISA(Agentic Nexus Operating Layer & Interface System Architecture):具备运行时、安全性、可观测性和 Tokenless 响应压缩能力的 Agentic OS,可降低 Token 使用量与成本。

mobius
首个自我演进的开源 Agent OS:连接你的团队、AI agent、设备与算力

deepseek-harness-desktop
DeepSeek Harness Tauri 桌面版 | Only 5mb installer, zero environment setup. Windows / macOS / Linux.

open-managed-agents
开源Claude管理代理API实现和自托管Claude标签式代理运行时。即插即用;在Cloudflare Workers/Durable Objects或Node.js上运行。Apache 2.0。