DeepSeek Harness Hub
← 返回列表

rayafriandion/dsh-oc-tui

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
✓ 可直接安装

DeepSeek Harness 的终端 UI —— 一个受 opencode 启发的聊天客户端,作为 profile…

自动检查通过:npm 包已发布且 engines 声明满足基线(声明 Node >=22);该结论来自程序自动检查,未经人工实机验证。 · 最近上游提交 2026/9/11 · 已提供中文文档

An opencode-inspired terminal UI (TUI) for DeepSeek Harness, shipped as a dsh profile app plugin. | DeepSeek Harness 的终端界面(TUI),受 opencode 启发,以 dsh profile 应用插件形式启动。

综合分
36.4
GitHub 分
36.4
用户评分
★ Stars
7
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add dsh-oc-tui
npm 包 dsh-oc-tui 已校验归属本仓库,走 npm 安装最省事
数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查✓ 自动检查通过

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

npm 包dsh-oc-tui @ 0.1.3
Node 引擎要求 >=22 · 基线 Node 22.19 满足
dsh CLI 依赖未声明 dsh 版本约束
入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/18 09:27:33

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-agent-loop@deepseek-ai/dsh-agent-presets@deepseek-ai/dsh-commands@deepseek-ai/dsh-cmdline@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-session-persistence@deepseek-ai/dsh-user-approval@deepseek-ai/dsh-user-questions@deepseek-ai/schemastery
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-oc-tui

DeepSeek Harness 的终端 UI —— 一个受 opencode 启发的聊天客户端,作为 profile 应用插件在 dsh 进程内启动。

npm latest
awesome-dsh-plugin
License: LGPL-3.0-or-later
Node

dsh-oc-tui 在终端中渲染 harness 的持久事件流——流式回复、工具卡片、待办列表、思考块——并将你输入的内容路由回 agent。模型路由、工具执行、审批、命令、持久会话和凭据仍由 DSH 负责;本包负责终端输入和呈现。

已发布到 npm,包名为 dsh-oc-tui,并收录于 awesome-dsh-plugin 市场。

中文文档:docs/用户手册.md

目录

- 功能特性
- 环境要求
- 安装
- 快速开始
- 使用方法
- 快捷键
- 斜杠命令
- 交互式提示
- 思考强度
- 会话统计与上下文计量
- 设置
- 应用内更新
- 工作原理
- 开发
- 故障排查
- 已知限制
- 布局
- 许可证

功能特性

| | |
| --- | --- |
| 持久会话 | 创建、恢复、列出和删除会话;对话记录从持久化的事件日志重建,因此恢复的会话与你离开时完全一致。 |
| 实时流式输出 | 助手文本和推理逐 token 流式输出;思考内容渲染在独立的可折叠框中,流式输出期间保持折叠。 |
| 工具活动 | 工具卡片带有一行摘要(read src/app.ts、run npm test),运行时显示流动的加载指示器,结果以 markdown 渲染。 |
| 交互式提问 | 模型可以暂停并向你提问——选项列表、多选、自由文本,以及可滚动的计划审阅——全部内联在终端中。参见交互式提示。 |
| 内联审批 | approval/request 提示可直接用 y / n 回答,无需离开 UI。 |
| 会话统计 | 输入框上方的一条统计栏——轮次/步骤、LLM 与工具墙钟时间、平均 TTFT、解码吞吐量、缓存命中率,以及计费的输入/输出 token 数——由持久化事件汇总而成。参见会话统计与上下文计量器。 |
| 统计窗口 | 点击统计栏或上下文计量器,或输入 /stats,查看完整的会话统计与 token 使用明细。 |
| 上下文计量器 | 实时上下文占用情况(ctx ▓▓░░ 32K/128K 25%),并在同一窗口中显示系统/工具/消息的构成。 |
| 思考强度 | Tab 循环切换当前模型的真实推理级别;Ctrl+E 打开滑块。该级别按请求应用并持久化。 |
| 共享设置 | 与 Web UI 使用相同的主机设置命名空间——通用、会话、各提供方的模型配置、凭据——持久化到 $DSH_HOME/settings.yaml。 |
| 应用内更新 | 在 TUI 内检测并切换 @deepseek-ai/dsh 和 dsh-oc-tui 的版本,并支持 Windows 安全的延迟安装。 |
| 零依赖终端引擎 | 原始模式、备用屏幕、差异单元格缓冲区、真彩色 ANSI、CJK 感知宽度、SGR + 传统 X10 鼠标解码,以及 IME 光标锚定。 |

