Skip to content

Releases

0.2.0 — visual experience, provider setup, and branch switching

Choose a tag to compare

@rayafriandion rayafriandion released this 01 Nov 07:20

0.2.0 is the visual-experience release — and the first stable one on this line. Install it untagged: latest carries it now, so nothing here needs @next any more.

Visual experience

Images render for real, through whichever graphics protocol the terminal answers to: kitty, iTerm2, sixel, or ANSI halfblocks as the universal fallback. Mermaid fences are laid out as native box-drawing art rather than a raster — lovely-mermaid does the layout in pure JavaScript, so a diagram is terminal text that scrolls, selects and copies like anything else. Grammars the engine cannot draw fall through to mmdc (offline, when installed) and then to mermaid.ink. Markdown gets a real renderer: headings, tables, syntax highlighting, links.

The transcript is flat rather than boxed, the header names the workspace and its git branch, and the right rail carries model, context and the running builds on wide windows.

Set up a provider without leaving the terminal

The Model tab used to edit only providers that already existed, and it hid every whole-section route — DeepSeek ships settingsPath: [], so a fresh install opened an empty page with nowhere to put a key. It now builds the same directory the WebUI does: configured routes listed one by one, addable routes behind a search row, and a create form — catalog or custom endpoint — that can adopt a discovered model list before the provider is saved. Single models can be added, edited and removed. A failed fetch reports the adapter's own refusal (…/models answered 401; check the API key) instead of an empty window.

Branch switching

Ctrl+B on the title screen lists local and remote branches, creates one, or switches. The workspace header follows.

Built for dsh 0.2.1-rc.5

Compared package by package against rc.2: the core is unchanged, and the one display change is handled here. Some endpoints prefix a reasoning block with <signature>…</signature> — the opaque blob a later request replays to prove the chain of thought is the one the model produced. It is routing data, not prose, and long enough to fill the thinking box on its own, so it is filtered out of the display. A block that carries nothing else draws no row at all.

Host output is also kept out of the frame now: while the alternate screen is up, anything a plugin writes to stdout/stderr goes to $DSH_HOME/tui-diagnostics.log instead of painting over the interface, and is replayed to the terminal on exit.

Fixes

  • The Mermaid disk cache had never cached anything — it wrote into a directory that was never created, and the failure was swallowed. It is created on first write, read before any provider instead of after it (which had made every session re-render diagrams that were already on disk, and send the diagram text to a public service for nothing), and keyed by pixel width.
  • An image render now carries the cell grid it was built for, so resizing the window re-renders instead of drawing the old raster at the wrong size.
  • A folded thinking box previews its first line instead of saying only "Thinking".
  • Resize painting is coalesced to 40ms; it was immediate, so dragging a window edge rebuilt the screen once per pixel column.

Install

dsh plugin --profile tui add -w dsh-oc-tui
npm install -g dsh-oc-tui

Both land on the stable channel. To pin this exact version, add @0.2.0.

Supports dsh >=0.1.1-rc.2 <0.3.0-0, declared as engines.dsh and verified on 0.2.1-rc.2, 0.2.0-rc.2 and 0.1.2-rc.1.

0.2.0-pre.13 — localized interface in 17 languages, switchable live from Settings

Choose a tag to compare

@rayafriandion rayafriandion released this 18 Oct 15:09

Pre-release of the 0.2.0 line — install with dsh-oc-tui@next.

Localized interface

Every string the TUI draws — chrome, transcript, dialogs, toasts, command help — now comes from a catalog, and the whole interface follows one setting: Ctrl+P → Language, switchable live with no restart. 17 languages plus System, each labelled in its own script: English, Chinese (simplified and traditional), Japanese, Korean, German, French, Spanish, Portuguese (Brazil), Italian, Russian, Polish, Dutch, Turkish, Vietnamese, Indonesian and Arabic.

image

System resolves in order: DSH_TUI_LOCALE → LANGUAGE → LC_ALL / LC_MESSAGES / LANG → OS locale → English. Values may be POSIX (de_DE.UTF-8), BCP 47 (pt-BR), or bare (zh, fr); an unknown language falls back to English rather than a neighbour it does not resemble.

