DeepSeek Harness Plugin Hub

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

探索

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

社区

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

相关链接

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

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

Pi Ai Sync — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
P

dsh-pi-ai-sync

Pi Ai Sync

dsh 插件:整合 dsh-model-sync(设置接口)和 dsh-opencode-go-models(pi-ai 目录文件),使提供商路由与 pi.dev 网关保持同步,并可选择新模型,无需手动编辑 node_modules。

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

npx -y @deepseek-ai/dsh plugin --profile web add github:jiaruihuang/dsh-pi-ai-sync#13e9fdf15f47dd05f0b615c085b07cc86b1a9654
README兼容性版本

兼容性与来源证明

Pi Ai Sync 以 dsh-pi-ai-sync 发布,当前版本为 0.4.0。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

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

版本

0.4.0stable
2026/10/16
0.3.0stable
2026/10/16
0.2.0stable
2026/10/15
查看其余 1 个版本收起版本
0.1.0stable
2026/10/14

相关插件

正在加载相关插件…

最新版
0.4.0
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
any
许可证
MIT
发布源
github
GitHub
★ 0
周下载
0
最近提交
2026/10/16
查看源码 ↗
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 源代码。Codex Subscriptiondsh-codex-subscription通过 OAuth 在 DeepSeek Harness 中使用 ChatGPT 和 Codex 订阅,支持配额管理、安全重置、网页搜索、图像和快速模式

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.