DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
S

dsh-steward

Steward

Conversation steward for DeepSeek Harness: one folder per conversation, a recoverable Delete conversation row, an automatic handover log per conversation, type-aware right-click file actions, link actions that open in any installed browser, and an opt-in three-rule safety baseline written into the g

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:John4874314/dsh-steward#a9fc662ae3923e200692ba139680c9282f91938a
READMECompatibilityVersions

Description

Conversation steward for DeepSeek Harness: one folder per conversation, a recoverable Delete conversation row, an automatic handover log per conversation, type-aware right-click file actions, link actions that open in any installed browser, and an opt-in three-rule safety baseline written into the global AGENTS.md.

Compatibility and provenance

Steward is published as dsh-steward and currently resolves to version 1.6.3. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
11/1/2026

Versions

1.6.3stable
11/1/2026
1.6.0stable
11/1/2026
1.4.1stable
10/29/2026
Show 5 more versionsCollapse versions
1.3.1stable
10/26/2026
1.3.0stable
10/26/2026
1.2.2stable
10/26/2026
1.1.0stable
10/25/2026
1.0.0stable
10/24/2026

Related plugins

Loading related plugins…

Latest
1.6.3
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 2
Weekly downloads
0
Last push
11/1/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in memory-context.

Hindsight Coding Agents@vectorize-io/hindsight-coding-agentsReflect-only Hindsight long-term memory for coding agents (harness-pluggable: opencode, …), with automatic background ingestion (no setup CLI).Contextdsh-contextA DeepSeek Harness plugin for context insight and management, with context dashboard and context command, for understanding how the context is made of, and how it evolves.Memory Plugin@openviking/dsh-memory-pluginOpenViking memory and context bundle for DeepSeek HarnessMnemondsh-mnemonComposable, view-based context for DeepSeek Harness. Pluggable sources and strategies, with layered memory and self-evolving skills out of the box.

README

dsh-steward · 对话管家

给 DeepSeek Harness 的对话管家: 每个对话一个文件夹、文件夹里自动写一份交接日志、可恢复的删除、 按文件类型分组的右键菜单、网址右键菜单, 外加一套由你手动开启的、写进全局 AGENTS.md 的运行守则。

尚未发布到 npm。 本项目不提供 npm 包,上面的徽章里也没有 npm 版本号 —— 请用「安装」一节的 tarball 方式,dsh plugin add dsh-steward 解析不到任何东西。

🌏 中文 · English


平台支持

核心功能(对话文件夹、交接日志、删除对话、右键菜单、备份、体检)在 Windows / macOS / Linux 都能用。 但有几项是 Windows 专用,在别的系统上会直接隐藏,不会留一个点了没反应的按钮:

功能WindowsmacOS / Linux
每个对话一个文件夹、交接日志✅✅
删除对话(可恢复)、批量删除✅✅
文件右键菜单:打开 / 复制路径 / 另存为 / 重命名 / 移到回收站✅✅
文件右键菜单:解压到此处✅ 用系统 tar.exe❌ 隐藏
网址菜单:用其它浏览器打开✅ 读 StartMenuInternet 注册表❌ 隐藏(只留「在默认浏览器打开」)
文件右键菜单:在终端中打开✅❌ 隐藏

如果你在非 Windows 上发现某个菜单项显示了但点了没反应,那是 bug,请开 issue。

它解决什么问题

DSH 原生把「对话」放在侧边栏,但:

  • 对话一多,找不到某个对话对应的文件 —— 它没有「每个对话一个目录」的概念。
  • 删对话是不可逆的 —— 手滑一次,记录就没了。
  • 对话里的文件卡片只能点开,不能右键做「打开文件夹 / 复制路径 / 另存为」; 而且不同文件想做不同的事(图片、代码、压缩包),没有分类型的入口。
  • 对话里的链接只能点开 —— 不能换浏览器打开、不能只复制 URL、不能复制成 Markdown 链接。
  • 想让 agent 每次都遵守同一套安全基线,没有统一入口 —— 只能每个工作区各写一份 AGENTS.md。

这个插件把这五件事一次做完,并且只有一个 bundle、一个开关、一个设置页。

更新日志

1.6.3

存储页多了「按产生日期」分组,让你能判断这批孤儿是什么时候来的。

起因是个真问题:有人问"那些孤儿附件都是我删过的对话的产物吗"。答案是没法证明—— 附件按 sha256 内容寻址,文件名就是哈希,DSH 不记录"这张图来自哪个对话"。

唯一能用的线索是时间。所以现在扫完会按日期列出:

按产生日期(帮你判断这批是什么时候来的)
  2026-10-25    1 个    0.0 MB
  2026-10-21   27 个   67.1 MB   ← 这一天的占了一大半,多半是同一次批量操作的产物
  2026-10-20    6 个   17.7 MB
  2026-09-30   16 个    2.6 MB

