DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Autofill Model Metadata — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
A

dsh-autofill-model-metadata

Autofill Model Metadata

DSH 插件:通过显式预先声明的映射,从 models.dev 填充 custom-provider 模型元数据——不进行猜测,失败即关闭。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:peach0x33a/dsh-autofill-model-metadata#7e1203391db177c6d4d3e7497d6e4b00f03661ef
README兼容性版本

兼容性与来源证明

Autofill Model Metadata 以 dsh-autofill-model-metadata 发布,当前版本为 0.1.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/18

版本

0.1.0stable
2026/10/18

相关插件

正在加载相关插件…

最新版
0.1.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/10/18
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 models-usage 分类下经过校验的插件。

Whale Widgetdsh-whale-widgetDSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义Usage@linxin666/dsh-usage用于 dsh Web GUI 的使用统计插件:检测各提供商的余额和编程套餐配额,并实时记录令牌使用情况;侧边栏 Settings 行上方显示紧凑的价格概览卡片Client Ui Model Capabilities@linxin666/dsh-client-ui-model-capabilities为自定义 pi-ai 提供商声明每个模型的能力(图像输入和推理力度),可直接在 Models 设置卡片中编辑;写入官方 llm-pi-ai 设置命名空间,不更改 DSH 源代码。Commandcode Provider@mars-sea/dsh-commandcode-provider适用于 Command Code 的非官方 DeepSeek Harness LLM 提供商插件,移植自 pi-commandcode-provider(MIT)。注册“commandcode”提供商路由,并在 Models 页面添加卡片和实时模型目录。

README

dsh-autofill-model-metadata

Fill a DSH gateway route's model metadata (name, contextWindow, maxTokens, input, reasoningEfforts) from the models.dev catalog — using only the mappings you declare by hand.

This is a port of the pi-autofill-model-metadata Pi extension: the same explicit-mapping philosophy, moved onto the DSH settings seam.

Why explicit mapping

DSH has no native metadata filling. The plugins that do it fall into two camps: provider-level refresh (dsh-models-dev: sources: { route: <models.dev-provider> }) and loose name matching. Both guess. This plugin refuses to:

  • You write down, per route and per local model id, exactly which models.dev model it is: mapping.<route>.<localModelId> = "<modelsDevProvider>/<modelsDevModel>".
  • No fuzzy match, no case folding across providers, no searching another provider when a lookup fails.
  • Anything unmapped, unknown, or ambiguous is a refusal, not a guess. A route whose plan refuses is not written at all — you never get a half-filled array.

Declared fields always win: the plugin only fills fields the profile leaves undefined.

Install

Requires DSH >= 0.2.0-rc.2. From the plugin checkout:

DSH="/Applications/DeepSeek Harness.app/Contents/Resources/runtime/cli/bin/dsh"
"$DSH" plugin --profile desktop add link:/absolute/path/to/dsh-autofill-model-metadata

Then restart DSH Desktop (plugins mount at startup).

Configure

The config accepts these fields (the graphical page edits the mapping, the rest stays in the settings document):

{
  "mapping": {
    // route name as it appears in Settings → Models
    "my-gateway": {
      // local model id on the wire  ->  models.dev provider/model
      "claude-opus-4-5": "anthropic/claude-opus-4-5",
      "gemini-3-pro": "google/gemini-3-pro-preview"
    }
  },
  "modelsDevUrl": "https://models.dev/api.json",
  "cacheTTLHours": 24,
  "applyOnStart": true,
  "dryRun": false,
  "requireCompleteMapping": true,
  "builtinSettingsForm": "auto"
}
fielddefaultmeaning
mapping{}the declared table; empty means the plugin does nothing at all
modelsDevUrlhttps://models.dev/api.jsoncatalog endpoint
cachePath$DSH_HOME/plugins/dsh-autofill-model-metadata/models.dev.jsoncatalog cache
cacheTTLHours24cache lifetime; 0 refetches every time
applyOnStarttrueapply once when the plugin mounts
dryRunfalseplan and log, write nothing
requireCompleteMappingtrueundeclared models on a mapped route are an error
builtinSettingsForm"auto"auto / always / never — see Settings

Manual run, from any local browser session (<port> is the DSH web server):

BASE=http://127.0.0.1:<port>/api/dsh-autofill-model-metadata
curl -X POST $BASE/apply   -H 'content-type: application/json' -d '{}'   # {"route":"..."} to narrow
curl $BASE/status                                                        # mapping state, no catalog fetch
curl $BASE/inspect                                                       # same, resolved against the catalog
curl "$BASE/catalog?q=gpt-5.4&limit=10"                                  # candidate mapping targets
curl -X POST $BASE/mapping -H 'content-type: application/json' \
  -d '{"mapping":{"my-route":{"fast-model":"openai/gpt-5.4"}},"apply":true}'

Every endpoint is loopback-only and answers 403 to anything else; /apply, /mapping and /page-live are POST, the rest are GET.

/mapping answers 200 once the write lands, even when a requested fill is then refused: the mapping really was saved, and a failed pass is reported separately in applyError rather than disguised as a failed save. /status and /inspect answer with the mapping read from the settings document, not from the volatile copy the loader refreshes a moment after a write.

Settings

The plugin ships a graphical settings page, and it also honours the host's autoGenerate flag for the schema above — so a host that renders generated forms, now or in a later version, keeps showing one whenever this page is not there.

builtinSettingsFormbehaviour
"auto" (default)the generated form stays available until the browser half loads and reports in (POST /page-live)
"always"the generated form is never suppressed
"never"the generated form is suppressed as soon as the plugin mounts

