dsh-session-folders
面向 DeepSeek Harness Web 界面的会话文件夹插件:侧边栏的会话浏览器被替换为支持会话文件夹的浏览器——每个工作区(workspace)可建立一层命名的文件夹。会话可通过拖拽或右键菜单移入文件夹;文件夹数据保存在服务端,刷新页面后依然保留。状态徽章与原版会话浏览器一致。不需要修改 Harness 本体。
截图
<table> <tr> <td><img src="https://raw.githubusercontent.com/EugeneVl/dsh_session_folders/master/assets/screenshot-1.jpg" alt="dsh-session-folders screenshot 1" width="280"></td> <td><img src="https://raw.githubusercontent.com/EugeneVl/dsh_session_folders/master/assets/screenshot-2.jpg" alt="dsh-session-folders screenshot 2" width="280"></td> <td><img src="https://raw.githubusercontent.com/EugeneVl/dsh_session_folders/master/assets/screenshot-3.jpg" alt="dsh-session-folders screenshot 3" width="280"></td> </tr> </table>
功能
#### 组织
- 会话文件夹:每个工作区一层命名文件夹;不在文件夹中的会话位于「收件箱」(自由区域)
- 移动会话:拖拽会话到文件夹,或使用右键菜单——「移动到文件夹…」,其中的「新建文件夹…」可当场创建文件夹并移入会话;子菜单的「Workspace」项把会话从文件夹移回自由区域
- 文件夹管理:新建、重命名、删除(需确认);名称在工作区内唯一(不区分大小写)
- 就地重命名:双击会话标题即可就地改名——Enter 提交,Esc 取消
- 自动命名:会话右键菜单提供「自动命名」——用会话自己的模型读取首条用户消息,生成至多 3 个词的简短标题(描述过程/功能/任务,使用消息的语言);结果像手动重命名一样被固定
- 拖拽排序:拖拽工作区行可调整工作区顺序;拖拽文件夹行可调整其工作区内的文件夹顺序(文件夹始终位于自由区域上方,会话按时间排序不变);顺序保存在服务端
- 显示更多 / 显示更少:每个文件夹和 Archive 块中最多先显示 5 条会话,点击溢出行后显示全部;展开状态按文件夹分别记忆,仅作用于当前浏览器会话
#### 会话操作
- 右键菜单:会话 / 文件夹 / 工作区的每一行右键都能打开操作菜单(已移除每行的「…」按钮);每个操作都带图标
- 置顶 / 取消置顶会话:置顶的会话始终位于所属文件夹或自由区域的最前面;置顶状态保存在服务端,并随会话一起移动;没有状态徽章的置顶会话在状态槽位显示一个小图钉图标
- 悬停快速归档:鼠标悬停会话行时,时间戳原位替换为一个小归档图标——点击即可归档会话(与右键菜单操作相同);原位替换,布局不会跳动
- 会话 ID 徽章:悬停会话行时,快速归档图标旁会出现一个小
ID徽章——点击一次即可将该会话的session-<id>复制到剪贴板 - 新建会话按钮:工作区行上的「+」在该工作区新建会话;文件夹行上较小的「+」直接在文件夹内新建会话(新建的空白会话会被移入该文件夹并打开)
- 状态徽章 运行中 / 已完成——与原版会话浏览器一致
#### 归档与恢复
- 归档(Archive)块:工作区行上的归档图标显示/隐藏虚拟的 Archive 文件夹,里面是该工作区所有已归档会话;显示时图标带删除线,同时会将文件夹展开;会话按最新在前排列(先显示前 5 条,带「显示更多 N 条 / 显示更少」行)。拖放:把会话拖到它上面即归档(与右键菜单操作相同);把已归档会话拖到某个文件夹或自由区域则恢复到该处
- 从归档恢复:右键点击已归档会话可「恢复到原文件夹」(会话回到归档前所在的文件夹,或回到自由区域);左键点击则恢复到该工作区的 Restored 文件夹(按需创建、若折叠会自动展开)并在聊天中打开。恢复的会话与普通会话分开:Restored 文件夹始终排在最前(紧挨 Archive 块下方),没有任何可见会话时自动隐藏
#### 导航
- Recent 分区:工作区列表上方显示最近 5 个会话(来自文件夹或自由区域),新的在前;点击某个会话会在聊天中打开它,自动展开被折叠的工作区/文件夹使其可见,并同时在 Recent 及其所属工作区/文件夹中高亮。分区头部可折叠(状态持久化)
- Recent 来源卡片:悬停 Recent 中的会话时,行右侧弹出小卡片,显示其所属工作区和文件夹
- 文件夹树连接线:从每个文件夹图标向其会话延伸的虚线引导线;包含当前打开会话的文件夹,其整棵树变为蓝色。浏览器顶栏可切换(默认开启)
- 会话搜索(标题与内容,带高亮)
- 打开工作区文件夹:工作区行上第一个按钮(文件夹图标)通过宿主原生
openPathAPI 用系统文件管理器打开工作区根目录 - 全部折叠 / 全部展开:浏览器顶部的两个按钮一键折叠或展开所有工作区分组、文件夹、Recent 分区与 Archive 块
- 工作区聚焦:工作区行上的准星切换按钮(也在其右键菜单中)会隐藏其他所有内容——其他工作区、Recent、Ungrouped——直到再次关闭;聚焦状态在重启后重置
#### 持久化与界面
- 服务端持久化:文件夹保存在 DSH 存储域中,刷新不丢;视图状态(折叠的文件夹等)保存在浏览器 localStorage
- 服务端是唯一事实来源:所有操作都在服务端校验(工作区是否存在、会话归属、名称冲突);客户端只镜像规则
- 双语界面:跟随页面语言(中文 / 英文)
- 折叠侧栏:窄条模式下仅渲染搜索和新建工作区两个按钮,与内置浏览器一致
安装
从 npm
dsh plugin --profile web add dsh-session-folders从注册表安装预构建包——跳过 allowBuilds 构建审批步骤。
从 GitHub
dsh plugin --profile web add 'github:EugeneVl/dsh_session_folders#v0.4.3'安装后请重启 dsh web(宿主插件与客户端 bundle 在启动时加载)。
使用
#### 开始
1. 打开侧边栏:每个工作区中,文件夹显示在自由区域上方
#### 文件夹
1. 新建文件夹——右键工作区行 →「新建文件夹」;名称在工作区内必须唯一 2. 重命名 / 删除文件夹——右键文件夹行 →「重命名」;删除需确认,文件夹内会话将变为自由会话 3. 排序——拖拽工作区行到新位置;在工作区内拖拽文件夹行(放到某行的上半/下半表示插到其前/后)
#### 会话
1. 移动会话——拖拽会话行到文件夹(只能移入同一工作区的文件夹),或右键会话 →「移动到文件夹…」→ 选择文件夹,或选「新建文件夹…」当场创建并移入 2. 移回自由区域——右键会话 →「移动到文件夹…」→「Workspace」(第一项) 3. 置顶会话——右键 →「置顶」:会话跳到其文件夹(或自由区域)顶部并在其他会话增减时保持;「取消置顶」恢复按最新优先排序;没有状态徽章的置顶会话在状态槽位显示小图钉 4. 新建会话——工作区行上的「+」在该工作区新建会话;文件夹行上较小的「+」直接在文件夹内新建会话 5. 重命名会话——双击其标题(Enter 提交,Esc 取消),或右键 →「重命名」 6. 自动命名——右键会话 →「自动命名」:会话的模型根据首条用户消息生成至多 3 个词的标题。空闲时不产生任何调用;失败显示在通知栏 7. 快速归档——悬停会话行:时间戳原位替换为归档图标;点击即归档
#### 归档与恢复
1. 归档——工作区行上的归档图标显示/隐藏虚拟的 Archive 文件夹(该工作区所有已归档会话,最新在前,每次显示 5 条)。把会话拖到上面即归档;把已归档会话拖到某个文件夹或自由区域即恢复到该处 2. 恢复——右键已归档会话 →「恢复到原文件夹」(回到原处);左键点击则恢复到 Restored 文件夹(若折叠会自动展开)并打开会话。Restored 文件夹始终排在最前,为空时自动隐藏
#### 查找与导航
1. 搜索——浏览器顶部的输入框;匹配结果高亮且可点击 2. Recent——工作区列表上方的分区显示最近 5 个会话(文件夹 + 自由区域)。点击某个会话打开它;Recent 中的行以及所属工作区/文件夹的图标会标记当前会话;分区头部可折叠 3. 打开工作区文件夹——工作区行上第一个按钮(文件夹图标)用系统文件管理器打开工作区根目录
#### 视图
1. 全部折叠 / 全部展开——浏览器顶部的两个按钮: - 折叠:折叠所有工作区分组与文件夹(包括 Recent 与 Archive) - 展开:再次全部展开
工作原理
| 层 | 实现 |
|---|---|
| 宿主 | lib/index.js——cordis 插件:10 个 POST 路由 /dsh-session-folders/{list,create,rename,delete,move,reorder-folders,reorder-workspaces,pin,unarchive};自有存储域 dsh_session_folders(一条全局记录保存文件夹列表);所有变更经 promise 队列串行化,两个浏览器不会互相覆盖;工作区与会话归属通过 ctx.workspaceRegistry 校验 |
| 客户端 | lib/client.js——通过 window.__ModuleLoader__.load 加载的 bundle,注册在 sidebar.workspaces 槽位(优先级 -1);依赖服务 slots / locale / sessions / workspaces;视图状态保存在 localStorage(dsh.session-folders.view.v1) |
- 文件夹不影响会话归属:工作区拥有会话,文件夹只是分组。不在任何文件夹中的会话即自由会话
- 删除工作区不会删除文件夹记录:它们只是停止被提供(按现存工作区 id 过滤),无害地留在存储中
- DSH 域保证持久化优先写入;存储文件为
~/.dsh/storages/dsh_session_folders.json - 不修改系统提示词,不新增模型工具——零 token 影响
限制
- 只有一层文件夹:不支持嵌套
- 会话只能移入其所属工作区的文件夹;不属于任何工作区的会话无法进入文件夹
- 文件夹名称最长 80 字符;重复名称会被拒绝(不区分大小写)
- 排序以服务端为准:客户端提交完整的有序 id 列表,服务端校验(工作区不能拖到活集合之外,文件夹不能离开其工作区)
兼容性
当前版本面向 DSH 0.1.0-rc.6(sidebar.workspaces 槽位、webServer / storageDomain / workspaceRegistry 服务、@deepseek-ai/dsh-storage-domain、@deepseek-ai/dsh-workspace、zod)。DSH 升级如果改变槽位/服务 API,可能需要适配。
开发
无需构建步骤:lib/ 就是随仓库提交的 bundle(宿主 + 客户端)。直接编辑文件并做语法检查:
node --check lib/index.js
node --check lib/client.js客户端改动(菜单项、按钮、渲染)通常只需刷新浏览器——bundle 按需加载;宿主端改动(路由、校验)需要重启 dsh web。
发布清单
1. 在 package.json 中提升 version 并在 CHANGELOG.md 中记录 2. 提交、打标签 vN.N.N,推送 master 与标签 3. 将 profile 指向新版本:dsh plugin --profile web add 'github:EugeneVl/dsh_session_folders#vN.N.N',然后重启 dsh web