Skip to content

Releases: cyjyyd/dsh-ssh-tui

0.8.4

Choose a tag to compare

@cyjyyd cyjyyd released this 27 Oct 08:33

0.8.4 — Input Ownership & Release Hardening (Stable)

稳定版:0.8.4-rc.2 观察期结束后的正式转正。 包版本为 0.8.4;产品代码与最终 RC.2
相同,只有版本元数据和发布材料变化,没有新增功能、兼容范围变化或存储迁移。
正式 tag、GitHub Release 与 npm latest 在最终四腿 CI 和规范 tarball 验证通过后创建;
next 同步到 0.8.4,不再停留在旧候选。

0.8.4-rc.2 的候选说明与收据保留在
release-notes-0.8.4-rc.2.md;0.8.4-rc.1 的历史记录保留在
release-notes-0.8.4-rc.1.md,不追溯改写。

dsh-ssh-tui 现在以 DSH Relay 为产品名展示;npm 包名与安装命令没有变化。

版本状态

  • 0.8.4-rc.1 的 annotated tag 是 a2645c9134646f83d8a5db758743476285f9840b,其指向的提交是
    0e1342a9f4a7cbb922971891e9b26a311a7c7026(2026-10-17)。
  • 0.8.4-rc.2 的 annotated tag 是 aa1688264c9ae246eb20651caced38bfd69d68d1,其指向的提交是
    5795f6052cdaba565b0db9bf1982aa622f40ac05(2026-10-24),已作为候选发布到 npm next。
  • 0.8.4 从该 RC.2 转正;稳定版只把包版本改为 0.8.4 并更新发布材料,没有产品代码变化。
    Stable 维护来源是 release/0.8.4,不是 main;main 上的 W-4 Completion 或 W-5 Search Screen
    不属于本线。
  • 正式发布后 npm latest 和 next 都指向 0.8.4。RC.2 的 tarball 哈希和测试收据保留为历史,
    不作为 0.8.4 稳定 tarball 的哈希。

本版包含(RC.1 之后)

FI1 — 首次安装的 Agent Plane 自动补齐

首次向导保存后、以及旧或不完整 profile 启动时,TUI 只补当前组合缺少的 Agent Plane 工具行;
已存在的行不重复写入,写入前保留备份,重复启动保持幂等。若行已经写入但当前进程尚未组合它们,
界面会明确提示重启,而不是把“已保存”误报成“已生效”。这不是安装钩子,也不会把所有缺失行
无条件重写。

WIN-CI1.H3 — RTT 探针的 Drain 不再丢弃按住的 Esc

RTT/liveness 探针开始时,输入过滤器可能正扣着一个单字节,因为它还可能是光标应答 CSI ... R
的开头。TerminalInputPump.drain() 不再重置过滤器并丢掉这个字节,而是保留它并重新安排释放:
如果后续应答到达,字节合并为应答;如果窗口结束仍不完整,就按原有规则交还为键入。切开的应答
仍不会被误认成 Escape。

APPR.BP1 — AI Reviewer 传递真实授权 Session

Reviewer 的 GenerateOptions 现在携带授权 Agent 的真实 sessionId。同一 Session 的复核共享
身份,不同 Session 或子 Agent 不共享。Reviewer prompt、400-token budget、15 秒 deadline、
reasoning effort、授权策略、缓存与 fail-closed 行为均未改变;该修复不写入用户对话记录。

DOC.R1 — /doctor 纳入已注册 Adapter

doctorRouting() 保留 llm-pi-ai.providers,并合并 ctx.llm.listProviders() 返回的实际注册
Adapter ID,去重后用于路由自洽性检查。已注册的 deepseek-official 不再被误报为“不在已配置
路由里”;第三方 Provider 缺失、已配置 Provider 的非法模型、以及子代理跨 Provider Family
仍会继续告警。LLM 服务缺失或 listProviders() 抛错时回退到已配置集合,/doctor 不会崩溃。

“已注册或已配置”只表示路由存在,不表示网络或 API 调用成功。官方模型目录的实时校验仍是
OPEN:routeModels 为空时继续按“目录未知”处理,不会伪造 Model Missing。

兼容性

声明窗口与 0.8.4-rc.1 相同,没有新增兼容声明:

>=0.2.0-rc.1 <0.2.1 || >=0.2.1-rc.2 <0.2.2
  • 0.2.1-rc.2 仍是默认开发线。
  • 0.2.0-rc.1 / 0.2.0-rc.2 继续保留兼容表态与 CI 腿。
  • 0.1.7 线自 0.8.4-rc.1 起为 incompatible。
  • 0.1.5 及更早从 0.8.0 起不再支持。

验证记录

0.8.4 与最终 RC.2 的产品代码相同;以下测试收据来自 RC.2 的最终验证,稳定版只改版本和发布材料:

  • npm run build:通过。
  • npm run typecheck:通过。
  • npm test:1540 项,1536 通过,0 失败,4 跳过。
  • npm run freeze / npm run freeze:input:通过。
  • npm run bench:五个动作均为增量绘制,0 次整屏清屏。
  • npm run bench:report -- --check:通过。
  • scripts/artifact-smoke.mjs:RC.2 候选 tarball 通过,包清单 252 files。
  • scripts/upgrade-smoke.mjs --from 0.8.4-rc.1 --pack 与 --from 0.8.3 --pack:通过
    (manifest、bundle 入口、凭据与会话存储均保留)。
  • 最终 0.8.4 的四腿 CI、规范 tarball 的 bytes / SHA1 / SHA256 / integrity 与 Registry
    回读结果记录在独立发布回执中;本文件不把 RC.2 的哈希写成稳定 tarball 的哈希。

Windows Terminal、conhost、IME 中文输入、多行中文粘贴、鼠标复制与 SSH 恢复仍按
release.md 的人工验收清单执行;H-2 的 conhost / ASCII 边框确认已由维护者完成,
其余未实际人工执行的项目仍保持 PENDING,不引用旧版本结果冒充本版验收。自动化 PASS 不是
人工 Gate PASS。

已知限制

  • 官方模型目录校验仍 OPEN:/doctor 可以看到已注册的官方 Provider,但尚未异步读取
    llm.listModels('deepseek-official') 来校验官方模型成员;自定义官方 Catalog 缺少所选模型时
    仍可能漏诊。
  • 过滤框对非 BMP 字符的限制(未修):picker 的过滤框仍以 text.length === 1 判单字符,
    '🚀'.length === 2,因此星平面字符在过滤框中会被丢弃。Composer、借用字段与向导字段正常。
  • 陈旧 lib/ 的打包风险(未修):tsc 不清理旧输出,prepack 也不跑 clean;发布必须从
    干净树构建。artifact-smoke 的清单检查是纪律证据,但脚本本身不阻止脏树打包。
  • 时间敏感的 Windows 单元测试:session-list.test.mjs 中 150ms mock 竞速用例在慢跑器上可能
    失败;这是测试 oracle 问题,不是产品行为,本版未修。
  • ConPTY 无法覆盖的帧级断言:ConPTY 会重写行寻址并自行插入清屏,逐行寻址/不清屏类检查在
    Windows 上标记为 NOT_MEASURED;功能断言照常执行。
  • 发布后 registry 比对仍是人工步骤:发布前自动化 pack → 清单 → 安装 → 探针;发布后从
    registry 取回 tarball、核对 shasum/integrity 与 lib/ 仍按 docs/release.md 执行。

安装

稳定版走 latest,当前正式版本为 0.8.4:

dsh plugin --profile tui add dsh-ssh-tui@latest
dsh --profile tui

@next 也已同步到 0.8.4;需要固定版本时可显式使用 dsh-ssh-tui@0.8.4。

历史候选仍可按精确版本安装:

# 历史 RC.2
dsh plugin --profile tui add dsh-ssh-tui@0.8.4-rc.2

# 历史 RC.1
dsh plugin --profile tui add dsh-ssh-tui@0.8.4-rc.1

已安装 0.8.3、0.8.4-rc.1 或 0.8.4-rc.2 的用户可以升级;配置、凭据和会话记录不需要迁移。

0.8.4-rc.2

0.8.4-rc.2 Pre-release
Pre-release

Choose a tag to compare

@cyjyyd cyjyyd released this 24 Oct 14:31
5795f60

0.8.4-rc.2 — First-install, Input & Doctor Reliability Candidate

发布通道:仅 npm next,不得触及 latest。
此文档是候选版的发版说明;它本身不表示已经创建 Tag、GitHub Release 或完成 npm 发布。
候选来源:从 release/0.8.4@127617b99101820ff548f6fa8b61f319b5084d24 切出的独立发行准备分支。

DSH Relay 仍使用 npm 包名 dsh-ssh-tui,没有改名、没有存储格式迁移。

为什么需要 RC.2

