前言¶
DSH 的理念是「一切皆插件」,插件多了,设置界面也会跟着多起来。给插件写设置界面是一件重复劳动:组件要自己写,样式要自己调,还要处理 load / save / busy / error / saved 提示、revision 冲突这一整套状态逻辑。每个插件各写各的,风格和官方设置页对不上,用户在不同插件之间来回切换时体验也是割裂的。
dsh-settings-ui 解决的就是这个问题:它把设置页 UI 和状态逻辑抽成一个可复用的服务,插件通过 ctx.settingsUi 拿到现成的组件、声明式表单和设置状态机,不必再手写 UI。下面介绍它的定位、功能和用法。
这是什么¶
dsh-settings-ui 是一个面向 DeepSeek Harness 插件的统一设置页 UI 套件加浮层面板套件,由 KaramachiA217 维护,MIT 许可证,仓库附 LICENSE 文件。从 package.json 的 dsh.client.platform 字段看,它面向 web 平台。
它对外暴露 ctx.settingsUi 服务,其他插件用这个服务构建设置区块和浮层面板,风格与 dsh-better-sidebar 及 --dsw-* 语义令牌对齐——不需要自己写组件、CSS,也不需要自己处理 load / save / busy / error / saved / revision 冲突的状态逻辑。
核心功能¶
三级 API¶
ui.pluginCard():rc7 官方 Plugins 标签页的插件配置卡片,经官方ctx.settingsScope持久化;ui.section():经典设置页卡片;ui.overlay()/ui.Panel/createPanelStore:自由浮层,支持拖拽、最小化、z-order、位置持久化,经 storage 事件跨标签页同步。
原子组件族¶
套件提供一组原子组件:SectionHeader / Field / TextInput / TextArea / Select / Button / Switch / Checkbox / Radio / Card / StatusDot / Badge / Spinner / Tabs / Banner / EmptyState / List / Dialog / ErrorBoundary / toast。
声明式表单¶
Rows 渲染字段描述;createSettingsStore + useSettings 处理 load / save / busy / error / saved-flash / revision 冲突,后端可跑在 fenced route 或官方 settingsScope 上。
向后兼容与自愈¶
向后兼容:这个插件只新增服务,直接 ctx.slots.inject('settings.section', ...) 的旧用法不变。
自愈能力:section() / overlay() / pluginCard() 自动包裹错误边界,单个卡片渲染崩溃只折叠该卡片,不影响整个设置页。
与官方契约对齐¶
套件只通过官方槽位/服务注册(settings.plugin.item / settings.section / shell.overlay / settingsScope / locale),.sui-* 样式从 --dsw-* 令牌解析,不导入官方卡片 chrome(value-import purity gate),自己渲染令牌对齐的外壳并自持表单、状态与可访问性。pluginCard 的 chrome 默认采用官方卡片模型:collapsed layer-3 → expanded layer-2、disclosure header、字段分隔线、discard/save footer。
安装与启用¶
先做安装。用官方 CLI 一步完成:添加依赖,reconcile 后追加到 dsh.profile.bundles:
dsh plugin --profile <profile-name> add dsh-settings-ui
后续升级用同一命令加 @latest 后缀即可。
再把它加入 profile bundles。host 已提供 peers 时,消费者不需要把它声明为 peer dependency。下面是 README 给出的示例,dependencies 里的版本号按实际情况填写:
{
"dependencies": { "dsh-settings-ui": "^0.2.22" },
"dsh": { "profile": { "bundles": ["dsh-base", "dsh-web-app", "dsh-settings-ui", "..."] } }
}
一个安装时的小坑:pnpm v11 的 minimumReleaseAge 供应链冷却机制,会让全新发布后 24 小时内的安装静默回退到上一版本。可以在 profile 的 pnpm-workspace.yaml 里加 minimumReleaseAge: 0,或者等一天再装。
本地开发时,先用 npm pack 构建 tarball,再用同一命令从本地安装,也可以用 file: 依赖:
npm pack
dsh plugin --profile <profile-name> add ./dsh-settings-ui-<ver>.tgz
注意 rc.6 下的已知差异:link: 开发挂载会 ESM 解析失败,需改用 file: tarball。
典型用法:pluginCard()¶
rc7 下,官方给插件设置的推荐路径是 Plugins 标签页的配置卡片(按 settings 命名空间 keyed 的 settings.plugin.item 槽位),经官方 ctx.settingsScope 持久化。pluginCard() 在这个契约之上提供带套件外壳的卡片,不用手写 scope 绑定和状态逻辑:
const card = ctx.settingsUi.pluginCard({
key: 'my-plugin', // 必填,等于 settings 命名空间,也是标签页 key
header: { title: '我的插件', desc: '一句话说明' },
fields: [
{ key: 'enabled', type: 'switch', label: '启用' },
{ key: 'endpoint', type: 'text', label: '服务地址' },
],
})
// card.store.setField('enabled', true)
调用之后不需要再做别的:store 内部调用 ctx.settingsScope.bind({ namespace: key }),每次修改经官方 revision fence 即改即存。
几个可选项:
content: (ctx) => ...:完全自定义主体;showIn: 'both'/'settings-page':让卡片同时在经典设置页露出;chrome: 'minimal':去掉套件的卡片外壳。
关于家族单轨:新的设置卡片建议优先用 pluginCard()(官方 Plugins 标签页),避免一半在设置页、一半在 Plugins 标签页的家族分裂。section() 对既有消费者和 rc6 / headless 环境继续完全支持,已经在用的不需要迁移。
兼容性与环境要求¶
- 已在 dsh 0.1.0-rc.5(官方桌面 shell、完整 profile 测试)验证;
- rc.6 已验证(2026-08-17):rc.5 与 rc.6 共享同一上游提交
47f9438,仅 npm 版本号变化,零适配; - rc.7(0.3.0,2026-08-20)已适配:
pluginCard()面向 keyedsettings.plugin.item槽位 + 官方ctx.settingsScope;经典面(settings.section/settings.general.item/shell.overlay)在 rc.7 不变,section()/overlay()继续可用。
依赖方面:peerDependencies 为 @deepseek-ai/cordis >=4.0.0-rc.0、@deepseek-ai/dsh-client-runtime >=0.1.0-rc.0、@deepseek-ai/dsh-client-ui-slots >=0.1.0-rc.0、react ^18.2.0;engines 要求 node >=20;dsh.client.platform 为 web,会 inject 三个 @deepseek-ai 客户端运行时/UI 包。
已知限制:同一页面挂载多个 ToastHost 会显示相同的 toast,每页只应挂载一个 host。范围外(官方契约限制):并行侧边栏席位(sidebar.workspaces / sidebar.settings 为单例)和浅色主题。
开发与质量门禁¶
如果要参与开发或本地验证,仓库提供三步命令:
pnpm install
npm run ci
npm test
npm run ci 是 5 步门禁:语法 + 单元测试 + 密钥扫描 + 净化 + pack 白名单;npm test 基于 node:test,共 45 个单元测试。
Roadmap 方面:1.0.0 计划提供 ui.describeForm,消费官方 settings.describe 的 schemastery schema 自动渲染表单,支持 redactSecrets 只写输入与 revision 冲突处理;工程上计划对 .d.ts 与实现的漂移做自动检查;维护承诺是上游 rc 漂移时重跑 contract-diff 方法论,反馈走 GitHub discussions。
适用场景与注意事项¶
适合谁:要给自己的 DSH 插件加设置界面、但不想手写组件和状态逻辑的插件作者;希望多个插件的设置风格保持一致、并跟随官方设置页演进的场景。
安装前必须清楚一点:插件以当前 dsh 进程的权限运行,装一个插件等于把它的代码跑进你自己的环境。dsh-settings-ui 是 MIT 许可证,源码公开在 GitHub,安装前应自行检查源码与许可证,确认可信再装。
小结¶
dsh-settings-ui 把 DSH 插件设置界面里重复的部分——组件、样式、状态机——收进一个 ctx.settingsUi 服务:三级 API 覆盖从官方 Plugins 卡片到经典设置页再到自由浮层的需求,与官方契约对齐、向后兼容,单个卡片崩溃也不会拖垮整个设置页。如果你在写带设置的 DSH 插件,可以直接从 pluginCard() 试起。
- 社区插件目录页:https://www.skillhub.cn/plugins/KaramachiA217/dsh-settings-ui (独立社区站点,与 DeepSeek / 幻方无官方从属关系)
- GitHub 仓库:https://github.com/KaramachiA217/dsh-settings-ui