某一天占了总数一半以上时会额外标出来 —— 那通常是"某次批量粘贴"的特征, 比零散分布更容易回忆起来。

日期按本地时区切,不是 UTC —— 你想的是"10 月 21 日那天",不是 UTC 的那天。

新增 2 条测试(test/storage-scan.test.mjs 现共 9 条):按日期分组的个数与字节 必须与孤儿总数严格一致(防止界面上出现自相矛盾的数字);没有孤儿时 days 是空数组。

1.6.2

修一个会误删还能用的附件的 bug:孤儿扫描没把回收站里的会话算进去。

scanAttachments 只扫 $DSH_HOME/sessions/,但 $DSH_HOME/trash/<id>/session/ 里还躺着被删对话的日志 —— 那些对话是可恢复的。只扫 sessions 会把它们引用的附件 判成孤儿,用户一旦从回收站恢复那个对话,图片就没了。

"已删除"和"可恢复的已删除"是两件事,只有前者能让引用失效。

修复后在真实数据上的效果(同一台机器,修复前后对比):

修复前修复后
仍被引用726731
孤儿附件5550
孤儿占用88.7 MB87.4 MB

多出来的 5 个就是回收站里那个会话引用的附件 —— 之前会被误删。

界面上「仍被引用」那行现在会显示 + N 个回收站日志,让用户知道这个数是怎么来的。

新增两条测试(共 7 条):回收站会话引用的附件不算孤儿;活会话与回收站会话的引用 要合并计算,不重复也不漏。

1.6.1

把「备份放哪、怎么写」变成随插件分发的约定,别人的 agent 也能照做。

1.6.0 给备份加了来源标注,但那套东西只活在我这台机器的记忆里 —— 换个 agent、 换台机器就不成立了。这次把它写进随插件分发的守则正文 (AGENTS.guardrails.md),于是只要你打开「运行三原则」, $DSH_HOME/AGENTS.md 里就会带上这段,agent 每次改文件前都会按它做备份。

新增的守则段落规定:

  • 位置 $DSH_HOME/backups/<YYYYMMDD-HHmmss>-<是什么>-<在改什么之前>/, 并明确「不要写死盘符」——别人机器上 DSH home 未必在 E 盘。
  • 每条备份自带 meta.json,字段表(kind / label / source / workspace / reason / createdAt)逐条说明必填与否。
  • 两条硬规矩:source 与 workspace 不许混用;不确定就不写,不按目录名猜来源。

同时纠正了 1.6.0 留下的一个语义错误:workspace 之前被我无条件填成同一个项目目录, 对「与该项目无关的备份」来说这是错的信息,会让字段退化成噪音。 现在明确:与被备份内容无关时留空字符串。已按此修正两条历史备份 (workbuddy 升级前备份、profile 锁文件改名前的备份)。

插件 README 也加了同样一节,说明这个目录不只插件在用、agent 的快照也放这儿。

新增 test 之外的端到端验证 12 条:守则注入幂等(连注两次结果完全一致)、 不破坏用户原有内容、标记恰好一对、preview 与 get 正文一致。

1.6.0

备份分页:每条备份都说清自己是从哪来的。

以前「备份」分页只能看到一句「11 项 · 5.2 MB」,下面一堆 20261026-122749-steward-before-review-fixes 这样的目录名 —— 过两周连我自己都认不出 哪个是哪个工作区的、为什么备份的。

这次给每条备份加一份 meta.json,界面按来源分组:

来源什么时候产生
插件源码快照改插件代码前的手动快照
插件升级前备份升级其它插件(如 workbuddy)前的备份
AGENTS.md 覆盖前自动备份你点「恢复守则」时插件自动生成的 AGENTS.md.<时间戳>.bak
手动备份其它手动留的
来源未知(旧备份)没有 meta 的历史条目

三条刻意的取舍:

  • 绝不根据目录名猜来源。 ...-steward-... 看着像插件快照,但名字里没有任何工作区 或时间语义保证。猜出来的来源比没有来源更糟 —— 它看上去像真的。所以没有 meta 的 一律进「来源未知」,界面上提供「补说明」入口让你自己填。
  • 「来源未知」不允许整组清理。 那一堆恰恰是最需要逐个看一眼的, 给个一键清掉的口子等于把风险最高的操作做得最省事。
  • 按组清理也是移进回收站。 备份本身就是回退手段,删备份是最不该鲁棒性差的操作。 进了回收站还能捞回来。

顺带修了一个真 bug:/chat-backup 的子命令解析用的是整行 trim, 于是 meta <id> 拼成 "meta 20261025-..." 永远不等于 'meta' —— 所有带参数的子命令都被当成未知动作。已改成取第一个词。