要求

| | |
| --- | --- |
| Node.js | >= 22 |
| dsh CLI | @deepseek-ai/dsh——例如 npm install -g @deepseek-ai/dsh |
| pnpm | 位于 PATH 中;dsh plugin 会转发给它 |
| 终端 | 交互式终端(Windows Terminal / ConPTY、iTerm2、GNOME Terminal 等) |
| 模型路由 | $DSH_HOME/settings.yaml + $DSH_HOME/.credentials.yaml 中可用的路由(与 Web GUI 使用相同的配置) |

dsh --version
pnpm --version

兼容性。 已针对 dsh 0.1.2-rc.1(以及 0.1.1-rc.2)验证。DSH 在 0.1.2 中重命名了部分会话 API——Session.events 变为 snapshotEvents()——本插件会读取主机提供的任一访问器,因此一个构建版本可同时服务于两条版本线。

安装

从 npm 安装

该包以 dsh-oc-tui 之名发布在 npm 上。将其安装到 tui 配置文件中:

dsh plugin --profile tui add -w dsh-oc-tui

或者全局安装启动器——这会将 dsh-oc-tui 命令放入 PATH,随后它会启动 dsh --profile tui:

npm install -g dsh-oc-tui

版本通道

npm 包和 awesome-dsh-plugin 市场条目均只发布稳定版本——预发布版本从不发布到这两处。因此 npm install 会给你最新的稳定版本,而非候选发布版本。

本 README 描述的是当前源码树,它可能领先于已发布的版本——此处记录的功能只有在对应版本发布到 npm 后,才保证存在于稳定构建中。

要运行预发布版本,或本仓库中尚未发布的成果,请从源码显式安装:

sh
npm pack                                   # -> dsh-oc-tui-.tgz
dsh plugin --profile tui add -w ./dsh-oc-tui-.tgz

一键安装脚本

仓库提供了安装脚本,会检查 Node >= 22、确保 pnpm 存在、将插件安装到 tui profile,并且还可以将 dsh-oc-tui 启动器添加到全局。
sh
Linux / macOS
curl -fsSL https://raw.githubusercontent.com/rayafriandion/dsh-oc-tui/main/install.sh | bash
powershell
Windows (PowerShell)
powershell -ExecutionPolicy Bypass -Command "iwr https://raw.githubusercontent.com/rayafriandion/dsh-oc-tui/main/install.ps1 -OutFile install.ps1; & .\install.ps1"

也可以从本地检出目录运行 ./install.sh / .\install.ps1,并加上 --launcher / -Launcher 以同时将 dsh-oc-tui 命令加入 PATH。其他参数:--local(-Local)安装当前检出目录,--source (-Source )使用自定义源,--profile (-Profile )指定其他 profile。

从检出目录或 tarball 安装
sh
npm pack                                             # -> dsh-oc-tui-.tgz
dsh plugin --profile tui add -w ./dsh-oc-tui-.tgz

dsh plugin 在转发给 pnpm 之前,会将相对路径锚定到你调用它时所在的目录。

为什么需要 -w

profile 目录声明自身为 pnpm workspace 根目录(pnpm-workspace.yaml → packages: [.]),因此 pnpm 会以 ERR_PNPM_ADDING_TO_ROOT 拒绝裸 add。-w 让依赖落到 profile 自己的 manifest 中——而这正是它本来的身份。随后 dsh plugin 会根据已安装的内容来协调 dsh.profile.bundles。

安装做了什么

1. dsh plugin 在首次使用时初始化 $DSH_HOME/profiles/tui(@deepseek-ai/dsh-base 加上一个空的用户 patch 层)。
2. pnpm 将 dsh-oc-tui 安装到该 profile 的 node_modules 中。
3. 由于该包声明了 dsh.bundle.patch,dsh 会将 dsh-oc-tui 追加到 dsh.profile.bundles。
4. dsh --profile tui 会组合基础层、此 bundle 的行以及你自己的 patch——无需手动编辑。

无需启动即可验证:
sh
dsh --profile tui --dump-config

该 dump 会显示一个 # == dsh-oc-tui 层,其中包含 tui-startup、tui-app、agent-presets 名单行以及 tool-ask-user 行。

