# dsh-ui-enhancements [English](./README.md) | 中文 为 DeepSeek Harness 提供独立、克制的小型界面增强。 ## 当前功能 ### 无工作区对话 点击 **新会话** 即可直接输入。输入框默认选择 **无工作区**,也可通过原有工作区选择器选择或添加工作区。工作区自己的新建会话操作仍然在对应工作区中开始。 - 对话显示在侧栏的 **无工作区** 分组中。这些是正常持久保存的 DSH 对话,沿用原生模型选择、附件、工具、历史、搜索、分支和归档,删除则使用本插件在会话行「⋯」菜单里提供的那一行。 - **无工作区** 在侧栏、输入框的工作区按钮和选择菜单中使用一致的对话气泡图标。支持键盘展开与折叠,右侧 **+** 可新建无工作区对话。 - 发送前,悬浮或聚焦已选工作区按钮,点击 **×** 即可直接切换为 **无工作区**,并携带草稿和附件。触屏设备始终显示 **×**。此操作清除新对话的工作区选择,不会删除工作区。 - 侧栏的淡蓝色背景用于标记当前对话所属的工作区,包含 **无工作区**;折叠时仍然显示。其他分组没有常驻高亮。 - 每个新对话都有独立的真实工作目录:`/projectless/session-projectless-`,DSH home 根据当前配置档确定。不会注册工作区,也不会借用已有项目目录;浏览器侧只把该对话呈现为一个 **无工作区** 的虚拟工作区条目,DSH 的工作区注册表保持原样。可在 **设置 → 对话管理 → 无工作区** 查看存放位置;原生 **在 Finder 中打开工作区** 操作可打开该对话的目录。 - 同一浏览器标签页会复用空白草稿,刷新后也可继续使用。有消息后再点 **新会话**,则分配另一个目录;分支沿用来源对话的目录。并发点击共用一次分配;创建失败可用同一标识重试,较晚完成的创建不会打断已切换到其他对话的导航。 - 发送前,在 **无工作区** 和工作区之间切换,会通过 DSH 原生草稿流程携带文字和附件。携带的文字会同步到原生草稿存储,刷新后可恢复。未发送附件使用 DSH 的内存草稿存储,请在刷新前发送。 - 归档和恢复保持同一个目录。删除对话会移除日志和列表记录,保留生成的文件和分支;空白草稿目录也会保留,此功能不会自动删除工作文件。 - 安装 [dsh-session-workspace](https://github.com/Unintendedz/dsh-session-workspace) 后,已有对话可通过 **移动到其他工作区** 关联工作区。请先切换到其他对话,等待原会话关闭。之后的文件操作使用新工作区,已有生成文件仍留在原目录。 交互参考 [Codex 的无项目对话方式](https://learn.chatgpt.com/docs/projects),保留 DSH 原有对话控件。 ### 工作区按最近活动排列 - **无工作区** 是固定锚点:始终排在侧栏最前,它自己的活动时间不会移动它。其余分组按各组最近可见对话的更新时间排序。折叠分组也遵循同一规则;置顶对话不会置顶整个工作区。空工作区按创建时间排列,时间相同时保留 Host 原有顺序。 - 对话活动、归档、恢复、删除及工作区归属变化直接通过已有会话事件更新排序。重排保留分组元素、展开状态和当前草稿,无需重新加载会话列表。 - **视图选项 → 手动排序** 保留 DSH 保存的工作区顺序和工作区拖拽操作。**无工作区** 在两种排序模式下都保持首位,并且不提供拖拽手柄,因为它的位置不属于 Host 顺序,拖拽只会看起来无效。自动排序模式关闭工作区拖拽;需要自行排列时可切换到手动排序。原生单列表对话视图不受影响。 ### 配置档插件开关 打开 **设置 → 插件 → 插件列表**,即可启用或停用当前 DSH 配置档中安装的每个插件包。 - 修改会立即应用到 Host Loader,并在 DSH 重启后继续生效。刷新页面可同步浏览器插件:开关成功后会显示明确提示和刷新按钮,提醒先保存未发送的内容;插件不会自动刷新。 - 选择结果保存在该配置档 `cordis.patch.yml` 的托管区块中,保留其他设置和注释。支持行内和块状序列(行内格式可能转换为块状格式);非法 YAML 或补丁条目会在原子替换文件前被拒绝。 - `dsh-ui-enhancements` 自身的开关保持可见但锁定为启用,避免恢复入口停用自己。 - DSH 内置运行组件仍然只读,因为停用核心服务可能导致 Web 界面或插件管理器不可用。 - 如果运行时更新失败,插件会恢复原有持久化状态,开关仍可重试。 `0.7.1` 版本需要 DSH `0.2.0-rc.2`。安装或升级后请重启 DSH,以便宿主端与浏览器端代码同时重新加载。 ### 会话行菜单里的删除 DSH 自己已经在会话行的「⋯」菜单里提供 **置顶**、**重命名**、**分叉** 和 **归档**,行尾的悬停按钮也是同一套 action。本插件不再另画置顶与归档按钮,只在菜单里原生归档之后补一行自己的 **立即删除**。 - 该行注册在 DSH 的 `sidebar.workspaces.session.menu.item` 扩展位上,排在原生条目之后、自带分隔线,外观与原生菜单行一致(危险色、悬停底色、键盘可达)。 - 立即删除会弹出一次确认,默认聚焦 **取消**。确认后停止这个对话,删除它的所有 JSONL 日志版本、工作区记录、归档记录和搜索记录,并通过 DSH 的移除事件更新侧栏。操作失败会显示错误,允许重试。 - 删除仅针对这个会话,保留工作区文件、独立分支和共享附件文件。日志不会移入回收站,删除无法撤销。 - 置顶与归档沿用 DSH 原生行为:本插件不再保存自己的置顶名单,也不再改写会话顺序。 ### 已归档对话 打开 **设置 → 对话管理 → 归档对话 → 管理**,即使普通会话列表为空也可进入。设置随后关闭,管理页在 DSH 主内容区打开;点击 **返回对话** 回到当前对话。 - 紧凑行显示标题、工作区名称(或 **无工作区**)和创建日期。悬停或键盘聚焦后显示 **恢复对话** 和 **立即删除**;触屏设备始终显示操作,并提供更大的点击区域。完整工作区路径可悬停查看,也可搜索。 - 搜索匹配标题和工作区路径。选择对话后,在列表旁显示只读文本预览;窄屏切换到带返回按钮的预览页。恢复后可在完整对话中查看工具和附件。 - **恢复对话** 会取消归档,保留原工作区归属或无工作区状态。管理页保持打开,便于继续整理。 - **立即删除** 使用一次确认,默认聚焦 **取消**。删除或恢复成功只移除对应行,保留搜索和滚动位置;失败时保留该行并允许重试。两种操作均不会重新加载归档列表或全部会话。 - 恢复后再次归档的对话,会在重新打开或刷新列表时出现。较晚返回的旧列表请求仍不能把请求期间已移除的行加回来。 - 首屏使用 DSH 已有的会话头与标题缓存,不读取对话日志。缺失标题在后台每批最多补读八条,同一条并发读取会合并;补读标题保留在 Host 内存中,一分钟后在后台检查日志版本;未变化的日志不会重复读取。检查期间保留已知标题,Host 重启后重新补读时也不会把已显示的标题换成加载提示。再次进入时保留现有列表并检查变化;点击 **刷新** 可重试读取失败的记录。 - 只显示 Host 的真实归档记录,不包含 `dsh-conversation-tree` 折叠隐藏的版本。缺失或不可读取的记录仍保持可见;不可用记录不能恢复,可以重试文本预览或删除记录。 本插件不添加 Agent 工具,不创建对话副本。补全标题可能读取会话日志;只有选择对话时才把消息文本发送到浏览器。浏览器内存最多保留三份文本预览,插件卸载时清空。 ### 兼容性 `0.7.0` 只针对 DSH `0.2.0-rc.2` 验证。0.2.0 改动了本插件依赖的三处内部契约:descriptor 的值 codec 由 `schema` 字段改为 `create()` 工厂;侧栏会话列表由 `useSessions` 钩子改为 `list` 快照属性;hero 与输入框不再经由 `main.conversation` 的 `renderSlot` 管道下发。本版本按这三处改写,并以客户端工作区模型中的虚拟工作区条目(`::dsh-no-workspace`)替代原先的渲染属性注入——宿主注册表不写入任何工作区。 会话行的置顶、重命名、分叉与归档是 DSH `0.2.0-rc.2` 的 `sidebar.workspaces.session.menu.item` 与 `sidebar.workspaces.session.row.action` 扩展位条目;本插件的删除行现在就注册在同一个列表里,不再改写行内 fiber 或悬停按钮。原生输入框的 **×** 一键切换依赖 0.1.5 的 composer chip 管道,0.2.0 上请直接用工作区选择器里的 **无工作区** 条目完成同样的切换。 `0.7.0` 变更:此前插件在原生菜单旁又画了一套 **置顶** 与 **归档** 按钮,并把置顶名单存在浏览器本地、反复写回会话顺序,与原生置顶互相打架。这两个按钮现已删除,改用 DSH 原生的行尾悬停按钮;**立即删除** 从悬停按钮移入会话行「⋯」菜单,位于原生归档之后并自带分隔线。 `0.6.2` 修复:0.2.0 还移除了 **新会话** 动作使用的 `navigation.sessions.clear()`,该调用会在点击处理中抛异常,使侧栏按钮与 ⌥⌘N 快捷键完全失效,本版本改为直接启动受管对话。同时修正了无工作区归属只覆盖当前会话的问题——那会让其余无工作区会话留在原生未分组区,出现两个同名 **无工作区** 分组。 `0.6.4` 修复:虚拟工作区条目的路径为空,而原生树形视图会把工作区挂到「包含它的最近已注册目录」之下——空路径包含所有绝对路径,于是 **按工作区树** 会把每个已注册工作区都渲染成 **无工作区** 的子项。该条目现在使用受管根目录,其中只有本插件自己的对话目录,工作区因此保持各自层级。 `0.6.3` 修复:**无工作区** 此前与真实工作区一起参与活动排序,繁忙的工作区会把它挤到下方;而 **最近更新** 视图本身关闭了分组拖拽,于是「拖动无工作区」看起来完全无效。现在该分组在两种排序模式下都固定置顶(渲染同一标签的原生未分组区跟随其后),活动排序只决定它下方的分组,锚点行也不再提供它无法兑现的拖拽手势。 输入框工作区按钮与选择菜单在 0.2.0 上由原生组件直接绘制,插件无法再包装它,因此一致的对话气泡图标改由 DOM 适配器套用:只有当按钮或菜单项显示本插件的 **无工作区** 标签时才替换图标,切回真实工作区时恢复原生文件夹图标。 DSH `0.2.0-rc.2` 没有原生的恢复和删除接口,本版本复用其工作区串行写入、Agent 原生生命周期句柄、JSONL 写锁及 SQLite 搜索清理。升级 DSH 前需要重新验证这些集成。如果某个会话在插件加载前已经启动,请重启 DSH。由其他 Agent 管理的子代理会话不能直接删除。存储根目录及各对话子目录必须是真实目录,不能是符号链接。 ## 安装 ```sh dsh plugin --profile web add github:Unintendedz/dsh-ui-enhancements#v0.7.1 ``` 安装或卸载后请重启 DSH Web 服务。 ## 卸载 ```sh dsh plugin --profile web remove dsh-ui-enhancements ``` ## 开发 ```sh npm install npm test ``` `tests/browser/workspace-choice.js` 浏览器回归检查一键清除、统一图标、当前分组高亮、键盘操作和草稿转移。在全新隔离配置档中创建合成的 **Alpha Workspace** 与 **Beta Workspace** 数据后,执行 `playwright-cli run-code --filename=tests/browser/workspace-choice.js`。测试保护要求临时 DSH home 名称匹配 `dsh-workspace-choice-test-*`,并使用独立回环端口;禁止使用现有配置档。 ## 许可证 MIT