命令行:

/chat-backup list                    # 按来源分组列出
/chat-backup meta <id> --kind=... --label64=... --workspace64=... --reason64=...
/chat-backup trash <id...>           # 指定条目
/chat-backup trash --group=<origin>  # 按来源整组

1.5.0

新增「存储」分页:插件开始管它自己的垃圾了。

之前的清理功能(回收站、备份清空、孤儿文件夹)只管插件自己产生的东西。 真正占空间的三项——附件库、会话日志、备份——一直没有入口。这次补上第一项。

能看到的:附件库 $DSH_HOME/attachments/v1/objects 一共有多少文件、多大, 多少还被会话引用,多少已经没有任何会话再引用它。

孤儿是怎么判定的:DSH 的附件按 sha256 内容寻址存放,文件名就是哈希。 插件把每个会话日志(多帧 zstd,追加式)逐帧解压成文本,抓出其中的 64 位 hex, 与附件文件名求差集 —— 剩下的就是孤儿。

实测一台用了两个月的机器:775 个附件 / 335 MB,其中 75 个 / 152 MB 没有任何会话再引用。

三个刻意的取舍:

  • 不自动扫描。切到这一页不会自动开跑,因为一次扫描要解压全部会话日志 (实测约 1.5 秒)。先看轻量信息,点「扫描孤儿附件」才做重活。
  • 不直接删。清理是把文件移进回收站,和删对话同一套逻辑,可以在「回收站」分页恢复。 恢复按 origin.json 记下的原始绝对路径逐个搬回,不是靠文件名倒推。
  • 如实说明判定的边界。如果某个会话记录早已被删掉(删完对话又清空了回收站), 它引用过的附件就会失去引用来源,从而被判成孤儿。这一点写在界面上,不在文档里藏着。

顺带修了一个真 bug:/chat-trash list 早先把「非 file 即 conversation」写死, 导致新加的附件批次条目在回收站里显示成对话。现在按 file / attachments / conversation 三类正确区分。

新增 test/storage-scan.test.mjs(5 条):覆盖「被引用不算孤儿」「多帧必须逐帧解压」 「没有日志时全部算孤儿」「目录不存在不抛错」「半截坏帧不影响判定」—— 第二条尤其重要,只读第一帧会把后面的引用全误判成孤儿。

命令行:/chat-storage scan | clean | open。

1.4.1

修:对话里 @ 引用的文件(截图里那个 交接日志.md 小标签)右键没有菜单。

那是 DSH 的「文件引用 chip」,DOM 上只有 title="交接日志.md"(文件名), 完整路径只存在 React props 里,拿不到。所以:

  • 客户端认出这个 chip(span[title] + 文本与 title 一致 + 内含 svg 图标, 三条同时成立才算,避免误判普通带 title 的文字);
  • 把文件名交给宿主,宿主在该会话的工作目录下按名查找;
  • 同名文件有多份时,取层级最浅的那份(DSH 里 @x.md 本来就相对会话 cwd, 浅层优先最接近原意),同时把「还有几份、分别在哪」一并告诉你,不静默挑一个;
  • 搜索限深度 4 层、跳过 node_modules / .git / dist 等目录,最多 4000 条目。

菜单与正文路径一致:打开 / 在文件夹中显示 / 另存为 / 复制路径。

顺带修了一个识别 bug:点在 chip 内部的文字上时,之前会取到子节点(没有 title)而认不出来; 现在统一 closest 往上找。这个 bug 是被新加的 test/chip-detect.test.mjs 抓到的。

1.4.0

新增:对话里的图片、正文里的文件路径,都能右键操作。

  • 图片右键(.png / .jpg / .webp / .gif / .svg …):打开图片、在文件夹中显示、 另存为、复制图片、复制文件名。图片在界面上是 blob: URL,没有磁盘路径, 所以插件把图片字节算出 sha256 交给宿主,宿主按内容寻址去 $DSH_HOME/attachments/v1/ 找回原图 —— DSH 的附件本来就按 sha256 存,哈希就是主键。 (刻意不把图片字节塞进命令:命令会原样记进会话日志,80KB 的 base64 会把对话刷成乱码。)
  • 正文路径右键:消息里出现的 E:\a\b.pdf、@docs/PRD.md、./notes.md 这类路径, 右键就能「打开 / 在文件夹中显示 / 另存为 / 复制路径」。相对路径用该会话的工作目录补全, 所以 @docs/PRD.md 这种写法也能直接打开。
  • 打开/定位走宿主的系统调用,不是浏览器下载。没有后缀的附件对象会先物化成 $DSH_HOME/cache/dsh-steward/attachments/<哈希前缀>/<原文件名>, 否则 Windows 不知道用什么程序打开它。
  • 判定刻意保守:只有指针真的落在像路径的那一段文字上才弹菜单。 docs/PRD.md(没有 @)、https://…、普通句子一律不认 —— 宁可少弹,不要满屏乱弹。
  • 新增 test/path-detect.test.mjs:把「什么算路径」的判定从源码里抠出来跑, 9 个正例 + 10 个反例,防止哪天手滑把正则放宽成"每句话都弹菜单"。