快速开始
sh
dsh --profile tui                        # 标题界面;你的第一条消息会创建一个会话
dsh --profile tui --resume    # 恢复一个已持久化的会话
dsh --profile tui --model       # 新会话的默认模型
dsh --profile tui --provider      # 默认 provider 路由
dsh --profile tui --no-sidebar           # 启动时不显示会话侧栏
dsh --profile tui --help                 # TUI 自身的参数

原版启动器仅将 web 和 plugin 硬编码为裸子命令,因此 --profile tui 才是预期的形式。想要字面上的 dsh tui?添加一个 shell 别名:
powershell
function tui { dsh --profile tui @args }   # PowerShell $PROFILE
bat
doskey tui=dsh --profile tui $*            :: CMD

便捷启动器

该软件包还附带一个 dsh-oc-tui 二进制文件,它等同于 dsh --profile tui,但会先检查该配置文件是否实际安装了插件,若未安装则打印一次性安装命令。
sh
dsh-oc-tui                 # 启动 tui 配置文件
dsh-oc-tui --profile mytui # 启动其他配置文件
dsh-oc-tui --help          # 启动器帮助
dsh-oc-tui --version       # 启动器版本

它优先使用 PATH 中的 dsh,若不存在则回退到 npx --yes @deepseek-ai/dsh。使用 npm install -g dsh-oc-tui 安装。

| 环境变量 | 作用 |
| --- | --- |
| DSH_TUI_PROFILE | 当缺少 --profile 时的默认配置文件(默认为 tui)。 |
| DSH_TUI_SKIP_CHECK | 设为 1 以跳过配置文件预检(高级安装)。 |

用法

快捷键

| 按键 | 操作 |
| --- | --- |
| Enter | 发送消息。 |
| Ctrl+Enter / Shift+Enter / Alt+Enter | 插入换行。 |
| Ctrl+C | 清空非空提示,取消正在运行的回合,或在空闲时按两次退出。 |
| Ctrl+P | 打开设置。 |
| Ctrl+E | 切换编辑器下方的思考强度滑块。 |
| Tab | 会话页面:循环切换思考强度。设置页面:切换左侧菜单。 |
| Ctrl+N | 新建会话。 |
| Ctrl+D | 在设置 → 管理会话中:删除聚焦的会话(按两次确认)。 |
| Ctrl+L | 清空对话记录视图。 |
| Up / Down | 在多行提示中移动光标;在第一行/最后一行时,浏览输入历史。 |
| Left / Right | 在输入框内移动光标。 |
| PgUp / PgDn | 滚动对话记录。 |
| Esc | 关闭会话统计窗口、思考滑块或帮助;取消审批;取消正在运行的回合;清空正在输入的提示。 |
| Esc Esc | 空闲且提示为空时:打开回退选择器。 |
| y / n | 回答内联审批提示。 |

鼠标。 滚轮滚动对话记录(或设置窗口打开时滚动设置窗口)。按住左键并拖过对话记录以选择文本,然后按右键复制所选内容。

斜杠命令

内置:/help /settings /new /resume  /model  /provider  /rewind /stats /clear /cancel /quit(/exit 也可用)。
回退。 Esc Esc(或 /rewind)会列出当前活动会话的提示词。恢复对话会从所选提示词之前的事件分叉出一个新会话——父会话在磁盘上保持原样,与 harness 自带的 session/fork 完全一致——选择器会落在最近的提示词上,因此按两次 Enter 即可回退最后一轮。/rewind  [conversation|code|both] 无需选择器即可执行。分叉以一个空收件箱开始:在某轮之前进行剪切,也会剪掉该轮所执行的收件箱声明,因此父会话中排队的任何内容——包括你回退掉的那个提示词——都不会再次投递;它会留在父会话的日志中,当存在此类内容时,结果行会显示 dropped N inherited pending input。恢复文件是尽力而为且有边界的:它需要一个 git 工作树(在其他任何地方,回退会报告 files not restored (not a git worktree) 并且不做任何更改),它会从 HEAD 重写已跟踪文件而不触碰索引,并且只有当转录记录中对该路径的首次写入发生在回退点或之后时,它才会删除未跟踪文件。它覆盖或删除的所有内容都会先复制到 $DSH_HOME/rewind-backups///,结果行会指明该目录。由于日志不存储文件内容,已跟踪文件会回到其最后一次提交的状态,而不是回退点时的确切状态。

