云计算百科
云计算领域专业知识百科平台

给 DeepSeek Harness 补一扇「归档」的门:一个已归档会话面板

归档是扇单向门

DSH 的归档做得非常轻——点一下,会话从所有分组里消失,然后就没有然后了。官方前端没有「查看归档」的入口,归档集合只存在于 workspace.json 的一个数组里,界面层一律过滤掉。

数据其实都在:会话正文在磁盘、投影缓存没删、工作区槽位没动。你只是没有门。

于是写了个插件,在侧栏加一个「已归档」面板:能搜、能看、能恢复,也能确定不要了再永久删除。

什么时候用得上

这个面板不是给「天天整理」的人准备的,是给三种具体时刻用的。

清理之后想反悔。 侧栏攒了十几个会话,手快清了一批,回头发现其中一个正是上周调接口的过程记录——里面有那个报错的完整堆栈。官方路径下你只能重新踩一遍,现在可以把它捞回来。

想找一段旧上下文。 有些结论当时没记进笔记,只留在对话里。比如"那个 token 为什么过期"、“当时为什么放弃方案 B”。归档会话被藏起来之后,这类回溯基本断了。面板的搜索框能按标题、摘要、嵌套项目名甚至会话 ID 找,找到直接只读打开看一眼。

确认真的不要了。 归档不等于删除,文件一直躺在磁盘上。攒了几十个之后,你可能会想彻底清掉——这个动作本来没有入口,现在有了,而且带二次确认和回滚。

装完长这样

已归档会话面板总览

面板顶部是四组统计:已归档会话数、总轮次、总 token、涉及的工作区数。截图这个状态是 4 个会话、7 轮、79,867 token、分布在 2 个工作区。

统计口径值得说一句:token 是输入 + 输出合计,轮次按"一问一答"算一次,工作区数只统计归档会话里出现过的不同工作区——所以它可能小于你侧栏里的工作区数量。

再往下是检索区,一行三个:

  • 搜索框匹配标题、会话摘要、嵌套项目名、会话 ID、工作区名五类字段,输入即时过滤
  • 三个筛选器分别管工作区、时间范围、排序方式
  • 排序支持按创建时间 / 按轮次 / 按 token / 按标题,每种都能正反序,点一下切换

每个会话行会显示归档时间、轮次、输入/输出 token、当时用的模型、所属工作区路径,以及一个 GIF 缩略图(如果那段对话里生成过)。右侧三个按钮就是这个面板的全部动作:查看只读 / 恢复 / 永久删除。

三个动作

一、先看一眼(只读)

不确定要不要恢复的会话,点「查看只读」,会按原样打开对话——用户提问、助手回复、轮次统计、甚至是当时报的错,都在:

只读查看会话内容

行本身也能展开,直接给出摘要级的预览(截图里 bug 那条展开后就是完整的 prompt 原文)。判断"这是哪个会话",看展开的摘要通常就够了,不必真的打开。

打开后的视图会标注「只读模式」,输入框禁用。这是故意的:归档会话不参与运行时状态,能发消息反而会制造"我到底恢复了没"的混乱——发了半句话、关掉、再打开发现消息不在了,比不能发更让人困惑。

二、恢复

点「恢复」,会话从归档集合里移除,回到它原来的工作区分组,和归档前一模一样——包括它在原工作区里的排序位置和上下文。

这个动作是幂等的:重复点不会产生第二个副本,因为改的是同一个 id 集合,不是复制文件。恢复之后面板里的统计会同步减少,不会出现"两边都有"的中间态。

三、永久删除(会真的删文件)

前两个动作都可逆,这个不可逆,所以界面先拦一道:

永久删除前二次确认

弹窗把「会删除会话正文、投影缓存,无法恢复」写在正文位置,按钮文字是「永久删除」而不是「确定」——文案上的区别,是为了让手指停半秒。

删完统计立刻更新:

删除后的统计变化

从 4 个会话 / 7 轮 / 79,867 token 变成 3 个 / 5 轮 / 78,908 token。差的这 959 token、2 轮,正好是被删掉那条会话的量——数字对得上,说明删干净了。

技术上做成两阶段:先把会话目录和投影文件重命名到临时 staging 目录,确认所有引用都清干净了,再真正删除;中途任何一步失败,按逆序把文件搬回去。删除前四道校验:id 必须匹配严格格式(同时用 basename 防路径穿越)、必须仍在归档集合里、会话不能在运行时内存中、界面必须过二次确认。任何一道不过就拒绝执行。

三个动作分别动了什么