1.3.1

修 1.3.0 引入的一个回归:本地包名残留 @local/。

1.3.0 把 patch 与 client 的 id 统一改成了 dsh-steward,但漏了本地开发目录的 package.json,它的 name 还是 @local/dsh-steward。

DSH 的 assertPackageOwned() 会从 icon.svg 的真实路径向上找一个 name 等于包名的 package.json。先找到的那个是 @local/dsh-steward,对不上,于是整个插件被标记为:

包元信息错误:Plugin metadata for dsh-steward:
icon.svg: icon must remain inside its package directory

界面上表现为插件被自动移出 bundle 列表并显示「已关闭」。

  • 本地 package.json 的 name 改为 dsh-steward,与发布版完全一致。 本地和发布从此共用同一个包身份,这类「本地能跑、发布坏 / 发布修了、本地又坏」的分叉不会再出现。
  • exports 补上 "./package.json": "./package.json"(其它插件都有;缺了会让 <包名>/package.json 解析报 ERR_PACKAGE_PATH_NOT_EXPORTED)。
  • 自检从 6 条扩到 9 条:新增「exports 必须导出 ./package.json」「包名必须是裸名, 不带 @scope/」「icon 满足 DSH 的类型/大小/包内约束」。已验证把 name 改回 @local/ 会立刻让 2 条断言变红。

1.3.0

这一版修的是一个发布阻断级 bug:1.0.0 ~ 1.2.2 从 tarball / npm 安装都加载不了。

  • 修 cordis.patch.yml 的 name:写的是本地开发用的 @local/dsh-steward, 而真实包名是 dsh-steward。宿主按 name 解析模块,所以装完会直接 ERR_MODULE_NOT_FOUND: Cannot find package '@local/dsh-steward', 插件整块不激活(dsh: warning: 1 entry did not activate)。 本地开发时看不出来,因为本地恰好装成了 @local/ 作用域 —— 这是它能溜进发布版的原因。
  • client.js 的 module id 同步改为 dsh-steward,与包名一致。
  • 运行守则改为默认关闭。以前 guardrails.install: true 且代码里用 !== false 判断,undefined 会被当成开启 —— 装个插件就往全局 AGENTS.md 写东西。 现在只有显式打开才写。要三原则请去设置页自己开。
  • 补上最小自检与 CI:npm test 跑断言,其中第一条就是 「package.json / patch insert / client module id 三个名字必须一致」。
  • README 去掉 npm 徽章(包没发布,徽章是假的),并补上平台支持矩阵。

1.2.0

  • 每个对话的文件夹里自动写一份「交接日志.md」:概览(会话 id / 工作目录 / 起止时间 / 消息数)、本次产出的文件清单、按时间顺序的对话记录(用户说了什么、助手回了什么、 调了哪些工具及成败)。用来把任务交给下一个人,或几天后的自己。
  • 自动触发:建目录时一次,之后每个轮次结束一次(同会话 4 秒节流); 整份重新生成后原子覆盖,不会留半截文档。
  • 剔除 DSH 每轮注入的 <system-reminder>(实测占原始事件篇幅 48%), 超长消息保留头尾并标注省略字数,默认保留最近 400 条对话。
  • 新增命令 /chat-session-log --session=<id>,给历史对话补导一份。
  • 设置页「对话管理」里新增「在文件夹里写「交接日志.md」」开关(默认开启, 仅在文件夹开关打开时显示)。

1.1.0

  • 文件右键菜单按类型分组:代码 / 文档 / 压缩包 / 图片 / 音视频 / 可执行 / 其它, 每类给一套专属动作(复制代码、解压到此处、复制文件内容、文件信息…)。
  • 网址右键菜单:在默认浏览器打开、用其它浏览器打开、复制网址、复制为 Markdown 链接。
  • 带账号密码的链接不再被静默忽略:菜单照常弹出,密码打码显示,打开前弹确认框。
  • 右键范围从「交付物卡片 + 变更审查行」扩展到右侧文件树。

1.0.0

首个发布版:对话文件夹、可恢复删除、批量删除、文件右键菜单、运行守则、备份管理、体检。

安装

把 <profile> 换成你的 profile 名(桌面端通常是 desktop,Web 端通常是 web)。

方式一:tarball(推荐,不依赖 git)

dsh plugin --profile <profile> add https://codeload.github.com/John4874314/dsh-steward/tar.gz/refs/tags/v1.6.3

