pi2dsh 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +311 -151
- package/README.zh.md +262 -132
- package/dist/host.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{runtime-Ce3PTbWU.mjs → runtime-Bh5k4Kjt.mjs} +163 -9
- package/dist/runtime-Bh5k4Kjt.mjs.map +1 -0
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +1 -1
- package/package.json +4 -2
- package/dist/runtime-Ce3PTbWU.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -2,205 +2,365 @@
|
|
|
2
2
|
|
|
3
3
|
**English** | [中文](README.zh.md)
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**Run the Pi ecosystem's plugins on DeepSeek Harness, unmodified.**
|
|
6
6
|
|
|
7
7
|
```sh
|
|
8
|
-
|
|
9
|
-
dsh plugin
|
|
10
|
-
dsh plugin --profile headless add @kassing/pi-vision
|
|
11
|
-
dsh plugin --profile headless add pi-vision-tool
|
|
8
|
+
dsh plugin add pi2dsh # once
|
|
9
|
+
dsh plugin add <any-pi-plugin> # then any Pi plugin, straight from npm
|
|
12
10
|
```
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
package you added to the profile and mounts them all through one bridge
|
|
16
|
-
instance. Mounting happens at startup — **restart `dsh` after adding or
|
|
17
|
-
removing plugins**. Remove a plugin with `dsh plugin remove <pkg>` (remove
|
|
18
|
-
plugins before removing the engine, or they sit unmounted); upgrade the
|
|
19
|
-
engine with `dsh plugin add pi2dsh@latest` (your plugins are untouched),
|
|
20
|
-
upgrade a plugin with `dsh plugin add <pkg>@latest` (the engine is
|
|
21
|
-
untouched).
|
|
12
|
+
## Why this exists
|
|
22
13
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) is built
|
|
15
|
+
on ideas worth betting on — a durable, reconstructable session log, a clean
|
|
16
|
+
service composition, an agent loop you can actually reason about. What it does
|
|
17
|
+
not have yet is a large plugin ecosystem: it is early, and the plugins people
|
|
18
|
+
want on day one — web search, memory, code navigation, subagents, vision — are
|
|
19
|
+
mostly not written for it yet.
|
|
27
20
|
|
|
28
|
-
|
|
21
|
+
[Pi](https://pi.dev/) has that ecosystem already, and it is mature: hundreds
|
|
22
|
+
of published packages, many with real users.
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
pi2dsh is one compatibility layer that implements Pi's public extension ABI on
|
|
25
|
+
top of DSH's native services, so a Pi package runs on DSH **as published** —
|
|
26
|
+
no fork, no patch, no per-package adapter. You install a Pi plugin the same
|
|
27
|
+
way you install anything else in DSH, and it works.
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
│ pi-tui / pi-coding-agent / pi-ai imports → vendored/headless │
|
|
45
|
-
│ shims (width/keys/session math byte-identical to Pi, MIT) │
|
|
46
|
-
│ setModel / setThinkingLevel → agent/request seam overrides │
|
|
47
|
-
└────────────────────────────────────────────────────────────────┘
|
|
48
|
-
▼
|
|
49
|
-
DeepSeek Harness native services (Cordis composition)
|
|
29
|
+
This is deliberately a bridge, not a destination. Every capability you reach
|
|
30
|
+
through pi2dsh is a capability DSH's own ecosystem will eventually offer
|
|
31
|
+
natively — and when a better native plugin shows up for something you use
|
|
32
|
+
here, you should switch to it. That would be the bridge doing its job.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
One engine, then whatever plugins you want:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
dsh plugin --profile web add pi2dsh
|
|
40
|
+
dsh plugin --profile web add @kassing/pi-vision
|
|
50
41
|
```
|
|
51
42
|
|
|
52
|
-
|
|
43
|
+
Then **restart `dsh`** — plugins mount at startup.
|
|
53
44
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
Engine config (optional, in the profile's `cordis.patch.yml`): `packages:
|
|
62
|
-
[a, b]` mounts exactly that list instead of discovering; `exclude: [c]`
|
|
63
|
-
skips individual dependencies; `visionCompanions: false` turns off the
|
|
64
|
-
automatic `<route>-vision` image-admission companions that every text-only
|
|
65
|
-
model route gets by default (an explicit `{route: [modelIds]}` map narrows
|
|
66
|
-
them instead).
|
|
67
|
-
|
|
68
|
-
**Plugin upgrades and compatibility.** Installed plugin versions are locked
|
|
69
|
-
by pnpm's lockfile — a plugin never upgrades behind your back; only an
|
|
70
|
-
explicit `dsh plugin add <pkg>@latest` moves it. Before upgrading, run
|
|
71
|
-
`pi2dsh inspect <pkg>@<version>` for the compatibility report. The bridge
|
|
72
|
-
intercepts the Pi runtime imports (`pi-coding-agent`/`pi-tui`/`pi-ai` are
|
|
73
|
-
served by its shims), so a plugin's own Pi dependency pins never load — the
|
|
74
|
-
only drift that can bite is a plugin adopting a Pi host API the bridge does
|
|
75
|
-
not cover yet, which the report shows and which fails loudly, package-
|
|
76
|
-
isolated, at runtime.
|
|
77
|
-
|
|
78
|
-
Three hard rules keep it general:
|
|
79
|
-
|
|
80
|
-
1. The core contains **no `if (packageName === …)`** branching.
|
|
81
|
-
2. Every capability has a **public-API contract test** (`pnpm test`, 55 tests); "some plugin loads" is never the success criterion.
|
|
82
|
-
3. The top-50 corpus is verified **black-box only**: failures file public ABI gaps, and fixing one gap unlocks every package that hits it (e.g. one jiti subpath-alias fix unlocked 4 packages at once).
|
|
83
|
-
|
|
84
|
-
## Progress: Pi catalog top 50 by monthly downloads
|
|
85
|
-
|
|
86
|
-
Status as of 2026-08-14. Static analysis screens; the black-box run certifies. Full per-package machine-readable evidence in [community/](community/).
|
|
87
|
-
|
|
88
|
-
| Tier | Count | Meaning |
|
|
89
|
-
|---|---|---|
|
|
90
|
-
| ✅ **Tested working** | **49 / 50** | Mounted in a real DSH runtime AND real execution verified: 42 returned success, 7 ran their business logic end-to-end and rejected the synthetic probe arguments (2 of the 49 verified through host mode). Real-service coverage along the way: a real LSP subprocess, real web search/fetch, PNG generation, a real MCP stdio server bridged end-to-end, real child-`pi` dispatch answered by a live model, real DeepSeek search on user credentials, and the official `dsh plugin` add/activate/remove flow |
|
|
91
|
-
| 🟡 **Mounts, not fully verified** | **1 / 50** | `@alexanderfortin/pi-deepseek-usage` — a pure event-hook package: all four lifecycle subscriptions attach, but every handler is gated on an active DeepSeek model session (it fetches billing usage and renders a footer), so a black-box probe has no safely-assertable callable surface. A harness limit, not a package or bridge gap |
|
|
92
|
-
| ❌ **Not yet supported** | **0 / 50** | The last four Pi-internal-runtime packages are bridged: vendored built-in tool constructors, provider factories, a real-semantics `ExtensionRunner` facade, and `createAgentSession` driving genuine DSH child agents |
|
|
93
|
-
| **Total mountable today** | **50 / 50** | 48 through convert/host bundles directly; 2 snapshot-limited packages through host mode ([evidence](community/host-mode-results.json)) |
|
|
45
|
+
> **Use `web` or `headless` as the profile name.** DSH ships a template for
|
|
46
|
+
> exactly those two, and each includes a surface (the web app / the one-shot
|
|
47
|
+
> driver). `dsh plugin --profile <any-other-name>` creates a profile with no
|
|
48
|
+
> surface at all, and that profile **starts up and then hangs with no
|
|
49
|
+
> diagnostic** — nothing to do with pi2dsh, but easy to hit on your first
|
|
50
|
+
> install. If you want a differently named profile, add the surface bundle to
|
|
51
|
+
> its `dsh.profile.bundles` yourself.
|
|
94
52
|
|
|
95
|
-
|
|
53
|
+
That is the whole model. There is no conversion step, no generated bundle, no
|
|
54
|
+
build. The engine discovers the Pi packages in your profile (every one is
|
|
55
|
+
something you explicitly added) and mounts them through a single bridge
|
|
56
|
+
instance: one model directory, one login, one credential store, one upgrade
|
|
57
|
+
unit.
|
|
96
58
|
|
|
97
|
-
|
|
59
|
+
Day-to-day:
|
|
98
60
|
|
|
99
|
-
|
|
61
|
+
| Task | Command |
|
|
62
|
+
|---|---|
|
|
63
|
+
| Add a plugin | `dsh plugin add <pkg>` (then restart dsh) |
|
|
64
|
+
| Remove a plugin | `dsh plugin remove <pkg>` — remove plugins before removing the engine |
|
|
65
|
+
| Upgrade a plugin | `dsh plugin add <pkg>@latest` — the engine is untouched |
|
|
66
|
+
| Upgrade the engine | `dsh plugin add pi2dsh@latest` — your plugins are untouched |
|
|
67
|
+
| Check a plugin before upgrading | `npx pi2dsh inspect <pkg>@<version>` |
|
|
68
|
+
|
|
69
|
+
Two installer messages worth knowing:
|
|
70
|
+
|
|
71
|
+
- **`ERR_PNPM_IGNORED_BUILDS`** — pnpm blocks dependency build scripts by
|
|
72
|
+
default. Run `pnpm approve-builds` inside
|
|
73
|
+
`$DSH_HOME/profiles/web`, or set the listed packages to `true`
|
|
74
|
+
under `allowBuilds` in that profile's `pnpm-workspace.yaml`. Then re-run the
|
|
75
|
+
add. (This is your call to make, so the bridge does not work around it.)
|
|
76
|
+
- **An add silently installs an older version** right after a release —
|
|
77
|
+
pnpm's `minimumReleaseAge` skips versions published very recently. Pin it:
|
|
78
|
+
`dsh plugin add pi2dsh@<version>`.
|
|
100
79
|
|
|
101
|
-
|
|
80
|
+
Requires Node.js 22.19+ and DeepSeek Harness.
|
|
102
81
|
|
|
103
|
-
|
|
82
|
+
## Walkthrough: give a text-only model eyes
|
|
104
83
|
|
|
105
|
-
The
|
|
84
|
+
The clearest example of what the bridge buys you. DeepSeek models are
|
|
85
|
+
text-only, so DSH cannot send them an image. The Pi ecosystem has a plugin for
|
|
86
|
+
exactly this — it hands the image to a vision model you choose and injects the
|
|
87
|
+
analysis back into the conversation.
|
|
106
88
|
|
|
107
|
-
###
|
|
89
|
+
### 1. Install the plugin
|
|
108
90
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
4. ✅ Done: the 2 snapshot-limited packages verified through host mode ([evidence](community/host-mode-results.json)).
|
|
113
|
-
5. ✅ Done: load-time vs lazy reachability screening landed; the five packages it unblocked all mount, four tested-working (see above).
|
|
91
|
+
```sh
|
|
92
|
+
dsh plugin --profile web add @kassing/pi-vision
|
|
93
|
+
```
|
|
114
94
|
|
|
115
|
-
|
|
95
|
+
### 2. Point it at a multimodal model
|
|
116
96
|
|
|
117
|
-
|
|
97
|
+
**This is the step to get right** — the plugin needs its own vision model, and
|
|
98
|
+
it is a different model from the one you chat with. Any OpenAI-compatible
|
|
99
|
+
vision endpoint works (OpenRouter, DashScope/Qwen-VL, a self-hosted vLLM, …).
|
|
100
|
+
|
|
101
|
+
The plugin reads its configuration from environment variables — the standard
|
|
102
|
+
way Pi plugins are configured, and a plain DSH-side action for you:
|
|
118
103
|
|
|
119
104
|
```sh
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
# Optional CLI (inspect / convert / host / mcp-config)
|
|
125
|
-
npx pi2dsh inspect @narumitw/pi-lsp # compatibility report
|
|
126
|
-
npx pi2dsh convert @narumitw/pi-lsp --out ./dsh-pi-lsp # vendored snapshot
|
|
127
|
-
npx pi2dsh host --packages 'pi-simplify' --out ./pi-host # pinned bundle
|
|
128
|
-
npx pi2dsh mcp-config # Pi mcpServers → DSH patch
|
|
105
|
+
export VISION_BRIDGE_BASE_URL=https://openrouter.ai/api/v1
|
|
106
|
+
export VISION_BRIDGE_MODEL=qwen/qwen2.5-vl-72b-instruct
|
|
107
|
+
export VISION_BRIDGE_API_KEY=$OPENROUTER_API_KEY
|
|
129
108
|
```
|
|
130
109
|
|
|
131
|
-
|
|
110
|
+
That is enough to work. If you would also like that vision model to appear in
|
|
111
|
+
DSH's own model picker (so you can chat with it directly), add it as a normal
|
|
112
|
+
DSH route as well — the `llm-pi-ai:` section of `$DSH_HOME/settings.yaml`:
|
|
132
113
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
114
|
+
```yaml
|
|
115
|
+
llm-pi-ai:
|
|
116
|
+
providers:
|
|
117
|
+
openrouter:
|
|
118
|
+
baseUrl: https://openrouter.ai/api/v1
|
|
119
|
+
apiKeyEnv: OPENROUTER_API_KEY
|
|
120
|
+
models:
|
|
121
|
+
- id: qwen/qwen2.5-vl-72b-instruct
|
|
122
|
+
```
|
|
138
123
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
| [`examples/vision-bridge`](examples/vision-bridge/) | A text-only model answers questions about images: mention an image path, a configured vision model reads it, the analysis is injected into the conversation (works in CLI and the DSH web app; probe images included) |
|
|
142
|
-
| [`examples/custom-gateways`](examples/custom-gateways/) | Add any OpenAI-compatible gateway the official DSH way (the `llm-pi-ai:` section of DSH settings) — it appears in the DSH model picker, works as the main model, and every Pi plugin sees it through the bridge's registry projection; the bridge owns zero model configuration |
|
|
124
|
+
Both are ordinary DSH configuration. The bridge owns no model configuration of
|
|
125
|
+
its own, and there is no Pi-format file for you to write.
|
|
143
126
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
each one is re-verified end to end under the same bar.
|
|
127
|
+
Avoid GPT-5/o-family models as the vision backend: that generation rejects the
|
|
128
|
+
non-default `temperature` some vision plugins send.
|
|
147
129
|
|
|
148
|
-
|
|
130
|
+
### 3. Ask about an image
|
|
149
131
|
|
|
150
|
-
|
|
132
|
+
In the CLI, mention a path:
|
|
151
133
|
|
|
152
134
|
```sh
|
|
153
|
-
|
|
154
|
-
/login openai-codex # prints the authorization URL, spins up the localhost callback
|
|
155
|
-
# → approve in your browser; the credential lands in auth.json (0600)
|
|
135
|
+
dsh --profile web "What color fills $PWD/photo.png ? One word."
|
|
156
136
|
```
|
|
157
137
|
|
|
158
|
-
|
|
138
|
+
In the web app, **just paste the image** — even though your main model is
|
|
139
|
+
text-only. DSH normally refuses image attachments for a text-only model, so
|
|
140
|
+
the engine registers an *image-admission companion* route for every text-only
|
|
141
|
+
route in your directory, named `<route>-vision`. Pick it in the model picker
|
|
142
|
+
(it shows up as a "+ Vision Bridge" group), paste, and ask.
|
|
143
|
+
|
|
144
|
+
What you will see: your image becomes guide text, a
|
|
145
|
+
`pi2dsh:@kassing/pi-vision` context-injection row carries the analysis, and
|
|
146
|
+
your text-only model answers about the picture. Pixels never reach the
|
|
147
|
+
text-only wire.
|
|
159
148
|
|
|
160
|
-
|
|
149
|
+
Companions are automatic. To turn them off, or narrow them to specific routes,
|
|
150
|
+
set `visionCompanions` in the engine's plugin config
|
|
151
|
+
(`$DSH_HOME/profiles/web/cordis.patch.yml`):
|
|
161
152
|
|
|
162
153
|
```yaml
|
|
163
|
-
- id:
|
|
164
|
-
name: '@deepseek-ai/dsh-llm-pi-ai'
|
|
154
|
+
- id: pi2dsh
|
|
165
155
|
config:
|
|
166
|
-
|
|
167
|
-
openai-codex:
|
|
168
|
-
apiKeyEnv: PI2DSH_OAUTH_OPENAI_CODEX
|
|
169
|
-
models:
|
|
170
|
-
- id: gpt-5.6-luna
|
|
156
|
+
visionCompanions: false
|
|
171
157
|
```
|
|
172
158
|
|
|
173
|
-
|
|
159
|
+
Full runnable version, with probe images: [`examples/vision-bridge`](examples/vision-bridge/).
|
|
160
|
+
|
|
161
|
+
## What actually works today
|
|
162
|
+
|
|
163
|
+
Two levels, and they are not the same claim.
|
|
164
|
+
|
|
165
|
+
### Level 1 — verified end to end, with a runnable example
|
|
174
166
|
|
|
175
|
-
|
|
167
|
+
Someone sat down, used the plugin's real feature on a real DSH loop, and saw
|
|
168
|
+
it work. **This is the list to trust.**
|
|
176
169
|
|
|
177
|
-
|
|
|
170
|
+
| Plugin | What was exercised | Where | Example |
|
|
171
|
+
|---|---|---|---|
|
|
172
|
+
| [`@kassing/pi-vision`](https://www.npmjs.com/package/@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`](examples/vision-bridge/) |
|
|
173
|
+
| [`pi-btw`](https://www.npmjs.com/package/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`](examples/side-conversation/) |
|
|
174
|
+
| [`pi-vision-tool`](https://www.npmjs.com/package/pi-vision-tool) | Tool registration through a JSON-Schema shape DSH had to convert (`anyOf` → `oneOf`) | CLI + web | — |
|
|
175
|
+
| [`pi-approval-guardian`](https://www.npmjs.com/package/pi-approval-guardian) | Every tool call reviewed by a second model before execution; allow and deny both observed | CLI (bare env) | — |
|
|
176
|
+
| [`pi-hermes-memory`](https://www.npmjs.com/package/pi-hermes-memory) | Cross-session memory: written in one process, read back in a second, fresh one | CLI | — |
|
|
177
|
+
|
|
178
|
+
Examples for the last three are still to be written; per this project's own
|
|
179
|
+
rule they get re-verified from scratch before an example lands, so the table
|
|
180
|
+
says plainly which have one today.
|
|
181
|
+
|
|
182
|
+
### Level 2 — mounts and its surface answers a probe
|
|
183
|
+
|
|
184
|
+
The Pi catalog's **top 50 packages by monthly downloads**, each mounted in a
|
|
185
|
+
real DSH runtime and then called through a black-box probe. Status as of
|
|
186
|
+
2026-08-14; per-package machine-readable evidence in
|
|
187
|
+
[`community/`](community/).
|
|
188
|
+
|
|
189
|
+
**47 of 50 exercised successfully · 1 with no probeable surface · 2 pending a
|
|
190
|
+
re-run.**
|
|
191
|
+
|
|
192
|
+
**What this level does not tell you:** that the plugin's actual feature works
|
|
193
|
+
the way you would use it. A probe calls a registered surface with synthetic
|
|
194
|
+
arguments; a user runs a workflow. `pi-btw` is the cautionary example — it
|
|
195
|
+
graded "working" here for weeks while `/btw <question>` failed on a real
|
|
196
|
+
session, because the feature needed two ABI gaps closed (Pi's settable
|
|
197
|
+
`AgentState.messages`, and an input descriptor on bridged commands) that no
|
|
198
|
+
probe exercised. Both are fixed in 0.11.0, and both were general fixes that
|
|
199
|
+
unlock every plugin doing the same thing.
|
|
200
|
+
|
|
201
|
+
So read the table below as **"the bridge covers what this plugin touches"**,
|
|
202
|
+
not as "this plugin is known-good". When you try one, a report either way is
|
|
203
|
+
useful.
|
|
204
|
+
|
|
205
|
+
| Area | Packages |
|
|
206
|
+
|---|---|
|
|
207
|
+
| **MCP** | `pi-mcp-adapter` · `pi-mcp-extension` |
|
|
208
|
+
| **Web search & fetch** | `pi-web-access` · `pi-deepseek-search` · `pi-web-search` · `@ollama/pi-web-search` · `@juicesharp/rpiv-web-tools` |
|
|
209
|
+
| **Code navigation & editing** | `pi-lens` (ast-grep) · `@narumitw/pi-lsp` · `pi-readseek` · `@ff-labs/pi-fff` · `pi-landstrip` · `pi-hashline-edit-pro`¹ |
|
|
210
|
+
| **Subagents & background work** | `@tintinweb/pi-subagents` · `@gotgenes/pi-subagents` · `pi-background-tasks`² · `@mjasnikovs/pi-task` |
|
|
211
|
+
| **Memory** | `pi-hermes-memory` · `pi-goosedump` |
|
|
212
|
+
| **Planning & goals** | `@narumitw/pi-goal` · `pi-goal-list-loop-audit` · `@narumitw/pi-plan-mode` · `@juicesharp/rpiv-todo` |
|
|
213
|
+
| **Asking you / approvals** | `@juicesharp/rpiv-ask-user-question` · `pi-ask-user` · `@gotgenes/pi-permission-system` · `@juicesharp/rpiv-advisor` |
|
|
214
|
+
| **Side conversations** | `pi-btw` · `@narumitw/pi-btw` |
|
|
215
|
+
| **Models & providers** | `pi-provider-litellm` · `pi-llama-cpp` · `pi-prompt-template-model` · `@vigolium/piolium` |
|
|
216
|
+
| **Images** | `@kassing/pi-vision` (see above) · `@amaster.ai/pi-image-gen` |
|
|
217
|
+
| **External integrations** | `@llblab/pi-telegram` · `pi-cursor-sdk`² · `@howaboua/pi-codex-conversion` · `pi-agent-browser-native`² · `pi-harness-runtime` |
|
|
218
|
+
| **Prompting & workflow** | `pi-simplify` · `pi-fabric`² · `mitsupi` · `pi-cc-extensions` · `pi-rtk-optimizer` · `pi-interview`¹ |
|
|
219
|
+
| **Terminal decoration** | `pi-powerline-footer` · `@narumitw/pi-statusline` · `pi-zentui` |
|
|
220
|
+
| **Voice** | `@juicesharp/rpiv-voice` |
|
|
221
|
+
| **Usage reporting** | `@alexanderfortin/pi-deepseek-usage`³ |
|
|
222
|
+
|
|
223
|
+
¹ Mounts; the exercise run is pending a re-run (a harness-side failure, not a
|
|
224
|
+
package or bridge gap). ² Ran its own business logic end to end and rejected
|
|
225
|
+
the synthetic probe arguments — working, correctly validating.
|
|
226
|
+
³ A pure event-hook package: all subscriptions attach, but every handler is
|
|
227
|
+
gated on a live DeepSeek billing session, so a black-box probe has nothing
|
|
228
|
+
safely callable to assert.
|
|
229
|
+
|
|
230
|
+
Packages outside the top 50 are not a separate case — the bridge has no
|
|
231
|
+
per-package code. If one hits an ABI gap, fixing that gap unlocks every
|
|
232
|
+
package that shares it.
|
|
233
|
+
|
|
234
|
+
Level 1 grows by working through Level 2 one plugin at a time. The full
|
|
235
|
+
verification ladder, with what each rung does and does not prove:
|
|
236
|
+
[support matrix](docs/posting-kit/support-matrix.md).
|
|
237
|
+
|
|
238
|
+
## How it works
|
|
239
|
+
|
|
240
|
+
Three layers, and nothing crosses them:
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
┌─ Pi plugin ─────────────────────────────────────────────────┐
|
|
244
|
+
│ unmodified npm package. It sees a complete Pi host: the │
|
|
245
|
+
│ three Pi runtime imports, registerX, ctx.*, 33 lifecycle │
|
|
246
|
+
│ events. It never learns DSH exists. │
|
|
247
|
+
└──────────────────────────┬──────────────────────────────────┘
|
|
248
|
+
│ Pi's public ABI
|
|
249
|
+
┌──────────────────────────▼──────────────────────────────────┐
|
|
250
|
+
│ pi2dsh — the translator, and the only place that knows both │
|
|
251
|
+
│ vocabularies. Registry projection, event bridge, session & │
|
|
252
|
+
│ subagent bridge, credentials, vendored Pi logic. │
|
|
253
|
+
└──────────────────────────┬──────────────────────────────────┘
|
|
254
|
+
│ ordinary DSH plugin + llm adapter
|
|
255
|
+
┌──────────────────────────▼──────────────────────────────────┐
|
|
256
|
+
│ DeepSeek Harness. Sees a normal plugin. Never learns Pi │
|
|
257
|
+
│ exists. │
|
|
258
|
+
└─────────────────────────────────────────────────────────────┘
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
The rules that keep it honest:
|
|
262
|
+
|
|
263
|
+
- **Never a second implementation of something DSH already has.** Tools go to
|
|
264
|
+
DSH's tool registry, models to DSH's llm configuration, MCP to
|
|
265
|
+
`dsh-mcp-client`, skills to `dsh-skill-filesystem`, questions to DSH's user
|
|
266
|
+
questions. The bridge translates configuration; it does not build a parallel
|
|
267
|
+
runtime.
|
|
268
|
+
- **You never see Pi.** Everything you configure, read, or type is DSH-shaped:
|
|
269
|
+
DSH settings, DSH commands, DSH credentials. Pi vocabulary exists only
|
|
270
|
+
inside the plugin's view and the bridge's own internals.
|
|
271
|
+
- **No per-package special cases.** The core contains no
|
|
272
|
+
`if (packageName === …)`. One ABI gap fixed unlocks every package that hits
|
|
273
|
+
it.
|
|
274
|
+
- **Never fake success.** A capability with no safe mapping is reported —
|
|
275
|
+
once, per plugin, in plain language — instead of silently returning
|
|
276
|
+
something invented. If a plugin needs one during startup, it is marked
|
|
277
|
+
unusable with a removal hint rather than half-working.
|
|
278
|
+
- **Verified, not asserted.** Every capability has a public-API contract test,
|
|
279
|
+
and ships only after running end to end on a real DSH loop — CLI *and* web.
|
|
280
|
+
|
|
281
|
+
## Pi capabilities on DSH
|
|
282
|
+
|
|
283
|
+
Every surface a Pi package can touch, and what it maps onto. These tables are
|
|
284
|
+
generated from the rules the bridge consults at runtime, so they cannot drift
|
|
285
|
+
from the code.
|
|
286
|
+
|
|
287
|
+
| Area | Pi surfaces | Status |
|
|
288
|
+
|---|---|---|
|
|
289
|
+
| [Tools](docs/capabilities/tools.md) | 12 | 3 same semantics · 9 mapped, difference stated |
|
|
290
|
+
| [Commands, flags, editor input](docs/capabilities/commands.md) | 13 | 13 mapped, difference stated |
|
|
291
|
+
| [Messages, context, agent loop](docs/capabilities/conversation.md) | 20 | 7 same semantics · 13 mapped, difference stated |
|
|
292
|
+
| [Sessions & side conversations](docs/capabilities/sessions.md) | 24 | 4 same semantics · 20 mapped, difference stated |
|
|
293
|
+
| [Models, providers, credentials](docs/capabilities/models.md) | 15 | 12 mapped, difference stated · 3 not available |
|
|
294
|
+
| [Asking the user, rendering](docs/capabilities/interaction.md) | 24 | 4 same semantics · 20 mapped, difference stated |
|
|
295
|
+
| [Project environment & resources](docs/capabilities/environment.md) | 4 | 1 same semantics · 1 mapped · 2 not available |
|
|
296
|
+
| **Total** | **112** | **19 same · 88 mapped with stated differences · 5 not available** |
|
|
297
|
+
|
|
298
|
+
Plus **202 imported symbols** from Pi's three runtime packages
|
|
299
|
+
(`pi-coding-agent`, `pi-tui`, `pi-ai`), served from vendored or headless
|
|
300
|
+
shims — so a plugin's own Pi version pins never load.
|
|
301
|
+
|
|
302
|
+
Start at the [capability index](docs/capabilities/README.md). Machine-readable:
|
|
303
|
+
`pi2dsh matrix --json`.
|
|
304
|
+
|
|
305
|
+
**Signing in with a subscription** works too: DSH ships static HTTP headers
|
|
306
|
+
only, and the bridge adds the Pi ecosystem's interactive OAuth layer. Any Pi
|
|
307
|
+
provider package that declares an `oauth` block gets a working
|
|
308
|
+
`/login <provider>`, driven by the package's own protocol code — Pi's four
|
|
309
|
+
official flows (OpenAI Codex, Anthropic, GitHub Copilot, Kimi Code) ship built
|
|
310
|
+
in. Credentials persist with Pi's `auth.json` semantics and resolve per
|
|
311
|
+
request through a standard `dsh-credentials` provider, so your subscription
|
|
312
|
+
drives real calls on DSH's native llm path. Details in
|
|
313
|
+
[models](docs/capabilities/models.md).
|
|
314
|
+
|
|
315
|
+
**What is deliberately not available**, and why: runtime package installation
|
|
316
|
+
and standalone model runtimes stay with the host and its security gates;
|
|
317
|
+
provider payload/header/response interception belongs in a DSH llm adapter;
|
|
318
|
+
project trust is a host decision. See
|
|
319
|
+
[models](docs/capabilities/models.md) and
|
|
320
|
+
[environment](docs/capabilities/environment.md).
|
|
321
|
+
|
|
322
|
+
**The one gap we own:** plugin-drawn cards. Pi plugins can ship their own
|
|
323
|
+
renderers; today those registrations are accepted but not invoked, so such a
|
|
324
|
+
note appears as a native context-injection row — the content reaches you and
|
|
325
|
+
the model, without the plugin's styling. DSH has the machinery for this; we
|
|
326
|
+
have not built our client half yet.
|
|
327
|
+
|
|
328
|
+
## Examples
|
|
329
|
+
|
|
330
|
+
Every verified capability ships as a complete, runnable example. Every command
|
|
331
|
+
in one has actually been executed against a real DSH loop before landing.
|
|
332
|
+
|
|
333
|
+
| Example | What you get |
|
|
178
334
|
|---|---|
|
|
179
|
-
|
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
|
|
|
183
|
-
| Model runtime | `modelRegistry` projects the live DSH llm directory as Pi Model objects (refreshed on `llm/adapters-updated`); `ctx.model` reflects the agent's real route; `setModel`/`setThinkingLevel` switch the loop through the `agent/request` waterfall; pi-ai `complete()`/`stream()` run REAL calls through `ctx.llm.stream()` with two-way message conversion (verified against a live model: `scripts/verify-model-bridge-e2e.mjs`) |
|
|
184
|
-
| Session control | REAL on DSH's own surfaces: `newSession` creates a DSH session with lineage, `fork` uses DSH's official prefix-fork (landing on completed-turn boundaries), `navigateTree` forks at the target with an optional vendored branch summary, `switchSession` targets live sessions. The DSH tree lives *between* sessions (fork lineage); which session the surface shows stays a host choice |
|
|
185
|
-
| Compaction & summaries | `ctx.compact()` triggers DSH's official manual compaction; Pi's `generateSummary`/`generateBranchSummary`/`findCutPoint` are vendored with model calls on the DSH llm bridge |
|
|
186
|
-
| shutdown / reload | `shutdown` is absorbed (Pi defines its behavior as host-provided; the user owns DSH process exit); `reload` really remounts extension entries — skills/prompts/themes reload with dsh itself |
|
|
187
|
-
| Host-owned capabilities | `ModelRuntime` and `DefaultPackageManager` stay unavailable **by design** (the host owns model configuration and package install with its security gates). Importing them is flagged at startup; constructing them throws a structured error, and doing so during plugin startup marks the plugin unusable with a clear removal hint. Every capability gap is reported to you once per plugin — never a silent failure, never a fake success. **Known plugins unusable for this reason: none so far** (this list will name any we find) |
|
|
188
|
-
| Terminal decoration | footer/statusline/shortcuts register but never fire — matching Pi's own non-TUI modes |
|
|
335
|
+
| [`vision-bridge`](examples/vision-bridge/) | A text-only model answers questions about images — CLI and web, probe images included |
|
|
336
|
+
| [`side-conversation`](examples/side-conversation/) | `/btw <question>` runs a side thread in DSH's native subagent UI; your main conversation stays clean |
|
|
337
|
+
| [`gateway-compat`](examples/gateway-compat/) | Private / domestic / proxy gateways that reject the `developer` role: why reasoning 400s, and how a Pi provider plugin gets past it (fake-endpoint probe included) |
|
|
338
|
+
| [`custom-gateways`](examples/custom-gateways/) | Add any OpenAI-compatible gateway the official DSH way, and every Pi plugin sees it |
|
|
189
339
|
|
|
190
|
-
|
|
340
|
+
## Other tools
|
|
191
341
|
|
|
192
|
-
|
|
342
|
+
Beyond the engine, the CLI has a few helpers:
|
|
193
343
|
|
|
194
344
|
```sh
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
# add DEEPSEEK_API_KEY=… PI2DSH_BLACKBOX_PI_BIN=$(command -v pi) for the
|
|
199
|
-
# credentialed probes and real child-pi dispatch (keys from env only)
|
|
200
|
-
pnpm test:community # deep runtime + official manager + host e2e
|
|
201
|
-
DEEPSEEK_API_KEY=… pnpm test:live # real-model acceptance (key from env only)
|
|
345
|
+
npx pi2dsh inspect <pkg>@<version> # compatibility report before an upgrade
|
|
346
|
+
npx pi2dsh matrix --json # the full capability matrix
|
|
347
|
+
npx pi2dsh mcp-config # Pi mcpServers config → official DSH MCP entries
|
|
202
348
|
```
|
|
203
349
|
|
|
350
|
+
## Development
|
|
351
|
+
|
|
352
|
+
```sh
|
|
353
|
+
pnpm verify # typecheck + contract tests + packaging
|
|
354
|
+
pnpm audit:community # static screening over the top-50 corpus
|
|
355
|
+
pnpm test:community # deep runtime + official plugin-manager + e2e
|
|
356
|
+
DEEPSEEK_API_KEY=… pnpm test:live # real-model acceptance (key from env only)
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
Acceptance evidence per capability: [docs/acceptance.md](docs/acceptance.md).
|
|
360
|
+
Working standards: [CLAUDE.md](CLAUDE.md) and [docs/STANDARDS.md](docs/STANDARDS.md).
|
|
361
|
+
|
|
204
362
|
## License
|
|
205
363
|
|
|
206
|
-
MIT. Vendored Pi sources retain their upstream MIT license
|
|
364
|
+
MIT. Vendored Pi sources retain their upstream MIT license
|
|
365
|
+
(`src/compat/vendor/PI-LICENSE`); generated bundles retain copied upstream
|
|
366
|
+
license and notice files.
|