0.8.4-rc.1(2026-10-17)已经作为 prerelease 发布;它提供 Reader → Router → Owner 输入归属整理,以及首次安装向导、工作区粘贴和发布 tarball 的 CI 门禁。

此后维护分支进行了四项实际运行时修复,因此 RC.2 不是 RC.1 的无变化重打包,不能沿用 RC.1 的字节、哈希、测试或人工验收收据。

RC.1 之后的修复

FI1 — First-install Agent Plane Repair

全新安装或旧的不完整 Profile 可能缺少 tool-ask-user 与 present 的 Agent Plane 组合行。TUI 现在能检测并定向补齐缺失项,写前备份、不覆盖已存在行、重复启动幂等。已写入但本进程尚未组合的工具会明确提示重启才生效,不把保存成功误报为运行时就绪。

WIN-CI1.H3 — RTT Probe 不再丢弃 Esc

Launcher 的 TerminalInputPump.drain() 原先会把正在等待判别的 ESC 通过 filter.reset() 丢弃:用户按下 Esc 后,恰逢 RTT/存活探测,/view 选择器可能无法取消。现在保留暂存字节、重新安排释放;完整或分片的光标应答仍由过滤器识别,不以强制转发半截应答换取按键恢复。

APPR.BP1 — Reviewer 绑定授权 Session

AI Reviewer 的直接 llm.stream() 调用携带 request.agent.session.id,保留同一会话身份、隔离不同 Agent Session 和子代理。Reviewer prompt、400-token 输出预算、15 秒 deadline、reasoningEffort: off、授权策略、缓存与 fail-closed 保持原样。未对完整真实线上审批延迟作保证。

DOC.R1 — 官方 Provider 路由诊断

/doctor 的路由事实来自 llm-pi-ai.providers 与实际注册的 ctx.llm.listProviders() 的并集。官方 deepseek-official 已注册时不再被误报为“既未注册也未配置”,仍保留第三方非法模型与子代理不同族警告。注册不等于联网调用成功,官方模型目录的实时成员校验仍为 OPEN。

未纳入本候选

  • W-4 Completion / W-5 Search Screen(main 开发线),未进入 release/0.8.4;
  • PR #8 的独立 InputReader 粘贴尾部 Esc 边界修复(慢粘贴 payload ESC 语义权衡仍未收口);
  • PR #9 的 Host/Relay 诊断插桩;
  • 官方模型目录实时校验、Reviewer 延迟预算重设计,以及其他未获授权的兼容范围变化。

兼容范围

与 RC.1 一致:

>=0.2.0-rc.1 <0.2.1 || >=0.2.1-rc.2 <0.2.2

默认宿主开发线为 0.2.1-rc.2,兼容测试仍覆盖 0.2.0-rc.1 / 0.2.0-rc.2。0.1.7 及更旧宿主不在本候选支持范围内。

发布前证据门槛

以下证据必须绑定最终候选 Commit 与其 tarball,不能沿用 RC.1 或 Stable 的旧收据:

Gate 必需结果
源码与包身份 package.json 和 lockfile 同为 0.8.4-rc.2;候选 Git SHA 冻结
四条 CI Linux 三线及 Windows test-windows 全部 SUCCESS
三道阻塞门 Fresh-home 向导、Paste Probe、Packed Artifact 在默认 Linux 和 Windows 真实执行
产物可重复性 干净构建、npm pack 文件清单、bytes、shasum、integrity 与候选 SHA 对应
升级验证 upgrade-smoke --from 0.8.4-rc.1 --pack;并核对 0.8.3 → RC.2
Windows 人工 真正 Windows Terminal / conhost、IME、中文粘贴、复制、重连、首次安装,H-1~H-11 逐项 PASS
最终发布许可 维护者明确授权 Tag / GitHub prerelease / npm publish --tag next

本文件不预先给出未生成的 RC.2 tarball 哈希、文件数或 CI 成功结论,人工 Gate 亦不得由 ConPTY 自动探针代替。

安装与发布通道

在 RC.2 正式发布之前,registry 的可用版本请以实际 packument 为准;既有历史记录中 latest 为 0.8.3,next 为 0.8.4-rc.1。

获得正式 RC.2 发布授权后,候选用户才能通过 dsh plugin --profile tui add dsh-ssh-tui@0.8.4-rc.2 或更新后的 @next 安装。正式 0.8.4 发布另走 latest,不在这次候选动作范围内。

历史候选记录:0.8.4-rc.1。正式稳定版准备说明:0.8.4。

v0.8.4-rc.1 — 输入归属 + 发布安全门(候选版)

Choose a tag to compare

@cyjyyd cyjyyd released this 17 Oct 15:51

0.8.4-rc.1 — Input Ownership & Release Hardening Candidate

发布方式:只上 next。 latest 保持 0.8.3(候选版不占 latest)。
上一次发版:0.8.3(2026-10-13,latest + next)。本文件描述的是候选版,
是否转正由独立审核与后续发版决定。

本版同时是:输入可靠性的修复批次、内部输入路由的结构整理、以及发布安全门的加固。
与 0.8.3 相比有 runtime 行为变化(见「修复」),这一点如实写在最前面;本轮发布准备
只为跨线兼容加了一处垫片(见「跨宿主线的兼容垫片」),没有别的 runtime 改动。

dsh-ssh-tui is now presented as DSH Relay.
The npm package name and the install command have not changed.

dsh-ssh-tui 现在以 DSH Relay 为产品名展示;npm 包名与安装命令没有变化。

没有协议变更、没有配置迁移、没有数据格式变更。升级即生效,不需要任何迁移动作。

概览

0.8.4-rc.1 的主线是输入归属:一次终端 read 里往往不止一个键(粘贴、合并读取、带尾巴的序列),
0.8.3 及以前由一串顺序判断逐段消费它们,于是同一类缺陷反复出现在不同 Owner 上——Screen 背后的草稿被
粘贴改写、Surface 的编辑键去改看不见的草稿、一次 read 里的第二个键被丢掉。这一版把这条路径拆成三层
(Reader 分帧 → Router 判定归属 → Owner 执行),并把每一层的行为用轨迹、归属矩阵与变异测试钉住。

同时,0.8.3 的真实事故(首次安装时向导收不下粘贴的 API Key)暴露了发布流程本身的缺口:CI 从来没有
跑过"未配置 home 的首启向导",也从来没有跑过 npm 发布包本身。这一版把两者都变成阻塞门。

修复

一次 read 不是一个键(W-3a / W-3a.1)

终端的粘贴、合并读取、以及"序列 + 尾巴"都会把多个键塞进同一次 read。此前合并 read 里的第二个键会被
整段匹配失败吞掉(two arrows in one read 两个都没移动、PgUp 连按只滚一次、改绑键与其它键同 read
时绑定丢失)。现在 Reader 把 read 切成单元(完整序列、Alt 和弦、控制字节、CR/LF、一段文本),
每个单元各问一次归属,于是"同一次 read"与"分两次 read"到达同一位置、同一终态。
Screen 的边界在单元内部同样成立:关闭 Screen 的那个字符之后的同一单元剩余部分被丢弃,而不是
落到它背后的 Composer(真实入口是粘贴尾巴 \x1bq)。

  • 提交:f7e5849(W-3a)、f44b56c(W-3a.1)
  • 证据:tests/input-reader.test.mjs(成对轨迹)、tests/input-ownership-regression.test.mjs、
    tests/input-reader-traces.json(参考轨迹 72 → 111 条;两条是本次切分用例,一条只改 handleInputText
    的拼接形状、消费者调用与终态不变)

Surface 的编辑键归 Surface,编辑的是读者看得见的那一行(W-3b.1)

Surface 打开时,Home/End/Delete 与 kitty 的复制序列此前被放行给 Composer:Home/End 移动看不见的
草稿光标,Delete 编辑它。现在这几个单元归 Surface——有借用字段就编辑屏幕上那一行,没有就消费掉。
复制键在 Surface 下保持无操作(与它原来的可观察行为一致)。

  • 提交:5ad6290
  • 证据:tests/input-ownership-matrix.test.mjs、tests/interaction-surface.test.mjs

借用字段的终端光标跟随它自己(W-3b.1a)

绘制时终端光标取的是隐藏草稿的列号,于是借用字段(自由文本问题)里光标会落在错误位置——中文与
宽字符下尤其明显。现在光标跟随正在绘制的字段。

  • 提交:fd3f638
  • 证据:tests/borrowed-field-caret.test.mjs(真实终端网格)

输入一个 emoji 会直接崩溃(W-3b.1b)