不要求本机装 git,也不要求 github.com:443 可直连 —— 只走 codeload.github.com。

方式二:github: 简写

dsh plugin --profile <profile> add github:John4874314/dsh-steward

需要本机 PATH 里有 git,且能连上 github.com:443。在国内网络下 github.com 常常超时(api.github.com / codeload.github.com 却正常), 这时会报 ERR_PNPM_GIT_RESOLVE_FAILED,换方式一即可。

装完之后

重启 DSH。客户端 bundle 图在进程启动时构建,只按 Ctrl/Cmd + Shift + R 刷新页面 不会重新扫描新插件。

环境要求

  • DSH 0.2.1-rc.1 或更新(在 0.2.1-rc.3 上实测通过)
  • Node ≥ 20
  • Windows / macOS / Linux 均可装;其中解压、多浏览器选择、终端三项目前是 Windows 专用, 见上面的「平台支持」。

装完先自检

不信任一个第三方插件是合理的。装完可以自己跑一遍它的自检:

git clone https://github.com/John4874314/dsh-steward && cd dsh-steward
npm test          # 9 条断言,不需要装任何依赖

或者只跑插件自带的只读体检:设置 → 对话管家 → 体检。它只读,不改任何文件。

功能

一、对话管理

每个新对话一个文件夹(默认关闭)

设置 → 对话管家 → 对话管理 → 「每个新对话创建一个文件夹」。

  • 默认在发出第一条消息时才建,空会话不留目录。
  • 子代理不建(跟随父会话);路径越界拒绝;非法字符替换成 -。
  • 开关即时生效,配置存 $DSH_HOME/chat-manager-config.json。

文件夹里自动写「交接日志.md」(默认开启)

设置 → 对话管家 → 对话管理 → 「在文件夹里写「交接日志.md」」。 这个开关只在「每个新对话创建一个文件夹」打开时才出现 —— 没有文件夹就没有落脚点。

每个对话自己的文件夹里会多出一份 交接日志.md,用途是把任务交给别人(或几天后的自己):

段落内容
概览会话 id、标题、工作目录、创建时间、导出时间、消息数、省略了多少
产出的文件这次对话里 present 过的交付物,一行一个绝对路径 + 说明
对话记录按时间顺序:用户说了什么、助手回了什么、调了哪些工具(成功/失败)

几个刻意的取舍:

  • 什么时候写:建目录时写一次;之后每个 turn/end 与 session/end-seed 各写一次, 同会话 4 秒内只写一次(节流),避免长对话把磁盘写满。
  • 怎么写的:整份重新生成、写 .tmp 再 rename 原子覆盖 —— 不会留下半截文档。
  • 为什么不是原样复制:DSH 每轮都会把 <system-reminder>(内含 AGENTS.md 全文) 拼进用户消息。实测一份 1.2 万条事件的对话里这类内容占 48%、同一份守则重复上千遍。 日志会剔除这些注入块,只留人真正说过的话。
  • 单条消息过长会截断:默认每条上限 4000 字,保留头尾并标注省略了多少字; 对话条数上限默认 400(超出的较早消息整段省略,页首写明)。 完整原文始终在 $DSH_HOME/sessions/ 里,日志只是"能读的摘要"。

想给一个历史对话补一份日志(早于本功能、或当时开关是关的):

/chat-session-log --session=<会话 id> [--force] [--folder=<路径>]

删除对话(可恢复)

对话行「⋯」菜单 → 「删除对话」。

确认框里可勾选「同时删除该对话的文件夹」。确认后:

  1. 归档该对话
  2. 发 api-session/removed,让侧边栏立即移除该行
  3. 把会话记录目录移进回收站(不是删除)
  4. 清理归档记录
  5. 可选:把文件夹也移进回收站

内容进 $DSH_HOME/trash/<id>/,并写一条 meta.json 记下标题、时间、原路径。 设置页「回收站」里可以恢复或彻底删除。

打开该对话的文件夹

对话行「⋯」菜单 → 「打开该对话的文件夹」,直接在资源管理器里定位。 没有登记过文件夹的对话不显示这一行 —— 不占位,也不会出现点了没反应的按钮。

批量删除

/chat-delete-batch --sessions=<id1,id2,...> [--with-folder]

逐个走同一条删除路径,全部进回收站,返回每个的成功/失败明细。

文件右键菜单(按类型分组)

对话里的文件卡片、右侧「变更」审查行、右侧文件树,点右键(或用键盘 Shift+F10 / 菜单键)都能弹出菜单。

菜单会先认文件类型,再决定放哪些动作。通用项永远在,专属项插在中间:

