DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Pi Ai Sync — DSH Plugin for DeepSeek Harness
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in
← Plugins
P

dsh-pi-ai-sync

Pi Ai Sync

dsh plugin: fuse dsh-model-sync (settings seam) and dsh-opencode-go-models (pi-ai catalog file) so provider routes stay in step with the pi.dev gateway — and new models become selectable without hand-editing node_modules.

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:jiaruihuang/dsh-pi-ai-sync#13e9fdf15f47dd05f0b615c085b07cc86b1a9654
READMECompatibilityVersions

Compatibility and provenance

Pi Ai Sync is published as dsh-pi-ai-sync and currently resolves to version 0.4.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
any
Release source
github
Registry updated
10/16/2026

Versions

0.4.0stable
10/16/2026
0.3.0stable
10/16/2026
0.2.0stable
10/15/2026
Show 1 more versionCollapse versions
0.1.0stable
10/14/2026

Related plugins

Loading related plugins…

Latest
0.4.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
any
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
10/16/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue

Related plugins

More verified plugins in models-usage.

Whale Widgetdsh-whale-widgetDeepSeek balance whale widget in the bottom-right corner of the DSH Web interface: balance/today’s usage/peak-off-peak pricing, customizable bubble click sequence (text/balance/today/peak-off-peak/image/random phrases and parallel weighted selection), per-line styles and fonts, floating quick editinUsage@linxin666/dsh-usageUsage statistics plugin for the dsh web GUI: per-provider balance and coding-plan quota detection plus a live token usage ledger, with a compact price glance card above the sidebar's Settings rowClient Ui Model Capabilities@linxin666/dsh-client-ui-model-capabilitiesPer-model capability declarations (image input and reasoning efforts) for custom pi-ai providers, edited in place on the Models settings cards; writes the official llm-pi-ai settings namespace, no DSH source changes.Codex Subscriptiondsh-codex-subscriptionUse ChatGPT and Codex subscriptions in DeepSeek Harness with OAuth, quota, safe resets, web search, images, and Fast mode

README

dsh-pi-ai-sync

A dsh Cordis plugin that keeps provider routes in step with the pi.dev gateway by maintaining both layers a model has to pass through:

  • the pi-ai catalog (@earendil-works/pi-ai/dist/providers/data/<route>.json) — the "does dsh know this model and which protocol does it speak?" layer, and
  • the settings model list (llm-pi-ai.providers.<route>.models) — the "does the model picker offer it?" layer.

It is the fusion of dsh-model-sync (settings seam) and dsh-opencode-go-models (pi-ai catalog file), with no hand-maintained protocol/family tables: pi.dev's listing already carries every record in pi-ai catalog shape.

Why

dsh resolves a configured model's wire protocol as route.api ?? catalog[id].api ?? sharedCatalogApi(route). On the dsh 0.1.x line the settings model schema has no per-model api field, so:

  • routes with a single protocol are fine — the route-level api fills the gap;
  • a mixed-protocol route (opencode: anthropic-messages + openai-completions + openai-responses + google-generative-ai) has no shared api, so any model missing from the installed catalog is rejected outright: hand-adding it errors, and a settings-only sync has to drop it.

dsh-pi-ai-sync fixes the root cause instead of working around it: it copies the missing records into the installed catalog, then lets the (now complete) catalog serve the route.

How it works

one round, per managed route
  1. GET https://pi.dev/api/models/providers/<route>     (catalog-shaped records)
  2. catalog layer  → copy records the installed catalog is missing into
                       dist/providers/data/<route>.json
                       (atomic write + first-modification backup)
                       ⇒ the model becomes base-matching; restart needed
  3. settings layer → reconcile llm-pi-ai.providers.<route>.models
                       (unset by default; mirror/keep optional)

A layer is where the data lives (the pi-ai catalog / the llm-pi-ai settings); a round touches both, in that order, for every managed route.

Because the catalog is imported into memory at boot, step 2 only takes effect after a dsh restart — a round that added models reports restartNeeded.

Install

Not on npm yet — install it from GitHub today:

# newest `main` (what you want while the plugin is still young)
dsh plugin --profile web add github:jiaruihuang/dsh-pi-ai-sync