搞清这三个动作各自碰到哪些文件,用起来会踏实很多(也方便你出事时手工兜底):

动作改了什么能不能反悔
归档(官方) 往 workspace.json 的 global.archivedSessionIds 追加一个 id 能,面板里点恢复
恢复(本插件) 从同一个数组里移除该 id,会话回原工作区 再归档一次即可
永久删除(本插件) 删会话目录 + 对应投影缓存文件,并清理引用 不能,但过程中有 staging 回滚

也就是说:归档只是改一个数组,正文一个字节都没动。这也是为什么"归档了却找不回来"这件事格外让人恼火——数据完好无损,纯粹是界面不给门。反过来说,只要那个 id 还在数组里,用面板恢复就一定能捞回来。

删除就完全不同了,它真的会 rm 掉文件。所以它才需要二次确认、staging 中转、四道校验这一整套——不是把简单的事做复杂,是这件事本身不可逆。

安装

dsh plugin –profile desktop add github:muning0214/dsh-archived-sessions

桌面版用 –profile desktop,Web 版用 –profile web。装完完全退出 DSH 再重开——bundle 在启动时装配,热重载对插件不生效。

也可以在 App 里操作:「插件」→「添加插件」→ 粘贴 github:muning0214/dsh-archived-sessions → 安装 → 启用 → 重启。

装好后侧栏会多一个「已归档」入口,点开就是上面那个面板:

侧栏入口与打开后的会话

卸载反过来一条命令:

dsh plugin –profile desktop remove dsh-archived-sessions

卸载不会动你的会话文件——它只删插件本身,归档集合仍是官方那个数组,会话该在哪还在哪。这也是这个插件相对"改安装包"方案的好处:装卸都不留痕迹。

它背后做了什么

三件事,都不复杂,麻烦的是 DSH 的插件模型。

宿主半边拿数据。归档集合挂在官方的 workspaceRegistry 服务上,读一个 id 数组就够;标题、轮次、token 这些不在里面,要去投影缓存里按会话 id 找,解析失败就降级返回空——不能因为一个坏文件让整个面板报错。

客户端半边负责界面。DSH 的界面是一堆具名插槽,面板往 main 插,侧栏按钮往 sidebar.panellist 插,靠 slots.inject 等槽位出现后再注册,所以不会因为加载顺序报错。

数据通道走官方 RPC。中间试过自建 HTTP 路由,被鉴权中间件拦了两次,最后放弃自制,改用 ctx.remote.workspace 直接读——省掉鉴权、CORS、分页三摊事。

踩过的两个坑(值得单独说)

一、清单文件是契约,不是注释。 有一版把浏览器端代码删了,顺手也删了 exports["./client"],但 package.json 里 dsh.client 那个字段忘了删。结果宿主的一个必需插件在校验时报错,整个应用起不来——窗口上只有「The application could not start」。

反过来也踩过:客户端插件有两份依赖清单,package.json 那份写包名(@deepseek-ai/…),代码里 exports.inject 那份写服务名短名(slots、locale、remote.xxx)。写混了不会报错,只会一直 pending,然后前端白屏。

二、装崩了可以先改现网文件救活。 应用起不来的时候没法用插件市场卸载,最快的办法是直接改 ~/.dsh/profiles/desktop/node_modules/<包名>/package.json,改完重启就能进界面,再从正常路径卸载或修。这招救过我两次。

这两个坑最后都被写成了测试:一条断言 exports.inject 里不许出现包名,一条从源码里扫 ctx.xxx 反推应该 inject 哪些服务——后者不依赖"我记得用了什么",加功能忘了补依赖,测试会直接指出来。

已知限制

  • 只读查看不搜正文:搜索只覆盖归档列表的元数据,会话正文的全文检索还没做(体量大了要上索引,暂时不值)
  • 两个遗留缺陷:删除用的 rmdir({ recursive: true }) 在 Node 里已废弃;路径前缀判断硬编码了 Windows 分隔符,macOS / Linux 上会出现"只清引用、正文留盘"——是少删,不会误删
  • 只在 Windows 桌面版验证过,涉及系统路径的功能在其它平台没实测
  • 归档集合是官方内部状态而非公开 API,DSH 大版本更新后可能需要跟着改

仓库

https://github.com/muning0214/dsh-archived-sessions

MIT。宿主 342 行、客户端 681 行、测试 614 行(23 项,npm test 一把跑完)。有问题欢迎提 Issue。

赞(0)
未经允许不得转载:网硕互联帮助中心 » 给 DeepSeek Harness 补一扇「归档」的门:一个已归档会话面板
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!