类型识别方式专属动作
代码.js .ts .py .go .rs .java .c .cpp .cs .php .sh .ps1 .sql .html .css .json .yaml …复制代码、复制为 Markdown 代码块(带语言标注)
文档.md .txt .pdf .docx .xlsx .pptx .csv .epub …复制文件内容
压缩包.zip .7z .rar .tar .gz .tgz .bz2 .xz .zst …解压到此处(同名目录已存在则拒绝,不覆盖)
图片.png .jpg .gif .webp .svg .bmp .ico .avif …文件信息
音视频.mp4 .mkv .mov .mp3 .wav .flac .m4a …文件信息
可执行.exe .msi .dll .so .dylib .bin .jar .wasm …只给「文件信息」,不提供任何运行入口
其它其余扩展名文件信息

通用项:

动作说明
打开 / 打开文件夹 / 选择打开方式走 remote.session.*,不写会话日志
在终端中打开在该文件所在目录起一个终端窗口
复制路径复制绝对路径
复制为引用复制成 @<路径>,粘贴到输入框即可定位
另存为…选目录后由宿主复制一份(同名自动加序号)
重命名…同目录内改名,不覆盖已有文件
文件信息大小 + 修改时间
移到回收站文件进 $DSH_HOME/trash/,可恢复

外观是液态玻璃,颜色取 --dsw-alias-* 令牌,随深浅主题自动切换。菜单顶部的类型标签按类别着色(代码蓝、压缩包橙、可执行红),扫一眼就知道这是哪类文件。

为什么不给可执行文件「运行」:右键菜单的路径来自对话内容,是模型可以影响的输入。 一个「运行」按钮等于给了一个静默执行任意程序的入口,收益远小于风险。

「打开 / 打开文件夹 / 打开方式 / 复制路径 / 复制为引用」不写日志; 「在终端中打开 / 另存为 / 重命名 / 移到回收站 / 解压 / 复制内容」必须由宿主执行,走 /chat-file, 会在对话里留一条命令记录 —— 这是浏览器无法直接写本地文件的必然代价。

网址右键菜单

对话里的 http/https 链接上点右键,得到一套网址专用动作:

动作说明
在默认浏览器打开交给系统默认浏览器
用其它浏览器打开列出本机已注册的浏览器(读 StartMenuInternet),逐个可选
复制网址复制原始完整 URL
复制为 Markdown 链接复制成 [链接文字](URL)

只接管 http / https。javascript:、data:、file: 一律放行给原生菜单,不进打开通道。

