- 语言
- TypeScript
- License
- MIT
- 分支
- main
安装
$ dsh plugin --profile web add github:weijiafu14/pi2dsh在终端中运行以上命令,通过 dsh CLI 安装此插件。可在右上角切换 Profile。 第一次用 dsh?看这篇新手教程
对话式安装
帮我安装 DeepSeek Harness 插件 weijiafu14/pi2dsh:先查看仓库 https://github.com/weijiafu14/pi2dsh 确认安全性,然后执行安装命令并验证插件加载成功。
把这段指令粘贴给 DSH Web GUI 里的助手,由它代你完成安装与验证。
English | 中文
Run the Pi ecosystem's plugins on DeepSeek Harness, unmodified.
dsh plugin add pi2dsh # once
dsh plugin add <any-pi-plugin> # then any Pi plugin, straight from npm
Why this exists
DeepSeek Harness is built on ideas worth betting on — a durable, reconstructable session log, a clean service composition, an agent loop you can actually reason about. What it does not have yet is a large plugin ecosystem: it is early, and the plugins people want on day one — web search, memory, code navigation, subagents, vision — are mostly not written for it yet.
Pi has that ecosystem already, and it is mature: hundreds of published packages, many with real users.
pi2dsh is one compatibility layer that implements Pi's public extension ABI on top of DSH's native services, so a Pi package runs on DSH as published — no fork, no patch, no per-package adapter. You install a Pi plugin the same way you install anything else in DSH, and it works.
At the same time, pi2dsh is an ongoing, full-surface, real-world test of DSH's architecture. Instead of patching individual plugins, it asks whether the models, tools, sessions, interaction, resources and client capabilities that Pi plugins rely on can preserve their logic and lifecycle using only DSH's public services and extension seams. If they can, that is strong evidence that DSH's architectural goals for building agents and an agent-plugin ecosystem have been achieved, at least along this dimension. Wherever the bridge must bypass, degrade or cannot express a capability, it pinpoints an architectural gap that remains.
Install
One engine, then whatever plugins you want:
dsh plugin --profile web add pi2dsh
dsh plugin --profile web add @kassing/pi-vision
Then restart dsh — plugins mount at startup.
Use
weborheadlessas the profile name. DSH ships a template for exactly those two, and each includes a surface (the web app / the one-shot driver).dsh plugin --profile <any-other-name>creates a profile with no surface at all, and that profile starts up and then hangs with no diagnostic — nothing to do with pi2dsh, but easy to hit on your first install. If you want a differently named profile, add the surface bundle to itsdsh.profile.bundlesyourself.
That is the whole model. There is no conversion step, no generated bundle, no build. The engine discovers the Pi packages in your profile (every one is something you explicitly added) and mounts them through a single bridge instance: one model directory, one login, one credential store, one upgrade unit.
Day-to-day:
| Task | Command |
|---|---|
| Add a plugin | dsh plugin add <pkg> (then restart dsh) |
| Remove a plugin | dsh plugin remove <pkg> — remove plugins before removing the engine |
| Upgrade a plugin | dsh plugin add <pkg>@latest — the engine is untouched |
| Upgrade the engine | dsh plugin add pi2dsh@latest — your plugins are untouched |
| Check a plugin before upgrading | npx pi2dsh inspect <pkg>@<version> |
Two installer messages worth knowing:
ERR_PNPM_IGNORED_BUILDS— pnpm blocks dependency build scripts by default. Runpnpm approve-buildsinside$DSH_HOME/profiles/web, or set the listed packages totrueunderallowBuildsin that profile'spnpm-workspace.yaml. Then re-run the add. (This is your call to make, so the bridge does not work around it.)- An add silently installs an older version right after a release —
pnpm's
minimumReleaseAgeskips versions published very recently. Pin it:dsh plugin add pi2dsh@<version>.
Requires Node.js 22.19+ and DeepSeek Harness.
Walkthrough: give a text-only model eyes
The clearest example of what the bridge buys you. DeepSeek models are text-only, so DSH cannot send them an image. The Pi ecosystem has a plugin for exactly this — it hands the image to a vision model you choose and injects the analysis back into the conversation.
1. Install the plugin
dsh plugin --profile web add @kassing/pi-vision
2. Point it at a multimodal model
This is the step to get right — the plugin needs its own vision model, and it is a different model from the one you chat with. Any OpenAI-compatible vision endpoint works (OpenRouter, DashScope/Qwen-VL, a self-hosted vLLM, …).
The plugin reads its configuration from environment variables — the standard way Pi plugins are configured, and a plain DSH-side action for you:
export VISION_BRIDGE_BASE_URL=https://openrouter.ai/api/v1
export VISION_BRIDGE_MODEL=qwen/qwen2.5-vl-72b-instruct
export VISION_BRIDGE_API_KEY=$OPENROUTER_API_KEY
That is enough to work. If you would also like that vision model to appear in
DSH's own model picker (so you can chat with it directly), add it as a normal
DSH route as well — the llm-pi-ai: section of $DSH_HOME/settings.yaml:
llm-pi-ai:
providers:
openrouter:
baseUrl: https://openrouter.ai/api/v1
apiKeyEnv: OPENROUTER_API_KEY
models:
- id: qwen/qwen2.5-vl-72b-instruct
Both are ordinary DSH configuration. The bridge owns no model configuration of its own, and there is no Pi-format file for you to write.
Avoid GPT-5/o-family models as the vision backend: that generation rejects the
non-default temperature some vision plugins send.
3. Ask about an image
In the CLI, mention a path:
dsh --profile web "What color fills $PWD/photo.png ? One word."
In the web app, just paste the image — even though your main model is
text-only. DSH normally refuses image attachments for a text-only model, so
the engine registers an image-admission companion route for every text-only
route in your directory, named <route>-vision. Pick it in the model picker
(it shows up as a "+ Vision Bridge" group), paste, and ask.
What you will see: your image becomes guide text, a
pi2dsh:@kassing/pi-vision context-injection row carries the analysis, and
your text-only model answers about the picture. Pixels never reach the
text-only wire.
Companions are automatic. To turn them off, or narrow them to specific routes,
set visionCompanions in the engine's plugin config
($DSH_HOME/profiles/web/cordis.patch.yml):
- id: pi2dsh
config:
visionCompanions: false
Full runnable version, with probe images: examples/vision-bridge.
What actually works today
Two levels, and they are not the same claim.
Level 1 — verified end to end, with a runnable example
Someone sat down, used the plugin's real feature on a real DSH loop, and saw it work. This is the list to trust.
| Plugin | What was exercised | Where | Example |
|---|---|---|---|
@kassing/pi-vision | Image analysis delegated to a vision model; image-admission companion route; analysis injected into a text-only model's turn | CLI + web | vision-bridge |
@crazygit/pi-codex-image-gen | ChatGPT/Codex OAuth → gpt-image-2 generation; local reference-image upload through DSH approval; image edit; native attachment storage and inline Web rendering | CLI + web | codex-image-gen |
pi-btw | /btw <question> as a real child session in DSH's subagent UI; /btw-inject; /btw --save; main thread stays clean | CLI + web | side-conversation |
pi-powerline-footer | A terminal status line — model, thinking level, project, context usage — drawn into DSH's widget dock, colour included | web | presentation-surfaces |
pi-vision-tool | Tool registration through a JSON-Schema shape DSH had to convert (anyOf → oneOf) | CLI + web | — |
pi-approval-guardian | Every tool call reviewed by a second model before execution; allow and deny both observed | CLI (bare env) | — |
pi-hermes-memory | Cross-session memory: written in one process, read back in a second, fresh one | CLI | — |
Examples for the last three are still to be written; per this project's own rule they get re-verified from scratch before an example lands, so the table says plainly which have one today.
Level 2 — mounts and its surface answers a probe
The Pi catalog's top 50 packages by monthly downloads, each mounted in a
real DSH runtime and then called through a black-box probe. Status as of
2026-08-14; per-package machine-readable evidence in
community/.
47 of 50 exercised successfully · 1 with no probeable surface · 2 pending a re-run.
What this level does not tell you: that the plugin's actual feature works
the way you would use it. A probe calls a registered surface with synthetic
arguments; a user runs a workflow. pi-btw is the cautionary example — it
graded "working" here for weeks while /btw <question> failed on a real
session, because the feature needed two ABI gaps closed (Pi's settable
AgentState.messages, and an input descriptor on bridged commands) that no
probe exercised. Both are fixed in 0.11.0, and both were general fixes that
unlock every plugin doing the same thing.
So read the table below as "the bridge covers what this plugin touches", not as "this plugin is known-good". When you try one, a report either way is useful.
| Area | Packages |
|---|---|
| MCP | pi-mcp-adapter · pi-mcp-extension |
| Web search & fetch | pi-web-access · pi-deepseek-search · pi-web-search · @ollama/pi-web-search · @juicesharp/rpiv-web-tools |
| Code navigation & editing | pi-lens (ast-grep) · @narumitw/pi-lsp · pi-readseek · @ff-labs/pi-fff · pi-landstrip · pi-hashline-edit-pro¹ |
| Subagents & background work | @tintinweb/pi-subagents · @gotgenes/pi-subagents · pi-background-tasks² · @mjasnikovs/pi-task |
| Memory | pi-hermes-memory · pi-goosedump |
| Planning & goals | @narumitw/pi-goal · pi-goal-list-loop-audit · @narumitw/pi-plan-mode · @juicesharp/rpiv-todo |
| Asking you / approvals | @juicesharp/rpiv-ask-user-question · pi-ask-user · @gotgenes/pi-permission-system · @juicesharp/rpiv-advisor |
| Side conversations | pi-btw · @narumitw/pi-btw |
| Models & providers | pi-provider-litellm · pi-llama-cpp · pi-prompt-template-model · @vigolium/piolium |
| Images | @kassing/pi-vision (see above) · @amaster.ai/pi-image-gen |
| External integrations | @llblab/pi-telegram · pi-cursor-sdk² · @howaboua/pi-codex-conversion · pi-agent-browser-native² · pi-harness-runtime |
| Prompting & workflow | pi-simplify · pi-fabric² · mitsupi · pi-cc-extensions · pi-rtk-optimizer · pi-interview¹ |
| Terminal decoration | pi-powerline-footer · @narumitw/pi-statusline · pi-zentui |
| Voice | @juicesharp/rpiv-voice |
| Usage reporting | @alexanderfortin/pi-deepseek-usage³ |
¹ Mounts; the exercise run is pending a re-run (a harness-side failure, not a package or bridge gap). ² Ran its own business logic end to end and rejected the synthetic probe arguments — working, correctly validating. ³ A pure event-hook package: all subscriptions attach, but every handler is gated on a live DeepSeek billing session, so a black-box probe has nothing safely callable to assert.
Packages outside the top 50 are not a separate case — the bridge has no per-package code. If one hits an ABI gap, fixing that gap unlocks every package that shares it.
Level 1 grows by working through Level 2 one plugin at a time. The full verification ladder, with what each rung does and does not prove: support matrix.
How it works
Three layers, and nothing crosses them:
┌─ Pi plugin ─────────────────────────────────────────────────┐
│ unmodified npm package. It sees a complete Pi host: the │
│ three Pi runtime imports, registerX, ctx.*, 33 lifecycle │
│ events. It never learns DSH exists. │
└──────────────────────────┬──────────────────────────────────┘
│ Pi's public ABI
┌──────────────────────────▼──────────────────────────────────┐
│ pi2dsh — the translator, and the only place that knows both │
│ vocabularies. Registry projection, event bridge, session & │
│ subagent bridge, credentials, vendored Pi logic. │
└──────────────────────────┬──────────────────────────────────┘
│ ordinary DSH plugin + llm adapter
┌──────────────────────────▼──────────────────────────────────┐
│ DeepSeek Harness. Sees a normal plugin. Never learns Pi │
│ exists. │
└─────────────────────────────────────────────────────────────┘
DSH is two halves, and so is the bridge. The column above is the server; the browser shell has its own plugin surface, and a Pi capability that is a SHAPE rather than a behaviour lands there:
┌──────────── DSH server (cordis) ────────────┐ ┌──────── DSH browser shell ────────┐
│ services · waterfalls · durable events │ │ dsh.client + exports "./client" │
│ │ │ slot registry (ui-slots) │
│ pi2dsh engine │ │ shell.overlay ← panel, pills │
│ tools · commands · models · sessions │ │ session.header.utilities ← hdr │
│ subagent bridge ─────────────┐ │ │ input.dock ← widgets │
│ browser-state registry │ │ │ composer.dock ← working/footer │
│ GET /pi2dsh/browser-state ─┼── own route┼──┼─▶ all four seats, one poller │
└────────────────────────────────┴────────────┘ └───────────────────────────────────┘
The browser half's data rides this package's own route, not DSH's typed
Remote system: that one is a first-party, code-generated contract, and an
out-of-tree plugin talking to its own UI should carry its own channel. One
payload per session serves every seat — the side-conversation panel, plus the
Pi presentation surfaces (status, widget, header, footer, title and the
working/thinking chrome), which are drawn in the host's own slot seats rather
than re-implemented. Two host rules make the browser half load at all — the
package must export ./package.json (the host resolves the manifest by
subpath), and the ./client bundle is a closure-factory artifact, not plain
ESM.
The rules that keep it honest:
- Never a second implementation of something DSH already has. Tools go to
DSH's tool registry, models to DSH's llm configuration, MCP to
dsh-mcp-client, skills todsh-skill-filesystem, questions to DSH's user questions. The bridge translates configuration; it does not build a parallel runtime. - You never see Pi. Everything you configure, read, or type is DSH-shaped: DSH settings, DSH commands, DSH credentials. Pi vocabulary exists only inside the plugin's view and the bridge's own internals.
- No per-package special cases. The core contains no
if (packageName === …). One ABI gap fixed unlocks every package that hits it. - Never fake success. A capability with no safe mapping is reported — once, per plugin, in plain language — instead of silently returning something invented. If a plugin needs one during startup, it is marked unusable with a removal hint rather than half-working.
- Verified, not asserted. Every capability has a public-API contract test, and ships only after running end to end on a real DSH loop — CLI and web.
What this is teaching us about DSH
pi2dsh is also an executable stress test of DSH's plugin architecture. Pi gives that test a useful workload: a large, already-used public plugin ABI rather than a set of examples invented to fit the host.
The result so far is specific, not a thumbs-up/thumbs-down verdict:
- DSH's public seams successfully carry whole capabilities: tools, commands, model adapters, user questions, native child sessions and browser slots.
- The pressure points appear when an out-of-repo plugin needs to extend an existing capability from the inside: add a durable session-event type, intercept the real provider request/response, control compaction before it happens, or participate in trust before project resources load.
- A working pi2dsh sidecar or alternate adapter is useful product behaviour, but it is not counted as proof that the native DSH seam is complete.
For example, a pi-btw answer is a real DSH child session — visible, resumable
and continuable by the host. Pi custom entries are different: they still need a
pi2dsh sidecar because an out-of-repo plugin cannot safely add a new event type
to DSH's durable log. Likewise, a transport-owning Pi provider can register a
native DSH route. Since DSH rc.8, a catalog-only provider also has a faithful
official path: pi2dsh translates its endpoint, modalities, reasoning levels and
the protocol-specific compat fields DSH offers into an llm-pi-ai profile, and
DSH owns the request.
The project follows one Pi → DSH architecture mapping standard.
It is a reasoning method, not another runtime layer: concrete Pi interface →
Pi capability contract → DSH carrying mechanism → public seam → real plugin
run → five-grade result. The evolving branches live in the handwritten
architecture model, real runs in
per-plugin validation records, and the
three result classes in architecture conclusions.
Architecture classifications are deliberately not generated from a JSON ledger.
The previously observed 111 Pi rule rows and 45 DSH subsystems are versioned
snapshots, not fixed totals or proof of completeness. Four DSH gap IDs remain
active; a fifth historical finding (DSH-ARCH-002) was fixed upstream in rc.8.
These are confirmed findings, not a claim of complete coverage. Current
upstream reports include
#2708 — durable events for out-of-repo plugins
and
#3076 — provider compat fields dropped by llm-pi-ai,
now resolved by the rc.8 profile schema.
Pi capabilities on DSH
Every surface a Pi package can touch, and what it maps onto. These tables are generated from the rules the bridge consults at runtime, so they cannot drift from the code.
For pinned Pi 0.84.1, the generated catalog has 111 upstream-shaped rule
rows. The bridge also keeps one
documented compatibility extension, unregisterTool; it appears on the tools
detail page but is deliberately outside that total. Nested objects such as the
session manager can expose several methods behind one row; the architecture
audit states this boundary explicitly.
| Area | Pi surfaces | Status |
|---|---|---|
| Tools | 11 | 2 same semantics · 9 mapped, difference stated |
| Commands, flags, editor input | 13 | 13 mapped, difference stated |
| Messages, context, agent loop | 20 | 9 same semantics · 11 mapped, difference stated |
| Sessions & side conversations | 24 | 6 same semantics · 18 mapped, difference stated |
| Models, providers, credentials | 15 | 1 same semantics · 12 mapped, difference stated · 2 not available |
| Asking the user, rendering | 24 | 4 same semantics · 20 mapped, difference stated |
| Project environment & resources | 4 | 1 same semantics · 1 mapped, difference stated · 2 not available |
| Total | 111 | 23 same semantics · 84 mapped, difference stated · 4 not available |
Plus 203 imported symbols from Pi's three runtime packages
(pi-coding-agent, pi-tui, pi-ai), served from vendored or headless
shims — so a plugin's own Pi version pins never load. They are listed in
Imported Pi runtime symbols.
Each area page states the Pi capability contract, the theoretical DSH mechanism and public seam, and the current implementation for every surface. Adding a surface without a capability assignment or theoretical mapping fails the docs check.
Start at the capability index. Machine-readable:
pi2dsh matrix --json.
Signing in with a subscription works too: DSH ships static HTTP headers
only, and the bridge adds the Pi ecosystem's interactive OAuth layer. Any Pi
provider package that declares an oauth block gets a working
/login <provider>, driven by the package's own protocol code — Pi's four
official flows (OpenAI Codex, Anthropic, GitHub Copilot, Kimi Code) ship built
in and are available immediately after installing the engine, even before the
first community Pi package. Credentials persist with Pi's auth.json semantics and resolve per
request through a standard dsh-credentials provider, so your subscription
drives real calls on DSH's native llm path. Details in
models.
What is deliberately not available, and why: runtime package installation and standalone model runtimes stay with the host and its security gates; provider payload/header/response interception belongs in a DSH llm adapter; project trust is a host decision. See models and environment.
The one gap we own: plugin-drawn cards. Pi plugins can ship their own renderers; today those registrations are accepted but not invoked, so such a note appears as a native context-injection row — the content reaches you and the model, without the plugin's styling. The client half exists and takes four seats (side-conversation panel, header, widget dock, working chrome) — the card renderers are what it does not draw yet.
Examples
Every verified capability ships as a complete, runnable example. Every command in one has actually been executed against a real DSH loop before landing.
| Example | What you get |
|---|---|
vision-bridge | A text-only model answers questions about images — CLI and web, probe images included |
codex-image-gen | Generate and edit images with a ChatGPT/Codex subscription; DSH approval and inline result included |
side-conversation | /btw <question> runs a side thread in DSH's native subagent UI; your main conversation stays clean |
presentation-surfaces | A real plugin's terminal chrome (pi-powerline-footer) in DSH's web seats, plus which of the top-50 Pi plugins draw at all |
subscription-login | Use a ChatGPT / Claude / Copilot / Kimi subscription as a DSH model: /login, then the route and credential appear on their own |
gateway-compat | Private / domestic / proxy gateways that reject the developer role: how rc.8's official profile carries Pi compat declarations to the wire (passthrough recorder included) |
custom-gateways | Add any OpenAI-compatible gateway the official DSH way, and every Pi plugin sees it |
Other tools
Beyond the engine, the CLI has a few helpers:
npx pi2dsh inspect <pkg>@<version> # compatibility report before an upgrade
npx pi2dsh matrix --json # the full capability matrix
npx pi2dsh mcp-config # Pi mcpServers config → official DSH MCP entries
Development
pnpm verify # typecheck + contract tests + packaging
pnpm audit:community # static screening over the top-50 corpus
pnpm test:community # deep runtime + official plugin-manager + e2e
DEEPSEEK_API_KEY=… pnpm test:live # real-model acceptance (key from env only)
CODEX_AUTH_FILE=… pnpm test:codex-image # real OAuth generation + reference edit + Web pixels
Acceptance evidence per capability: docs/acceptance.md. Working standards: CLAUDE.md and docs/STANDARDS.md.
License
MIT. Vendored Pi sources retain their upstream MIT license
(src/compat/vendor/PI-LICENSE); generated bundles retain copied upstream
license and notice files.
收录徽章
[](https://deepseek-plugin.org/plugins/weijiafu14/pi2dsh)把这段 markdown 粘贴到你的 GitHub README,链接回本插件详情页。徽章只声明已被本站收录,不代表安全认证。