Harness 命令——/compact、/goal、/plan、……——会被转发到 ctx.commands 并在不进行模型回合的情况下运行。它们需要一个活动会话:在标题屏幕上,TUI 会回答 /: start a session first,而不是静默丢弃该命令。

/stats 是 TUI 自己的命令:它切换会话统计窗口,并且与 harness 命令一样,需要一个活动会话。

交互式提示

批准。 当工具需要权限时,输入区会显示 Approval ·  · y allow / n deny。y 允许一次,n 拒绝,Esc 取消。该插件还会遵循生效的权限预设,因此自动批准的预设根本不会提示。

问题。 模型可以通过 ask_user_question 工具直接向你提问。该工具由此 bundle 的 tool-ask-user 行声明——dsh-base 挂载了 user-questions 服务但没有挂载该工具,而 TUI 会话是从 base 而非 agent 预设组合而成——它通过一个模态框来回答:

| 按键 | 操作 |
| --- | --- |
| Up / Down | 在选项之间移动(循环)。 |
| Space | 切换高亮选项(多选)或选中它(单选)。 |
| Enter | 继续:单选会被选中并前进;在自由文本行上会开始编辑;在多选中会确认已切换的集合。 |
| 任意可打印按键 | 跳转到自由文本行并开始输入。 |
| PgUp / PgDn、滚轮 | 滚动较长的计划或详情窗格。 |
| Esc | 推迟:拒绝在此回答(编辑时按 Esc 会返回选项)。 |
| Ctrl+C | 仍然会取消正在运行的回合;待处理的问题会被撤回。 |

问题一次只暂存一个,与 Web UI 输入框暂存问题的方式完全一致,答案编码也相同:自由文本答案会替换单选问题的选项,而对于多选问题,则会与选项一同提交。

带有 plan-review 意图的问题——即 exit_plan_mode 所发送的内容——会在 Approve / Keep planning 上方以可滚动窗格的形式渲染计划 markdown。回答 Approve 会退出计划模式,模型继续执行;其他任何回答都会继续规划。

推迟是刻意为之,而非取消:在没有其他回答者的情况下,该工具会报告 no user-questions answerer accepted the request,这不会被误认为是人类的选择。

思考强度

有效级别以裸级别名称的形式显示在输入框右上角的边框上,与 provider · model 标签呈对角相对。

- 在会话页面上按 Tab 会循环切换当前模型的各个级别(从最强到最弱循环);Shift+Tab 则反向切换。
- Ctrl+E 会在输入框下方打开一个滑块:按 Tab 或 ←/→ 进行调整并持久化,按 Esc 或 Ctrl+E 关闭。
- 级别来自提供商适配器(ctx.llm.resolveModelInfo),因此布尔型思考模型只显示其两端,DeepSeek 的 Off/High/Max 显示这三个级别,而全范围模型会显示所有公布的级别——绝不会是一刀切的 none → max 刻度。

该选择通过 agent/request 瀑布流应用于会话的请求,并存储在 agent-default-model.reasoningEffort 中。

会话统计与上下文计量器

输入框上方的那一行是会话统计条,相当于 Web 聊天统计行的 TUI 版本:相同的数字、相同的顺序,以 │ 分隔:

▤ 1 turn · 2 steps│LLM 1.3s · tools 1.2s│TTFT avg 400ms · 20.0 tok/s│cache 55%│in 110 · out 30

- turns / steps 统计的是已关闭的步骤(step/end),因此失败、取消和达到最大 token 数的步骤也会计入。LLM 是 step/start → 组装完成的回复;tools 配对的是 tool/call → tool/result。
- TTFT avg 是每个步骤的首 token 平均时间;tok/s 是解码吞吐量(首 token → 组装完成的回复,基于所报告的输出 token 数)。
- cache 是提示侧缓存命中占比(缓存读取量占全部计费输入的比例);in / out 是会话的计费输入和输出 token 数。
- 窄终端会整体丢弃末尾的分组,并用 │… 标记省略,而不是把一个数字截成两半;窗口始终携带完整的一组数据。
- 没有已关闭步骤且没有计费 token 的会话会完全隐藏该统计条,并把这一行还给对话记录。
整条状态栏都是点击目标。点击它——或状态行右端的上下文计量条(ctx ▓▓░░ 32K/128K 25%),或输入 /stats——会打开 会话统计窗口;再次点击、点击别处,或按 Esc 即可关闭。该窗口将同一行拆分为带标签的多行(usage / duration / speed / tokens / cache),并添加上下文占用读数及其启发式构成——系统提示词、工具和消息——与 Web UI 的 ContextMeter 对话框一致。