带账号密码的链接(https://user:pass@host/)不会被静默忽略 —— 那样右键毫无反应,像是坏了。 这类链接照常弹菜单,但:

  • 顶部 URL 打码显示:https://user:***@host/,密码不露在屏幕上
  • 多一行橙色警示:⚠ 这个网址包含账号密码
  • 点「在浏览器打开」时弹一次确认框,说明凭据会被发给目标站点
  • 复制类动作仍然可用,复制的是完整原始 URL(含真实密码)——复制到剪贴板是你主动的动作,不该被改写

安全靠「打开前确认」保证,不靠「什么都不给」。静默失败会让人以为插件坏了, 明确警示才会让人真的看一眼地址。

图片右键菜单

对话里显示的图片(.png / .jpg / .jpeg / .webp / .gif / .svg / .bmp / .avif), 点右键就能:

动作说明
打开图片用系统默认看图程序打开
在文件夹中显示在资源管理器里选中这个文件
另存为…选目录后复制一份(同名自动加序号)
复制图片图片直接进剪贴板,可以直接粘到聊天窗口
复制文件名复制原始文件名(如 image.png)

为什么需要绕一圈:界面里的图片是 blob: URL,浏览器不给你它的磁盘路径。 插件把图片字节算成 sha256,宿主按内容寻址到 $DSH_HOME/attachments/v1/ 找回原图。 DSH 的附件本来就按 sha256 存,哈希就是天然主键 —— 这样不必把 80KB 的图片 base64 塞进命令(那会把会话日志刷成乱码)。

正文里的文件路径也能右键

消息里出现的路径,右键就有「打开 / 在文件夹中显示 / 另存为 / 复制路径」:

E:\islet\docs\交接文档.md
@docs/PRD.md
./notes.md
~/Documents/a.pdf
  • 相对路径(@docs/PRD.md、./notes.md)用这个对话的工作目录补全, 所以拖进去的引用可以直接打开。
  • 只认「指针真的落在那段文字上」的情况,而且必须是完整的一段带路径特征的文本。 没有 @ 的 docs/PRD.md、https://…、普通句子都不会触发 —— 宁可少弹,不要满屏乱弹。
  • 想省事的话,拖选一段路径再右键也行(选中优先)。
  • 对话里带文件图标的 @引用 小标签(比如 交接日志.md)也能右键。那种标签的 DOM 上只有文件名、没有路径,所以插件会把文件名交给宿主,在这个对话的工作目录里按名查找; 同名文件有多个时会列出全部候选让你看清,不会猜一个打开。

二、运行守则(三原则)—— 默认关闭,要你自己开

默认是关的。 安装本插件不会改动你的 $DSH_HOME/AGENTS.md。 想用三原则,去 设置 → 对话管家 → 运行守则 → 「启用运行三原则」自己打开。 打开后才会往全局文件里写内容;关掉后不再注入,已写的那段留在文件里,需要你手动删。

打开后把三原则写进 $DSH_HOME/AGENTS.md(DSH 的全局指令文件), 每个工作区、每个新会话都会带上,harness 升级也不丢:

  1. 不破坏 DSH 与系统 —— 不碰安装目录 / profile 配置 / 会话凭据 / 系统设置;不为完成任务降级安全。
  2. 有风险的操作先验证 —— 说清「改什么 / 最坏怎样 / 怎么撤回」再执行;能小步试就不全量。
  3. 留好备份、保证可回退 —— 改前备份、确认回退路径存在、改完验证、验证不过就回退。

正文见 AGENTS.guardrails.md。

本 bundle 的 patch 会重新启用 agent-instructions(web-app bundle 默认禁用了它), 否则守则写进 AGENTS.md 也进不了上下文。副作用:项目里的 AGENTS.md / CLAUDE.md 也会被读进上下文。这一步与上面的开关无关 —— 它是 bundle 层的,装了就有。 如果你只想要对话文件夹/右键菜单、完全不想让 agent 读项目里的 AGENTS.md, 请删掉 cordis.patch.yml 里 agent-instructions 那一段再安装。

三、设置页的五个分页

分页内容
对话每个新对话一个文件夹、交接日志 两个开关
回收站列表 / 恢复 / 彻底删除 / 清空,显示每条占用
备份备份目录位置与占用,一键清空 或 打开文件夹 自行取舍
运行守则三原则开关、全文展开、写入结果预览、用内置版本恢复
体检一次只读自检,报告守则块 / 表单 / 配置 / 登记表 / 回收站 / 备份

备份由你自己决定留还是删

写 AGENTS.md 等文件前会自动备份到 $DSH_HOME/backups/,备份会一直留着占磁盘。 「备份」分页因此给了两个按钮:一键清空 或 打开备份文件夹 自己挑。 插件不会替你自动删 —— 那是不可逆操作,该由你决定。

备份约定:每条都要说清自己从哪来

这个目录不只插件在用:你的 agent 改东西前留的快照也放这儿。为了让这些备份在 一段时间后还看得懂,插件把下面这套约定写进了随它分发的守则正文 (AGENTS.guardrails.md)——你打开「运行三原则」后,它会随守则一起进 $DSH_HOME/AGENTS.md,于是 agent 每次改文件前都会照它做。

位置:$DSH_HOME/backups/<YYYYMMDD-HHmmss>-<是什么>-<在改什么之前>/

不要写死盘符 —— DSH 的 home 在不同机器上位置不同。放在这里的额外好处是: 它和 sessions/、trash/ 同一个卷,移动是 rename,不复制字节。

每条备份自带 meta.json(目录备份放在目录里):

{
  "kind": "plugin-source",
  "label": "dsh-steward 源码快照",
  "source": "/绝对路径/到/被备份的东西",
  "workspace": "/触发这次备份的工作目录,无关就留空",
  "reason": "加备份来源分组之前",
  "createdAt": 1793542028019
}
字段必填含义
kind是plugin-source / plugin-upgrade / guardrails / manual
label是一句话说清这是什么
source是被备份的东西原来在哪(不是触发者)
workspace否哪次工作流触发的;与被备份内容无关时留空字符串
reason是为什么备份,用「<动作>之前」的句式
createdAt是毫秒时间戳

两条硬规矩:

  1. source 与 workspace 不许混用。 备份的是 $DSH_HOME/profiles/... 下的插件, 就不该把某个项目目录塞进 source;反过来,一次与工作区无关的备份, workspace 应当留空,而不是填一个「反正也对」的默认值 —— 那会让这个字段变成噪音。
  2. 不确定就不写。 宁可 kind 留 manual、reason 空着, 也不要根据目录名猜一个看起来合理的来源。猜出来的来源比没有来源更糟, 因为它看上去像真的。

「备份」分页会读这些元信息并按来源分组(插件源码快照 / 插件升级前 / 守则自动备份 / 手动 / 来源未知)。没有 meta.json 的历史备份显示为「来源未知」,不会被猜; 你可以直接在界面上给它补说明。「来源未知」那一组不提供整组清理 —— 那堆恰恰最需要逐个看一眼。

体检报告什么

检查项说明
guardrails守则块在不在、标记是否配对、有没有残留旧标记
config-schemaschemastery 是否可用(拿不到就没设置表单)
config-file配置文件能否读取、当前开关值
folder-registry登记表里有多少条指向已不存在的目录
trash回收站条目数与占用
backups备份条目数与占用

全部只读,不改任何文件。

为什么不会拖垮 harness

这是本插件最看重的设计目标 —— 任何失败都只表现为「少一个功能」,绝不连累 DSH 本身:

  • 宿主半侧没有 Config 就降级:schemastery 用运行时尝试获取(先本地、再 profile), 拿不到就导出 Config = undefined,插件照常加载,只是没有设置表单。
  • 守则写入整段包在 try/catch,apply 结尾 catch(() => {}),任何失败都只是「没写进去」。
  • 写 AGENTS.md 前先备份到 $DSH_HOME/backups/,备份失败就放弃写入。
  • 幂等:靠 <!-- dsh-steward:begin/end --> 定位,只替换自己那段; 还会顺手清理旧 guardrails 插件留下的 guardrails:begin/end 段。
  • 客户端适配是弱引用:对其它插件(如 dsh-better-sidebar)的集成一律用 ctx.get(...) 探测 + try/catch,目标不存在就跳过,不影响本体。

已做故障注入:DSH_HOME 不存在、config 为 null、依赖缺失、重复 apply 均不抛错。

关于信任:这个插件会碰什么、不会碰什么

一个第三方插件要能删对话、能写文件,你当然该先问清楚它到底动什么。

会写的文件(全都在你明确开启对应开关之后):

路径什么时候能不能反悔
$DSH_HOME/chat-manager-config.json你在设置页改开关是,就是个 JSON
对话文件夹 + 其中的 交接日志.md打开「每个新对话一个文件夹」后是,删掉即可
$DSH_HOME/AGENTS.md 里 <!-- dsh-steward:begin/end --> 之间你手动打开「运行三原则」是,关掉后手动删那一段
$DSH_HOME/backups/每次改 AGENTS.md 前自动备份是,设置页可一键清空
$DSH_HOME/trash/删除对话 / 文件时移动进来是,设置页可恢复

明确不会做的:

  • 不联网,不上传任何东西。宿主侧没有任何 http / net / https 调用。 客户端有 2 处 fetch,只读本地 blob: / data: 地址(读界面里已经显示的那张图, 用来算 sha256 和写剪贴板),不发往任何服务器。
  • 不读 $DSH_HOME/sessions/ 之外的数据;读会话只是为了生成交接日志,走 DSH 官方 sessionController.inspect() 通道,不直接解析磁盘。
  • 不改 DSH 安装目录、不改 cordis.yml / cordis.patch.yml、不改系统设置。
  • 删除一律走回收站,不直接 rm;清空回收站需要你二次确认。

已知的粗糙之处(写在这里而不是藏起来):

  • 单文件插件,index.js 约 2,600 行、client.js 约 2,400 行,没有拆分模块。
  • 测试只有 9 条契约断言,覆盖「名字一致 / 默认值 / 模块能加载 / icon 元信息」, 不覆盖 UI 交互。
  • Windows 优先开发,非 Windows 的三项功能是直接隐藏而非降级实现。
  • 尚未发布 npm,只能从 git / tarball 装。

配置

配置文件在 $DSH_HOME/chat-manager-config.json:

{
  "folder": {
    "enabled": false,
    "trigger": "first-message",
    "template": "chat-{date}-{time}",
    "useAsWorkingDirectory": false
  },
  "guardrails": {
    "install": false
  },
  "sessionLog": {
    "enabled": true,
    "maxMessages": 400,
    "includeTools": true
  }
}
字段默认说明
folder.enabledfalse是否每个新对话建一个文件夹
folder.triggerfirst-messagefirst-message 或 session-start
folder.templatechat-{date}-{time}支持 {date} {time} {title} {id}
folder.useAsWorkingDirectoryfalse建好后是否把该对话的工作目录切过去
guardrails.installfalse是否把三原则写进全局 AGENTS.md。默认关
sessionLog.enabledtrue是否在对话文件夹里写 交接日志.md
sessionLog.maxMessages400最多导出多少条对话(0 = 不限,超出保留最近的)
sessionLog.includeToolstrue日志里是否包含工具调用与结果

设置页暴露 folder.enabled、sessionLog.enabled、guardrails.install 三个开关; 其余字段需要手改这个 JSON。改完重启 DSH 生效。

卸载

设置 → 插件 → 已安装 → 移除。

$DSH_HOME/AGENTS.md 里的守则段不会自动删除(那是你的文件), 需要的话手删 <!-- dsh-steward:begin --> 与 <!-- dsh-steward:end --> 之间的内容。

node_modules/ 里指向 schemastery 的链接是设置表单用的, 删掉只会让设置页退化,不会让插件崩。

许可证

MIT