# a pinned release
dsh plugin --profile web add github:jiaruihuang/dsh-pi-ai-sync#v0.1.0

# or from a local checkout:
dsh plugin --profile web add /path/to/dsh-pi-ai-sync

Restart dsh afterwards (bundle-layer change).

GitHub installs need the build script allowed

A github: install runs the package's prepare script (never prepublishOnly), because the TypeScript sources are the only thing in the repository — lib/ is gitignored. pnpm blocks install-time scripts by default, so add the key it prints to the profile's pnpm-workspace.yaml:

allowBuilds:
  "dsh-pi-ai-sync@git+https://github.com/jiaruihuang/dsh-pi-ai-sync.git": true

Use that form, not a bare dsh-pi-ai-sync: true (pnpm cannot match a name to a git source) and not the commit-pinned …/tar.gz/<sha> form pnpm's own error message suggests — the pinned key goes stale on the next push, the git+https key does not. dshmarket's "allow build scripts and retry" button writes both forms for you.

Integrity note: the tarball your install resolves to is the tag/commit you asked for, and the build happens on your machine from those sources. Use #vX.Y.Z when you want a reproducible environment.

Behind a proxy

This plugin reaches pi.dev with Node's global fetch, which ignores http_proxy / https_proxy unless Node is told to read them. On a network that only reaches pi.dev through a proxy, a round fails with a bare TypeError: fetch failed — and only sometimes, because the direct route is usually still there for other hosts. Start dsh with:

NODE_USE_ENV_PROXY=1 dsh web          # Node >= 24; see: node --help | grep proxy

(--use-env-proxy is the same switch as a CLI flag.) NO_PROXY is honoured either way. This is a host setting on purpose: reading the environment from inside the plugin would mean taking on an HTTP-proxy dependency, and this package has none.

Configuration

Edit the pi-ai-sync section of your settings document (on the dsh 0.1.x line that is ~/.dsh/settings.yaml):

pi-ai-sync:
  managedRoutes:
    - opencode
    - opencode-go
  settingsMode: unset
  intervalMinutes: 240
KeyDefaultDescription
managedRoutes[]Routes to sync; empty = opencode, opencode-go
settingsModeunsetunset removes the route's models override; mirror rewrites it from pi.dev; keep leaves settings alone
catalogSynctrueMaintain the installed pi-ai catalog files (the core layer)
updateExistingModelsfalseAlso refresh records the catalog already has with the fields pi.dev states today
intervalMinutes240Auto-refresh interval; 0 = startup only
startupDelaySeconds5Delay before the first auto round
refreshTimeoutMs120000Abort budget for one round's request
fetchAttempts3Fetch attempts per route, with exponential backoff; 1 disables retrying
syncNotifytrueLog the report when there was something to report
keepCatalogOnlytrueIn mirror mode, also write ids that exist only in the catalog

Choosing settingsMode

models replaces the served catalog. dsh resolves configured.length > 0 ? configured : catalog, so a non-empty list stops the catalog's own list from being used at all. That is what makes the three modes different things:

