oneinitAI
dsh-settings-plus
No description
- Stars
- 1
- Language
- TypeScript
- Created
- Aug 14, 2026
- Updated
- Aug 14, 2026
Introduction
DSH Settings Plus
English · 中文
███╗ ██╗ ███████╗ ██╗ ██╗
████╗ ██║ ██╔════╝ ██║ ██║
██╔██╗ ██║ ███████╗ ███████║
██║╚██╗██║ ╚════██║ ██╔══██║
██║ ╚████║ ███████║ ██║ ██║
╚═╝ ╚═══╝ ╚══════╝ ╚═╝ ╚═╝
┌─────────────────────────────────────────────────────────────┐
│ dsh-settings-plus │
│ the plus for DeepSeek Harness settings │
│ form-level + file-level configuration management │
│ + an open registration SDK for every plugin │
│ │
│ 175 tests | MIT | TypeScript ESM | Cordis v4 │
└─────────────────────────────────────────────────────────────┘
dsh-settings-plus is the plus for the DeepSeek Harness official settings. The official entry is a single settings form. This plugin adds a settings management surface: every registered settings namespace and every mounted plugin's composition configuration, browsed and edited either as forms or as configuration files. Any plugin can register its own settings namespace through a thin SDK.
This is a self-contained standalone ESM Cordis plugin repository. A DSH host is a runtime consumer of the finished package, not a source or build input.
Published under the dsh-plugin topic, with a PR into awesome-DSH-plugin and a follower in dsh-market.
Architecture
flowchart LR
subgraph HOST["DSH host (runtime)"]
REG["cordis registry: settings namespaces + composition rows"]
GW["gateway: exposed-namespaces allowlist"]
FS["ctx.fs shaped channel"]
end
subgraph PLUS["dsh-settings-plus (this repo)"]
C1["C1 host crawling"]
C2["C2 form-level editing (browser half)"]
C3["C3 file-level editing"]
C4["C4 plugin SDK"]
CLIENT["lib/client.js"]
end
C4 -->|registers user namespaces| C1
C1 -->|enumerates, secret redacted| REG
C1 -->|writes via settings seam + revision guard| REG
C1 -.->|Fabric widening, optional| GW
C3 -->|atomic rw + expected-version guard| FS
C2 -->|served as| CLIENT
C2 -->|reads catalog via source seam, wire pending| C1
The four capabilities
🔭 C1 · Host crawling
(src/crawler.ts, src/service.ts, src/fabric.ts)
A read-only crawler enumerates every registered settings namespace (ctx.settings.describe with secret redaction) and every mounted plugin's composition configuration (schemastery Config + row id) from the live cordis registry. The bundle publishes these as the ctx.dshSettingsPlus host service: listNamespaces, listCompositionConfigs, updateComposition, removeComposition. Writes route through the host settings seam with optimistic-concurrency revision guards. Plain cordis.yml composition rows are not writable through the service (edit them with the file surface or cordis.patch.yml). The Fabric binding widens the gateway's exposed-namespaces allowlist at load time, mounted optionally and a safe no-op without it.
🎛️ C2 · Form-level editing
(src/client/)
The browser half registers settings.section contributions: an always-present 高级设置 entry (order 30), a loading/empty/error status row while the catalog has no data, and one section per catalog entry, reconciled by signature diffing (${key}\u0000${label}). The generic schema form renderer (src/client/schema-form.tsx) renders whitelisted controls: string/number/boolean natively, const-only unions as selects, nested objects as groups, everything else as a JSON textarea. The secret placeholder protocol never lets placeholders travel, empty input keeps the stored value, and only explicit input commits. Per-field reset uses unset operations, never value writes. Revision conflicts surface a reload prompt, and restart notices explain when the host needs one. The renderer is complete and test-proven; wiring it into data sections lands with the host wire surface (see Known limitations).
🗂️ C3 · File-level editing
(src/file-browser.ts, src/file-store.ts, src/yaml-editor.ts, src/patch-validator.ts, src/hmr-aware.ts)
A closed configuration manifest (writable $DSH_HOME root YAML files plus per-profile cordis*.yml, read-only bundle layers) is validated against a realpath boundary. Reads and writes are atomic through the injected ctx.fs-shaped channel, with byte-size limits and an expected-version write guard. YAML round-trip preserves comments. Semantic validation rejects patch edits that would break the document. The HMR story is honest: the plugin owns no watcher, the host already hot-reloads cordis.patch.yml and settings.yaml, and the save strategy only guarantees atomic writes.
🧩 C4 · Open registration SDK
(src/sdk.ts, docs/sdk-contract.md)
Other plugins register their own settings namespaces on the host through registerUserSettings (live registration + explicit disposer), defineSettingsSection (declarative, no side effects), and settingsNamespace (naming brand, ^[a-z][a-z0-9-]*$). Registration rides the calling fiber, secrets stay the host seam's business, and duplicates fail loud at the host.
Official settings vs dsh-settings-plus
| Area | Official settings entry | dsh-settings-plus |
|---|---|---|
| Edit surface | a single settings form | form-level editing, plus a file-level editing surface |
| What you can browse | the harness settings form | every registered settings namespace and every mounted plugin's composition config, secrets redacted |
| File writes | not in scope | closed writable manifest with atomic writes and a version guard |
| Plugin-authored settings | host-managed only | any plugin registers its own namespace through the SDK |
Design principles
- Read-only by default. The crawler never writes; the file browser only enumerates and validates.
- Secrets stay at the host seam. Placeholders never travel, and redaction happens in the schema walk.
- Writes are guarded. Expected-version guards, byte caps, and a realpath boundary on every write path.
- No watcher of its own. The plugin never restarts you; it tells the truth about what the host already hot-reloads.
- Fail loud, degrade safe. Malformed Fabric facades error loudly; a missing facade is a safe no-op.
Quick start
1. Install into a DSH profile through the bundle route (file: install of this repository):
dsh plugin --profile <name> add file:/<repo-dir>/dsh-settings-plus
2. Start the profile. The package manifest declares dsh.bundle.patch (cordis.patch.yml), which composes three rows over the selected profile's runtime: dsh-settings-plus, its dsh-settings-plus-invariant companion, and a disabled cordis-fabric stub that widens the gateway's exposed-namespaces allowlist at load time (runtime binding: src/fabric.ts). The patch composes plugins; it does not alter host source, compiler settings, or build scripts. The profile's resolved node_modules provides the bare-name peer dependencies.
3. Open the settings navigation. The 高级设置 entry appears with a loading/empty/error status row. Per-entry data sections render once the host wire surface lands (see Known limitations).
SDK usage for plugin authors
One namespace registration inside your plugin's apply, reclaimed with the calling fiber:
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' }))
}
The namespace immediately joins the host settings surface: the crawler's ctx.dshSettingsPlus.listNamespaces() includes it and the configuration UI renders its schema. Full contract (naming, secrets, lifecycle, dedup semantics) in docs/sdk-contract.md.
Browser half
src/client/ is the web bundle served as lib/client.js (exports map ./client). It registers the settings.section contributions and the dsh-settings-plus locale namespace (src/client/locales.ts: zh/en dictionaries, Chinese is the product copy, English mirrors it, and en satisfies Record<keyof typeof zh, string> keeps the pair aligned). The catalog reads through the injectable settingsPlusCatalog source seam. The production default is an honest local empty source until the host wire surface lands, so the settings navigation shows the status row's empty phase and no data sections yet.
Known limitations
Stated honestly:
- Deferred to v2 (by plan): the aggregated settings page, per-namespace rejection lists, export/import, and the required-secret save fix.
- Host wire surface in honest degraded state: T16's distribution smoke test verified plugin install/load and service mounting; the host wire surface (the browser catalog data channel, a real
ctx.fsadapter, and the Fabric patch end-to-end) still awaits verification after a host upgrade. Today this is an honest degraded state: catalog empty source, Fabric no-op, file writes riding the localFsLikechannel. - Fabric dependency posture:
cordis-fabricis loaded optionally from the host context at binding time. No facade mounted → safe no-op (the stub row stays disabled, the gateway keeps its default allowlist); facade mounted but malformed → loud error. - Write scope of
updateComposition: only ids that are registered settings namespaces are writable through the service; plaincordis.ymlcomposition rows fail loudly and must be edited through the file surface orcordis.patch.yml.
Roadmap (follow-ups)
- L2 browser RPC integration: wire the client catalog to a real host data channel so it moves off the empty local source.
- L3 external HTTP API: expose the settings service over HTTP on demand.
- Host version range lock: keep the compatible host range pinned (see
peerDependencies) and re-verify the wire surface after the host upgrade.
Development
Run every command from this directory:
pnpm install
pnpm run verify:self-contained
pnpm run typecheck
pnpm test
pnpm run build
pnpm run prepare
verify:self-contained rejects filesystem dependency specs, compiler paths that leave the repository, external or broken Markdown links, absolute workstation paths, and malformed bundled skill metadata. typecheck checks both the declaration project and the source-plane tests. build is the development/CI type-safety gate; prepare emits the consumer-side artifacts (including lib/) for Git and tarball installation.
Repository layout
.
├── .agents/skills/ # Repository-local plugin development workflow
├── docs/
│ ├── dsh-plugin-contracts.md # Shared local contract for all plugin skills
│ └── sdk-contract.md # The registration SDK contract (C4)
├── patches/ # Dependency and DSH-host patch contract
├── scripts/ # prepare, verify-self-contained, patch helpers
├── src/
│ ├── index.ts # Loader-facing function-plugin namespace
│ ├── config.ts # Serializable schema and resolved defaults
│ ├── runtime.ts # Cordis activation and host-boundary wiring
│ ├── invariant.ts # Package-owned invariant companion
│ ├── crawler.ts # Read-only settings/composition enumeration (C1)
│ ├── service.ts # ctx.dshSettingsPlus service surface (C1)
│ ├── fabric.ts # Optional gateway allowlist widening (C1)
│ ├── sdk.ts # Open registration SDK (C4)
│ ├── file-browser.ts # Closed configuration manifest + boundary (C3)
│ ├── file-store.ts # Atomic reads/writes + version guard (C3)
│ ├── yaml-editor.ts # Comment-preserving YAML round-trip (C3)
│ ├── patch-validator.ts # Semantic patch validation + self-guard (C3)
│ ├── hmr-aware.ts # Hot-reload description for saves (C3)
│ └── client/ # Browser half, served as lib/client.js (C2)
│ ├── index.ts # settings.section registrations + status row
│ ├── catalog.ts # Observable catalog store + injectable source seam
│ ├── component.tsx # Entry / status-row / data-section components
│ ├── schema-form.tsx # Generic schema form renderer
│ ├── form-logic.ts # Form logic + secret/reset/conflict protocol
│ └── locales.ts # zh/en locale dictionaries
├── tests/ # Host specs (node) and client specs (jsdom)
├── AGENTS.md # Repository-local contributor contract
├── LICENSE # MIT
├── README.md / README.zh.md # Repository and usage contract
├── cordis.patch.yml # Profile bundle contribution
└── package.json # Exports, peers, dsh.bundle.patch
License
MIT, copyright (c) 2026 oneinitAI. Contributor rules live in AGENTS.md.