中文EN

@xmoon76/dsh-profile-settings

toolsnpmMIT

为 DeepSeek Harness 提供按 profile 分层的设置覆盖:全局 settings.yaml 仍为基线,每个 profile 可用自己的 profiles/<name>/settings.patch.yml 覆盖任意设置命名空间——对象段递归合并,数组与标量整体替换,!unset 显式屏蔽继承值。覆盖层对现有插件透明(照常读 ctx.settings),写入只落在 profile 覆盖层;官方 schema 语义、revision、expectedRevision 冲突检测、watcher 与事件均不改动。附带 settings 命令族(get/set/unset/mask/

下载量 / Downloads
657

安装

dsh plugin --profile web add @xmoon76/dsh-profile-settings

沙箱测试

这个插件还没测过。提交测试 →

README

@xmoon76/dsh-profile-settings

[English](README.md) | 中文

一个 DSH profile bundle 插件:在官方用户设置 seam 之上增加按 profile 隔离的

Settings 覆盖层。$DSH_HOME/settings.yaml 继续作为全局基线;每个 profile 可以

通过自己的 $DSH_HOME/profiles/<name>/settings.patch.yml 覆盖任意 Settings

namespace —— object 递归合并,array/scalar 整体替换,!unset 显式删除继承值。

Schema Defaults
      ↓
Composition Base
      ↓
~/.dsh/settings.yaml              (全局用户层)
      ↓
~/.dsh/profiles/<name>/settings.patch.yml   (profile 用户层)
      ↓
Effective Settings

已有插件仍然只使用 ctx.settings,完全感知不到覆盖层的存在。写操作

(update / replace / mutate)只落在 profile 覆盖层;replace({})

回退到 global 层而不是 composition 默认。官方 schema 校验、revision 语义、

expectedRevision 冲突检测、watcher 与事件全部保持不变。

安装

要求 profile 的 bundles 包含 @deepseek-ai/dsh-base(官方 web / headless

模板都满足)。为每个需要独立覆盖层的 profile 安装:

dsh plugin --profile web add @xmoon76/dsh-profile-settings
dsh plugin --profile pi-tui add @xmoon76/dsh-profile-settings

dsh plugin --profile <name> add 会自动把声明了 dsh.bundle 的包 reconcile

进该 profile 的 dsh.profile.bundles。下次启动时 bundle patch

(cordis.patch.yml)会:

1. 禁用 base 的 settings 行(@deepseek-ai/dsh-settings-file);

2. 插入 profile-settings 行成为 ctx.settings 的唯一 owner。

一个 composition 只能有一个 ctx.settings owner:如果 base 行仍然活跃,

启动会 fail loud(Cordis 重复服务注册错误),绝不静默覆盖。

配置

插入的行不需要配置(下方为默认值);profile 自己的 cordis.patch.yml 可以按

行 id 覆盖 config:

key · 默认值 · 含义

profile · 自动检测 · 显式指定 profile 名

globalPath · $DSH_HOME/settings.yaml · 全局 settings 文档

profileFile · settings.patch.yml · profile 目录内的覆盖文件名

dshHome · $DSH_HOME 或 ~/.dsh · harness home

watch · true · 热加载两个文档

debounceMs · 100 · watcher 写稳定窗口

writable · true · 允许进程内写入覆盖层

当前 profile 按以下顺序解析(绝不通过 cwd 猜测):显式 profile 配置 →

安装位置(profiles/<name>/node_modules/…,即 dsh plugin 布局)→ launcher

--profile <name> / --profile=<name> → DSH_PROFILE 环境变量。无法确认时

启动 fail loud。

覆盖文件

# $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 值 = override;!unset = 显式 mask(删除下层继承值,回退 schema

默认,除非覆盖层自己提供值)。mask 永不进入解析后的 JSON 文档 —— UI 不会把

它当作普通值。文件可以手工编辑,也可以通过 settings 命令修改;进程内写入

只落在这个文件,绝不写 settings.yaml。

settings 命令

命令运行时挂载后,ctx.profileSettings 与 settings 命令族可用:

settings layers [ns [path]]        每个叶子值的来源链
settings get <ns.path>             读取生效值
settings set <ns.path> <value>     写入 profile 覆盖层
settings unset <ns.path>           删除覆盖值(重新继承)
settings mask <ns.path>            写入 !unset
settings unmask <ns.path>          移除 mask
settings reset <ns>                对覆盖层执行 replace({})
settings promote <ns.path>         把值提升到全局文档
settings demote <ns.path>          把值降级到 profile 覆盖层
settings migrate <ns.path> [--copy]  把全局值迁入 profile(先备份 .bak.<时间戳>;--copy 保留全局)
settings diff [ns]                 全局与覆盖层的叶子级差异
settings ui [ns]                   机器可读 JSON 快照(供 Web 页面预览)
settings profile                   当前 profile 与文档路径

Web UI(Profile Settings 页面)

bundle 自带浏览器半端(client/):Web 设置面板新增 Profile Settings

页面——每个字段带来源徽标(默认 / 组合 / 全局 / 本 profile / 已屏蔽)、生效值,

以及 set / unset / mask / unmask / promote / reset 操作。页面通过 host 半端注册的

/profile-settings loopback RPC 通道通信,不依赖会话上下文、不写命令日志。

配置链与设计说明

Provider 保持官方基类的 document 为 profile raw section,因此

update/replace/mutate/revision/expectedRevision/describe 的语义

完全不变;global 层被折进每个注册的合成 base

(applyMasks(merge(composition, global), masks))。对基类 TS-private 成员

只通过一个窄类型 facade 访问 —— 不 fork 任何 Settings 机制。完整 M0 调研见

docs/research.md。

Fail-loud(启动):无法解析 profile、覆盖文件根非 map、namespace section

非 object、数组内出现 !unset、不支持的 YAML tag(!!js/、!!python/、

自定义 tag)、覆盖路径逃逸 profile 目录、global 与覆盖文件同路径、重复

ctx.settings owner。

Warn + 保留 last good(热加载):任一文档临时无效 YAML、未注册 namespace

(原样保留,等待对应插件稍后加载)。

并发边界与限制

范围 · 保证

同进程普通 set/replace/mutate · 官方 Settings 语义(per-namespace 串行写队列、expectedRevision 冲突检测)

跨进程文件完整性(read-modify-write) · 双文档写锁 + 原子 rename

跨进程自定义层操作(promote/demote/migrate/mask/unmask) · 真事务:固定顺序双锁、锁内 fence 校验、layer fence 随每次写入推进

跨进程对同一 profile、同一 namespace 的普通 update/mutate · 继承官方 seam 限制:官方 revision 是进程内写队列的,跨进程 CAS 尽力而为(文件锁下后写者胜)

开发

npm run typecheck   # tsc(src + tests)
npm test            # vitest
npm run build       # tsc 构建 + copy-lib(lib/)
npm pack            # prepack 构建 + postpack tarball 冒烟(防泄漏检查)

需要 Node ≥ 22.6(type stripping)与 DSH harness(0.1.1-rc.2 系列)提供 peer

依赖 —— 运行时从安装环境解析,包自身不打包 harness 副本,避免 module twin。

License

MIT

以上内容来自 npm 上的 README,我们只做格式化,不改内容。

版本

npm 上共发布:1,最后更新 2026-08-23

链接

GitHub · Homepage · npm

同类插件