Removed

  • Hindi (hi) — Windows Terminal performs no Indic shaping (microsoft/terminal#17838, wontfix), so the interface painted matrae detached from their base consonants and read as broken. A stored hi preference now falls back to the system locale instead.
  • The dead tab agents hint on the title screen — Tab's only binding in the composer is cycling thinking intensity; no agents affordance exists. The shortcut row now shows only the two real affordances, Ctrl+P settings and Tab thinking.

Install

dsh plugin --profile tui add -w dsh-oc-tui@next   # newest pre-release
npm install -g dsh-oc-tui@next

Untagged installs keep landing on the stable channel; latest is untouched by this release.

0.2.0-pre.9 — flat transcript, one-row header with workspace+git, wide-window rail

Choose a tag to compare

@rayafriandion rayafriandion released this 05 Oct 11:47

dsh-oc-tui v0.2.0-pre.9

Pre-release of the 0.2.0 line. This build targets dsh 0.2.0. It is not on npm's latest tag — install from the asset below, or dsh plugin --profile tui add -w dsh-oc-tui@next once it has been published under the next tag.

New — the shell is OpenCode-shaped

  • Title screen: the DeepSeek brand mark is one line tall (blue→white gradient text, no ASCII-art logo), followed by the workspace and its git branch, and a shortcut row where Ctrl+P (settings) and Tab (thinking intensity) stay ahead of the cosmetic hints.
  • Mermaid fences are drawn as native box-drawing art in the terminal (lovely-mermaid), before the image provider chain (mmdc → mermaid.ink → disk cache) ever sees the diagram. Width is verified in both directions: every art line's display width is compared cell by cell against the engine's own measurement.
  • From 140 columns a right-hand status rail takes over the status figures, OpenCode-style: the session title pins to the top, scrollable sections fill the middle (MODEL, THINKING, CONTEXT, SESSION, GOAL, SUBAGENTS — sections with no data drop out whole), and the running builds pin to the bottom. Shift+↑/↓ or the wheel over the rail scrolls it; clicking CONTEXT opens the session stats window.

New — a flat transcript

  • The rounded chat bubbles and tool cards are gone. Assistant output is flat rows (a dsh · time label row plus full-width text at a two-space indent), tool actions are one-line rows — status mark, accented verb, muted target, a ⎿ result gutter, and click-to-expand for the full result — user turns use a brand-blue ❯ pointer with a hanging indent and a trailing timestamp, and thinking/note/system markers keep their own flat rows in their own colours.
  • Header: the model name no longer repeats in the top-right corner (the status row and the rail both already carry it); the workspace path and its git branch take that slot behind a yielding budget ladder (label → branch, clipped at 20 columns → whole block), and the header is one row at every width. The old tinted workspace strip and the rail footer's duplicate path are deleted.
  • Truncation is marked: a clipped title, command or path ends in …. An exact cut at the column boundary — the common case — used to pass unmarked and read as broken rendering.
  • Window consistency: the session stats window is one centered modal at every width; the maximized window's right-hand panel variant is gone. And every modal — stats, help, settings, rewind, questions, secret — now centers inside the main area instead of the full terminal, so the rail no longer displaces each modal half a rail's width to the right.
  • Images: the paint diff keys on position and size, so an image re-rendered narrower or taller no longer leaves its old pixels behind; a placement whose payload lands after it was reserved is re-sent instead of being skipped forever; and an image whose first row scrolled above the window registers the first row still visible and asks the host for a cropped variant. The title screen's rows now carry an explicit background instead of falling through to the terminal's black.

Tests

npm test runs 1152 assertions; npm run check is clean. The only 8 failures are the pre-existing esc-questions ones — the pinned @deepseek-ai/dsh-user-questions rc revision and no registered provider, a dependency gap rather than a defect in this build. The layout boundary is pinned at every width in tests/render.test.mjs, the rail's own layout in tests/rail.test.mjs, and the image slab/background regressions in tests/graphics.test.mjs.

What this release does not claim

  • No live TTY session. dsh refuses to start without a TTY, so the evidence is the test suite booting the real plugin through a real cordis context against a fake terminal, plus a hash-verified install into a tui profile (all 18 shipped files matched) before the suites were run against the installed copy. --resume is covered as an apply-time path.
  • Not published to npm yet. This release asset is the packed tarball; publishing to the registry is a separate step (see the tag guidance in the repo).

Install

dsh plugin --profile tui remove -w dsh-oc-tui                    # optional: drop the installed copy
cp dsh-oc-tui-0.2.0-pre.9.tgz "$USERPROFILE/.dsh/profiles/tui/"  # pnpm resolves the tarball from here
dsh plugin --profile tui add -w ./dsh-oc-tui-0.2.0-pre.9.tgz
rm "$USERPROFILE/.dsh/profiles/tui/dsh-oc-tui-0.2.0-pre.9.tgz"

中文

dsh-oc-tui v0.2.0-pre.9

0.2.0 线的预发布版本。 该构建面向 dsh 0.2.0,不会进入 npm 的 latest 标签——请从下方资产安装,或在它按 next 标签发布后使用 dsh plugin --profile tui add -w dsh-oc-tui@next。

新功能 —— OpenCode 式外壳

  • 启动页:DeepSeek 品牌标记是一行高的蓝→白渐变文字(不再是 ASCII-art logo),下面跟着工作区与其 git 分支,以及一行快捷键——Ctrl+P(设置)与 Tab(思考强度)排在装饰性提示之前。
  • Mermaid 代码块在终端里直接绘成制表符方框画(lovely-mermaid),图片 provider 链(mmdc → mermaid.ink → 磁盘缓存)根本看不到它。宽度校验是双向的:每一行的 displayWidth 都与引擎自己的测量逐格对齐。
  • 140 列起右侧出现状态栏,接管状态信息:会话标题固定在顶部,中间是可滚动的 MODEL / THINKING / CONTEXT / SESSION / GOAL / SUBAGENTS 分区(没有数据的分区整体消失),底部固定显示运行中的构建版本。Shift+↑/↓ 或在栏上滚滚轮可滚动;点击 CONTEXT 打开会话统计窗口。

新功能 —— 平铺转录

  • 圆角聊天气泡与工具卡片全部移除。assistant 输出是平铺行(dsh · 时间 标签行 + 两空格缩进的全宽正文),工具动作是一行式——状态标记、着色动词、弱化目标、⎿ 结果槽,点击可展开完整结果,用户消息用品牌蓝 ❯ 指针加悬挂缩进、行尾带时间戳,思考/备注/系统标记各自保留自己的平铺行与配色。
  • 顶栏:右上角不再重复模型名(底部状态行与右侧状态栏都已经有它);该位置改放工作区路径和 git 分支,按「标签 → 分支(截到 20 列)→ 整块」的顺序让位,顶栏在任何宽度下都只有一行。旧的工作区色带行与状态栏底部重复的路径一并删除。
  • 截断有标记:被截断的标题、命令、路径以 … 结尾。列边界处的精确截断(最常见的情况)以前没有任何标记,看起来像渲染坏了。
  • 窗口尺寸一致:会话统计窗口在任何宽度下都是同一个居中圆角弹窗,最大化时右侧面板的变体已删除。所有弹窗——统计、帮助、设置、回退、提问、密钥输入——现在都按主区居中而不是整个终端宽度居中,右侧状态栏不会再把弹窗整体推偏半条栏宽。
  • 图片:绘制差分同时按位置与尺寸记账,图片重渲染得更窄或更矮时不再把旧像素留在屏幕上;预留之后才到达的 payload 会补发,不会被永久跳过;首行滚出窗口的图片改为登记窗口内仍可见的首行,并向宿主索取裁剪变体。启动页各行现在显式带背景色,不再落入终端的黑色默认背景。

测试

npm test 跑 1152 条断言;npm run check 干净。仅有的 8 项失败是既有的 esc-questions——锁定的 @deepseek-ai/dsh-user-questions rc 修订加上从未注册 provider,属于依赖缺口,不是本构建的缺陷。宽度边界由 tests/render.test.mjs 在各档宽度下钉住,状态栏自身布局由 tests/rail.test.mjs 覆盖,图片残片与背景回归在 tests/graphics.test.mjs。

本版本没有声称什么

  • 没有真机 TTY 会话。 dsh 没有 TTY 拒绝启动,因此证据是:测试套件通过真实 cordis 上下文带假终端启动真实插件,加上装入 tui profile 后的哈希对账(18 个发布文件全部一致),随后在已安装副本上跑完各套件。--resume 作为 apply 期路径已被覆盖。
  • 尚未发布到 npm。 本 release 的资产就是打包好的 tarball,发布到 registry 是另一步(tag 用法见仓库文档)。

安装

dsh plugin --profile tui remove -w dsh-oc-tui                    # 可选:先移除已安装的副本
cp dsh-oc-tui-0.2.0-pre.9.tgz "$USERPROFILE/.dsh/profiles/tui/"  # pnpm 从这里按名字找 tarball
dsh plugin --profile tui add -w ./dsh-oc-tui-0.2.0-pre.9.tgz
rm "$USERPROFILE/.dsh/profiles/tui/dsh-oc-tui-0.2.0-pre.9.tgz"

0.1.5 — updates that never race dsh, and standing clear of the dsh 0.2.0 preset rename

Choose a tag to compare

@rayafriandion rayafriandion released this 01 Oct 08:36

dsh-oc-tui v0.1.5

⚠️ dsh (the harness) 0.2.0 is a breaking update for this plugin — update the plugin first, then dsh.

From dsh 0.2.0-rc.1 the agent-preset packages were split apart: the roster provider @deepseek-ai/dsh-agent-presets (which shipped its own presets) became @deepseek-ai/dsh-agent-preset-registry, and a brand-new @deepseek-ai/dsh-agent-preset package is only a declarative preset row — it injects a service the registry provides and never activates on its own. A TUI older than 0.1.5 still names the old provider, so every boot of such a profile reports:

dsh: disabling profile plugin row "agent-presets": Plugin @deepseek-ai/dsh-agent-presets@0.1.1-rc.2 is
incompatible with dsh 0.2.0-rc.2: peerDependencies {…}. Running it may cause crashes or data loss.
Update the plugin or install a plugin version compatible with this dsh runtime. …

The TUI still starts and your sessions are untouched; what that report costs you is the Settings → Default preset dropdown, whose roster is exactly the row being disabled.

The order that keeps this painless:

dsh plugin --profile tui add -w dsh-oc-tui@0.1.5   # or: npm install -g dsh-oc-tui@0.1.5
# then upgrade dsh

If you already moved dsh to 0.2.0-rc.x: nothing is broken, and updating the plugin removes the report. 0.1.5 mounts no roster row at all — measured against a live dsh 0.2.0-rc.2, the old plural name always triggers the report above, the singular name never activates, and the registry activates empty unless a host declares presets. No single package name serves both dsh lines, so this bundle stays out of it and Settings hides the row instead of showing an empty one. A dsh 0.2.0 profile that wants a roster mounts the registry plus its own preset declarations, exactly as dsh-web-app does. See README § Compatibility and the reasoning next to the rows in cordis.patch.yml.

Recommended version

  • Recommended pairing: dsh-oc-tui 0.1.5 + dsh 0.2.0-rc.2 (the current latest). This release's real-terminal evidence is from booting the packed tarball under a real dsh 0.2.0-rc.2 install, in throwaway profiles, where it reaches apply() with no dsh report at all.
  • The same build also boots the dsh 0.1.x line. The plugin reads whichever session accessor the host provides (snapshotEvents() since 0.1.2, Session.events before that), so one build serves both.

New — an update is a download, then a restart

The in-app updater (Ctrl+P → Update) no longer installs anything while a dsh process is alive. Picking a version downloads the registry tarball with live byte progress (Esc cancels mid-flight, an unknown total reports bytes only and never invents a percentage), checks the sha512 the registry publishes before the file is kept, and stages it under $DSH_HOME/updates. Applying it is a restart: the TUI spawns a detached applier (bin/apply-update.cjs, plain CJS so it survives being the package it replaces), exits, and that child:

  1. waits for this pid to disappear (up to 10 minutes; a pid that never goes away means nothing is installed),
  2. installs from the staged tarball — npm install -g for dsh, dsh plugin … remove -w then add -w for the TUI,
  3. re-reads the on-disk manifest, because npm's exit code alone is not proof,
  4. writes the outcome to $DSH_HOME/tui-dsh-install.json and drops the staged record,
  5. relaunches dsh in the same terminal with the same arguments and working directory (--profile tui --resume … included), re-resolving the dsh entry through the shim after the install so a layout change inside a new dsh cannot break the relaunch.

The restart is also refused while any other dsh process is alive. This shape closes the window the 2026-09-04 corruption came through — on Windows, npm replacing a global directory whose native DLLs are still memory-mapped by a running process can silently leave an old/new hybrid tree behind while exiting 0. Nothing is installed until this process is gone, on every platform, not just Windows.

New — a rollback costs no download

Every downloaded tarball stays in the cache, so version rows are tagged [cached] when that tarball is already on disk and [staged] for the one waiting to be applied. A staged install appears on the Update tab as Restart to apply x.y.z (one Enter) and Discard downloaded x.y.z, and it only appears while the staged tarball actually exists — a crash after a download leaves no dead entry behind.

Changed — the bundle mounts no agent-preset row

cordis.patch.yml now inserts three rows (tui-startup, tui-app, tool-ask-user) and none for the preset roster, for the reasons quoted above. A regression test asserts the row set, so a future edit cannot quietly reintroduce a row that warns or never activates. The startup version gate that shipped in the first draft of 0.1.5 is gone: it compared the running build's own version against 0.1.5, so it could never fire — the only build that reports a pre-0.1.5 version is one that does not contain the check. The honest surface for "your TUI is too old for this dsh" is dsh's own report plus these notes, and that is what the README and the manual now say.

Tests

npm test runs 918 assertions, 0 failures; npm run check (which also syntax-checks the applier) is clean. The new pure builders — restart plan and spec, cache paths, byte and progress formatting, sha512 checking, the staged record, tagged version rows — are covered without touching the network, and the bundle-patch assertions above read the real cordis.patch.yml.

What this release does not claim

  • The restart handoff was not exercised end-to-end in a real TTY session. Its pieces are unit-tested against real inputs — the plan the TUI writes, the parent-wait loop, both install commands, the manifest verification, the relaunch resolution — but no live TTY exit-and-relaunch was run before publishing. That is the first thing to try on a real terminal.
  • Boot evidence is from throwaway probe profiles, not from a full interactive session under dsh 0.2.0-rc.2.
  • The preset roster is not available on a stock tui profile on either dsh line. That is a deliberate trade (see above), not an oversight.

Install

dsh plugin --profile tui remove -w dsh-oc-tui              # optional: drop the installed copy
dsh plugin --profile tui add -w ./dsh-oc-tui-0.1.5.tgz     # install from the asset below

Or from npm: dsh plugin --profile tui add -w dsh-oc-tui@0.1.5.


中文

dsh-oc-tui v0.1.5

⚠️ dsh(harness 本体)0.2.0 对本报插件是破坏性更新——请先更新插件,再升 dsh。

从 dsh 0.2.0-rc.1 起,预设相关的包被拆开了:原来的名册提供方 @deepseek-ai/dsh-agent-presets(自带预设)改名为 @deepseek-ai/dsh-agent-preset-registry;而新出现的 @deepseek-ai/dsh-agent-preset 只是声明式的预设行——它注入注册表提供的服务,自己永远不会激活。0.1.5 以下的 TUI 引用的还是旧名,于是每次启动都会打印:

dsh: disabling profile plugin row "agent-presets": Plugin @deepseek-ai/dsh-agent-presets@0.1.1-rc.2 is
incompatible with dsh 0.2.0-rc.2: peerDependencies {…}. Running it may cause crashes or data loss.
Update the plugin or install a plugin version compatible with this dsh runtime. …

TUI 照样能起来,会话数据也不受影响;这段报告的代价是 Settings → Default preset 下拉列表——它的名册正是被禁用的那一行。

不会疼的顺序:

dsh plugin --profile tui add -w dsh-oc-tui@0.1.5   # 或:npm install -g dsh-oc-tui@0.1.5
# 然后再升 dsh

如果你已经把 dsh 升上去了:没有坏任何东西,更新插件即可让报告消失。0.1.5 完全不挂载名册行——在真实的 dsh 0.2.0-rc.2 上实测:旧名必然触发上面那段报告,单数名永远不会激活,注册表在没有主机声明预设时激活出来也是空的。没有一个包名能同时服务两条 dsh 线,所以本 bundle 干脆不挂,Settings 里那一行直接隐藏而不是留一个空列表。需要名册的 dsh 0.2.0 profile 应当自己挂载注册表并声明预设(dsh-web-app 正是这么做的)。理由同时写在 cordis.patch.yml 的行旁注释里。

新功能 —— 更新是「先下载,再重启生效」

程序内更新(Ctrl+P → Update)不再在 dsh 进程活着的时候安装任何东西。选中版本后,TUI 自己把 registry 上的 tarball 下载下来(实时字节进度,Esc 随时取消;拿不到总长度时只报字节数,绝不编一个百分比),并按 registry 公布的 sha512 校验后才保留文件,暂存到 $DSH_HOME/updates。应用它是一次重启:TUI 先派生一个独立的安装进程(bin/apply-update.cjs,纯 CJS,因此即便它自己就是被替换的那个包也能活下来),然后退出;子进程随后:

  1. 等本进程消失(最多 10 分钟;pid 一直不死就什么都不装);
  2. 从暂存的 tarball 安装——dsh 走 npm install -g,TUI 走 dsh plugin … remove -w 再 add -w;
  3. 重新读磁盘上的 manifest 核对版本,因为 npm 的退出码本身不算证据;
  4. 把结果写进 $DSH_HOME/tui-dsh-install.json,并清掉暂存记录;
  5. 用原来的参数和工作目录(含 --profile tui --resume …)在同一终端里把 dsh 重新拉起来,并在安装之后才通过 shim 重新解析 dsh 入口,这样新版本 dsh 内部的目录变化也弄不坏 relaunch。

确认重启前还会检查是否有别的 dsh 进程在跑,有就拒绝。这套形状彻底关上了 2026-09-04 那次损坏的入口——Windows 上 npm 替换一个仍被运行中进程内存映射着原生 DLL 的全局目录时,可能静默留下新旧混杂的树却仍然以 0 退出。而现在:本进程消失之前什么都不装,任何平台都是如此。

新功能 —— 回退不需要重新下载

下载过的 tarball 都留在缓存里,因此版本行会打 [cached](该版本已在磁盘上)与 [staged](等待重启应用的那个版本)标记。已暂存的安装会在 Update 页多出 Restart to apply x.y.z(直接 Enter)与 Discard downloaded x.y.z 两行,且只在 tarball 确实还在磁盘上时出现——下载后崩溃不会留下一个假入口。

变更 —— bundle 不再挂载 agent 预设行

cordis.patch.yml 现在只插三行(tui-startup、tui-app、tool-ask-user),不再有名册行,原因如上。测试里加了针对行集合的断言,以后误改回去会立刻红。0.1.5 初版里那个启动版本检查也被移除了:它拿正在运行的这个构建自己的版本去和 0.1.5 比,因此永远不可能为真——唯一会报告 pre-0.1.5 版本的构建,恰恰是不含这段检查的构建。「你的 TUI 对这个 dsh 太旧了」这件事,诚实的出口是 dsh 自己的报告加上这份说明,README 与用户手册现在也是这么写的。

测试

npm test 跑 918 条断言,0 失败;npm run check(含 applier 的语法检查)干净。新增的纯函数——重启计划、缓存路径、字节与进度格式化、sha512 校验、暂存记录、带标记的版本行——全部不联网,bundle 行集合的断言则直接读真实的 cordis.patch.yml。

本版本没有声称什么

  • 「重启交接」没有在真实 TTY 会话里端到端跑过。 它的每一块都针对真实输入做了单测——TUI 写出的计划、等父进程的循环、两条安装命令、manifest 核对、relaunch 解析——但发布前没有真的退出再拉起来一次。上真机第一件该试的就是这个。
  • 启动证据来自临时的 probe profile,不是在 dsh 0.2.0-rc.2 下的完整交互会话。
  • 默认 tui profile 在两条 dsh 线上都没有预设名册,这是刻意的取舍(见上),不是漏了。

安装

dsh plugin --profile tui remove -w dsh-oc-tui              # 可选:先移除已安装的副本
dsh plugin --profile tui add -w ./dsh-oc-tui-0.1.5.tgz     # 从下方资产安装

或从 npm:dsh plugin --profile tui add -w dsh-oc-tui@0.1.5。

0.1.4

Choose a tag to compare

@rayafriandion rayafriandion released this 20 Sep 13:05

dsh-oc-tui v0.1.4

v0.1.4 makes this plugin a discoverable @dsh-std component — it now ships a dsh-plugin.json manifest and a facet that a @dsh-std host can find without running any code — and it hardens the approval box, the clipboard and the output stream along the way.

Recommended version

  • Recommended pairing: dsh-oc-tui 0.1.4 + dsh 0.1.5-rc.1 or above. Everything in this release was developed and verified on dsh 0.1.5-rc.1 — real sessions in a real terminal, with the rendered frames checked against what the terminal actually showed. Use it there. 0.1.5-rc.2 also exists on npm; this release's real-terminal evidence is from rc.1, and the notes say so rather than implying otherwise.

New — a @dsh-std component manifest

dsh-plugin.json is now packed into the npm tarball, so @dsh-std/adapter-dsh can discover this plugin without executing it:

  • A Community 0.15 manifest declaring io.github.rayafriandion.dsh-oc-tui, one facet (host, lib/facet.js, apiVersion: v1alpha1 — matched exactly, not by semver), two storage permissions scoped to this component's own id, and nine Command contributions under x-dev.dsh-std.extensions.
  • One requires.contracts entry — the commands.dsh/v1alpha1 Command resource — declared optional: true. It is inert today: nothing calls protocols.client(...), and the TUI parses its own command line from the cordis ctx.commands service, so it behaves identically whether or not a Command provider exists. An unsatisfiable non-optional requirement is a hard activation failure rather than a warning, and the optional flag is what keeps the declaration honest about that.

What is not live yet, and why that is upstream's call

The runtime protocol support is currently gated off. A Community v0.15 manifest cannot declare protocol supports — the schema rejects both requires.supports and a top-level supports, and projectManifest emits only protocols.requires — and @dsh-std/lifecycle's implement, which is stageProtocol, refuses to stage a support the facet has not declared. Since a throw there makes mountProfileComponents roll back every component it had already mounted in the profile, lib/facet.js stages nothing at all and reports { state: 'degraded' } with the reason attached.

The shims are written and test-covered, and they go live unchanged the day upstream closes the gap. Layer-by-layer evidence, with the exact adapter and lifecycle line numbers: docs/dsh-std-接入说明.md.

New — the facet never starts the TUI

mountProfileComponents mounts the facet of every dsh-plugin.json it finds in a profile's dependencies, without checking whether the cordis bundle rows already loaded that component — and this plugin is a profile dependency that cordis.patch.yml also activates. Because the TUI seizes the terminal (raw mode, alternate screen, mouse tracking), a manifest alone would start it twice. The facet is therefore an interop shell: when it stages protocol support it forwards the calls through lib/bridge.js to whichever TUI instance is live, and it reports degraded when none is. A dsh-plugin.json whose facet never starts the TUI is working as intended, not broken.

New — the approval box shows what the request actually says

The composer area is replaced by an approval box instead of the old one-line Approval · <tool> · y allow / n deny:

  • The first row carries the action (Approval · <tool>) with the key hints riding along when they fit; the explanation the request supplies follows as a Summary · row. y allows once, n rejects, Esc cancels.
  • A request from a @dsh-std component can additionally carry Origin, Risk and Details rows. They are drawn when present and omitted when not; a detail marked private shows its label but not its value; and on a narrow terminal the middle yields with a … N more marker while the action and the hints always survive.

New — an approval deadline is an expiry, not a cancellation

An approval that outlives the deadline its caller set disappears on its own, and the caller is told expired rather than cancelled — so a timeout can never be read as a human decision.

New — the standalone secret prompt

A secret-input request opens a masked prompt with minLength / maxLength bounds:

  • Pasted and clipboard text lands in the masked draft and never in the composer; the plaintext is nowhere on screen, including in the error state.
  • A multi-line paste collapses to one line, so a credential can never smuggle a newline into the answer.
  • The bounds are metered in UTF-16 units the way the validator does, so a two-emoji draft counts as 4 and maxLength: 2 refuses it; backspace deletes a whole code point, not one UTF-16 unit.

This path has no caller today — it is reachable only through a standard secret-input request, and the runtime protocol support is gated off (above). It is written and integration-tested; a normal dsh --profile tui session cannot reach it.

Fixed — control characters can no longer reach the terminal

The cell buffer is now the single chokepoint where every painted string is sanitized: C0, DEL and C1 characters are replaced with a visible \uFFFD. A tool name, a path, a title or a @dsh-std request's action can no longer smuggle an escape sequence into the output stream — screen clears, cursor moves, even clipboard writes. The width-preserving placeholder is deliberate: dropping the character instead would silently change the layout, whereas a visible one makes the injection obvious.

Fixed — Esc on a question modal no longer hangs the tool call

Deferring a question with Esc now threads the waterfall continuation instead of cancelling, so the tool call ends. With no other answerer it still fails — but as the service's own ASK_ABORTED, not as a hang. The abort context is forwarded too, so a caller that gives up is not left waiting.

Fixed — private clipboard text stays off the command line

Text marked private now takes the in-band OSC 52 path only. The Windows fallback passes base64 as a powershell.exe command-line argument, which any process of the same user can read back — private text must not go there. Two follow-ups: the options handling is null-safe (an explicit null would previously throw outside every try/catch, breaking the never-throws contract), and the outstanding-read flag is cleared when a clipboard reply is dropped, so a later unsolicited reply can no longer be routed into the composer.

Fixed — the question adapter rejects what a select field cannot carry

A custom answer on a single-select question is no longer forwarded as free text: the protocol's validateQuestionAnswers rejects any answer that is not one of the field's option ids, so it is dropped rather than failing the whole request. Field ids and option labels are also allocated against null-prototype maps — a field id of toString would previously read Object.prototype.toString as a decoder, and an option label of __proto__ would not store a normal key.

Testing

npm test runs 870 assertions, 0 failures, up from three suites to seven. The four new suites drive a real cordis context and a real apply() rather than stubs:

  • tests/std.test.mjs — the manifest's raw JSON and its projection, the facet's guard, the bridge registry's contract, and the question/answer adapter against the real protocol validators.
  • tests/esc-questions.test.mjs — the question modal's Esc path over a real cordis context and a real TTY key path.
  • tests/deadline.test.mjs — a real live handle: expiry, expiry ≠ cancellation, and no timer leak.
  • tests/secret-prompt.test.mjs — raw bytes through a real live handle: paste isolation, masking, multi-line collapse, the UTF-16 bounds, and code-point backspacing.

Install

dsh plugin --profile tui remove -w dsh-oc-tui              # optional: drop the copy already installed
dsh plugin --profile tui add -w ./dsh-oc-tui-0.1.4.tgz     # from the asset below

dsh-oc-tui v0.1.4(中文)

v0.1.4 让本插件成为可被 @dsh-std 发现的组件——npm 包里现在带 dsh-plugin.json 清单与一个 facet,宿主无需执行任何代码就能找到它;与此同时,审批框、剪贴板与输出流也一并收紧。

推荐版本

  • 推荐组合:dsh-oc-tui 0.1.4 + dsh 0.1.5-rc.1 及以上。 本版本的全部改动都在 dsh 0.1.5-rc.1 上开发并验证——真实会话、真实终端,渲染帧与终端实际显示逐格核对。请在该版本上使用。npm 上还有 0.1.5-rc.2,但本版本的真实终端证据来自 rc.1,这里如实说明,不暗示已验证过 rc.2。

新功能 —— @dsh-std 组件清单

dsh-plugin.json 现在会打进 npm 包,@dsh-std/adapter-dsh 因此可以不执行本插件就发现它:

  • 一份 Community 0.15 清单:声明 io.github.rayafriandion.dsh-oc-tui,只有一个 facet(host、入口 lib/facet.js、apiVersion: v1alpha1——adapter 是精确匹配,不是 semver),两条 scope 为本组件 id 的存储权限,以及 x-dev.dsh-std.extensions 下的 9 条 Command。
  • requires.contracts 只有一条——commands.dsh/v1alpha1 的 Command 资源——且标了 optional: true。它今天不起作用:没有任何地方调用 protocols.client(...),TUI 自己的命令行是从 cordis 的 ctx.commands 服务解析的,因此无论有没有 Command 提供方,行为完全一致。不可满足的非 optional 需求是硬性激活失败而不是警告,optional 这个标记正是让这条声明对得起这一点。

还没上线的部分,以及为什么取决于上游

运行时协议支持目前是关闭的。 Community v0.15 清单无法声明 protocol supports——schema 同时拒绝 requires.supports 与顶层 supports,projectManifest 也只产出 protocols.requires——而 @dsh-std/lifecycle 的 implement(它就是 stageProtocol)拒绝暂存 facet 未声明过的 support。由于在那里抛错会让 mountProfileComponents 把该 profile 里已经挂载的所有组件全部回滚,lib/facet.js 干脆一条都不暂存,并以 { state: 'degraded' } 连同原因上报。

这些协议外壳已经写好并有测试覆盖;上游补上这个缺口的那天,它们原样生效。逐层证据(含 adapter 与 lifecycle 的准确行号)见 docs/dsh-std-接入说明.md。

新功能 —— facet 永远不启动 TUI

mountProfileComponents 会挂载它在 profile 依赖里找到的每一份 dsh-plugin.json 的 facet,不检查 cordis bundle 行是否已经加载过该组件——而本插件既是一条 profile 依赖,也被 cordis.patch.yml 激活。由于 TUI 会抢占终端(raw mode、备用屏、鼠标跟踪),光有一份清单就会把它启动两次。因此 facet 是一个协议外壳:它暂存协议支持时,通过 lib/bridge.js 把调用转给当前活着的那个 TUI 实例,没有活体时就上报 degraded。一份 face...

Read more

0.1.3

Choose a tag to compare

@rayafriandion rayafriandion released this 11 Sep 07:28

dsh-oc-tui v0.1.3

v0.1.3 brings the Web UI's session statistics and token usage to the terminal: a one-line stats strip in the session page, and the full breakdown one click — or one /stats — away.

Recommended version

  • Recommended pairing: dsh-oc-tui 0.1.3 + dsh 0.1.5-rc.1 or newer. Every figure in this release was built and verified end-to-end against dsh 0.1.5-rc.1 (real turns, all three window entry points, and the rendered frame compared cell by cell against the terminal), so that is the version to run it on.

New — the session stats strip

One row above the composer carries the same figures the web chat prints under its composer, in the same order:

▤ 2 turns · 5 steps│LLM 12.3s · tools 1.2s│TTFT avg 0.6s · 24.0 tok/s│cache 98%│in 120K · out 12.4K
  • turns / steps count closed steps (step/end), so failed, cancelled, and max-tokens steps count too; LLM is step/start → the assembled reply, tools pairs tool/call → tool/result.
  • TTFT avg is the per-step average time to first token; tok/s is decode throughput over the output tokens the provider reported.
  • cache is the prompt-side cache-hit share; in / out are the session's billed input and output tokens.
  • A session with no closed step and no billing hides the strip entirely, returning the row to the transcript. A narrow terminal drops trailing groups whole and marks the elision with │… rather than cutting a figure in half; a wide one also seats a faint /stats hint at the right edge.

New — the session stats window

Clicking the strip, clicking the context meter at the right end of the status row (ctx ▓▓░░ 32K/128K 25%), or typing /stats opens one window with everything:

  • usage / duration / speed / tokens / cache rows — the strip's figures spelled out, including the cache read/write/miss split.
  • The context occupancy reading and its bar, with the heuristic composition of system prompt, tools, and messages (the Web UI's ContextMeter dialog).
  • Clicking the same place again, clicking elsewhere, or Esc closes it. /stats needs a live session and answers start a session first on the title screen.

How the numbers are sourced

Projection-first, with the plugin's own fold as the fallback — the same split the web stats strip uses. tokenUsage, contextPressure, and contextBreakdown come from the token-meter row dsh-base mounts; sessionStats is mounted only by the web app bundle, so lib/metrics.js folds the durable log by that unit's own rules (step/end counts, a step's first-token boundary surviving an in-step retry, decode measured only over steps that also report output tokens, tool pairs matched by callId, and a repeated usage sample for one step replacing the earlier one instead of double counting it), and ports the web strip's cacheHitPercent so both surfaces print the same percentage. A profile that mounts neither row still shows the same window from the events the process already consumed.

Changed

  • The status row no longer duplicates the readings the strip owns. Session tokens, throughput, and cache-hit rate moved to the strip; the status row keeps the model, the draft-token estimate, and the context meter. One home per fact.
  • The average TTFT is now per step, not one sample per turn — it has to agree with the sessionStats projection the window can also read from.
  • /stats joined the slash-command palette and the help overlay; the README and the Chinese manual document the strip, the window, and the sources.

Install

dsh plugin --profile tui remove -w dsh-oc-tui              # optional: drop the copy already installed
dsh plugin --profile tui add -w ./dsh-oc-tui-0.1.3.tgz     # from the asset below

dsh-oc-tui v0.1.3(中文)

v0.1.3 把 Web 界面的会话统计与 token 用量搬进了终端:会话页多出一行统计条,点一下——或敲一次 /stats——即可展开完整明细。

推荐版本

  • 推荐组合:dsh-oc-tui 0.1.3 + dsh 0.1.5-rc.1 及以上。 本版本的所有数字都是在 dsh 0.1.5-rc.1 上开发并端到端验证的(真实轮次、三种开窗入口,并把渲染帧与终端逐格比对),因此请在该版本上使用。

新功能 —— 会话统计条

输入框上方一行显示与 Web 界面 composer 下方完全相同的数字、相同的顺序:

▤ 2 turns · 5 steps│LLM 12.3s · tools 1.2s│TTFT avg 0.6s · 24.0 tok/s│cache 98%│in 120K · out 12.4K
  • turns / steps 统计已结束的步(step/end),因此失败、取消、触顶的步同样计入;LLM 是 step/start → 组装完成的回复,tools 是配对的 tool/call → tool/result。
  • TTFT avg 是每步首 token 延迟的平均值;tok/s 是按 provider 上报输出 token 计算的解码吞吐。
  • cache 是提示词侧缓存命中率;in / out 是本场会话累计的计费输入与输出 token。
  • 没有任何已结束的步、也没有任何计费时,统计条整行隐藏,把该行归还转录区。窄终端会整组丢弃放不下的尾部数字并标出 │…,绝不把某个数字截成两半;宽终端还会在右端显示一个淡淡的 /stats 提示。

新功能 —— 会话统计窗口

点击统计条、点击状态栏右端的上下文仪表条(ctx ▓▓░░ 32K/128K 25%),或输入 /stats,打开同一个窗口:

  • usage / duration / speed / tokens / cache 明细行——统计条上的数字逐项展开,并给出缓存的 read / write / miss 拆分。
  • 上下文占用读数与占用条,以及按启发式拆分的系统提示词 / 工具 / 消息构成(对应 WebUI 的 ContextMeter 弹窗)。
  • 再次点击同一位置、点击别处或按 Esc 关闭。/stats 需要有活动会话,在标题屏会提示 start a session first。

数据来源

投影优先、本地折叠兜底——与 Web 统计条完全相同的分工。tokenUsage、contextPressure、contextBreakdown 来自 dsh-base 挂载的 token-meter 行;sessionStats 只由 Web 应用层 bundle 挂载,因此 lib/metrics.js 按该单元自身的规则从持久日志折叠(step/end 计步、步内重试后仍保留首次首 token 边界、仅在同时上报输出 token 的步上计算解码、按 callId 配对工具调用、同一步的重复 usage 采样替换而非重复累加),并移植 Web 统计条的 cacheHitPercent,保证两处打印同一个百分比。即使 profile 两个投影行都没挂载,窗口也会用本进程已经消费的事件显示同样的内容。

行为变化

  • 状态栏不再重复统计条已有的读数。 会话 token、吞吐与缓存命中率移到统计条;状态栏保留模型名、草稿 token 估算与上下文仪表条——同一事实只留一个位置。
  • 平均 TTFT 改为按步统计,不再是每轮取一个样本——它必须与窗口同样可能读取的 sessionStats 投影一致。
  • /stats 加入斜杠命令提示与帮助面板;README 与中文手册补充了统计条、窗口与数据来源说明。

安装

dsh plugin --profile tui remove -w dsh-oc-tui              # 可选:先移除已安装的副本
dsh plugin --profile tui add -w ./dsh-oc-tui-0.1.3.tgz     # 从下方资产安装

0.1.2

Choose a tag to compare

@rayafriandion rayafriandion released this 10 Sep 09:08

dsh-oc-tui v0.1.2

v0.1.2 is the recommended version for all users: it makes the TUI work again on dsh 0.1.2-rc.1, and adds the model-facing question modal (option lists, multi-select, free text, and plan review) that neither the TUI nor the docs had before.

Recommended version

  • Recommended pairing: dsh-oc-tui 0.1.2 + dsh 0.1.2-rc.1. It also still runs on dsh 0.1.1-rc.2 — one build serves both lines.
  • Upgrade paths: in-app Ctrl+P → Update → dsh-oc-tui → Versions, or on the command line dsh plugin --profile tui add -w dsh-oc-tui@0.1.2.
  • The npm package and the awesome-dsh-plugin listing both ship stable releases only; pre-releases are never published there.

Fixed — the TUI was unusable on dsh 0.1.2

  • Session.events was removed in dsh 0.1.2. The transcript replay read that getter on the shared session-open path, so every session open failed with failed to open session: session.events is not iterable. The plugin now prefers Session.snapshotEvents() and falls back to the old getter, which keeps one build working on 0.1.1 and 0.1.2.
  • --resume raced the agent factory. ctx.agents.create/resume throws no agent factory registered (load an agent-loop plugin) until the dsh-agent-loop row calls ctx.agents.setFactory(). --resume opens its session during apply and could lose that race, while a new session (opened on first input) never did. The open now retries that one condition with a bounded wait.
  • The one-command installers are fixed: install.sh / install.ps1 now pass -w. The profile is its own pnpm workspace root, so a bare add fails with ERR_PNPM_ADDING_TO_ROOT — the installers could not complete before this.

New — interactive questions (ask_user_question)

The model can now pause a turn and ask you, and the answer goes back as an ordinary tool result.

  • A modal in the terminal: option lists with descriptions, single and multi select, and a free-text row reached by just typing. Questions stage one at a time, exactly as the Web UI composer stages them.
  • Identical answer encoding to the Web UI: a free-text answer replaces the selection for a single-select question and accompanies it for a multi-select one.
  • Plan review built in: a question carrying the plan-review intent — what exit_plan_mode sends — renders the plan markdown in a scrollable PgUp/PgDn + wheel pane above Approve / Keep planning. Approving exits plan mode; previously plan review failed closed because the TUI had no answerer at all.
  • Keys: Up/Down move, Space toggles or selects, Enter continues, typing jumps to the free-text row, Esc defers, and Ctrl+C still cancels the running turn.
  • The tool row matters: dsh-base mounts the user-questions service but not @deepseek-ai/dsh-tool-ask-user — the agent presets mount the tool, and a TUI session composes from the base rather than from a preset. The bundle now declares the tool-ask-user row itself; without it the tool is absent from the model's catalog.

Docs

  • README rewritten: badges, table of contents, a feature table, three install paths with the -w requirement explained, keybinding and slash-command tables, the interactive-prompt reference, settings, updates, architecture, the build-install development loop, a troubleshooting table, and known limitations.
  • Chinese manual updated to match, with a new section on the question modal and on version channels.
  • The README no longer embeds images (docs/max-thinking.gif removed).

Install

dsh plugin --profile tui add -w dsh-oc-tui                 # from npm
dsh plugin --profile tui add -w ./dsh-oc-tui-0.1.2.tgz     # from the asset below

dsh-oc-tui v0.1.2(中文)

v0.1.2 是所有用户都应升级到的版本:它让 TUI 在 dsh 0.1.2-rc.1 上重新可用,并补上了此前 TUI 与文档都没有的「模型向你提问」弹窗(选项列表、多选、自由文本、计划评审)。

推荐搭配

  • 推荐组合:dsh-oc-tui 0.1.2 + dsh 0.1.2-rc.1。同时仍兼容 dsh 0.1.1-rc.2——一份构建服务两条版本线。
  • 升级方式:界面内 Ctrl+P → Update → dsh-oc-tui → Versions,或命令行 dsh plugin --profile tui add -w dsh-oc-tui@0.1.2。
  • npm 包与 awesome-dsh-plugin 收录都只提供稳定版,永不发布预发布版本。

修复 —— 在 dsh 0.1.2 上 TUI 原本完全不可用

  • dsh 0.1.2 移除了 Session.events。 转录重放会在「打开会话」这条共用路径上读取该 getter,导致每一次开会话都失败并报 failed to open session: session.events is not iterable。现在插件优先使用 Session.snapshotEvents()、并回退到旧 getter,因此同一份构建在 0.1.1 与 0.1.2 上都能工作。
  • --resume 与 agent factory 的启动竞态。 在 dsh-agent-loop 那一行调用 ctx.agents.setFactory() 之前,ctx.agents.create/resume 会抛 no agent factory registered (load an agent-loop plugin)。--resume 是在 apply 期开会话的,可能输掉这个竞态;而新会话(首条输入时才开)不会。现在该路径会用有界等待重试这一个特定错误。
  • 一键安装脚本修好了:install.sh / install.ps1 现在会传 -w。profile 目录本身是 pnpm workspace 根,裸 add 会失败并报 ERR_PNPM_ADDING_TO_ROOT——在此之前这两个脚本根本装不成功。

新功能 —— 交互式提问(ask_user_question)

模型现在可以暂停当前轮次向你提问,而你的回答会作为一次普通的工具结果回到模型。

  • 终端内的弹窗:带描述的选项列表、单选与多选、以及直接打字即可进入的自由文本行。问题一次问一个,与 WebUI composer 的分步方式完全一致。
  • 答案编码与 WebUI 完全相同:自由文本答案在单选问题中替换已选选项,在多选题中与已选项并存。
  • 内置计划评审:带 plan-review 意图的问题(即 exit_plan_mode 发出的那种)会把计划 markdown 渲染在上方可滚动区域(PgUp/PgDn + 滚轮),下面是 Approve / Keep planning。选 Approve 即退出计划模式;在此之前计划评审会因为 TUI 没有任何应答者而直接失败。
  • 按键:↑/↓ 移动、Space 切换或选中、Enter 继续、直接打字跳到自由文本行、Esc 让出,Ctrl+C 仍然取消进行中的轮次。
  • 那一行挂载很关键:dsh-base 只挂载 user-questions 服务,不挂载 @deepseek-ai/dsh-tool-ask-user 工具;工具是 agent 预设挂的,而 TUI 会话是从 base 进程级组合、不走预设。本 bundle 现在自己声明 tool-ask-user 行——没有它,模型工具表里根本不存在这个工具。

文档

  • README 重写:徽章、目录、功能表、三条安装路径(并解释 -w 的必要性)、快捷键与斜杠命令表、交互式提示参考、设置、更新、架构、构建-安装开发回路、故障排查表、已知限制。
  • 中文手册同步更新,新增问答弹窗与版本渠道章节。
  • README 不再嵌入图片(已删除 docs/max-thinking.gif)。

安装

dsh plugin --profile tui add -w dsh-oc-tui                 # 从 npm 安装
dsh plugin --profile tui add -w ./dsh-oc-tui-0.1.2.tgz     # 从下方资产安装

0.1.1

Choose a tag to compare

@rayafriandion rayafriandion released this 04 Sep 09:48

dsh-oc-tui v0.1.1

v0.1.1 is the recommended version for all users: it adds the in-app update manager and fixes a Windows update trap that could silently corrupt the global dsh install.

Recommended version

  • Recommended pairing: dsh-oc-tui 0.1.1 + dsh 0.1.1-rc.2 or newer (including dsh 0.1.2-rc.1). 0.1.1 adapts to the dsh 0.1.1-rc.2 plugin API.
  • Upgrade paths: in-app Ctrl+P → Update → dsh-oc-tui → Versions, or on the command line dsh plugin --profile tui add -E dsh-oc-tui@0.1.1.

What's new

  • In-app update manager (Ctrl+P → Update): a new Update settings tab detecting the installed versions, registry versions, and dist-tags of @deepseek-ai/dsh and dsh-oc-tui; a version list (newest first) with color-coded [latest] (green) / [next] (cyan) / (installed) (light blue) markers; pick any version (pre-releases included) to switch to, confirm with y/n, and the install goes through npm / dsh plugin, respecting your configured registry and mirror. Update prompts target stable releases only — pre-releases never prompt. Check now re-reads the registry; Startup check runs a silent background check at boot (on by default, toggleable, synced to the dsh web settings). Checks and installs are fully async — the UI never blocks; the page subtitle shows a spinner while busy.
  • Update entry in the settings menu: Main → System gains an Update manager shortcut row; the settings left menu extends to three tabs (Main / Model / Update).
  • Launcher injects DSH_TUI_BOOT_PROFILE: the dsh-oc-tui launcher passes the profile name to the plugin, so the updater installs/switches the TUI into the right profile without guessing (non-default profiles supported).
  • Slash commands on the title screen: commands such as /new now work before entering a session, and command hints show full command names.

Fixes

  • (Critical) Updating dsh on Windows silently corrupted the global install: the updater ran npm install -g while dsh processes were still running (including the TUI itself). Windows locks native DLLs loaded by a running process (sharp), npm failed to replace the directory — and still exited 0, leaving a hybrid old/new tree that failed to boot with loader entries failed / missing State / ./internal exports. 0.1.1 adds three layers of protection:
    • On Windows, dsh installs are deferred until the TUI exits: a detached helper process waits for this process to exit, runs the install, and records the outcome in $DSH_HOME/tui-dsh-install.json, which the Update page verifies on the next visit.
    • Every direct install re-reads the on-disk manifest and compares versions after npm finishes — a mismatch (silent corruption) surfaces as an install corrupt toast with repair instructions, instead of trusting the npm exit code alone.
    • The Update page dsh Status row flags an already-damaged install in red: Install damaged — reinstall below.
    • macOS/Linux have no DLL lock, but the install is refused while other dsh processes (e.g. dsh web) are running.
  • Local-install switch warning: when the TUI is installed from a file:/local path, the confirm text now warns that switching converts it to a registry install.
  • Adapted to the dsh 0.1.1-rc.2 plugin API (earlier fix in the 0.1.1 series, including the PR #2 merge).
  • Test suite extended to 334 assertions (including real-process E2E regressions: node -e argv parsing, non-zero exit classification).

Requirements

  • Node.js ≥ 22
  • DeepSeek Harness (dsh) 0.1.1-rc.2 or newer

Install

dsh plugin --profile tui add -E dsh-oc-tui@0.1.1
dsh --profile tui

Or download dsh-oc-tui-0.1.1.tgz from the assets and run: dsh plugin --profile tui add -E /path/to/dsh-oc-tui-0.1.1.tgz


中文版

dsh-oc-tui v0.1.1

0.1.1 是推荐所有用户升级的版本:新增程序内更新管理器,并修复了一个会导致全局 dsh 安装静默损坏的 Windows 更新陷阱。

推荐版本

  • 推荐升级路径:dsh-oc-tui 0.1.1 + dsh 0.1.1-rc.2 或更新(含 dsh 0.1.2-rc.1)。0.1.1 适配了 dsh 0.1.1-rc.2 的插件 API。
  • 升级方式:TUI 内 Ctrl+P → Update → dsh-oc-tui → Versions,或命令行 dsh plugin --profile tui add -E dsh-oc-tui@0.1.1。

更新内容

  • 程序内更新管理器(Ctrl+P → Update):新建 Update 设置页,检测 @deepseek-ai/dsh 与 dsh-oc-tui 的已装版本、npm registry 版本与 dist-tags;版本列表(新→旧)带 [latest](绿)/[next](青)/(installed)(浅蓝)彩色标识,可选择任意版本(含 pre-release)切换,y/n 确认后通过 npm / dsh plugin 安装,尊重用户配置的 registry 与镜像;更新建议只以稳定版为目标,pre-release 不主动提示;Check now 手动重新检查;Startup check 启动后台静默检查(默认开启、可关闭,开关同步到 dsh Web 设置页);检查与安装全程异步不阻塞界面,安装期间页面副标题显示 spinner。
  • 设置菜单新增 Update 入口:Main → System 增加 Update manager 快捷行;设置页左侧菜单扩展为 Main / Model / Update 三个标签。
  • launcher 注入 DSH_TUI_BOOT_PROFILE:dsh-oc-tui 启动器把当前 profile 名传给插件,更新器安装/切换 TUI 时不再猜测目标 profile(支持非默认 profile)。
  • 斜杠命令在标题屏可用:标题屏(未进会话)也能执行 /new 等命令,命令提示显示完整命令名。

修复问题

  • (重要)Windows 上更新 dsh 会静默损坏全局安装:更新器在 dsh 进程仍在运行(包括 TUI 自己)时执行 npm install -g,Windows 锁定运行中进程加载的 sharp 原生 DLL,npm 替换目录失败后仍报成功,留下新旧版本混杂的损坏安装树,下次启动报 loader entries failed、State/./internal 导出不存在。0.1.1 起三层防护:
    • Windows 上 dsh 安装延迟到 TUI 退出时执行(detached 独立进程等待本进程退出后再安装,结果写入 $DSH_HOME/tui-dsh-install.json,下次打开 Update 页自动核对);
    • 所有直接安装完成后重读磁盘 manifest 校验版本,退出码与版本不符即报 install corrupt 并给出修复命令,不再只信 npm 退出码;
    • Update 页 dsh Status 行会对已损坏的安装显示红色 Install damaged — reinstall below 修复指引。
    • macOS/Linux 无 DLL 锁,但检测到其他 dsh 进程(如 dsh web)运行时会拒绝安装并提示先关闭。
  • 本地安装切换确认提示:TUI 为 file:/本地路径安装时,切换到 registry 版本前确认文案会明确提示。
  • 适配 dsh 0.1.1-rc.2 插件 API(0.1.1 系列内早前修复,含 PR #2 合并)。
  • 测试套件扩展到 334 个断言(含真实进程 E2E 回归:node -e argv 解析、非零退出码分类)。

Requirements

  • Node.js ≥ 22
  • DeepSeek Harness(dsh)0.1.1-rc.2 或更新

Install

dsh plugin --profile tui add -E dsh-oc-tui@0.1.1
dsh --profile tui

或从附件下载 dsh-oc-tui-0.1.1.tgz 后:dsh plugin --profile tui add -E /path/to/dsh-oc-tui-0.1.1.tgz

0.1.0

Choose a tag to compare

@rayafriandion rayafriandion released this 24 Aug 15:54
2dd1a45

DeepSeek Harness TUI v0.1.0

An opencode-inspired terminal UI for DeepSeek Harness, booting as a profile app plugin. Dark blue theme, session sidebar, streaming chat transcript, and a context meter.

Features

  • Chat interface — streaming assistant responses with thinking/reasoning blocks (collapsible), tool call rendering, todo lists, and system notes
  • Context meter — port of the web ContextMeter: always-visible occupancy bar with click-open breakdown panel showing system prompt / tools / messages composition
  • Reasoning-effort slider — driven by the current model's actual selectable levels, with an animated "max effort" effect
  • Composer — multi-line input with command autocomplete (/new, /model, /settings, etc.), pasted-image support, and a flowing (marching-ants) frame while a turn runs
  • Session management — sidebar with recent sessions, Ctrl+N new session, double Ctrl+D to delete
  • Settings dialog — shared with the DeepSeek Harness WebUI, with left-menu navigation (Main / Model) and scroll support
  • Mouse support — left-drag text selection with right-click copy, click-to-toggle thinking/notes, scroll wheel, focus-follows-cursor
  • Cross-platform install — automatic install scripts for Linux and Windows, dsh-oc-tui launcher

Fixes

  • Fixed panel windows (context meter, help, settings) rendering with missing backgrounds and misaligned borders when over CJK text
  • Fixed orphaned wide-character (CJK/emoji) continuation cells causing column misalignment when overlays cover them
  • Fixed npx.cmd spawn warning on Windows
  • Tolerate null/undefined input in setContextMeter

Requirements

  • Node.js ≥ 22
  • DeepSeek Harness (dsh) installed as a peer