# DSH 高级设置(Settings Plus) [English](README.md) · 中文 ```text ██████╗ ███████╗ ██╗ ██╗ ██╔══██╗ ██╔════╝ ██║ ██║ ██║ ██║ ███████╗ ███████║ ██║ ██║ ╚════██║ ██╔══██║ ██████╔╝ ███████║ ██║ ██║ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ``` ```text ┌─────────────────────────────────────────────────────────────┐ │ dsh-settings-plus │ │ DeepSeek Harness 官方设置的 plus │ │ 表单级 + 文件级配置管理 │ │ + 面向所有插件的开放注册 SDK │ │ │ │ 175 个测试 | MIT | TypeScript ESM | Cordis v4 │ └─────────────────────────────────────────────────────────────┘ ``` **dsh-settings-plus** 是 DeepSeek Harness 官方设置的 plus。官方入口是单个设置表单;本插件提供的是设置**管理**面:所有已注册的 settings namespace 与所有已挂载插件的组合配置,既可以表单方式浏览编辑,也可以文件方式浏览编辑。任何插件都能通过薄 SDK 注册自己的设置 namespace。 本仓库是自包含的独立 ESM Cordis 插件仓库。DSH 宿主是成品包的运行时消费者,不是源码或构建输入。

175 个测试通过 MIT 许可证 TypeScript ESM Cordis v4 dsh-plugin topic 版本 0.0.1

已发布至 dsh-plugin topic,PR 进入 awesome-DSH-plugin,dsh-market 跟随。 ## 架构 ```mermaid flowchart LR subgraph HOST["DSH 宿主(运行时)"] REG["cordis registry:settings namespace + 组合行"] GW["gateway:exposed-namespaces 白名单"] FS["ctx.fs 形态通道"] end subgraph PLUS["dsh-settings-plus(本仓库)"] C1["C1 宿主爬取"] C2["C2 表单级编辑(浏览器半)"] C3["C3 文件级编辑"] C4["C4 插件 SDK"] CLIENT["lib/client.js"] end C4 -->|注册用户 namespace| C1 C1 -->|枚举,secret 脱敏| REG C1 -->|经 settings seam + 版本守卫写入| REG C1 -.->|Fabric 加宽,可选| GW C3 -->|原子读写 + expected-version 守卫| FS C2 -->|打包为| CLIENT C2 -->|经 catalog source seam 读取,wire 待落地| C1 ``` ## 四大能力 ### 🔭 C1 · 宿主爬取 (`src/crawler.ts`、`src/service.ts`、`src/fabric.ts`) 只读 crawler 枚举所有已注册的 settings namespace(`ctx.settings.describe` + secret 脱敏)与所有已挂载插件的组合配置(schemastery `Config` + 行 id,来自 cordis 运行时 registry)。bundle 以 `ctx.dshSettingsPlus` 宿主服务发布:`listNamespaces`、`listCompositionConfigs`、`updateComposition`、`removeComposition`。写操作经宿主 settings seam + 乐观并发版本守卫。普通 `cordis.yml` 组合行不可经服务写入(请用文件编辑面或 `cordis.patch.yml`)。Fabric 绑定在加载时加宽 gateway 的 exposed-namespaces 白名单:可选挂载,缺失时安全 no-op。 ### 🎛️ C2 · 表单级编辑 (`src/client/`) 浏览器半注册 `settings.section` 贡献:始终存在的 高级设置 入口(order 30)、catalog 无数据时的 loading/empty/error 三态状态行、每 catalog 条目一个分区,按签名差分(`${key}\u0000${label}`)reconcile。通用 schema 表单渲染器(`src/client/schema-form.tsx`)渲染白名单控件:string/number/boolean 原生、const-only union 下拉、嵌套对象分组、其余 JSON textarea 兜底。secret 占位协议保证占位永不回传、留空保持原值、显式输入才提交。逐字段 reset 用 unset 操作,绝不写值。revision 冲突给出重载提示,restart 提示说明宿主何时需要重启。渲染器已完整实现并通过测试;接入数据分区随宿主 wire 面落地(见"已知限制")。 ### 🗂️ C3 · 文件级编辑 (`src/file-browser.ts`、`src/file-store.ts`、`src/yaml-editor.ts`、`src/patch-validator.ts`、`src/hmr-aware.ts`) 封闭配置清单(可写的 `$DSH_HOME` 根 YAML 文件 + 每 profile 的 `cordis*.yml`,bundle 层只读展示)经 realpath 越界校验。读写经注入的 `ctx.fs` 形态通道原子进行,带字节上限与 expected-version 写守卫。YAML round-trip 保留注释。语义校验拒绝会破坏文档的补丁编辑。HMR 说明诚实:插件不拥有 watcher,宿主已热重载 `cordis.patch.yml` 与 `settings.yaml`,保存策略只保证原子写。 ### 🧩 C4 · 开放注册 SDK (`src/sdk.ts`、[docs/sdk-contract.md](docs/sdk-contract.md)) 其他插件通过 `registerUserSettings`(实注册 + 显式移除 disposer)、`defineSettingsSection`(声明式,无副作用)、`settingsNamespace`(命名品牌,`^[a-z][a-z0-9-]*$`)在宿主上注册自己的 settings namespace。注册随调用方 fiber 回收,secret 语义归宿主 seam,重复注册在宿主响亮报错。 ## 官方设置 vs dsh-settings-plus | 领域 | 官方设置入口 | dsh-settings-plus | | --- | --- | --- | | 编辑形态 | 单个设置表单 | 表单级编辑,外加文件级编辑面 | | 可浏览范围 | 宿主设置表单 | 所有已注册 settings namespace 与所有已挂载插件的组合配置,secret 脱敏 | | 文件写入 | 不在范围内 | 封闭可写清单,原子写 + 版本守卫 | | 插件自定义设置 | 仅宿主管理 | 任何插件经 SDK 注册自己的 namespace | 来自真实 DSH profile 的实机截图——左为官方设置入口,右为 SDK 注册 namespace 渲染出的插件设置页:

官方设置入口 插件设置页

## 设计原则 - **默认只读。** crawler 从不写入;文件浏览器只枚举与校验。 - **secret 归宿主 seam。** 占位永不回传,脱敏在 schema 遍历中完成。 - **写入有守卫。** 每条写路径都有 expected-version 守卫、字节上限与 realpath 越界校验。 - **不自建 watcher。** 插件从不擅自重启你,只如实说明宿主已经热重载什么。 - **响亮失败,安全降级。** 畸形 Fabric facade 响亮报错;缺失 facade 是安全 no-op。 ## 快速开始 **1. 安装** 到 DSH profile(对本仓库做 `file:` 安装): ```sh dsh plugin --profile add file://dsh-settings-plus ``` **2. 启动 profile。** 包 manifest 声明 `dsh.bundle.patch`(`cordis.patch.yml`),在所选 profile 的运行时上组合三行:`dsh-settings-plus`、`dsh-settings-plus-invariant` companion、以及一个禁用状态的 `cordis-fabric` 桩(加载时加宽 gateway 的 exposed-namespaces 白名单,运行时绑定在 `src/fabric.ts`)。补丁只组合插件;不改宿主源码、编译器设置或构建脚本。profile 的 `node_modules` 提供裸名 peer 依赖。 **3. 打开设置导航。** 高级设置 入口出现,带 loading/empty/error 三态状态行。每条目数据分区随宿主 wire 面落地后渲染(见"已知限制")。 ## 插件作者的 SDK 用法 在插件 `apply` 内注册一个 namespace,随调用方 fiber 回收: ```ts import { Context } from 'cordis' import z from 'schemastery' import { registerUserSettings } from '@oneinitai/dsh-settings-plus/sdk' export const name = 'my-plugin' export const inject = ['settings'] const MySection = z.object({ host: z.string().default('localhost'), token: z.string().role('secret'), }) export function apply(ctx: Context) { ctx.effect(() => registerUserSettings(ctx, 'my-plugin', MySection, { applies: 'live' })) } ``` 注册后 namespace 立即进入宿主设置面:crawler 的 `ctx.dshSettingsPlus.listNamespaces()` 会包含它,配置 UI 自动渲染其 schema。完整契约(命名、secret、生命周期、去重语义)见 [docs/sdk-contract.md](docs/sdk-contract.md)。 ## 浏览器半 `src/client/` 是 Web bundle,以 `lib/client.js` 提供(exports map `./client`)。它注册 `settings.section` 贡献与 `dsh-settings-plus` locale namespace([src/client/locales.ts](src/client/locales.ts) 中 zh/en 双字典;中文是产品文案,英文镜像,`en satisfies Record` 保证对齐)。catalog 通过可注入的 `settingsPlusCatalog` source seam 读取。生产默认是诚实的本地空源(宿主 wire 面落地前),因此设置导航显示状态行的 empty 阶段,尚无数据分区。 ## 已知限制 如实陈述: - **defer 到 v2**(计划约定):聚合配置页、per-namespace 拒绝名单、导出/导入、required secret 保存修复。 - **宿主 wire 面处于诚实降级状态**:T16 分发冒烟验证了插件安装/加载与服务挂载;宿主 wire 面(浏览器 catalog 数据通道、真实 `ctx.fs` 适配器、Fabric patch 端到端)待宿主升级后补验证。当前为诚实降级状态:catalog 空源、Fabric no-op、文件写走本地 `FsLike` 通道。 - **Fabric 依赖姿态**:`cordis-fabric` 在绑定时从宿主上下文可选加载。未挂载 facade → 安全 no-op(桩行保持禁用,gateway 保持默认白名单);facade 挂载但畸形 → 响亮报错。 - **`updateComposition` 的写范围**:只有已注册 settings namespace 的 id 可经服务写入;普通 `cordis.yml` 组合行响亮失败,须经文件编辑面或 `cordis.patch.yml` 修改。 ### 后续计划(Roadmap) - **L2 浏览器 RPC 接入**:把客户端 catalog 从空本地源接到真实宿主数据通道。 - **L3 外部 HTTP API**:按需将 settings 服务暴露为外部 HTTP 接口。 - **宿主版本兼容范围锁定**:维持宿主版本范围锁定(见 `peerDependencies`),宿主升级后补验证 wire 面。 ## 独立开发 所有命令都在本目录运行: ```sh pnpm install pnpm run verify:self-contained pnpm run typecheck pnpm test pnpm run build pnpm run prepare ``` `verify:self-contained` 拒绝文件系统依赖 spec、离开仓库的编译器路径、外部或损坏的 Markdown 链接、绝对工作站路径和格式错误的 bundle skill 元数据。`typecheck` 同时检查声明工程与源码平面测试。`build` 是开发/CI 类型安全门禁;`prepare` 产出消费者侧产物(含 `lib/`),供 Git 与 tarball 安装。 ## 仓库布局 ```text . ├── .agents/skills/ # 仓库本地插件开发工作流 ├── docs/ │ ├── dsh-plugin-contracts.md # 所有插件 skill 共享的本地契约 │ └── sdk-contract.md # 注册 SDK 契约(C4) ├── patches/ # 依赖补丁与 DSH host patch 契约 ├── scripts/ # prepare、verify-self-contained、补丁辅助 ├── src/ │ ├── index.ts # Loader 面向的函数插件命名空间 │ ├── config.ts # 可序列化 schema 与解析后的默认值 │ ├── runtime.ts # Cordis 激活与宿主边界接线 │ ├── invariant.ts # 包自有的 invariant companion │ ├── crawler.ts # 只读设置/组合枚举(C1) │ ├── service.ts # ctx.dshSettingsPlus 服务面(C1) │ ├── fabric.ts # 可选 gateway 白名单加宽(C1) │ ├── sdk.ts # 开放注册 SDK(C4) │ ├── file-browser.ts # 封闭配置清单 + 越界校验(C3) │ ├── file-store.ts # 原子读写 + 版本守卫(C3) │ ├── yaml-editor.ts # 保留注释的 YAML round-trip(C3) │ ├── patch-validator.ts # 语义补丁校验 + 自保护(C3) │ ├── hmr-aware.ts # 保存的 HMR 说明(C3) │ └── client/ # 浏览器半,以 lib/client.js 提供(C2) │ ├── index.ts # settings.section 注册 + 状态行 │ ├── catalog.ts # 可观察 catalog store + 可注入 source seam │ ├── component.tsx # 入口 / 状态行 / 数据分区组件 │ ├── schema-form.tsx # 通用 schema 表单渲染器 │ ├── form-logic.ts # 表单逻辑 + secret/reset/冲突协议 │ └── locales.ts # zh/en locale 字典 ├── tests/ # 宿主 spec(node)与客户端 spec(jsdom) ├── AGENTS.md # 仓库本地贡献契约 ├── LICENSE # MIT ├── README.md / README.zh.md # 仓库与使用契约 ├── cordis.patch.yml # profile bundle 贡献 └── package.json # 导出、peers、dsh.bundle.patch ``` ## 许可证 [MIT](LICENSE),Copyright (c) 2026 oneinitAI。贡献规则见 [AGENTS.md](AGENTS.md)。