数据来自与 Web UI 相同的来源,优先使用投影,并以插件自身的折叠作为回退:tokenUsage、contextPressure 和 contextBreakdown 由 dsh-base 的 token-meter 行挂载,而 sessionStats 仅由 web 应用包挂载——因此 TUI 按相同规则折叠持久化的 step / chunk / message / tool 事件。缺失的投影仅对该项数据回退,而无人能提供的数据则保持隐藏,而不是打印为零。

设置

Ctrl+P 在与 Web UI 相同的主机设置命名空间上打开设置菜单,通过 ctx.settings 持久化到 $DSH_HOME/settings.yaml。左侧菜单将其分为三个标签页(按 Tab 或点击切换):

- Main — 常规(忙碌时 Enter 行为、默认 agent 预设、权限预设)、会话(新建会话、管理会话)、系统(provider API 提示、更新管理器快捷方式、设置文件路径)。
- Model — 默认 provider/model/reasoning 选择,然后每个 provider 一个分组,包含其 URL、API 密钥和模型列表。在 Models 上按 Enter 会获取 provider 公布的目录(ctx.llm.discoverModels)并打开一个复选框窗口;在列出的模型上按 Enter 会将其设为默认路由。
- Update — 参见应用内更新。

仅列出你实际添加过的 provider(存在于你的用户设置层中);从未添加过的 provider 保持隐藏。默认 agent 预设来自配置文件挂载的名单(随附预设加上你在 $DSH_HOME/.agent-presets 下编写的任何预设)——注意,TUI 会话会从 base 进行进程级组合,因此存储的默认值适用于从预设创建会话的场景。仅限 Web UI 的选项(ui-theme 外观、locale)不会显示,因为它们在 TUI 中无效。

应用内更新

Ctrl+P → Update 显示 @deepseek-ai/dsh 和 dsh-oc-tui 的已安装版本、最新的 npm dist-tag,以及一行仅针对 stable 发布的状态:

- Update available → x.y.z — 存在更新的 stable 发布。
- Up to date — 无需操作。
- No stable release — pick from Versions — 注册表尚无 stable 发布;请手动选择一个。
- Install damaged — reinstall below — 全局 dsh 树处于新旧混合状态;请重新安装。
在包的 Versions 行上按 Enter 会打开完整的注册表列表(最新的在前,[latest]/[next]/其他标签和 (installed) 以颜色区分),你可以从中选择任意版本——包括预发布版本——经 y/n 确认后通过 npm/dsh plugin 安装。Check now 会重新读取注册表;Startup check 切换启动时的静默稳定版检查。安装会在后台运行,绝不阻塞 UI,并且需要重启才能生效。

Windows:为什么 dsh 安装会被推迟到退出时

在 Windows 上,当任何 dsh 进程正在运行时更新 dsh 可能会静默损坏全局安装:npm 会在正在运行的进程仍持有内存映射的原生 DLL 时替换目录,仍然以 0 退出,而由此产生的旧/新混合目录树将无法启动。更新器通过三层防护来防止这种情况:

1. dsh 安装会被推迟到 TUI 退出时——一个分离的辅助进程会等待 TUI 关闭,运行安装,并将结果记录到 $DSH_HOME/tui-dsh-install.json,Update 页面会在下次访问时验证该文件。
2. 每次直接安装后都会将磁盘上的版本与请求的目标版本进行比较,因此静默损坏会以 install corrupt 提示的形式浮现,并附带修复说明。
3. 已经损坏的安装会在 Status 行中被标记,而不是被报告为虚假的成功。

macOS/Linux 没有 DLL 锁,但当其他 dsh 进程正在运行时会拒绝安装。

工作原理

