liutian11451-png/dsh-plugin-model-config ↗★ 0
dsh-plugin-model-config
Full model-configuration editor for the DeepSeek Harness web Settings > Models page: every field the deployment's model-config schema declares, not just the handful the shipped UI exposes.
安装
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:liutian11451-png/dsh-plugin-model-config说明文档
阅读完整 README ↗dsh-plugin-model-config
English | 中文
AI-generated code. This package was written by an AI agent (DeepSeek Harness, model
deepseek-flash) in a human-directed session, and published by the human who ran it. Review it before you install it, and especially before you allow itspreparescript to run on your machine. See AI disclosure for exactly what has and has not been verified.
A model-configuration control for the DeepSeek Harness web Settings → Models page: inside each provider's own card, one row per setting, ready to edit.
What it does
The shipped Models card already shows a provider's route, credential and model catalog. What it has no control for is the rest of the provider's configuration — for the DeepSeek adapter that is thinking mode, reasoning effort, the context-window and token defaults, the four image budgets, the four file and quota limits, and the timeouts.
This plugin adds those settings as rows inside the provider's own card: each row is the setting's name on the left and its control on the right, so the block reads like the settings form it sits in.
| Schema node | Control |
|---|---|
number | number box (carrying the schema's min, max, step), e.g. context window |
boolean | Yes/No switch |
| union of literals | select |
string | text box (a credential reference is labelled as one) |
Structural values are left to the card that already owns them: the model catalog, a nested retry policy, and anything the schema declares as a dict or an unmodelled node are document-shaped configuration, not settings rows, and the shipped card already edits the catalog.
Nothing about the setting list is hardcoded. The namespaces come from the deployment's own llm.listConfigurableProviders() and the settings come from each namespace's serialized schema, so a setting added to an adapter — or a whole adapter this plugin has never seen — appears as a row with no change here.
Install
dsh plugin --profile web add dsh-plugin-model-config
Substitute your profile name for web if you run a different one. The package declares dsh.bundle, so dsh plugin registers its patch layer in the profile automatically. Restart dsh web and reload the page: the build payload is composed at boot, so a reload alone is not enough the first time.
From a GitHub checkout
dsh plugin --profile web add github:liutian11451-png/dsh-plugin-model-config
A git install fetches sources, not built artifacts, so the package ships a prepare script that builds lib/ from src/ with plain tsdown — no sibling repository, no type checking. pnpm ≥10 refuses to run a git dependency's prepare until you allow it, so the first add fails with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED and prints the exact key to add. For a git install that key names the resolved tarball, not the bare package name:
allowBuilds:
dsh-plugin-model-config@https://codeload.github.com/liutian11451-png/dsh-plugin-model-config/tar.gz/: true
Copy the line pnpm prints verbatim — it carries the commit the install resolved to — then re-run the add. Treat that allowance as permission to execute this package's code on your machine at install time, and pin a commit (github:liutian11451-png/dsh-plugin-model-config#) so a later push cannot silently change what runs.
One caveat when moving an existing install: if the plugin was previously installed from a local directory, remove that first. A leftover link in the profile's node_modules collides with the incoming git install and pnpm fails with an EPERM symlink error during import.
To avoid asking users for the allowance altogether, publish to npm or ship a tarball from pnpm pack — neither needs build permission.
Requirements
A settings provider must be mounted (@deepseek-ai/dsh-settings-file is part of the standard preset — it is what gives settings.describe anything to answer). A deployment whose settings provider is read-only renders the controls disabled and says so.
How a write works
Each row reads the namespace's resolved value (schema defaults → composition base → user layer) for display, and writes only the user layer, one path at a time, through settings.mutate(ns, ops, expectedRevision). A row is shown as overridden exactly when the raw user section carries that path — presence, not equality, is the harness's own rule — so resetting a setting is an unset, never a write of the default back. A write that loses a revision race is reported instead of overwriting.
Layout
package.json # dsh.bundle + dsh.client manifests
cordis.patch.yml # inserts this package's loader row
src/index.ts # node half (inert)
src/client/index.ts # browser half: one keyed seat entry per namespace
src/client/fields.ts # the schema walker
src/client/ProviderRows.tsx # the setting rows and the write plumbing
src/client/locales.ts # zh/en dictionaries, including the setting names
tsdown.config.ts # consumer-side build
smoke.mjs # loader-contract smoke test
The node half is deliberately empty. The harness client module registry discovers dsh.client packages by walking the host Loader's rows, so the package needs one mounted row as its carrier; that is all the row is for.
The plugin registers into settings.models.provider-card, the seat the Models section exposes for exactly this: a card's adapter extension area, dispatched by the card that owns the namespace. That seat is keyed and matched exactly (options.key against the card's entryKey), so the plugin registers one entry per configurable namespace — a single entry would render nothing anywhere. No file of the DeepSeek Harness repository is modified.
Development
pnpm install
pnpm build # emits lib/index.js and lib/client.js
pnpm typecheck
pnpm test # the walker contract, the rows, and dictionary coverage
node smoke.mjs # evaluates the built browser half against a stub shell
Known limitations
- It edits the live settings document, not a file you can diff. A change lands in the harness settings store, the same one the shipped controls write to. There is no per-change preview and no undo beyond resetting a setting.
- Structural settings are not rows. The model catalog, a nested retry policy,
headers/queryParamsmaps and any unmodelled node are handled by the card that already owns them (the catalog) or not at all. A row is a scalar a person sets with one control; a document-shaped value is not. - A value with no dictionary entry shows its schema key. Every setting the shipped adapters declare has a name; a third-party adapter's new setting renders with its raw key until the dictionary covers it, and the test suite fails in this repository when a fixture adds one.
- A dict-typed provider family registers one profile per card.
llm-pi-ainests profiles underproviders; each profile is sliced out for its own card, and the profile's own schema decides which settings appear. - Secret-role settings are not round-tripped. A
role('secret')value never rides the wire, so no row can show or set it; use the credential surface the adapter documents. - Web profile only — declared
platform: web; there is no terminal-surface equivalent.
AI disclosure
This package was written by an AI agent, not by a person typing the code. It was produced by DeepSeek Harness running the deepseek-flash model in a session directed by its human publisher (@liutian11451-png), on 2026-09-12. The human chose the feature, approved the approach, and reported the behaviour; the agent read the harness sources to establish the settings, slot, and schema contracts, then wrote the source, tests, build configuration, and documentation in this repository. The same disclosure is recorded in machine-readable form under aiDisclosure in package.json.
Treat the code accordingly: read it before you install it, and treat the allowBuilds permission a git install asks for as permission to run unreviewed generated code on your machine.
What has been verified
pnpm test— 34 tests: the schema walker's mapping of every node kind in both envelope shapes, the row filter, the rows themselves (control kind per schema type, resolved values, overrides, reset), the write path (op shape, revision, nested profile paths, conflict handling), and dictionary coverage against the schema fixturespnpm typecheck— cleannode smoke.mjs— loader-contract assertions against the built artifact, including thatapplyregisters one keyedsettings.models.provider-cardentry per configurable namespace, which is the wiring the page silently depends on- The GitHub Actions workflow in this repository runs those four steps on every push
- The page was driven headlessly and read back (
node drive-ui.mjs: Edge over the DevTools protocol, no dependencies). On a live deployment it confirmed the block renders inside the DeepSeek card — the模型配置heading, sixteen numbered settings showing their resolved values, andthinking/reasoningEffortas closed selects — and that editing one number persisted it to the settings document.
Three faults were found this way and fixed:
remote.settingsandremote.llmwere read without being declared ininject, so the whole loader entry failed (cannot get property "remote.settings" without inject).- The settings schema arrives as a reference table (
{ uid, refs }) whose nested schemas are integer ids; the walker read those ids as nodes, so it found no fields and rendered nothing. Both shapes are now fixtures, and a test asserts they agree. - A union member's literal can live in
valueor inmeta.defaultdepending on how the union was written; reading only the first turned a closed set into a JSON editor.
What has not been verified
- No human line-by-line review. The publisher verified behaviour in the running app, not the source.
- No security audit. Nothing here was examined for hostile or careless behaviour beyond what the tests and the described behaviour cover.
- One machine, one platform. Development, testing, and live use all happened on Windows with Node 24 and pnpm 11. The CI workflow runs on Linux, so the build is exercised on two platforms, but the UI has only been seen on one.
- No clean-machine install test. The publishing machine already had a plugin install in its profile; an install onto a profile that has never held this plugin was not exercised.
- The boolean switch has no live counterpart on the adapters tested. None of this deployment's provider schemas declares a boolean, so the Yes/No control is covered by a component test rather than by a rendered page.
- The
llm-pi-aidict-typed layout was reasoned from the settings document. Its slicing path is covered at the component level, but no live card for it was inspected.
License
MIT