在 Composer 里输入 🚀、𠮷 等非 BMP 字符会抛 RangeError: Maximum call stack size exceeded:
判定"这是不是一段文本"用的是 UTF-16 长度(🚀.length 是 2,但它是一个码点),于是同一个码点被无限次
送回自己。借用字段与确认框同样命中。现在按码点判定,ASCII 热路径零分配;多字符单元仍逐码点重新判定
(yes 在确认框上仍然由第一个字符作答、随后的 es 仍交给它当时的 Owner)。
同一根因的第二处(借用字段的 grapheme 编辑切的是隐藏草稿而不是借用字段)一并修掉。

  • 提交:d0db720
  • 证据:tests/unicode-input-safety.test.mjs(12 条:Composer/借用字段/拒绝方、UTF-8 逐字节分片、
    粘贴与键入等价、grapheme 编辑),与修复前构建 40 个场景逐字节等价

一个 Surface 借走字段后,不再改写 Composer 的历史与草稿(W-3b.3a)

两条实际可达的越权路径:借用字段里的退格 / Delete / Ctrl+U / Ctrl+K / 粘贴会经
leaveHistoryBrowse() 结束 Composer 的历史浏览,并把正在浏览的那条历史写进 historyDraft——
读者原先未发送的草稿再也回不来;Surface 打开时 Alt+f / Alt+F / Alt+/ 会把 /find 直接写进
看不见的草稿。现在历史浏览只由 Composer 自己的字段结束,/find 种子只写进 Composer 拥有的字段
(Surface 内该和弦被消费),Alt+1…4 / Alt+n/p 的既有语义保持不变。

  • 提交:48efd24
  • 证据:tests/surface-state-isolation.test.mjs(真实 ↑ 进入浏览的完整流程)、
    scripts/input-freeze-audit.mjs 新增 composer history 写入类与 historyGuards 检查

反馈行不再随消息长度漂移(W-3b.2a)

/copy 之类的回执此前是状态行上最低优先级的一组,放得下就画在第一行、放不下才退到最后一行——
同一条消息的行号由它的长度与窗口宽度决定(真实报告:"copy 提示跑到第一行")。现在回执恒在身份行,
状态行只留仪表;警告(notice)仍优先于回执。

  • 提交:915578f
  • 证据:tests/feedback-routing.test.mjs(短/长回执、notice、160/100/60/40 列)
  • Ctrl+L 的重绘归属经独立审核后保留双 Painter(KEEP_DUAL),合同与理由见 AD-22 §10;
    证据 tests/ctrl-l-repaint.test.mjs(一次有意的完整清屏,之后回到增量)

粘贴的结束标记被切成两半(W-1 补)