- 该插件是一个由 tui profile 加载的 Cordis 函数插件。lib/startup.js 解析应用的标志并提供 tuiStartup 服务;lib/index.js 拥有 UI 循环。
- lib/term.js 是一个零依赖的终端引擎:原始模式、备用屏幕、差异单元格缓冲区,以及一个按键解码器(真彩色 ANSI、感知 CJK 的宽度)。它将隐藏的终端光标停放在输入插入符处,以便操作系统 IME 将其组合窗口锚定在编辑器中,并且它同时理解 SGR 和旧式 X10 鼠标编码,因此滚轮和点击字节绝不会泄漏到输入文本中。
- lib/ui.js 是响应式视图模型和渲染器(DeepSeek 蓝白主题、会话栏、转录、多行编辑器、命令建议、遥测页脚)。转录行按块缓存,每帧只物化可见窗口,流式绘制会被合并,实时块以短节流重新渲染——因此随着历史增长,渲染成本保持有界。Thinking 会折叠以保持转录可读,正在运行的工具和 thinking 块会以流动的旋转指示器进行动画显示。
- lib/metrics.js 将持久的 step/chunk/message 事件折叠为 token、TTFT、吞吐量和缓存命中指标。
- lib/interrupt.js 拥有 stdin 和 SIGINT 使用的 clear/cancel/double-exit 状态机。
- lib/markdown.js 将模型输出(标题、列表、引用、代码、行内 span)渲染为带样式的行。
- lib/updates.js 将 Update 标签页的所有 npm/pnpm 交互隔离开来——注册表查询、无依赖的 semver 比较、dsh 安装检测以及安装操作——全部通过 child_process.spawn 完成,绝不使用 spawnSync。
- Agent 通过 ctx.agents 创建和恢复,transcript 从会话的持久日志重建,并由 session/event(包括 assistant/chunk)实时供给,模型默认值来自 ctx.agentDefaultModel,审批则以内联方式应答 approval/request 瀑布流。
- ask_user_question 通过 user-questions/request 瀑布流应答:这是一个作用域化的 Cordis 瀑布流,其中模态框要么返回答案,要么通过 next() 委托。被中止的请求会 reject,因此服务会报告自己的 ASK_ABORTED;发往其他 agent 的请求则原样委托。

开发
sh
npm run check   # node --check over lib/, bin/
npm test        # standalone smoke tests (no dsh needed)

安装即构建,所以编辑 → 构建 → 安装。 profile 中包含的是插件的压缩包副本,而 profile 的 HMR 根目录是 profile 目录,不是插件目录——在重新打包并重新安装之前,编辑此检出不会产生任何变化:
sh
npm pack                                        # -> dsh-oc-tui-.tgz
dsh plugin --profile tui remove -w dsh-oc-tui   # detach the old copy FIRST
Remove-Item .\*.tgz                             # then drop the stale tarball
npm pack
dsh plugin --profile tui add -w .\dsh-oc-tui-.tgz

先分离再删除:pnpm 在添加时会解析 profile 现有的 file: 依赖,因此指向已删除压缩包的依赖会以 ENOENT 中止整个安装。

验证替换确实生效——版本字符串证明不了任何东西:
powershell
foreach ($rel in @('lib\index.js','lib\ui.js','lib\util.js','lib\term.js','lib\metrics.js',
'lib\interrupt.js','lib\web-settings.js','lib\updates.js','lib\markdown.js',
'lib\startup.js','bin\dsh-oc-tui.js','cordis.patch.yml')) {
$a = (Get-FileHash ".\$rel").Hash
$b = (Get-FileHash "$env:USERPROFILE\.dsh\profiles\tui\node_modules\dsh-oc-tui\$rel").Hash
if ($a -ne $b) { "DIFFERS: $rel" }
}

然后真正启动它。到达标题界面还不够——会话打开路径才是宿主 API 破坏暴露的地方,所以发送一条消息。单独测试 --resume,因为它是一条应用时路径,可能会输掉一场启动竞争,而启动后的路径则能赢。

对于完全跳过打包的零安装引导,创建一次 profile 并将其补丁指向此检出:
sh
dsh --profile tui --dump-config   # initializes the base profile once
yaml
$DSH_HOME/profiles/tui/cordis.patch.yml
- insert:
- id: tui-startup
name: 'file:///D:/Projects/DeepSeekHarnessPlugins/dsh-oc-tui/lib/startup.js'
- id: tui-app
name: 'file:///D:/Projects/DeepSeekHarnessPlugins/dsh-oc-tui/lib/index.js'
config:
sidebar: true
showReasoning: true

该插件的 dsh 导入通过 dsh 维护的共享 $DSH_HOME/profiles/node_modules 回退路径解析,因此无需向插件目录安装任何内容。

