前言¶
DSH 的标准设置机制通过 ctx.settings 管理配置。为特定配置文件(如 web)定制这些设置通常需要在全局 settings.yaml 中手动管理复杂的覆盖逻辑。xmoon/dsh-profile-settings 插件在官方用户设置机制之上添加了一个透明的配置文件覆盖层,使每个配置文件拥有自己的覆盖文件(settings.patch.yml),而不会破坏现有的设置行为。
介绍¶
这是一个 DSH 配置文件插件,由 XMoon 维护。它添加了配置文件特定的设置覆盖,将全局 settings.yaml 与 profiles/<name>/settings.patch.yml 分开,允许每个配置文件在继承全局设置的同时覆盖特定命名空间。
核心功能¶
- 在
ctx.settings下添加配置文件特定的设置覆盖。 - 透明层叠:全局
settings.yaml+profiles/<name>/settings.patch.yml。 - 递归对象合并,数组与标量整体替换。
- 支持 YAML
!unset指令以显式隐藏继承的值。 - 提供 Web UI,展示每个字段的来源标记(Default / Composition / Global / Profile / Masked)及操作按钮。
- 支持热重载,配合写入锁和事务保证文件完整性。
安装与启用¶
此插件需要配置文件捆绑包包含 @deepseek-ai/dsh-base(所有内置的 web / headless 模板均具备此条件)。安装命令如下:
dsh plugin --profile web add @xmoon76/dsh-profile-settings
安装过程会自动将包添加到 dsh.profile.bundles。重启 Harness 后,插件会执行以下操作:
1. 禁用基础 settings 行(@deepseek-ai/dsh-settings-file)。
2. 插入拥有 ctx.settings 的新行。
注意:一个组合只能拥有一个 ctx.settings 拥有者。如果基础行仍处于活动状态且未完全被禁用,引导过程会因 Cordis 重复服务错误而失败。
配置¶
插入的行默认配置如下(通常无需修改):
| key | default | meaning |
|---|---|---|
profile |
auto-detected | 显式指定的活动配置文件名称 |
globalPath |
$DSH_HOME/settings.yaml |
全局设置文档路径 |
profileFile |
settings.patch.yml |
配置文件目录内的覆盖文件名 |
dshHome |
$DSH_HOME 或 ~/.dsh |
Harness 主目录 |
watch |
true |
热重载两个文档 |
debounceMs |
100 |
监听器写入稳定窗口 |
writable |
true |
允许进程内写入覆盖文件 |
活动配置文件的解析顺序为:显式 profile 配置 -> 安装位置(profiles/<name>/node_modules/…)-> 启动器参数 --profile <name> -> DSH_PROFILE 环境变量。若无法确定,引导失败。
Overlay 文件示例¶
Overlay 文件位于 $DSH_HOME/profiles/<name>/settings.patch.yml。文件由人工编辑或通过 settings 命令修改,进程内的写入操作会落在此文件中,而非 settings.yaml。
# $DSH_HOME/profiles/web/settings.patch.yml
agent-default-model:
provider: pi-ai
model: gpt-5.6
permission:
mode: danger-full-access
some-plugin:
endpoint: !unset
纯 YAML 值用于覆盖;!unset 会隐藏较低层的值(继承值被删除,除非覆盖层提供了新值)。这些掩码不会进入最终解析的 JSON 文档,UI 中不会将其作为值显示。
Settings 命令¶
插件挂载后,ctx.profileSettings 和 settings 命令族可用:
settings layers [ns [path]] 查看每个叶子节点的来源证明
settings get <ns.path> 获取有效值
settings set <ns.path> <value> 写入配置文件覆盖
settings unset <ns.path> 删除覆盖值(重新继承)
settings mask <ns.path> 写入 !unset
settings unmask <ns.path> 移除掩码
settings reset <ns> 对覆盖层执行 replace({})
settings promote <ns.path> 将值上移至全局文档
settings demote <ns.path> 将值下移至配置文件覆盖
settings migrate <ns.path> [--copy] 移动全局值到覆盖层(带 .bak 时间戳备份,--copy 保留原值)
settings diff [ns] 叶子级全局与覆盖的差异
settings ui [ns] 机器可读的层快照(Web UI)
settings profile 查看活动配置文件和文档路径
Web UI¶
插件包含一个浏览器端 (dsh.client)。Web 设置面板增加了一个“配置文件设置”部分,显示每个字段的来源标记、有效值以及操作(设置/取消设置/掩码/提升/重置等)。所有主机交互通过注册在主机端的 /profile-settings 回环 RPC 通道进行,不涉及会话上下文或命令日志。
并发模型与限制¶
- 进程内操作:普通的
update/replace/mutate遵循官方设置语义(命名空间序列化队列、expectedRevision冲突检测)。 - 跨进程文件完整性:使用写锁 + 原子重命名保证。
- 跨进程自定义层操作(
promote/demote/migrate/mask/unmask):使用固定顺序的锁和 fence,确保事务一致性,每次文本更改都会推进层修订。
限制与失败模式:
* 需要 Node >= 22.6。
* 引导时配置文件不可解析、覆盖根不是 map、非对象命名空间、数组中存在 !unset、不支持的 YAML 标签、覆盖路径逃逸配置文件目录、全局与覆盖指向同一文件、重复 ctx.settings 拥有者,均会导致引导失败。
* 热重载期间临时无效的 YAML 会触发警告,但保留最后一个有效版本。
总结¶
此插件为 DSH 配置文件提供了标准化的设置管理方案,无需修改底层设置逻辑即可实现多配置文件隔离。更多细节请参考 目录页 或 GitHub 仓库。