ValueWhat it does to llm-pi-ai.providers.<route>.modelsUse it when
unset (default)removes the key; modelOverrides is deliberately left aloneyou want the enriched catalog to be the single source of truth — the plugin's design
mirrorwrites the full list: pi.dev entries the catalog can back, plus catalog-only ids as bare { id }you want the list visible and editable in settings (dsh-model-sync's behaviour)
keepnothing — the catalog layer onlyyou manage the list entirely yourself

Notes worth knowing before you pick:

  • mirror rewrites the whole list every round, so hand-edited fields on it do not survive. To hand-tune a model, leave models out — see below.
  • mirror refuses a route with non-empty modelOverrides: dsh rejects the two together ("models already replaces the served catalog").
  • keep does not mean "the catalog decides". If you leave a non-empty models list, that list is still what serves the route.
  • keepCatalogOnly (default true) is what holds catalog-only models in the mirror list; false drops them from the picker.

Hand-tuning a model without models

When a route has no models key, dsh builds the list from the catalog and then applies modelOverrides per id:

llm-pi-ai:
  providers:
    opencode:
      apiKeyEnv: OPENCODE_API_KEY
      baseURL: https://opencode.ai/zen/v1
      modelOverrides:
        step-5-preview-free:
          maxTokens: 65536

The route then offers every catalog model, with your values layered on. This is the shape settingsMode: unset leaves in place. dsh enforces three rules: modelOverrides may only name ids the installed catalog describes, it cannot sit beside a non-empty models, and its fields are name, contextWindow, maxTokens, input, reasoningEfforts, compat — no api and no id (the id is the dict key).

Why some ids are "catalog-only"

Two lists move independently:

  • the catalog on disk — the factory snapshot plus every id past rounds merged in, and merges are add-only;
  • pi.dev's live listing — which gains and drops models over time.

An id the catalog has and pi.dev currently does not list is catalog-only. It is not a pi.dev error and nothing was deleted: the catalog is the union of everything ever seen, so the two differ whenever pi.dev stops offering an id. In practice that is mostly the promo -free and experimental -exp models, which rotate out — and the count moves on its own (observed: opencode at 85 ids, then 83, twenty minutes later).

Removal is deliberately out of scope for v0.1: a partial pi.dev outage or a bad network day must never delete models from your picker.

Refreshing records you already have

The catalog merge is add-only: a record that is already there is never touched, which is what keeps a partial pi.dev listing from rewriting your models. The cost is that a model whose parameters pi.dev later corrected keeps the stale values forever.

updateExistingModels: true closes that gap. Only the fields pi.dev actually states are applied — a cost or capacity pi.dev stays silent about keeps the catalog's value, so nothing is zeroed out by omission — and a record pi.dev has moved to another protocol is re-grouped under the new api instead of leaving dsh speaking the old one. It is still never a removal.

Measured on a real profile (see AGENTS.md for the same numbers):

RouteRecords refreshedProtocol moves
opencode65 (baseUrl, type, inputLimits, compat, cost…)0
opencode-go31 (step-5-preview-free: 8k → 1M context, 4096 → 65536 maxTokens)7 — e.g. claude-haiku-5-5 openai-completions → anthropic-messages

That second column is the point: 7 models had been flattened to openai-completions by an earlier plugin, so dsh was addressing them with the wrong wire protocol.

baseUrl is the one field to look at twice. pi.dev moved opencode to its new inference/* host where the catalog (and that earlier plugin) had zen/*. Both families are live and identical — measured 2026-10-15, /zen/v1/models and /inference/v1/models both answer 200 with the same 86 ids — so following pi.dev here is safe today. To pin an endpoint instead, set baseURL on the route in llm-pi-ai: a route-level baseURL overrides a record's baseUrl while everything else still tracks pi.dev.

A refreshed catalog needs the same restart as an added one, the report shows catalog ↻N(…), and the first refresh writes the usual backup.

Commands and services

  • /pi-ai-sync — force one round and print the report (registered through the shared command registry when the host provides one).
  • piAiSync.syncNow() — the same round as a service, for UIs.

Caveats

  • The catalog layer writes into node_modules. That is inherent: the installed pi-ai catalog is the only place dsh 0.1.x can learn a protocol for a base-less model. Writes are atomic, a first-modification backup is kept, and a real uninstall restores it (a pi-ai upgrade that wholly replaces the file is left untouched). A pi-ai upgrade wipes the additions; the next round re-applies them.
  • A round says why it gave up. A failed fetch is retried fetchAttempts times (default 3) with exponential backoff, then that route is skipped and the report carries the whole cause chain — fetch failed ← connect ETIMEDOUT 172.67.221.13:443 rather than a bare fetch failed. A 4xx other than 429 is pi.dev answering, so it is not retried. Skipping is deliberate: a route whose listing could not be verified keeps its settings untouched.
  • Restart to see new models. Catalog changes are read at boot only.
  • Do not run this beside dsh-model-sync on the same routes. One rewrites models, the other unsets it. Pick one.
  • mirror + modelOverrides. A route with non-empty modelOverrides is skipped in mirror mode (folding/persisting overrides is dsh-model-sync's models-store job). unset mode is unaffected and is the recommended default.

Development

npm install
npm run build   # tsc → lib/
npm run check   # tsc --noEmit
npm test        # node --test (pretest builds)
node scripts/smoke-boot.mjs

See AGENTS.md for the architecture, the host facts this implementation relies on, and the roadmap.

License

MIT.