故障排除

| 症状 | 原因与修复 |
| --- | --- |
| pnpm failed in profile directory / ERR_PNPM_ADDING_TO_ROOT | 该 profile 是一个 pnpm 工作区根目录;在 add/remove 命令中添加 -w。 |
| 安装期间出现 ENOENT: … dsh-oc-tui-.tgz | 该 profile 仍引用你已删除的 tarball。执行 dsh plugin --profile tui remove -w dsh-oc-tui,然后重新添加。 |
| pnpm not found on PATH | 安装 pnpm(npm install -g pnpm)后重试。 |
| --dump-config 没有 TUI 层 | 安装未完成,或包名拼写错误。重新运行 add 并检查 dsh.profile.bundles。 |
| 立即退出 / 无 UI | stdin 和 stdout 必须都是 TTY——不要使用管道或重定向。然后验证模型路由和凭据是否存在。 |
| --resume 或 Manage sessions 不可用 | 两者都需要共享的 sessionQuery 服务;请将 @deepseek-ai/dsh-base 保持在 dsh.profile.bundles 的首位。 |
| --resume 时出现 no agent factory registered | 与 agent-loop 行存在启动竞态;当前构建会重试。在较旧的构建上,请在启动后改为运行 /resume 。 |
| 更新 dsh 后出现加载器错误(State、./internal) | 全局 dsh 安装是旧/新混合的目录树。关闭所有 dsh 进程并重新安装:npm install -g @deepseek-ai/dsh@。 |
| 源码修改没有效果 | 安装的副本是 tarball;请重新打包并重新安装(参见开发)。 |

更多细节(中文):docs/用户手册.md。

已知限制

- 零依赖终端引擎尚未暴露输入法(IME)组合输入。粘贴的图片会:以原始图片字节的括号粘贴、data:image/...;base64,... URL、本地图片路径或图片 URL 的形式成为 [Image N] 附件,而粘贴无法识别的文本会向终端请求其剪贴板(OSC 52)。
- 该插件不支持热重载:profile 的 HMR 根目录就是 profile 目录,因此正在运行的 TUI 会保留其启动时的副本。
- 将 dsh tui 作为裸子命令需要 shell 别名——原版启动器仅硬编码了 web 和 plugin。
- Harness 斜杠命令需要活动会话;在标题屏幕上,TUI 会提示你先启动一个会话。
- 用 Esc 推迟问题不会取消工具调用——它会进行委托,而在没有其他应答者时,工具调用会失败。按问题跳过(如 Web UI 编辑器所提供)尚未实现。
- --resume、Settings → Manage sessions、上下文计量器和统计条依赖于由 @deepseek-ai/dsh-base 挂载的服务(sessionQuery、sessionProjections);手工构建的 profile 必须提供它们。sessionStats 投影是 web 应用层的一行,因此当没有 profile 挂载它时,TUI 会从会话日志本身汇总这些数字。
- Windows 上延迟的 dsh 安装会等待调度它的那个 TUI,而不是机器上的每个 dsh 进程——在它运行之前,请关闭其他 TUI 窗口(以及 dsh web)。

布局

lib/index.js         插件入口:agents、events、input、commands、approvals、user questions
lib/startup.js       命令行提供程序(tuiStartup 服务)
lib/term.js          终端引擎(原始模式、屏幕、按键解码)
lib/ui.js            响应式视图模型 + 渲染器(包含问题模态框)
lib/metrics.js       整个会话的统计信息 + token 用量折叠(web 统计条 / tokenUsage 端口)
lib/interrupt.js     Ctrl+C 生命周期状态
lib/web-settings.js  共享的 WebUI 设置投影
lib/updates.js       应用内更新管理器(npm registry + 安装)
lib/markdown.js      markdown -> 带样式的行
lib/util.js          文本/显示辅助函数
bin/dsh-oc-tui.js    dsh --profile tui 的便捷启动器
install.sh           一键安装程序(Linux/macOS)
install.ps1          一键安装程序(Windows)
cordis.patch.yml     捆绑补丁层(TUI 行、agent-presets 名册、ask-user 工具)
docs/用户手册.md       中文用户手册
tests/smoke.test.mjs 独立冒烟测试

许可证

LGPL-3.0-or-later。

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

💬 加入 DPharness 群聊

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

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