# 更新日志
本文件记录 dsh-workspace 各版本的主要变化。开发中的改动先写在「未发布」下,发布时(`npm run release`)自动定稿为对应版本。
## 未发布
## 0.12.3(2026-10-12)
### SSH 连接
- 修复:远程工作区连接建立后,服务器侧断开连接(ECONNRESET)或保活超时会让整个 DSH 崩溃(宿主进程 exit 1,issue #6)。根因是 `rawDial` 握手成功后摘掉了 ssh2 Client 的 `error` 监听,已建立连接上的 `error` 无人接收成为未捕获异常。现在保留一个常驻监听只记 warn 日志(握手期错误仍由原逻辑记录并 reject,不重复记),断线回收与自动重连沿用连接池的 close / end 处理;跳板链每一跳同样受益。补回归测试 `src/ssh/connection.test.ts`。
### HTML 预览
- 修复:HTML 预览出问题时只留一片白、看不出原因。`.html` / `.htm` 预览页注入纯 ASCII 的预览探针(`src/wire/preview-probe.ts`,桌面版在 srcdoc 内联时注入,网页版由预览路由对带 `?probe=1` 的主文档按 latin1 原字节插入、相对资源不受影响;页面自带 meta CSP、svg / xhtml 不注入),把页面脚本报错、资源加载失败、加载完成但正文为空、10 秒内未完成加载回报给查看器,显示在沙箱提示条下方;沙箱里访问 localStorage / cookie 被拒(SecurityError)时提示可临时解除沙箱,未加载时提示打开开发者工具(标题栏扳手菜单或 Ctrl+Shift+I)看 Console。
- 改进:预览 iframe 的渲染决策抽成纯函数 `framePlan`(`src/client/viewers/html-frame.ts`),键同时包含 nonce 与沙箱状态(解除 / 恢复沙箱、保存、刷新都重建浏览上下文),补回归测试(探针注入位置、沙箱切换换键、预览路由注入后长度与 CSP)。
- 修复:Windows 桌面版(兼容模式页面是 `http://127.0.0.1:<端口>`)解除沙箱后,页面里 `new Worker('worker.js')`、`fetch`、动态 `import` 等运行时相对地址解析到 DSH 根目录(如 comlink 示例报 `Failed to construct 'Worker'`)。根因是桌面版一律走 srcdoc,srcdoc 文档基址是父页面地址。现在加载方式由 `frameLoadMode` 决定:http(s) 页面上网页版两种模式、桌面版解除沙箱都让 iframe 直接加载预览路由(文档基址 = 文件所在目录,同源,Worker 可用);桌面版沙箱仍走 srcdoc 内联(不透明源的请求拿不到桌面渲染进程令牌,关闭「允许浏览器访问」时会被拒),非 http(s) 页面(dsh-app:// / file:)走 srcdoc;srcdoc 能拿到预览路由时注入 `` 指向文件目录(尽力而为,页面自带 `` 时不覆盖;签发失败不报错,照常内联)。
- 改进:探针提示分类(`probeNotes`):沙箱下报错含 `origin 'null'` / SecurityError / Worker / 内联模块导入失败 / localStorage / sessionStorage / cookie 时追加「该页面需要同源能力,请点击『临时解除沙箱』」;页面有自己的脚本但没有可见元素时改为中性说明「页面没有可见元素(内容可能由脚本弹窗或控制台输出)」,不再按故障提示(探针统计可见元素时排除 script / style 等,并回报脚本数)。沙箱 iframe 与预览路由 CSP sandbox 均含 `allow-modals`(alert / confirm / prompt 不再被静默忽略,仍无 `allow-same-origin`)。
### 右侧栏标签右键菜单与固定标签
- 新增:右侧栏标签右键菜单(宿主「关闭」之后,分隔线开头)增加「关闭左侧 / 关闭右侧 / 关闭其他 / 关闭全部」——只作用于该标签所在窗格、跳过固定标签,没有可关闭目标时禁用;以及「固定 / 取消固定」。文件类标签(插件文件查看器、宿主文档预览等 `dsh-resource://file/...` 地址)另有「复制路径」「在文件管理中显示」(文件不在当前会话工作区内或文件管理未开启时禁用;远程工作区会话不提供「在文件管理中显示」,只保留「复制路径」)。对所有停靠窗格标签生效(含宿主文件 / 浏览器 / 终端)。
- 新增:固定标签。固定后排在所在窗格最左(多个按固定先后),不显示关闭按钮(只能右键关闭);以任何方式关闭固定标签即取消固定。打开侧边栏(或切到已展开的会话)时自动补开缺失的固定标签到记住的窗格(不存在则最左窗格;窗格只有引导页时顶替它),并恢复原来的激活标签;分屏下同一内容已在任意窗格 / 浮窗时不重复打开;拖到另一窗格后记住新窗格。终端、浏览器、SSH 终端等可开多个的标签不能固定(菜单项禁用并说明原因)。固定按会话独立保存在浏览器 `localStorage`(`dshws.sidebar-pins.v1.<会话>`),新会话不继承。
- 新增:「侧边栏」管理页开关「标签右键菜单增强与固定」(偏好 `sidebar.tabEnhance`,默认开);关闭后撤销菜单项与隐藏关闭按钮的样式、停止补开与排序(固定记录保留)。
- 说明:排序 / 补开 / 关闭即取消固定依赖宿主右侧栏控制器的非公开字段(`adopted` 布局仓库、`placeTab`、`closeIn` / `openResourceIn` / `openTabIn`、`tabDomain`),缺失时自动降级为只提供可实现的菜单项、不抛错。预览场景:`node scripts/preview-ui.mjs tabmenu`。
### Git 侧栏
- 修复:右侧栏被拖窄时,Git 顶部页签(文件 / 改动 / 历史 / AI 改动)文字逐字折行成竖排。页签与角标改为不换行,放不下时页签栏横向滚动(隐藏滚动条,触控板横滑、普通滚轮纵向滚动自动转为横向),切换页签时激活项自动滚到可见。抽出通用类 `.dshws-tabstrip` + `useTabStrip`(`src/client/tabstrip.ts`);任务页、AI 改动、文件标签等标题行里的分段按钮(`.dshws-side-seg`)同样改为不压缩、不换行。
- 新增:「历史」页签悬停浮窗展示完整提交说明。鼠标停在提交行约 400ms(或键盘聚焦该行)后,在行左侧(放不下时下方 / 上方,自动避让视口边界)弹出浮窗:加粗标题、作者、时间、可点击复制的短 hash,正文按 Markdown 渲染(单个换行保留),右上角可切换「渲染 / 原文」;最大宽 420px、最大高 60vh 内部滚动。移出约 150ms 后隐藏,移入浮窗时保持(可选中复制、点链接、滚动);Esc、列表滚动即关闭,同一时间只显示一个。触屏 / 窄屏(≤640px)没有悬停,改为在展开的提交详情里点「说明」按钮打开同一浮窗。展开详情不再内嵌提交说明,只保留提交信息与改动文件。渲染做 XSS 安全处理:原始 HTML 一律转义、链接只放行 http(s) / mailto 且新窗口打开(noopener)、图片不加载改为链接,再经 `stripActiveTags` 纵深防御。
- 改进:提交说明浮窗按所在容器固定方向。右侧栏里固定显示在行的左侧(伸进主区,纵向对齐行并收进视口,极窄窗口放不下才退回下方 / 上方);会话顶部「Git 仓库」标签页(主区)里固定显示在行的右侧(伸进详情区,放不下时退回左侧 / 下方)。`placeCommitPopover` 新增 `prefer: 'left' | 'right'` 参数,容器经 `CommitPopoverSideContext` 传入(会话顶部标签注册处提供 `'right'`)。
- 改进:移动端(≤640px 或无悬停设备)长按提交行约 500ms 弹出屏幕居中的模态弹窗查看完整说明:半透明遮罩、宽 min(92vw, 420px)、最大高 70vh 内部滚动,点遮罩 / 关闭按钮 / Esc / 手机返回键关闭;手指移动超过 10px 或列表滚动即取消,短按仍是展开 / 收起详情,长按后浏览器补发的 click 被吞掉不会误展开;长按期间屏蔽系统长按菜单与文字选中。展开详情里的「说明」按钮保留为备用入口,同样打开居中弹窗。长按逻辑抽成纯状态机 `createLongPress` + `useLongPress`(`src/client/sidebar/long-press.ts`,带单测)。
- 改进:`git log` 改用 `-z` + `%B`(完整说明放在最后一个字段,只按前 5 个字段分隔符切分),提交说明里出现 `\x1f` / `\x1e` 等控制字符也不会让字段错位;提交对象新增 `body` 字段(单条正文上限 2 万字符),远程与本机仓库同样适用。
### 侧边栏管理页与 dsh-better-sidebar
- 新增:「远程工作区」主页新增「侧边栏」页签(位于「连接日志」与「全局配置」之间),集中管理侧栏能力:
- 标签开关:文件管理、Git、文件查看器、SSH 终端、任务、侧边对话,切换即时注册 / 撤下(文件管理与 Git 同时作用于会话顶部标签;关闭文件查看器后文件交还宿主查看器)。
- 「接管 DSH『文件』侧栏」从「全局配置」迁入(偏好键不变,已有设置照常生效)。
- 文件关联(扩展名 → 查看器 + 默认预览 / 编辑,可增删改、一键恢复默认)、忽略规则编辑(复用原 `ignore` 偏好)、大文件阈值(默认 20MB)、HTML 默认不沙箱、文件树自动刷新、自定义「打开方式」URL 模板。
- Agent 打开工具 `open_in_sidebar` 开关与「自动打开任务页」开关(均默认开)。
- 外观:IME 守卫、自定义 CSS(见下)。
- 偏好统一存于宿主 `prefs.json` 的 `sidebar` 字段(新网关方法 `setSidebarPrefs`,严格校验),浏览器端经 `src/client/sidebar-prefs.ts` 读取与订阅。
- 新增:dsh-better-sidebar 状态检测与一键禁用 / 重新启用(网关 `betterSidebarStatus` / `betterSidebarSetEnabled`,经宿主 pluginManager,整个 profile 生效,界面先确认;完成后提示刷新页面)。禁用后本插件自动接管「文件」侧栏;pluginManager 不可用时引导到宿主插件页手动处理。本插件的侧栏能力已覆盖 dsh-better-sidebar,不再依赖它。
- 新增:IME 守卫(默认开)—— 输入法组字期间的按键在 document 捕获阶段停止传播,不再误触宿主 / 其他插件的快捷键(只 stopPropagation,不 preventDefault;终端与代码编辑器放行)。
- 新增:自定义 CSS —— 注入 `