true/false are accepted as aliases for always/never.

What "the original form" means in 0.2.0-rc.2. It is worth being exact here: the shipped client contains no generic schema-driven form renderer at all. Every official settings page (Models, Shell, Agent loop, …) is a hand-written companion package, and autoGenerate is carried by the settings transport but consumed by nothing yet. So on this version the surfaces for a plugin config are:

  1. this page, when its bundle loads;
  2. the profile's own configuration document, always — hand-editable, and the thing the page writes back to;
  3. a generated form, on any host that starts rendering one.

The auto policy is what keeps (3) honest: it does not suppress the flag until the page has actually reported in, so a page that never loads never costs you a surface. The page's own failure banner says the same thing when its host endpoints are unreachable.

The page appears as Settings → Model metadata. It lists only relevant routes — a route the profile configures, or one that appears in the mapping — so the dozens of providers the host advertises but nobody configured cannot bury the ones that matter. A mapped route the host does not offer is still listed, with its reason, so a typo cannot hide. Each card shows: every declared model, the fields it declares by hand (never overwritten), what a pass would fill, the mapping source in an editable field with catalog search, and the refusals that would apply. Save mapping writes the whole table in one revision-fenced op; Save and fill does that and runs a pass. Nothing is written until you save, unsaved edits survive a reload, and a dry run or an already-complete route is reported as exactly that rather than as a fill.

Both the page and the config document end up in the same settings service. The page reads the settings revision along with its state and sends it back when saving, so an edit made in the config document while the page sat open makes the save fail closed — the page is told the mapping moved and to reapply — rather than replacing the whole table with what the page happened to be showing. A fill pass re-reads and re-plans the route inside the same fence, so a model added by hand between planning and writing is never dropped: the pass refuses instead. Without a revision from the caller there is nothing to compare against, so the freshest one is used and the write proceeds.

What gets filled

local fieldfrom models.devrule
namemodel.name
contextWindowlimit.contextwritten only when > 0
maxTokenslimit.outputwritten only when > 0
inputmodalities.inputimage present → ['text','image']
reasoningEffortsreasoning_options (effort values)see below

reasoningEfforts follows the pi-ai schema, where a map containing only off is invalid:

  • effort values present → map them, including none → off;
  • only off usable, or reasoning: false → false;
  • catalog says nothing → field left absent, so the profile's own default stands.

A model is eligible only when tool_call === true and status !== 'deprecated'. Eligibility is checked but never written — the plugin does not flip tool_call.

Refusals

Per route, all-or-nothing. A refused route writes nothing.

kindwhen
malformed-sourcethe mapping value is not provider/model
unknown-providerthat provider id is not in the catalog
unknown-modelthat model id is not under that provider
ambiguous-sourceseveral catalog models match case-insensitively
not-agent-capablematched model cannot call tools, or is deprecated
missing-mappingrequireCompleteMapping and a route model is undeclared
undeclared-mappinga mapping points at a model the route does not configure

undeclared-mapping fires even with requireCompleteMapping: false, so a typo in a local id is never silently ignored.

Design notes

  • One atomic write per route: a single set op at ['providers', <route>, 'models'], fenced by the revision re-read immediately before mutate. Routes are independent — one refusal does not block another.
  • Inert when unmapped: with mapping: {} there is no catalog fetch, no cache write, no settings read.
  • Offline tolerant: a failed fetch falls back to the cached catalog and logs; a stale cache is used rather than refusing.
  • User layer wins: the merge base is the settings user layer when present.

Development

pnpm install
pnpm run verify     # tsc --noEmit && tsdown && vitest

verify runs the whole suite: unit tests per module, a composition test driving apply() against a stub host, a contract test validating planned output against the real @deepseek-ai/dsh-llm-pi-ai@0.2.0-rc.2 schema (it skips itself if that package is absent), render tests for the settings page, and a client-bundle test that loads the built lib/client.js through a stub window.__ModuleLoader__ with the same seeded modules the shell provides.

Two halves

halfentryoutputloaded by
hostsrc/index.tslib/index.mjs (ESM)the DSH Loader, via the cordis.patch.yml row
browsersrc/client/index.tsxlib/client.js (CJS + window.__ModuleLoader__ banner)the Web shell, via dsh.client in package.json

react, react/jsx-runtime and @deepseek-ai/dsh-client-ui-primitives are external and resolved by the shell's module seed — bundling a second React would break hooks. The bundle id must stay the package name: it is the cache key the loader serves at /plugins/<package>/client.js.

Client-only changes need the shell to re-read the bundle: a rebuild is enough while the client-plugin HMR receiver is active, otherwise restart DSH Desktop.

macOS: vitest cannot start under the DSH runtime node

The node shipped with DSH Desktop is signed with the hardened runtime, while rollup's native binary is ad-hoc signed. macOS refuses the load (ERR_DLOPEN_FAILED, "mapping process and mapped file (non-platform) have different Team IDs"), so vitest dies before collecting. Re-sign a copy of node ad-hoc and run the suite with it:

mkdir -p .devnode && cp "$(command -v node)" .devnode/node
codesign --force --sign - .devnode/node
PATH="$PWD/.devnode:$PATH" pnpm run verify

.devnode/ is git-ignored. This affects any project in this environment that runs vitest, including dsh-deep-sleep.

Limitations

  • Reads models.dev only; no other metadata source.
  • Never invents a mapping: unmapped models stay untouched.
  • Does not touch tool_call, status, cost, or compat.
  • Applies on mount and on config edit; there is no scheduled refresh — use the apply endpoint or restart to force one.