前面 11 章讲的都是"模型 ↔ 工具"。这一章讲两个边界:模型 ↔ 知识(技能系统)和人 ↔ 模型(命令、提问、计划模式、Web UI)。最后看 dsh 的扩展生态:第三方插件怎么接进来,哪些能力装了但没接线。
这一章和你的日常使用最相关 —— 你正在读的这份仓库的 56 个技能,就是通过本章讲的机制被加载的。
dsh-skill:
纯 agent 技能提供方注册表。 —— dsh-skill/README.zh.md
技能(skill)和工具(tool)的区别:工具是模型主动调用的函数,技能是"按需加载的指令包"。第 1 章提过 Pi 的"渐进式披露" —— dsh 同样只在技能被调用时才加载全文,不预载进每个会话。第 9 章那个系统提示词里就有技能相关的段落:
技能采用渐进式披露:只在被调用时才加载……你可以拥有一座丰富的能力库,而不必为用不上它们的会话付上下文开销。
本机实测,技能来源是文件系统:
dsh-skill-filesystem 就是扫描这些目录的 provider。每个技能目录含 SKILL.md(描述 + 触发条件 + 指令),加载时注入 skill 工具的说明里。
实测细节:本机会话的 skill 工具说明(第 1 章的 27 个工具之一)会列出现场可用的全部技能名 + 触发说明 —— 但不加载它们的全文。只有模型调用 skill <name> 后,dsh-skill 才把该技能的完整内容注入上下文。
理解:这解释了为什么你的技能库有 56 个技能而每次请求不爆上下文 —— 模型看到的只是每个技能的一句话摘要(catalog),调用时才展开全文。
dsh-commands:
插件拥有的面向人类命令注册表。 —— dsh-commands/README.zh.md
dsh 的命令注册表允许插件注册 / 命令。本机实际挂载的命令(从 preset 推断 + 官方文档):
| 命令 | 来源 | 作用 |
|---|---|---|
| /compact | dsh-command-compact | 显式触发会话压缩 |
| /goal | dsh-command-goal | 查看/管理目标 |
| /plan | dsh-plan-mode | 进入计划模式 |
| /model | dsh-client-ui-model-selection | 切换模型 |
| /permission | dsh-client-ui-permission-presets | 切换权限预设 |
| /feedback | dsh-command-feedback | 反馈(仅日志) |
注意:命令注册在host 平面的进程还是 agent 平面的会话,决定它是否对当前会话可见 —— 又是第 3 章那两套账。
dsh-user-questions:
抽象用户问题 seam:在 agent 运行期间向人类提问。 —— dsh-user-questions/README.zh.md
dsh-tool-ask-user 把它暴露给模型 —— 就是本机会话里的 ask_user_question 工具(27 个工具之一)。它的用途:agent 信息不足时停下来问人,而不是猜。
第 2 章提过 dsh-plan-mode 也注入 ctx.userQuestions —— 计划模式用它让用户在退出计划前确认。
与 approval 的区别:ctx.approval 是"要不要允许这个操作"(权限),ctx.userQuestions 是"这个信息是什么"(信息)。两个 seam 分工明确。
dsh-plan-mode:
按 agent 分别记录到日志的 plan 协作状态,提供由部署方配置的引导内容、用于直接进入的 /plan [message] 命令、用于直接退出的 /plan off 命令,以及经用户评审的 exit_plan_mode 退出方式。Plan mode 是软引导;沙箱模式和批准策略各自强制执行限制,且不读写 plan 状态。 —— dsh-plan-mode/README.zh.md
这是本章最重要的一个设计区分:
| 机制 | 性质 | 谁在强制 |
|---|---|---|
| plan mode | 软引导 | 模型自觉遵守(提示词引导 + 退出前用户复核) |
| 沙箱模式 | 硬强制 | 操作系统级(第 10 章) |
| 审批策略 | 硬强制 | approval seam(第 10 章) |
软引导可以违反,硬强制不能。plan mode 只是告诉模型"先想清楚再动手",真正的限制在沙箱和审批。这个分层避免了"计划模式做成了安全边界"的常见错误 —— 计划是协作协议,安全是强制机制。
第 1 章说过约 34 个 dsh-client-ui-* 插件。它们遵循一个模式:每个插件负责 UI 的一个"座位"(slot)。第 2 章 cordis 的作用域机制在这里体现为:每个 UI 插件是一个 cordis 插件,注册到布局的特定位置。
本机实际装载的 UI 插件(从 web-app patch 提取)[实测]:
理解:这些插件大多是纯 UI,逻辑在 host 平面的服务(第 4 章清单),UI 只是投影。比如 ui-jobs 从 session/jobs 帧镜像任务状态,ui-goal 从 goal 会话投影读目标 —— UI 是只读投影层。
本机用户 patch(~/.dsh/profiles/web/cordis.patch.yml)实际接入了第三方包 dsh-toolbelt 的 8 个插件 [实测]:
这就是第 3 章"加一个插件的完整路径"的真实案例 —— 8 个插件,8 行 YAML,每个配 id/name/disabled/config。其中 cross-agent-memory 就是本教程开头那段 Claude Code 记忆的注入者 —— 你读到的 <memory_data> 块就是它写的。
有趣的事实 dsh-toolbelt 有 8 个插件,但本机 patch 只开了 7 个 —— vision-fallback(视觉降级)没在启用列表里。这再次说明:插件树里有什么 ≠ 启用了什么,一切以配置为准。
第 1 章说过"装了但没接线的能力"。实测核对 [实测]:
| 包 | 能力 | 本机状态 |
|---|---|---|
| dsh-mcp-client | 连接 MCP 服务器并注册其工具 | 装了,无配置 |
| dsh-terminal + dsh-terminal-bash + dsh-tool-bash-persistent | 持久 PTY 会话 | 装了,未启用 |
| dsh-tool-cordis | 模型自省运行时、热挂自己写的插件 | 装了,未启用 |
| dsh-schedule | 会话级持久提醒 | 装了,未启用 |
| dsh-time-context / dsh-tmux-context | 每步时间 / tmux 位置上下文 | 装了,未启用 |
| dsh-session-reference | 跨会话快照引用 | 装了,未接线 |
| dsh-session-telemetry-otel | OpenTelemetry 遥测 | 装了,DSH_TELEMETRY_MODE 默认 DISABLED |
这意味着什么 dsh 的"扩展点"不只是代码级 —— 安装包 + 一行配置 = 启用。这 7 个能力包已经躺在你的 node_modules 里,想用 MCP 就加一行 mcp-client 配置,想要定时提醒就加 schedule。它们是被留白的,不是被移除的。
最后看一个最能说明 dsh 设计意图的包:dsh-tool-cordis。
自指涉的 cordis 工具集:检查活运行时,挂载和卸载模型写的插件。 —— dsh-tool-cordis/README.zh.md
翻译:模型可以调用这个工具查看运行时里有哪些插件,然后写一个插件并现场挂载 —— 给自己加能力,不需要重启,不需要人改配置。
配合 dsh-cordis-host-runner / dsh-cordis-client-runner("模型挂载的双半插件的宿主/浏览器两侧"),dsh 实现了 Pi 教程第 11 章讲的"让 Agent 修改自己的能力"的 cordis 版。
安全含义 让模型挂载插件 = 让模型执行任意代码。这也是为什么 dsh-tool-cordis 本机未启用 —— 它是个强大到需要显式选择的能力。启用它之前,请确保沙箱和审批能兜住。
技能、人机界面与扩展点组成了 dsh 的"外围生态":
到这里,12 章的技术内容讲完了。最后一章把整套设计放回天平上:全插件化的收益与代价。