joslynSmall/dsh-plugin-reasoning-effort-sync ↗★ 0
dsh-plugin-reasoning-effort-sync
Keep DeepSeek Harness model reasoning-effort levels in sync with what an OpenAI-compatible gateway advertises, so a new route or model needs no hand-written reasoningEfforts. 适合使用兼容 OpenAI 网关且不想手动维护推理配置的系统管理员。
インストール
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:joslynSmall/dsh-plugin-reasoning-effort-syncドキュメント
README 全文を読む ↗Configuration
The bundle's patch registers one row with these defaults:
- id: reasoning-effort-sync
name: dsh-plugin-reasoning-effort-sync
config:
enabled: true
syncOnLoad: true
intervalMinutes: 0 # 0 disables the periodic sync
requestTimeoutMs: 10000
dryRun: false
routes: {} # empty means every route the pi-ai row declares
modelsDev: # fallback source, read only for models the endpoint does not describe
enabled: true
url: https://models.dev/api.json
ttlHours: 12
timeoutMs: 30000
minShare: 0.5 # agreement the dominant declaration needs before it is trusted
| Field | Meaning |
|---|---|
enabled | Master switch. Off means no request and no write. |
routes | Empty processes every route. A populated dict is an allowlist: name a route to include it, and enabled: false under that name to exclude it. |
syncOnLoad | Sync once when the profile loads. |
intervalMinutes | Also sync on this interval. 0 (the default) disables periodic sync; load and configuration-change sync remain active. |
requestTimeoutMs | Deadline for one listing request. |
dryRun | Compute and log the result without writing. Start here. |
modelsDev.enabled | Consult models.dev for models whose endpoint published no levels. |
modelsDev.url | Dataset address. The default is models.dev's full dataset, about 5 MB. |
modelsDev.ttlHours | How long one fetched dataset is reused in memory. |
modelsDev.timeoutMs | Deadline for that one fetch. |
modelsDev.minShare | Agreement the dominant declaration needs. 1 demands unanimity (kimi-k3 would then be skipped), 0 accepts any plurality, 0.5 accepts a majority. |
The load-time sync is not awaited, so an unreachable gateway never delays a profile. The plugin observes app-boot/config-reload, emitted after DSH finishes reconciling a profile save, and synchronizes when the addressable pi-ai configuration changes. A channel or model added in the Models page is picked up without restarting DSH or refreshing the page. Unrelated or unchanged profile saves do not fetch model metadata. Changes arriving during a sync are coalesced into a subsequent serial pass, so a slow gateway cannot discard a new model. Every pass is diff-first: a sync that resolves nothing new writes nothing. When HMR is present, sync work starts outside the profile transaction's async context, so its later config-editor write can queue normally rather than being rejected as nested.
Where the levels come from
- The route's endpoint, when it names them. It describes the very gateway being configured, so its answer is final.
- models.dev, for the models the endpoint did not describe. The same model name is declared differently by dozens of providers there —
deepseek-v4.1-flashhad 15 distinct level sets across 75 declarations when this was written — so one rule has to pick. The offered levels are the dominant declaration: the exact set the largest number of declarations agree on, taken only when at leastmodelsDev.minShareof them agree and at least two providers say it. A weaker or tied plurality falls back to the intersection, so loweringminSharecan only add levels some declaration already named.
Two details make that rule work in practice:
- "Off" levels are dropped before anything is compared.
none,off,disabledandfalsesay "do not reason", which the picker's Default row already expresses by sending no parameter. Counting them would duplicate that row and let a reseller recording only "off" veto every real level. Dropping them also merges declarations that differ only in whether they mention it — which is whydeepseek-v4.1-flashresolves tolow, high, max, the very set the unrelated WorkBuddy gateway declares authoritatively for that name. - A weak or tied plurality is refused. Under-offering is recoverable; a level the upstream rejects is a hard failure at request time. A model neither rule can place is left untouched, so some names still need a hand-written block even with the fallback on.