终端的粘贴用 ESC[200~ … ESC[201~ 包起来,而字节流不保证按 read 边界对齐:ESC[201~ 可能分成
…ESC[20 和 1~ 两次到达。麻烦在于 ESC[20 同时是"半个光标应答"的形状——输入过滤器会先把它扣住,
30ms 后当打字放行。于是后半截到达时已经没有开头,Reader 的粘贴状态永远关不掉:此后每个键都被当作
粘贴内容,Esc 关不掉对话框,/exit 也退不出去(只能杀进程)。

这条不是本版引入的:0.8.3 的内联实现有同样的跨 read 粘贴状态与同样的朴素切分,所以同样中招;只是要
"结束标记恰好跨两次 read 到达"才触发,之前没人撞上。本版新增的 tui-paste-probe.mjs 在 CI 上撞上了
(/view 对话框里的 Esc 不再生效),才把它逼出来。

修法两处,各管一半:

  • 输入过滤器(TerminalInputFilter):粘贴流量里的尾巴不再被当成半个应答扣留——设备应答不会出现在
    括号粘贴里面;

  • Reader(InputReader):把切开的标记留到下一读补齐;另有一只看门狗盯整段粘贴——2 秒内没有任何
    粘贴流量就认定这次粘贴已经结束(终端的 close marker 有可能被直接吞掉,ConPTY 就会吞掉半个 CSI),
    把状态放回"不在粘贴中",而不是让键盘继续当粘贴内容。

  • 证据:tests/input-reader.test.mjs(跨 read 补齐 + 悬空尾巴放行)、tests/terminal-input.test.mjs
    (粘贴尾巴不扣留)、scripts/tui-paste-probe.mjs 的 "split-marker" 步骤(粘贴后 Esc 仍必须是键)

跨宿主线的兼容垫片(0.2.1-rc.2)

/subagents kill <id> 调用 subagent 服务的 drainContinuableChildren(parent, ids);0.2.1-rc.2 把它
改名为 drainChildren(parent, ids)(同义、签名一致),旧名不再存在。窗口里同时有两条线,所以调用点
改走 src/dsh-compat.ts 的 drainChildSubagents():它按宿主实际拥有的名字调用,两者都没有时解析为
Promise.resolve()。这是本版唯一一处为兼容而改的 runtime 代码。

  • 证据:npm run typecheck 在 0.2.1-rc.2 上 0 error;0.2.0 两条腿在 CI 上同样编译(它们只认旧名)。

内部结构

  • Reader(src/input-reader.ts,新文件,W-1):解码、探测回复过滤、ESC 组装、粘贴边界、单元切分。
  • Router(src/input-router.ts,新文件,W-2):route(kind, unit, ownershipView) → screen | surface | composer | workspace,纯函数、无状态;handleInputText 变成 Reader → Router → owner 三行能读完。
  • 共享执行体的合同:composerUnit 仍是 Composer 与 Surface 的共用执行体,经必要性审核后保留
    (KEEP_SHARED_WITH_INVARIANTS,S-1…S-6,AD-20 §19)。本版没有做 executor split,也不打算在
    0.8.4 里做;完整拆分留给后续的独立结构轮。
  • W-3b ownership / input-routing 合同已收口(CLOSED):G1–G4 证据(Surface × 共享体敏感键、
    options question / filtering picker 进归属矩阵、两条 /find 种子路径、Ctrl+N/P 的焦点环记录)
    与 M1–M7 变异全部实测为红。
  • 参考轨迹 111 条(两条新增;paste-split-close-marker 的拼接形状改变,消费者调用与终态不变):
    新增只追加,旧读法以台账形式记录在
    tests/input-reader.test.mjs 的 GAP_FIXTURES / W3A1_FIXTURES / W3B1_FIXTURES / W3B1B_FIXTURES。

发布安全门(Release Hardening)

这一版新增三道阻塞门,在 CI 的默认腿(0.2.1-rc.2)与 test-windows 上各跑一次:

  1. 首次安装向导(probe-home.mjs --probe --unconfigured --script tui-setup-probe.mjs):
    在真实 PTY / ConPTY 上用未配置的 home 启动 → 向导自动出现 → 列表步 → 字段步 →
    括号粘贴一段 API Key → 字段收下且全程掩码(掩码按 • 计数断言,密钥既不出现在画面、
    也不出现在原始字节流里)→ resize → Esc 交还工作区 → 写入凭据后再启动不再出现向导 →
    resumed 首启保存:走完九步按 y,不需要任何额外按键工作区自己回来。

  2. 发布产物冒烟(scripts/artifact-smoke.mjs):npm pack 出真实 tarball → 检查包内清单
    (必须有 package.json / lib/index.js / lib/tui.js / cordis.patch.yml / README.md /
    LICENSE;不得有 src/tests/scripts/.github/本地缓存/嵌套 tgz/node_modules)→
    把 tarball 装进仓库之外的临时 home(不是 link:<repo>)→ 证明 dependencies 记录的是
    file:<tgz>、安装实体不是指向 checkout 的符号链接、realpath 在 profile 内且不等于仓库 →
    --dump-config 通过 → 在上述安装产物上再跑一遍向导探针、工作区探针与粘贴探针。

  3. 粘贴探针(probe-home.mjs --probe --script tui-paste-probe.mjs):世界不是只靠打字——0.8.2 的事故
    是粘贴进不了字段,而当时的探针只会打字。向导那一半在第 1 道门里;这一道补工作区那一半:
    单行粘贴落进 Composer、多行粘贴只插入不提交、Ctrl+U 清空、4 kB 粘贴不崩不闪、
    Screen / picker 打开时粘贴不漏进层、也不落到背后的 Composer、粘贴里的 \x1bq 尾巴保持字面
    (不当作 Esc 关掉 Screen)、结束标记被切成两半后键盘仍然可用(这一步在 ConPTY 上跳过并说明原因:
    它会把半个 CSI 直接吞掉,切不出这个形状;那里的"粘贴后 Esc 仍然生效"由别的步骤覆盖)。
    负向证明:把 Reader 的
    paste 分帧关掉(isPasteRead() 恒 false),
    该探针立刻判红("多行粘贴没进 Composer"——即粘贴被当成按键执行了)。

另外:

  • scripts/upgrade-smoke.mjs(基础设施):装上一个已发布版本 → 写凭据与会话 → 装候选 →
    断言 bundle 条目、凭据、会话存储存活、--dump-config 仍通过。同版本互换不算升级,脚本会明确
    拒绝(--allow-same-version 才跑机制,并把自己标成 reinstall smoke);真正的升级验证是版本
    bump 之后的必跑项
    ,本版即按此执行(见发版记录)。
  • 三道门都有负向证明:清单门对"缺 lib/tui.js"与"夹带 tests/"两种坏 tarball 均判红;
    向导门在"home 明明是未配置的、向导却没出现"时从 SKIP 改为 FAIL(0.8.1 那类首启缺陷不再能伪装成绿);
    粘贴门在 Reader 的 paste 分帧被关掉时判红(粘贴被当成按键执行)。

实测(本候选版准备时,本机 100×20)

场景                          毫秒    字节   寻址行  整屏清屏
流式输出时的一次重绘          1.68     501      3       0
等待卡片时钟走一格            1.13     465      3       0
报告屏翻一页(PgDn / PgUp)   1.40    2457     17       0
菜单里移动一次光标            0.91     588      4       0
向导字段里打一个字符          0.19     140      1       0

五个动作合计 0 次整屏清屏(npm run bench,OK: every measured action was incremental)。
毫秒列是本机数字,只有字节 / 寻址行 / 清屏数是跨机器可比的合同值。README 里的实测块由
npm run bench:report 单独跑一次生成(因此毫秒列与本表可能相差零点几毫秒,字节/行数/清屏数逐项相同),
npm run bench:report -- --check 校验提交的数字与当前树一致。

同一轮的本机收据:

  • npm run typecheck → 0 error
  • npm test → 1509 项 · 1505 通过 · 0 失败 · 4 跳过
  • npm run freeze / npm run freeze:input → 全绿(八条不变量 + 七条退役路径;输入归属无基线超限)
  • 参考轨迹 111 条(2 条新增)
  • scripts/artifact-smoke.mjs → PASS(0.8.4-rc.1 · 250 文件 · 约 1.53 MB;在装好的 tarball 上依次跑
    向导探针、工作区探针与粘贴探针)
  • scripts/upgrade-smoke.mjs --from 0.8.3 --pack → PASS(真实 0.8.3 → 0.8.4-rc.1)
  • scripts/verify-batch.mjs --home <新建的探针 home> → RESULT: PASS:typecheck、1509 项套件、
    十类真 PTY/ConPTY 探针(含 tui-unmeasured-probe 的两条 leg 与 tui-paste-probe)、footer 帧检查全过,
    无 SKIP:
  • npm run bench:report -- --check → PASS(README 两个语种的实测块与当前树一致)
  • CI → 四条腿全 success:test (0.2.1-rc.2) / test (0.2.0-rc.2) / test (0.2.0-rc.1) / test-windows。
    默认腿与 test-windows 上的三道阻塞门(首启向导、粘贴、发布产物冒烟)都是实际执行并 success,不是
    skip;unmeasured 探针在两条腿上也已转绿。具体的 run 号与提交写在 docs/release.md 的发版记录里——
    这份说明随包发布,把 run 号钉进来只会在下一次改动里立刻过期。

兼容性

声明窗口本版变了,两条线一进一出:

>=0.2.0-rc.1 <0.2.1 || >=0.2.1-rc.2 <0.2.2
  • 新增 0.2.1-rc.2(上游 next):整族随之移动到这条线,族的 root pins 各前进一个 patch
    (cordis 4.0.5、include 1.0.10、loader 1.0.6、group 1.0.5),默认线(提交的 manifest / 锁 /
    test-windows)改为它。
  • 摘除 0.1.7 线(0.1.7-rc.1 / 0.1.7-rc.2):dshReleases 改为 incompatible、两条 CI 腿删除。
    原因是实打实的范围判断而不是喜新:0.2.1-rc.2 移动了族的 root pins,并把 subagent 的 wind-down 调用
    改名(drainContinuableChildren → drainChildren——签名一致,但旧名在新宿主上不存在);
    一个构建同时面向两代 seam,就得在类型面上各写一份分支。0.2.0 的两个 rc 仍在窗口内,仍各有一条腿。
  • 0.1.5 及更早仍不支持(dshReleases 保留 incompatible 表态)。
  • 0.2.1-alpha.x 不在声明承诺内:承诺的是跑过并表态的 rc。
  • 默认线现在是 0.2.1-rc.2;0.2.0-rc.2 与 0.2.0-rc.1 继续跑既有的兼容性回归。

已知限制

  • 过滤框对非 BMP 字符的限制(R4,未修):picker 的过滤框以 text.length === 1 判单字符,
    '🚀'.length === 2,因此星平面字符在过滤框里被丢弃。与上面已修复的 Composer emoji 崩溃不是同一件
    事
    ——Composer / 借用字段 / 向导字段输入 emoji 都是正常的。属"过滤字段模型",留待后续。
  • 陈旧 lib/ 的打包风险(未修):tsc 不清理旧输出、prepack 也不跑 clean,从脏 lib/
    打包会带上已删除源文件的陈旧模块(实测:本机 252 文件,干净重建与 CI 都是 249)。本版发布必须从
    干净树打包;artifact-smoke 的清单检查是这道纪律的证据,但脚本本身不阻止脏树打包。
  • 一个时间敏感的 Windows 单元测试:tests/session-list.test.mjs 的
    "a title is cached and painted as soon as it re...
Read more

0.8.3 — 紧急修复:向导收得下粘贴,也走得掉

Choose a tag to compare

@cyjyyd cyjyyd released this 13 Oct 13:24

0.8.3 发版说明

发布方式:latest + next。 上一次发版:0.8.2(2026-10-05,latest + next)。
本版是紧急修复:0.8.2 把首启向导改成 Screen 之后,向导的输入与退场出了三个缺陷,
都在"首次安装 / /setup"这条路上。没有协议变更、没有配置变更、没有数据损坏;
升级即修复,不需要任何迁移动作。

头等事:向导收得下粘贴,也走得掉

三个缺陷都是 0.8.2 引入的(0.8.1 的向导借工作区的输入行,所以既收得到粘贴、也不需要自己退场)。

1. 粘贴的 API Key 进不了字段,只能手敲

终端粘贴(Ctrl+V / Cmd+V / 右键,即括号粘贴)此前落到了向导 Screen 背后那个看不见的工作区草稿里:
向导字段一个字都收不到,而粘贴并没丢——它会留在草稿里,Esc 离开向导后在输入行现形,按回车就会被当成
一条消息发出去。受影响的是所有做括号粘贴的终端(Windows Terminal、iTerm2、GNOME Terminal、WezTerm、
kitty、VS Code 终端、tmux……),也就是几乎所有现代终端;受影响的是每一个字段步骤(提供商过滤、
Provider ID、Base URL、API Key、模型列表、上下文窗口)。

现在粘贴归字段所有:字段步骤直接落进字段(行尾换行折叠掉,多行按分隔拼成一行),没有字段的步骤
(模型多选、确认)不接收,两种情况都不再改写工作区草稿。老控制台不发括号粘贴时,多行 burst 也按粘贴处理。

2. 走完向导没有退回工作区

保存成功后向导仍然占着屏,读者要随便按一个键才退得出去(那个键的"Screen 背后没有向导 → 关掉它"兜底
才是真正的退场)。保存本身就是退场,现在与 Esc 一致:按 y 的同一帧,工作区回来。

同一处的失败路径也修了:保存失败时错误写在了一个立刻被丢弃的状态上——Screen 留着、错误没了、填好的答案
也没了,下一次按键还把这套流程当作没发生过。现在失败保留向导与错误,改完可以直接重试。

向导自己的提示行会随 Screen 消失,所以"配置完成,已记住 X / Y"现在落在转写行里(凭据那一行是
footer 回显,会过期),回到工作区后还读得到。

3. 一次读取里的多个按键(顺带修掉的同类)

一次终端读取里的多个按键此前被当成一个键:text\r(慢链路上的快速输入、终端合并写入)会收下文字却
丢掉那个回车,步骤停住不动——读者只能再按一次回车。现在一次读取按 composer 一直以来的规则拆开:
转义序列保持完整、CRLF 算一个回车、控制字节各自成键、可打印文本连成一段(所以没有括号粘贴的
"yes" 仍然不会替读者按下确认)。

兼容

上游兼容窗口与 0.8.2 相同:0.2.0-rc.1 / 0.2.0-rc.2 / 0.1.7-rc.1 / 0.1.7-rc.2。
0.1.5 及更早的宿主不再支持。 本版不改协议、不加命令、不动上游接口,也不改任何配置文件的形状。

安装 / 升级

dsh plugin --profile tui add dsh-ssh-tui@latest

装完退出再启动。/status 可确认当前版本;装不上先看 /doctor。
更新时请显式带 @latest,否则已有 lockfile 可能继续沿用旧版本。

实测数字(本版,100×20)

动作 毫秒(中位) 字节 寻址行 全屏清屏
流式 delta 1.67 501 3 0
等待卡时钟 1.12 465 3 0
报告屏翻页 1.21 2457 17 0
菜单光标移动 0.90 588 4 0
向导字段打字 0.19 140 1 0

复现:npm run bench;README 里的同一张表由 npm run bench:report 从这次真跑生成。
本版没有触碰绘制路径,数字与 0.8.2 同一量级。

已知问题

  • 向导字段没有左右光标键,粘贴总是追加在末尾(掩码字段 + 中间光标这条组合目前不存在)。
  • 未测 那一格在 Windows 本机看不到(ConPTY 代答光标位置),由管道父进程形状的探针覆盖。
  • 完整已知问题与人工验收清单见 checkpoints.md 的 0.8.2 一节。

v0.8.2

Choose a tag to compare

@cyjyyd cyjyyd released this 12 Oct 12:47

0.8.2 发版说明

发布方式:latest + next。 上一次发版:0.8.1(2026-09-30,latest + next)。
本版由 0.8.2-rc.1(2026-10-04 只上 next)沉淀一周后转正:候选版期间没有收到新的回归报告,
CI 五条腿与全部真 PTY 探针持续全绿,Windows / ConPTY 实机人工验收也已完成(见
checkpoints.md「Windows 实机轮」)。内容与 0.8.2-rc.1 完全相同,
逐项说明见 release-notes-0.8.2-rc.1.md。

dsh-ssh-tui is now presented as DSH Relay.
The npm package name and the install command have not changed.

dsh-ssh-tui 现在以 DSH Relay 为产品名展示;npm 包名与安装命令没有变化。
发布坐标仍是 dsh-ssh-tui,安装命令仍是
dsh plugin --profile tui add dsh-ssh-tui@latest。依据:decisions/brand-dsh-relay.md。

头等事:全新安装第一次就会出现配置向导(此前根本不会出现)

0.8.1 及以前,一台没有任何配置的机器上装好插件、启动 dsh --profile tui,看到的是一个空工作区、
一行提示都没有,模型调用必然失败——配置向导永远不会自动出现。原因是前端拉起的 Host 永远带
--resume=<id>(连它自己刚铸的新 id 也带),而首启判定把 resume 当成"这台机器配置过"。
0.8.2 起只看凭据存不存在。详见候选版说明第一节。

另外两件用户直接看得见的事

  • resume 不再有一段 1–3 秒黑屏:进屏序列现在跟着第一帧一起发出,加载提示全程在屏
    (20k 事件实测:清屏与落地同一 tick,此前中间有 3.5 秒全黑)。
  • 思考卡片不再发白:reasoning 角色此前只写属性、不写颜色,"暗"完全靠 faint;不实现 faint 的终端
    会退回默认前景色。四个调色板现在各自给出 muted 颜色。
  • 链路那一格不再把"绘制节奏"当延迟:终端不回 CSI 6n 时显示 未测 / n/a,不再印一个看起来像
    测量值的 160ms。

兼容

上游兼容窗口与 0.8.1 相同:0.2.0-rc.1 / 0.2.0-rc.2 / 0.1.7-rc.1 / 0.1.7-rc.2。
0.1.5 及更早的宿主不再支持。 本版不改协议、不加命令、不动上游接口。

安装 / 升级

dsh plugin --profile tui add dsh-ssh-tui@latest

装完退出再启动。/status 可确认当前版本;装不上先看 /doctor。
更新时请显式带 @latest,否则已有 lockfile 可能继续沿用旧版本。

实测数字(本版,100×20)

动作 毫秒(中位) 字节 寻址行 全屏清屏
流式 delta 1.47 501 3 0
等待卡时钟 1.26 465 3 0
报告屏翻页 1.40 2457 17 0
菜单光标移动 1.09 588 4 0
向导字段打字 0.25 140 1 0

复现:npm run bench;README 里的同一张表由 npm run bench:report 从这次真跑生成。

已知问题

见候选版说明的「已知限制」一节。要点:Windows / ConPTY 实机人工验收已完成(12 项清单;
两处 ConPTY 盲区在探针里显式 SKIP 并在 Linux 腿上真跑,SKIP 不算通过);未测 那一格在
Windows 本机看不到(ConPTY 代答光标位置),由管道父进程形状的探针覆盖。

v0.8.2-rc.1

v0.8.2-rc.1 Pre-release
Pre-release

Choose a tag to compare

@cyjyyd cyjyyd released this 04 Oct 05:38

0.8.2-rc.1 发版说明(候选版)

发布方式:只上 next。 这是候选版(RC):latest 保持 0.8.1,只有显式装 @next 或指定
版本号的人才会拿到它。上一次发版:0.8.1(2026-09-30,latest + next)。
这一版是架构收尾 + 稳定性:把 0.8.x 期间分批落地的终端架构(screen / 表示管线 / 工作区区域)
冻结下来,并修掉两处只有全新安装或弱链路才会遇到的问题。

头等事:全新安装第一次就会出现配置向导(此前根本不会出现)

0.8.1 及以前,一台没有任何配置的机器上装好插件、启动 dsh --profile tui,看到的是:
一个空工作区、一行都没有的提示,模型调用必然失败 —— 配置向导永远不会自动出现。

原因不在向导本身(它是好的),而在触发它的判断:前端拉起后台 Host 时永远带上
--resume=<id>(连它自己刚生成的那个新 id 也带),而首启判定把 --resume 当成"这台机器配置过",
于是直接跳过了首启流程。

0.8.2 起这条判断只看凭据存不存在:没有凭据、环境里也没有 key,就是首启,向导自动打开(Enter 走步骤、
Esc 随时退出),并且工作区会同时留下一行说明告诉你怎么手动重开 /setup。第二次启动不会再出现。

这同时修掉一个连带问题:向导不再借用 composer 的输入框。0.8.1 里进入向导会清掉你已经打了一半的草稿;
现在向导有自己的字段、自己的光标,工作区里的草稿、历史、正在进行的输入一个字都不动。

工具卡与输入法:两处"画面串行"的修复

  • 工具卡内容含多行代码时不再窜到输入区。bash 卡片的标题就是命令行原文,遇到 heredoc(<<'PY')会带
    着换行进入"一行"——终端因此真的换了行,而这一版之前按绝对行号绘制的帧随后把下面每一行都写错位:卡片内容
    落在输入框和页脚上,甚至两段文字拼在同一行。现在标题行会把换行折成空格,单行裁剪器也不再把换行交给终端。
  • Windows Terminal + 微软输入法:预输入不再在处理中卡片那一行闪烁。终端把输入法的预输入画在光标处,
    而"写一行"会把光标留在该行末尾;跑一轮时实时区域每 tick 重画又正好在输入框上方,所以光标停在处理中卡片
    上。现在每写完一行就把光标交还输入框,预输入只会出现在它该在的地方。

resume 不再黑屏,思考卡片不再"发白",q 真的能关掉报告

  • resume 进入时的 1–3 秒黑屏。前端先在备用屏打出"正在载入历史会话…",relay 接入时宿主又写了一次
    ?1049h——终端已经在备用屏时这个序列会清屏,而重建会话日志期间按设计不合成任何帧,于是那块加载
    提示被擦掉、屏幕空着,直到历史重建完成(实测 20k 事件:9.1 s 清屏、12.6 s 首帧落地,中间 3.5 s 全黑)。
    现在这条"进屏"序列跟着第一帧一起发出,同一 tick 内清屏并重画;没有东西要等的重连行为不变。
  • 思考卡片的文字不再发白。"思考 / 已思考"这一角色此前只写 2;3 两个属性、不写颜色——"暗"完全
    靠 faint,而不实现 faint 的终端(报告的 256 色终端)于是退回默认前景色,看起来和旁边的回复一样亮。
    四个调色板现在各自给出 muted 颜色,属性保留给支持的终端(mono 仍然只用属性)。
  • q / Q 能关掉报告。inspectClosesOn 一直声明接受它们("全屏报告理应响应 q"),但可打印字符的
    提示分支在它之前返回,于是这两个键只会打印"这是报告视图,按 Esc 返回"。

状态行不再把"绘制节奏"当成"链路延迟"

现场报告(/diag):Linux + xterm-256color + SSH,探测 未知(终端未回 DSR)——这台终端多数时候不回答
CSI 6n
,于是状态行常年显示 SSH ○○○○ 160ms。两个部分要分开看:

  • 空心圆是对的:没测到往返就是 unknown,不该假装知道链路好坏。
  • 160ms 是错的:那不是延迟,是回退的绘制节奏(探测不到时用的安全默认值)。它出现在"延迟"该在的
    位置上,读者无法分辨"离我 160ms"和"从来没测过"。这一格现在改为 SSH ○○○○ 未测 / SSH ○○○○ n/a;
    测到过的链路照旧显示真实值,绘制节奏仍然出现在 /diag 那一行、并且写明是"绘制"。

另外两个"看起来像 bug"的现象是设计使然,不是缺陷:

  • 有回 DSR 时数值也不怎么动:显示的是最近 3 次测量的中位数,重测间隔 20 秒;稳定的 SSH 链路上
    中位数本来就该是一条直线。Windows 本机之所以看得见跳动,是因为那些数字只有 1–12ms,同样抖动在两位数
    里显得大。
  • 连续 3 次探测失败后不再每 20 秒重试:退避到 10 分钟——避免"不回答 DSR 的终端被永远每 20 秒扫一次"。

命令提示会自己让位(排队提示除外)

命令的确认("已复制 412 字")与警告(命令失败)从此显示约 6 秒后自动让位,恢复原来的遥测行;按 Enter
提交仍会立刻清掉。唯一的例外是"运行中已提交,将在下个步骤生效"这条:它显示到那条消息真正被提交
为止——它是"你有话在排队"的唯一标记,提前消失等于把排队这件事藏起来。

弱链路 / SSH:画面更稳,流式不再整屏重画

这一版把 0.8.x 期间逐块落地的渲染架构冻结下来,对远程、跳板机、弱网最直接的三条:

  • 流式输出不再每个 tick 整屏重画:正在生成的回复是一个投影,不再是往历史里追加行,所以每个
    token 批次只重画它自己那几行。实测(100×20):一次流式 delta 寻址 3 行 / 478 字节 / 0 次全屏清屏。
  • 报告不再污染对话记录:/status、/help、/doctor、/subagents、/diag 现在是独立的屏,
    打开不改变历史窗口位置,翻页只重画正文,Esc 回到你原来的位置,也不会在重连后被重新画出来。
  • 断线重接后表示一致:提问、审批、计划三种卡片从会话日志折叠出来,因此掉线重接、换窗口、
    --resume 之后读到的状态与当时一致,而不是"重连后多出一张卡"或"状态回到未知"。

/clear 只清可见视图

/clear 不删除任何东西:不删会话日志、不动模型上下文、不动计划 artifact。它只是把可见视图切到
当前时刻之后(并且用一行提示告诉你这件事)。/resume 进来仍然是完整历史。/find 只在你看得见的
范围里搜索,这一点也在提示里说明。

计划与实时处理的抢占关系

计划条(Plan Dock)不再被"处理中"的实时区域盖住:实时区域现在是自己的行,而不是画在历史上面。
计划条高度上限为工作区一半,所以它不会把输入框和光标挤出屏幕(中文输入法的预输入串也不会再落到
计划卡上)。终端很矮时计划条按三档降级(完整 / 紧凑 / 极简),不会直接消失。

反馈去哪了("我执行了命令但没有任何提示")

  • 控制面的确认(切主题、切视图、preset 写入…)进页脚,显示到下一次输入为止;
  • 警告与失败进身份行(原来 目录: 那一行),不盖住你正在读的内容;
  • 只有会改变历史的事实才进对话记录。
    页脚挤不下时确认会退到身份行显示,所以再也不会有"执行了但什么都没有"。

上游 400:现在会告诉你它是什么

command-code 这类思考模式网关偶尔会成串拒收请求(实测:一次长会话里 13 个失败轮次中 12 个是这种),
以前你只看到一行原始错误。现在:

  • 明确说出网关拒收的是请求本身、不是你的 key;
  • 指名已知的那一族缺陷(上游 #1780 / #231,思考模式的 reasoning 回传);
  • 给出可操作的两条绕法(该路线 /effort off,或换同一网关的 command-code-messages);
  • 不会自动重试 —— 实测这类失败会成串出现(连续 8 轮),重发通常值得,但同一个请求确定性失败时
    自动重试会白花一整段上下文。什么时候重发由你决定。

数字(本版实测,100×20)

动作 毫秒(中位) 字节 寻址行 全屏清屏
流式 delta 1.43 501 3 0
等待卡时钟 1.25 465 3 0
报告屏翻页 1.19 2457 17 0
菜单光标移动 0.97 588 4 0
向导字段打字 0.22 140 1 0

发版候选(c2fe073)自检,逐条可复现:

自检 结果 命令
冻结不变量 八条全绿 · 七条退役路径 0 命中 npm run freeze
性能基线 上表五行 · 全部 0 次整屏清屏 npm run bench
全套测试(Linux) 1376 项 · 1372 通过 · 0 失败 · 4 跳过 npm test
全套测试(Windows 实机) 1376 项 · 1365 通过 · 0 失败 · 11 跳过(跳过均为平台互斥用例) npm test
打包 243 个文件 · tarball 1.4 MB · 解包 4.2 MB · shasum 92b7f517… · 无凭据 / 无 home / 无 sqlite npm pack --dry-run

跳过只代表"这台机器上没跑",不代表通过:verify-batch 见到 SKIP: 就收尾 INCOMPLETE(见
release.md)。

兼容

上游兼容窗口与 0.8.1 相同(0.2.0-rc.1 / 0.2.0-rc.2 / 0.1.7-rc.1 / 0.1.7-rc.2)。
这一版不改协议、不加命令、不动上游接口。

安装 / 升级

dsh plugin --profile tui add dsh-ssh-tui@0.8.2-rc.1

装完退出再启动。/status 可确认当前版本;装不上先看 /doctor。

已知限制

  • Windows / ConPTY 实机人工验收:已完成(2026-10-03,维护者)。用一份单独安装的 CLI dsh 逐条走过
    12 项清单,逐项结论见 checkpoints.md「Windows 实机轮」。分三类:
    可自动化的部分全绿(verify-batch --home <dir>:12 PASS · 2 SKIP · 0 FAIL);两处 ConPTY 盲区
    明确打印 SKIP: 并附理由(ConPTY 自己回 CSI 6n,"慢链路"与"终端静默但没断连"这两个形状它扮演不了);
    没有自动化、只能人眼的两目已由维护者确认通过——微软拼音 IME 组合、多行中文粘贴(清单与走法见
    release.md「发布前人工门槛」)。两处 SKIP 是覆盖边界,不是通过:它们
    在 Linux 腿上是真跑的(link 第一段、cut 的"静默终端"那一半),在 ConPTY 上才无信号。
  • 未测 那一格在 Windows 本机看不到:ConPTY 代答光标位置,本机链路芯片因此永远是"已测量"。
    该形状由 scripts/tui-unmeasured-probe.mjs 用管道父进程覆盖(两条腿:不回话读 未测、每条必答读
    真值),已进 CI 两条腿。
  • 拖放探针此前约 1/7 概率误报(探针自身与自己的 /status 重试竞态,不是产品行为)。本版已修,
    并连跑 20 次验证。
  • --resume 与首启的关系见上文:本版修的是"新机器不显示向导",不是"resume 不再触发向导"。
  • 依赖旧版 inbox 通知(inbox P3)与新协议的命令不在本版范围内。

v0.8.1

Choose a tag to compare

@cyjyyd cyjyyd released this 30 Sep 10:37

发布方式:latest + next。 上一次发版:0.8.0(2026-09-29,next,随后提前提升为 latest)。
这是一版修稳定性的补丁:桌面版装上它不会再把宿主带崩;终端侧的几处"残留"也一并清掉。

头等事:桌面版装了不会再弄坏宿主

0.8.0 在没有终端的进程里是抛错退出插件的。桌面版 Harness 的启动器是 Electron-as-Node(GUI 子系统,
没有 console),于是插件管理把它显示成"1 entry did not activate / 插件失败",在桌面版上还会把 GUI 带崩。

0.8.1 起按"能不能画"分四种情形,只有真能画时才挂载:

情形 行为
本进程就是分离的 TUI Host 照常服务(它的终端在随后接入的那个窗口里)
stdin 与 stdout 都是 TTY 照常挂载 TUI
桌面版启动器(Electron-as-Node / app.asar / DeepSeek Harness.exe) 不挂载任何东西(不取锁、不装定时器、不查更新),记一行说明,措辞是"此处不启用"而不是报错
其它没有终端的情形(管道 … | tee、cron、服务) 同上,文案换成"没有终端"。退出码 0

需要"没终端就报错"的场合(脚本断言某个终端 profile 真能起来)在 profile 行加 requireTerminal: true
——那是唯一会抛错的路径,而且只在显式要求时。桌面版用户不需要这个插件:用应用本身或 dsh web;
想在终端里用它,用 npm 安装的 CLI(npm i -g @deepseek-ai/dsh)在真实终端/SSH 里跑 dsh --profile tui。

新增:宿主自带终端控件时,可以把这个 TUI 当子进程用

桌面版自己不需要它,但"宿主会开终端控件"(PTY 面板、xterm.js、GUI 里嵌的终端)是另一条路:
声明 DSH_TUI_DISPLAY=stdio(或 --display stdio),插件就不再要求 TTY——画面走 stdout、按键走 stdin、
面板尺寸由宿主用 CSI 8 ; rows ; cols t 报告(管道没有 resize 事件也没有 SIGWINCH)。协议、父进程
必须做的五件事、Node 最小示例与限制写进 display-mode.md(这一版起随包发布)。

终端侧修掉的三处"残留"

  1. 会卡住的"处理中"卡片:渲染缓存把"活尾巴"(等待卡、流式缓冲、还没有回复的突发摘要)收进了
    最后一行的缓存条目,于是每一帧都把那一份冻结在旧秒数的副本重放出来。真实会话里攒到过四条
    (0s / 12s / 19s / 30s)夹在工具卡中间,0s 那条永远不动。现在缓存条目只包含它自己那行画的内容。
  2. 退出后提示符旁的 ①—…“”·•Ⅰ 与 ^[[25;1R:歧义字形探针打印的那行自己没有擦(调用方可能一帧
    都没画),而它的光标回答要一个往返才回来——慢链路上那时终端已经交还给 shell,tty 就把回答回显成了
    文本。现在探针自己擦行、归还终端前多留一个往返吞掉回答、并且不再对已经交还的终端探测;探针期间
    暂存 Host 的输出,避免擦除打在刚画好的帧上。
  3. 极简视图:单文件编辑卡不再重复自己的标题与 diffstat;失败的工具行补回状态球(●),与其它卡片行一致。

性能与渲染(0.8.0 之后陆续落地)

  • 每行渲染缓存 + 逐行脏比较:5000 行会话的整帧重画从约 1050ms 降到约 22ms,按键帧从约 1040ms 降到约 13ms;
    多行帧用 DEC 2026 同步刷新,避免慢链路上一行行"落下来"的撕裂(这就是本插件存在的意义的那个不闪屏)。
  • 歧义宽度字形(①–⑩、—、“”、CJK 标点…)改为问终端:接入时打印探针并用 CSI 6n 读回列号,
    答案随帧下发给绘制的 Host;终端不回答就退回按 locale 推断,DSH_TUI_NO_GLYPH_PROBE=1 可整体关掉探针。

上游兼容

通道 版本 表态
latest / next 0.2.0-rc.2 compatible:本版默认线(干净树安装、tsc 0 错、套件 1086 项 1082 通过 / 0 失败 / 4 跳过、真机探针全过;桌面版基线)
线内 0.2.0-rc.1 compatible:typecheck + 套件
线内 0.1.7-rc.2 compatible:完整探针
线内 0.1.7-rc.1 compatible:typecheck + 套件
已摘 0.1.5-* 及更早 incompatible(明确表态,请求升级到 0.1.7-rc 或 0.2.0-rc)

声明窗口:>=0.1.7-rc.1 <0.1.8 || >=0.2.0-rc.1 <0.2.1。CI 四条腿:0.2.0-rc.2(默认,完整探针)、
0.1.7-rc.2(完整)、0.2.0-rc.1 与 0.1.7-rc.1(typecheck + 套件)、外加 Windows leg(ConPTY 真机)
——两条腿新增无 PTY 的管道探针(scripts/tui-stdio-probe.mjs)。

安装 / 升级

dsh plugin --profile tui add dsh-ssh-tui@latest      # 0.8.1

装完退出再启动。/status 可确认当前版本;装不上先看 /doctor。

已知限制

  • 0.1.5 及更早不再支持(见上)。
  • 桌面版应用本身仍然不能跑终端 profile(它的启动器没有 console)——这是上游的事,见
    docs/desktop.md。本版保证的是
    "装了它不会把宿主弄坏",以及"宿主愿意开终端控件时能用"。
  • 管道宿主必须自己报告尺寸变化(CSI 8 ; rows ; cols t),否则会停在启动时声明的 COLUMNS/LINES。
  • 真实 Windows 上仍只能人工确认的两条:宿主那个控制台窗口确实是隐藏的;%USERPROFILE% 与 $HOME
    不一致的账户行为。

0.8.0

Choose a tag to compare

@cyjyyd cyjyyd released this 29 Sep 09:45

头等事:跟上宿主的 0.2.0-rc 线,同时摘掉 0.1.5

上游把 next 指向 0.2.0-rc.1。这条线保留了 0.1.7 引入的两处结构(设置表单由 loader entry 自己的
Config 投影、终端 profile 在进程级组合代理),所以插件源代码一行没改就跑了:类型面 0 错、七条真机探针
全过。真正需要改的是三处"宿主代际判定"——它们原来用 0.1.7 前缀判断,把 0.2.x 读成了旧代,会让
profile 挂错行。现在统一读一个按版本元组比较的共用规则。

0.1.5 这条线不再支持。 还在 0.1.5 的用户会从商店读到明确的 incompatible(而不是沉默),
请先升级宿主到 0.1.7-rc 或 0.2.0-rc 再装这一版。

401/403 不再混为一谈,并可自动重试一次

宿主的 llm/retry 不重试 AUTH 类错误,所以一次提供商侧的瞬时 403 会直接终结整轮,而屏幕上只有
permission_error 一行。实测过一次:同一会话 37 轮在同一条路由上成功,失败只有间隔 45 秒的两次,
随后同一把 key 打同一模型 200。

  • 失败时补一行来源判断:提供商拒绝了请求(HTTP 403)…{ENV} 已配置(意思是别改 key,重发即可)
    或 本机没有可用的 {ENV}(意思是先去配)。判据是真的解析一次凭据,不是猜。
  • /retryauth on|off(默认关):只在"提供商拒绝 + 本机有凭据 + 这一轮还没重试过"时自动重发上一条
    消息一次。默认关是因为重试会把整段上下文再发一遍,长会话很贵。
  • 排查三步(三种错误信封、两条文件检查、一条直连 curl)写进 docs/remote-ops.md §4.8;
    附带一个会误导人的坑:GET /provider/v1/models 是公开端点,带不带 key 都 200,不能用它验鉴权。

上游兼容

通道 版本 表态
latest 0.1.7-rc.2 compatible:完整 CI 腿
next 0.2.0-rc.1 compatible:本版默认线(干净树安装、tsc 0 错、套件 1021 通过 / 0 失败、七条真机探针)
0.1.7 线 0.1.7-rc.1 compatible:typecheck + 套件
已摘 0.1.3-alpha.* / 0.1.5-* incompatible(明确表态,范围不再收;请求升级到 0.1.7-rc 或 0.2.0-rc)

CI 四条腿:0.2.0-rc.1(默认,6 条探针)、0.1.7-rc.2(完整)、0.1.7-rc.1(类型+套件)、Windows(ConPTY 真机)。
验证细节见 docs/upstream-0.2.0.md。

安装 / 升级

dsh plugin --profile tui add dsh-ssh-tui@next        # 0.8.0(宿主 0.2.0-rc 或 0.1.7-rc 都可以)
dsh plugin --profile tui add dsh-ssh-tui@latest      # 0.7.4(仍是默认;10-01 之后 latest 会变成 0.8.0)

装完退出再启动。/status 可确认当前版本;装不上先看 /doctor。

发布方式

这一版只上 next:latest 仍是 0.7.4,等 2026-10-01 再把 0.8.0 提升为 latest。
宿主已升到 0.2.0-rc 线的用户现在就可以用 @next 装。

热度基线(发版当日)

  • 14 天窗口(2026-09-29):views 278(169 unique)· clones 1585(371 unique)
  • referrers:github.com 56 · Google 12 · Bing 2 · npmjs.com 2 · chatgpt.com 1 · dshfind.com 1
  • npm 上周(09-21→09-27)1059 次下载;0.7.3 单版本 380 次;仓库 ★ 2

0.7.4

Choose a tag to compare

@cyjyyd cyjyyd released this 29 Sep 07:32

头等事

这一版是「把已经做出来的东西做对」:0.7.3 之后落的六个功能各自被真机与对抗式审查拧了一遍,
修掉了 8 个实际缺陷(含两个只有读代码才看得见的:现场思考卡被挤出焦点环、覆盖层里的复制
拿到的是另一份正文)。行为上最明显的变化是回复变成了可选中的卡片。

回复可以选中、可以复制(本版主线)

/copy 取的是"被选中的那一行",而可选列表里从来没有回复——所以只要按过一次 ↑/↓ 选中
任何卡片,/copy 就再也拿不到回复,最新回复只是"没有选中时"的兜底。现在:

  • 空输入 ↑/↓ 在回复与卡片之间按屏幕顺序走,选中的那一行带 ▶ 标记;Alt+4 直接选中最新回复。
  • /copy(或 Ctrl+Shift+C)复制的是选中的那一条的原文——不是折行后的屏幕文本;
    复制后保留选中,连按两次拿到的是同一条。
  • 在选中的回复上按 Enter:打开「回复全文」(可滚动、Esc 返回),长回复里的表格与代码块
    不再被窗口宽度切碎。覆盖层里也能复制,取的是屏幕上那份正文,并在覆盖层底部回显「已复制 …」。
  • 工具卡 / 子代理 / 改动卡的「全文」覆盖层里,复制键取的同样是屏幕上那份正文(工具全文、那份 diff、
    子代理日志),不再是卡片摘要。
  • 拖选照旧:被选中回复第一行前面的 ▶ 是装饰,拖过它不会把标记复制进去。

底栏与链路

  • 链路质量在会话运行中持续重测并按中位数读数:进会话那一瞬间的网络抖动不再把整场会话钉在最低档
    (绘制节奏与每帧字节预算都跟着这档走)。
  • 选择器把「可接入 / 已占用」两个词固定下来,并且在首帧之前就把"已经挂掉的窗口"判完——列表不会先
    显示「已占用」再改口。判定走一次真实往返(光标探针),因为断掉的 SSH 链路会让 launcher 还连着显示通道。
  • 接管(把别人的窗口接过来)现在要确认,Esc 是取消而不是退出。

空回合不再被误读为完成

上游网关偶尔只回思考、finish_reason: stop、正文为零(实测某网关 10/35 个回合如此),
宿主如实组装成"只有思考的助手消息",状态栏显示完成/空闲。现在转录里会补一行明确提示
(含 finish_reason: stop 与"按 Enter 继续"),回放/中断/报错的回合不提示。

上游兼容

  • dsh 声明窗口:>=0.1.7-rc.1 <0.1.8(next)与本条线并行;0.1.7-rc.2 已按完整流程验过并声明
    compatible(干净树安装、tsc 0 错、套件全绿、六个真 PTY 探针全过),CI 里单独一条腿。
  • CI 现有 5 条腿:0.1.7-rc.1(默认,提交的 manifest)、0.1.7-rc.2、0.1.5-rc.3、0.1.5-rc.1
    (只跑类型与单元)、test-windows(ConPTY 真机)。默认腿新增一条 Reply copy probe:真 PTY 跑一轮
    脚本化模型,断言拖选复制、/find 高亮、以及选中回复后按复制键拿到原文。

安装 / 升级

dsh plugin --profile tui add dsh-ssh-tui@0.7.4

装完退出再启动。/status 可确认当前版本;装不上先看 /doctor。宿主在 0.1.5 线上的用户可以继续用 0.7.4
(0.1.5 仍在本版声明窗口里);下一次(0.8.0)会随上游 0.2.0-rc 线调整支持面。

热度基线(发版当日)

  • 14 天窗口(2026-09-29):views 278(169 unique)· clones 1585(371 unique)
  • referrers:github.com 56 · Google 12 · Bing 2 · npmjs.com 2 · chatgpt.com 1 · dshfind.com 1
  • npm 上周(09-21→09-27)1059 次下载;0.7.3 单版本 380 次;dshfind 卡片 0.7.3;仓库 ★ 2
  • 与前一周相比:views −15% · clones −14%

0.7.3

Choose a tag to compare

@cyjyyd cyjyyd released this 24 Sep 09:53

这一版的头等事是跟上宿主的 0.1.7-rc 线:0.1.7 的 launcher 会拒绝声明不兼容的插件,所以 0.7.2 在那条线上装不上。同一个版本里还落地了 Windows 的地基与 P1 四条,以及两个实测出来的可靠性修复。

支持 0.1.7-rc.1(next)

0.1.7 换了三处结构,插件现在两条线共用一份代码:

  • 设置接缝重写:settings.get / installSection / settings.document 全部删除,表单由 loader entry 自己的 Config 投影,只有 .volatile() 字段可读可写,命名空间 = entry id。插件把自己的段落落成三条 entry,/setup、/mode、/doctor 在两条线上都能读写。
  • presets 改名:复数包没有 0.1.7 版本,拆成 dsh-agent-preset(组合行)+ dsh-agent-preset-registry(服务);终端不再有 roster,/mode fix 在 0.1.7 上写的是 persona / tool-ask-user / present 三行。
  • 声明窗口:dsh.compatibility.dsh 与 14 条 peer 纳入 >=0.1.7-rc.1 <0.1.8。launcher 会逐条读 peer 范围(optional 也算),所以这一步是升级路径的硬前提,不是收尾动作。

真机核验:同一份 src/ 对着两条线 tsc 各 0 错;mock 轮次探针真跑一轮并完成拖选复制与 /find;settings.yaml 四段迁移在 PTY 下全部落到新 entry。

不再支持 0.1.2-rc

0.1.2 与 0.1.5 属于同一个 API 代,但兼容层里专为它保留的分支一直占着维护成本。现在:

  • 范围去掉 >=0.1.2-rc.1 <0.1.6,dshReleases 把 0.1.2-rc.1 标成 incompatible(保留条目,让还在那条线的用户看到明确结论,而不是"没有表态");
  • 只服务该 API 代的兼容分支与测试固定装置(Session.events、裸 header list()、inspect()、images 标志、durable assistant/chunk 回放链……)一并删除。

还在 0.1.2-rc 的用户:请先把 dsh 升到 0.1.5-rc.1 及以上(推荐 latest 或 next),再装本插件;0.7.2 仍可继续使用。用 0.1.2 宿主写下的旧会话在新版本里仍能正常回放文本,只是底栏不再为它们重建 TTFT / tok/s。

Windows:从"用户发现"变成"CI 发现"

  • 真 ConPTY 端到端进 CI:test-windows 腿驱动真 TUI(boot、断连重连、关窗、终端矩阵),不再只跑单元测试。
  • 文件权限不再是空操作:icacls /inheritance:r /grant:r 落到 env 文件、.credentials.yaml、OAuth token、锁/套接字目录与宿主 stderr 日志。(顺带:POSIX 下宿主 stderr 日志过去没有任何 mode,是 0644,现在 0600。)
  • 宿主活过"关掉终端窗口":宿主改由系统 PowerShell Start-Process -WindowStyle Hidden 启动——它有自己的隐形控制台、不在启动器的 KILL_ON_JOB_CLOSE job 里,关窗带不走它,回合继续跑完;没有 PowerShell 的机器回退到直接 spawn,并会在会话里明确提示这是回退路径。
  • 终端能力矩阵:Windows Terminal / conhost / VTE 系(GNOME、XFCE)/ Konsole / xterm / tmux / screen / Linux 控制台 / dumb 一张表,探针逐种起 TUI 断言实际发出的序列。

可靠性

  • 深 DSH_HOME 下显示通道起不来:AF_UNIX 的 sun_path 只有 107 字节(macOS 103),而过去只把会话标签截到 80 字符、从不校验整条路径——地址一超长 listen() 就 EINVAL,用户只看到一句 host display socket did not appear,最容易被误判成"宿主没起来"。现在按字节预算截断(非 ASCII 的 home 也按字节算),浅目录逐字节保持原名,深到放不下时直接说明原因。注意默认 ~/.dsh 距上限只有 1 字节,所以这不是罕见配置。
  • 0.1.7 的 DeepSeek 适配器不加载:那条 CI 腿过去用 --legacy-peer-deps 安装,连 peer 一起跳过——37 个 peer-only 包缺失,base 里 25 行(llm-deepseek、tool-fs、subagent …)没有 fiber,loader 把 import 失败静默吞掉。改为用 overrides 把整族钉在该线并正常安装,该腿的 busy-drop 探针也重新跑起来了。

安装 / 升级

dsh plugin --profile tui add dsh-ssh-tui@latest

装完退出再启动。/status 可确认当前版本;装不上先看 /doctor。宿主是 0.1.7-rc 的用户需要 0.7.3 及以上(0.7.2 会被 launcher 拒绝加载)。

已知限制

  • 真实 Windows 上仍只能人工确认的两条:宿主那个控制台窗口确实是隐藏的;%USERPROFILE% 与 $HOME 不一致的账户行为。
  • 尚未做(计划 0.7.4):非 UTF-8 控制台/ locale 的 ASCII 回退渲染;安装/校验脚本去 bash 化;面向普通用户的 Windows 文档。

热度基线(发版当日)

snapshot appended: github ok · npm ok · dshfind ok · store /root/heat-0.7.3.jsonl

  • 14 天窗口(2026-09-24):views 278(169 unique)· clones 1585(371 unique)
  • referrers:github.com 56 · Google 12 · Bing 2 · npmjs.com 2 · chatgpt.com 1 · dshfind.com 1
  • npm 上周(09-15→09-21)1070 次下载;dshfind 卡片 0.7.2;仓库 ★ 2