@dan-ai-studio/dshopencodego 0.1.34 → 0.1.36
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.en.md +14 -12
- package/README.md +14 -12
- package/lib/client.js +2 -2
- package/lib/index.js +19 -4
- package/lib/types/catalog/index.js +30 -2
- package/lib/types/catalog/metadata.js +7 -1
- package/lib/types/config.d.ts +2 -2
- package/lib/types/config.js +1 -1
- package/lib/types/conversion/context.js +1 -1
- package/lib/types/conversion/stream.js +3 -3
- package/package.json +21 -21
package/README.en.md
CHANGED
|
@@ -15,7 +15,7 @@ This plugin serves the `opencode-go` route with its own adapter and closes both
|
|
|
15
15
|
|
|
16
16
|
## Install
|
|
17
17
|
|
|
18
|
-
Prerequisites: a DSH `0.
|
|
18
|
+
Prerequisites: a DSH `0.2.0` release (`0.2.0-rc.1` or later; see "Compatibility"); Node `^22.19.0 || >=24.0.0`; `dsh` and `pnpm` on PATH.
|
|
19
19
|
|
|
20
20
|
> **One owner per route**: a profile can have exactly one adapter for `opencode-go`. Remove the previous plugin (`dsh plugin --profile <p> remove @dan-ai-studio/dsh-opencode-go`) or clear any `opencode-go` provider in `llm-pi-ai` first. Otherwise the plugin logs an explicit ownership diagnostic and does not register the route — everything else keeps working.
|
|
21
21
|
|
|
@@ -71,7 +71,7 @@ Installation **must** go through the in-app UI — do not use the `dsh plugin` c
|
|
|
71
71
|
|
|
72
72
|
Why: Electron owns the Desktop profile, and **the CLI cannot boot or mutate it** (Desktop README: *The CLI cannot boot or mutate this profile.*). Plugin management runs through the app's authenticated HTTP APIs and Desktop's bundled pnpm, so no `pnpm` on `PATH` is required. Upgrades and removals happen on the Plugins page too.
|
|
73
73
|
|
|
74
|
-
The version constraint matches the CLI: the DSH bundled with the Desktop app must stay inside the declared and verified band (`>=0.
|
|
74
|
+
The version constraint matches the CLI: the DSH bundled with the Desktop app must stay inside the declared and verified band (`>=0.2.0-rc.1 <0.3.0`, see "Compatibility"). If the plugin ever breaks startup, the Desktop's native recovery dialog can **disable third-party plugins, back up `cordis.patch.yml`, and restart** in one action — it will not lock the app out.
|
|
75
75
|
|
|
76
76
|
## Configuration
|
|
77
77
|
|
|
@@ -153,7 +153,9 @@ The "OpenCode Go" section shows the live gateway catalog (the count follows the
|
|
|
153
153
|
|
|
154
154
|
## Compatibility
|
|
155
155
|
|
|
156
|
-
**Supported**: DSH `0.
|
|
156
|
+
**Supported**: DSH `0.2.0` releases (`0.2.0-rc.1` and later) and the `0.2.1` line. Every `@deepseek-ai/dsh-*` peer dependency declares `>=0.2.0-rc.1 <0.3.0`.
|
|
157
|
+
|
|
158
|
+
**`0.2.0` and earlier are no longer supported**: support for the `0.1.7` line and older was removed in v0.1.36 — the runtime seam across that range differs from the one this plugin is built against, and continuing to declare it would only let the gate admit an untested combination. (`0.1.8` and `0.1.9` were never published.)
|
|
157
159
|
|
|
158
160
|
**The mechanism (not a hard pin)**: before mounting a plugin, DSH reads its `package.json` `peerDependencies` and semver-checks each against the **running DSH version** (prereleases participate):
|
|
159
161
|
|
|
@@ -161,26 +163,26 @@ The "OpenCode Go" section shows the live gateway catalog (the count follows the
|
|
|
161
163
|
- any mismatch → **that plugin row is disabled with a printed reason** (`Plugin … is incompatible with dsh …`), leaving other plugins untouched;
|
|
162
164
|
- to take the risk anyway, grant an **exact-version exemption**: `dsh plugin --profile <profile> allow-version <pkg>@<version> --dsh-version <exact> --accept-risk` (applies only to that package and that exact runtime version); `dsh plugin --profile <profile> version-exemptions` lists what a profile holds.
|
|
163
165
|
|
|
164
|
-
The `engines.dsh` field is informational for readers and package managers; **DSH's compatibility gate reads only `peerDependencies`**. `@deepseek-ai/cordis` is declared separately as `4.0.
|
|
166
|
+
The `engines.dsh` field is informational for readers and package managers; **DSH's compatibility gate reads only `peerDependencies`**. `@deepseek-ai/cordis` is declared separately as `4.0.4 || 4.0.5-alpha.1 || 4.0.5-alpha.2` — the runtimes used by DSH `0.2.0-rc.1`/`rc.2`, `0.2.1-alpha.1`/`alpha.2`, and `0.2.1-alpha.3` and later respectively (`4.0.2`/`4.0.3` were dropped along with pre-`0.2.0` support).
|
|
165
167
|
|
|
166
|
-
**Outside the declared range**:
|
|
168
|
+
**Outside the declared range**: everything before `0.2.0-rc.1`, and `0.3.0+`, are refused. If the seam is compatible, widen the peer range in your own build (never in DSH core), or wait for a plugin release.
|
|
167
169
|
|
|
168
170
|
### Version-binding notes
|
|
169
171
|
|
|
170
172
|
| Binding layer | Declared | Enforced by |
|
|
171
173
|
| --- | --- | --- |
|
|
172
|
-
| `peerDependencies` (17 `@deepseek-ai/dsh-*` packages) | all `>=0.
|
|
173
|
-
| `@deepseek-ai/cordis` | `4.0.
|
|
174
|
-
| `engines.dsh` | `>=0.
|
|
174
|
+
| `peerDependencies` (17 `@deepseek-ai/dsh-*` packages) | all `>=0.2.0-rc.1 <0.3.0` | **DSH's gate, at plugin load time** |
|
|
175
|
+
| `@deepseek-ai/cordis` | `4.0.4 \|\| 4.0.5-alpha.1 \|\| 4.0.5-alpha.2` | the same gate |
|
|
176
|
+
| `engines.dsh` | `>=0.2.0-rc.1 <0.3.0` | informational only; DSH never reads it |
|
|
175
177
|
| `engines.node` | `^22.19.0 \|\| >=24.0.0` | the package manager |
|
|
176
|
-
| bundled `@earendil-works/pi-ai` | patch-level range `~1.0
|
|
178
|
+
| bundled `@earendil-works/pi-ai` | patch-level range `~1.3.0` (within 1.3.x) | an independent coupling: a change in pi-ai's request construction changes this plugin's wire behaviour, and its builtin catalog is this plugin's fallback data |
|
|
177
179
|
| bundled `@deepseek-ai/schemastery` | `~3.18.5-alpha.2` | kept in step with `dsh-settings`'s peer |
|
|
178
180
|
|
|
179
181
|
Things to keep in mind when maintaining this:
|
|
180
182
|
|
|
181
183
|
- **Required versus optional peers**: six of the eighteen are marked `optional` (`dsh-api-remotes`, `dsh-client-locale`, `dsh-client-store`, `dsh-client-ui-model-selection`, `dsh-client-ui-settings`, `dsh-client-ui-slots`). The twelve that actually block loading are `cordis`, `dsh-attachment`, `dsh-brand`, `dsh-client-ui-conversation`, `dsh-client-ui-renderer`, `dsh-credentials`, `dsh-fs`, `dsh-launch-environment`, `dsh-llm`, `dsh-timeout`, `dsh-typert-protocol`, and `dsh-typert-registry`. `dsh-llm` is the heaviest coupling — more than twenty imports across the source.
|
|
182
|
-
- **Declared range ≠ verified range**:
|
|
183
|
-
- **The upper bound is a tracking line**: `<0.3.0` means that the moment DSH ships `0.3.0`, this plugin must ship a new release in the same window or every user loses the plugin.
|
|
184
|
+
- **Declared range ≠ verified range**: the declaration is `>=0.2.0-rc.1 <0.3.0`. What was actually verified here, in order, is `0.2.0-rc.1` (the dev-dependency baseline: gate verdict + typecheck + full suite), `0.2.0-rc.2` (the same plus a `prepareCall` generation freeze), `0.2.1-alpha.3` (the first target release), `0.2.1-alpha.4` (T-24), and `0.2.1-alpha.5` (T-26). Other versions inside the range were not verified one by one.
|
|
185
|
+
- **The upper bound is a tracking line**: `<0.3.0` means that the moment DSH ships `0.3.0`, this plugin must ship a new release in the same window or every user loses the plugin. After changing a range, `npm test` is the verification (local mock gateway, no network, no tokens) — ranges follow what the interfaces declare, and are never "measured" with live probes.
|
|
184
186
|
- **Peer coverage is now guarded both ways**: `dsh-typert-registry`, `dsh-client-ui-conversation`, and `dsh-client-ui-renderer` were imported by the source but absent from `peerDependencies`, invisible to the gate; they are declared now, and `tests/peer-coverage.spec.ts` asserts both directions — anything the source imports must be declared, and anything declared but unreached must be removed (`dsh-settings` went that way: the settings form is actually provided by `dsh-client-ui-settings`).
|
|
185
187
|
- **Exemptions are per profile**: only a profile that ran `dsh plugin allow-version` has one, and no record means the plugin must stay inside the declared range. `dsh plugin version-exemptions` lists a profile's exemptions.
|
|
186
188
|
|
|
@@ -196,7 +198,7 @@ Things to keep in mind when maintaining this:
|
|
|
196
198
|
| "The settings write was rejected" | Usually a concurrent writer (another window or process) holding the same profile. The plugin retries once automatically; if it still fails the view has reloaded — click again. |
|
|
197
199
|
| The usage button shows "unavailable" | An endpoint or credential change invalidated the previous reading. Fix the configuration and press Retry. It never shows `0` in place of a missing reading. |
|
|
198
200
|
| npm publish fails with `ENEEDAUTH` | OIDC did not match: check the Trusted Publisher's **workflow filename** (must be exactly `publish-npm.yml`, case-sensitive) and the organization/repository fields; run on GitHub-hosted runners with `id-token: write`. A `repository.url` that does not match the GitHub repository is rejected as well. |
|
|
199
|
-
| The whole DSH process stalls during ultra-long tool calls (multi-MB arguments) | Observed on pi-ai `0.87.1`: per-delta re-parsing of the accumulated arguments (issue #9265 / PR #9461). This plugin does not port DSH's consumer-side patch (ADR-0005); the bundled dependency is now `~1.0
|
|
201
|
+
| The whole DSH process stalls during ultra-long tool calls (multi-MB arguments) | Observed on pi-ai `0.87.1`: per-delta re-parsing of the accumulated arguments (issue #9265 / PR #9461). This plugin does not port DSH's consumer-side patch (ADR-0005); the bundled dependency is now `~1.3.0`, so a recurrence would be upstream behaviour and would be fixed by an upstream release. |
|
|
200
202
|
|
|
201
203
|
## Development
|
|
202
204
|
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
## 安装
|
|
17
17
|
|
|
18
|
-
前提:DSH `0.
|
|
18
|
+
前提:DSH `0.2.0` 系列(`0.2.0-rc.1` 及之后,见「兼容性」);Node `^22.19.0 || >=24.0.0`;`dsh` 与 `pnpm` 可用。
|
|
19
19
|
|
|
20
20
|
> **路由互斥**:同一个 profile 里 `opencode-go` 只能由一个适配器提供。装本插件前请先卸载旧插件(`dsh plugin --profile <p> remove @dan-ai-studio/dsh-opencode-go`),或清空 `llm-pi-ai` 配置里名为 `opencode-go` 的 provider。否则插件会记录一条明确的占用诊断,路由不会注册(其余功能照常)。
|
|
21
21
|
|
|
@@ -71,7 +71,7 @@ DSH 桌面端是 Electron 壳 + 完整的 dsh Web 应用,本插件对它同样
|
|
|
71
71
|
|
|
72
72
|
原因:桌面端 profile 由 Electron 自己拥有,**CLI 不能启动也不能修改它**(桌面端 README 原文:*The CLI cannot boot or mutate this profile.*)。插件管理由应用内插件页经认证 HTTP API 完成,使用应用自带的 pnpm,不依赖 PATH 里的 `pnpm`;升级与卸载同样在 Plugins 页操作。
|
|
73
73
|
|
|
74
|
-
版本约束与 CLI 一致:桌面端内置的 DSH 要落在已声明并验证过的版本带内(`>=0.
|
|
74
|
+
版本约束与 CLI 一致:桌面端内置的 DSH 要落在已声明并验证过的版本带内(`>=0.2.0-rc.1 <0.3.0`,见「兼容性」)。若插件导致启动失败,桌面端的原生恢复对话框可以一键**禁用第三方插件、备份 `cordis.patch.yml` 后重启**,不会把应用锁死。
|
|
75
75
|
|
|
76
76
|
## 配置
|
|
77
77
|
|
|
@@ -153,7 +153,9 @@ API Key 通过 Harness 凭证库提供(引用名 `OPENCODE_GO_API_KEY`),
|
|
|
153
153
|
|
|
154
154
|
## 兼容性
|
|
155
155
|
|
|
156
|
-
**支持**:DSH `0.
|
|
156
|
+
**支持**:DSH `0.2.0` 系列(`0.2.0-rc.1` 及之后的正式版)与 `0.2.1` 系列。插件在每个 `@deepseek-ai/dsh-*` 的 `peerDependencies` 上声明 `>=0.2.0-rc.1 <0.3.0`。
|
|
157
|
+
|
|
158
|
+
**不再支持 `0.2.0` 之前**:`0.1.7` 系列及更早的版本自 v0.1.36 起被移除支持——那段范围内的运行时接口与本插件当前依赖的接口已经不同,继续声明只会让门禁放行一个未经验证的组合。`0.1.8`、`0.1.9` 从未发布。
|
|
157
159
|
|
|
158
160
|
**机制(不是写死)**:DSH 在挂载插件前会读取插件 `package.json` 的 `peerDependencies`,对**运行时的 DSH 版本**逐个做 semver 判定(含预发布):
|
|
159
161
|
|
|
@@ -161,26 +163,26 @@ API Key 通过 Harness 凭证库提供(引用名 `OPENCODE_GO_API_KEY`),
|
|
|
161
163
|
- 任一不满足 → **该插件行被禁用并打印原因**(`Plugin … is incompatible with dsh …`),其他插件不受影响;
|
|
162
164
|
- 需要冒险时可用**精确版本豁免**:`dsh plugin --profile <profile> allow-version <包>@<版本> --dsh-version <精确版本> --accept-risk`(只对该包与该精确版本生效);`dsh plugin --profile <profile> version-exemptions` 可列出当前 profile 的豁免。
|
|
163
165
|
|
|
164
|
-
`package.json` 里的 `engines.dsh` 是本插件为读者/包管理器写的信息字段;**DSH 的兼容门禁只读 `peerDependencies`**,请以它为准。`@deepseek-ai/cordis` 单独声明为 `4.0.
|
|
166
|
+
`package.json` 里的 `engines.dsh` 是本插件为读者/包管理器写的信息字段;**DSH 的兼容门禁只读 `peerDependencies`**,请以它为准。`@deepseek-ai/cordis` 单独声明为 `4.0.4 || 4.0.5-alpha.1 || 4.0.5-alpha.2`——三者分别是 DSH `0.2.0-rc.1`/`rc.2`、`0.2.1-alpha.1`/`alpha.2`、`0.2.1-alpha.3` 及之后所用的运行时(`4.0.2`/`4.0.3` 随 `0.2.0` 之前的支持一并移除)。
|
|
165
167
|
|
|
166
|
-
**声明范围之外**:`0.
|
|
168
|
+
**声明范围之外**:`0.2.0-rc.1` 之前的所有版本、以及 `0.3.0+` 会被拒绝加载。如果 DSH 侧接口兼容,可自行放宽该插件的 peer 范围并重新构建(不改 DSH 核心);否则请等插件跟进发版。
|
|
167
169
|
|
|
168
170
|
### 版本绑定的注意事项
|
|
169
171
|
|
|
170
172
|
| 绑定层 | 声明 | 谁在把关 |
|
|
171
173
|
| --- | --- | --- |
|
|
172
|
-
| `peerDependencies`(17 个 `@deepseek-ai/dsh-*`) | 均为 `>=0.
|
|
173
|
-
| `@deepseek-ai/cordis` | `4.0.
|
|
174
|
-
| `engines.dsh` | `>=0.
|
|
174
|
+
| `peerDependencies`(17 个 `@deepseek-ai/dsh-*`) | 均为 `>=0.2.0-rc.1 <0.3.0` | **DSH 加载时的真门禁** |
|
|
175
|
+
| `@deepseek-ai/cordis` | `4.0.4 \|\| 4.0.5-alpha.1 \|\| 4.0.5-alpha.2` | 同一门禁 |
|
|
176
|
+
| `engines.dsh` | `>=0.2.0-rc.1 <0.3.0` | 仅信息字段,DSH 不读 |
|
|
175
177
|
| `engines.node` | `^22.19.0 \|\| >=24.0.0` | 包管理器 |
|
|
176
|
-
| 自带依赖 `@earendil-works/pi-ai` | 补丁级范围 `~1.0
|
|
178
|
+
| 自带依赖 `@earendil-works/pi-ai` | 补丁级范围 `~1.3.0`(1.3.x 内) | 独立耦合:pi-ai 改请求构造即影响本插件的线上行为;其内置目录同时是本插件的打底数据 |
|
|
177
179
|
| 自带依赖 `@deepseek-ai/schemastery` | `~3.18.5-alpha.2` | 与 `dsh-settings` 的 peer 保持一致 |
|
|
178
180
|
|
|
179
181
|
维护时需要注意:
|
|
180
182
|
|
|
181
183
|
- **必选与可选之分**:18 个 peer(17 个 `dsh-*` 加框架 `cordis`)中 6 个标了 `optional`(`dsh-api-remotes`、`dsh-client-locale`、`dsh-client-store`、`dsh-client-ui-model-selection`、`dsh-client-ui-settings`、`dsh-client-ui-slots`);真正卡住加载的是 12 个——`cordis`、`dsh-attachment`、`dsh-brand`、`dsh-client-ui-conversation`、`dsh-client-ui-renderer`、`dsh-credentials`、`dsh-fs`、`dsh-launch-environment`、`dsh-llm`、`dsh-timeout`、`dsh-typert-protocol`、`dsh-typert-registry`。其中 `dsh-llm` 是最重的一处耦合(源码 import 二十余处)。
|
|
182
|
-
- **名义范围 ≠
|
|
183
|
-
- **上界就是跟版线**:`<0.3.0` 意味着 DSH 一旦发布 `0.3.0
|
|
184
|
+
- **名义范围 ≠ 实测范围**:声明范围是 `>=0.2.0-rc.1 <0.3.0`,本项目实际验证过的基线依次是 `0.2.0-rc.1`(开发依赖基线:门禁判定 + typecheck + 全量用例)、`0.2.0-rc.2`(同上 + `prepareCall` 代次冻结)、`0.2.1-alpha.3`(首个目标版本)、`0.2.1-alpha.4`(T-24)与 `0.2.1-alpha.5`(T-26)。范围内的其他版本没有逐个验证过。
|
|
185
|
+
- **上界就是跟版线**:`<0.3.0` 意味着 DSH 一旦发布 `0.3.0`,本插件必须同批发新版,否则所有用户加载失败。调整范围后用 `npm test` 验证即可(本地 mock 网关,零网络零 token)——范围以接口声明为准,不要用线上探测来"测"出一个范围。
|
|
184
186
|
- **peer 覆盖已双向守住**:`dsh-typert-registry`、`dsh-client-ui-conversation`、`dsh-client-ui-renderer` 曾被源码 import 却未声明、门禁管不到,现已补进 `peerDependencies`;`tests/peer-coverage.spec.ts` 双向断言——源码用到的必须声明,声明了却没人用的必须删(`dsh-settings` 就这样被移除:设置表单实际由 `dsh-client-ui-settings` 提供)。
|
|
185
187
|
- **豁免是按 profile 记的**:只有显式执行过 `dsh plugin allow-version` 的 profile 才享有豁免;没有记录就代表必须落在声明范围内。用 `dsh plugin version-exemptions` 可查看当前 profile 的豁免。
|
|
186
188
|
|
|
@@ -196,7 +198,7 @@ API Key 通过 Harness 凭证库提供(引用名 `OPENCODE_GO_API_KEY`),
|
|
|
196
198
|
| 设置页出现「设置写入被拒绝」 | 通常是与另一个窗口/进程并发写同一 profile;插件会自动重试一次,仍失败时界面已重载最新状态,再点一次即可。 |
|
|
197
199
|
| 用量按钮显示「不可用」 | 端点或凭证变化导致旧读数作废;配置正确后点「重试」。数值不会以 0 冒充。 |
|
|
198
200
|
| npm 发布报 `ENEEDAUTH` | OIDC 没匹配上:核对包设置里 Trusted Publisher 的 **workflow 文件名**(必须恰为 `publish-npm.yml`、大小写敏感)与组织/仓库字段;确认跑在 GitHub 托管 runner 上且工作流带 `id-token: write`。`package.json` 的 `repository.url` 与仓库不符也会被拒。 |
|
|
199
|
-
| 超长工具调用(多 MB 参数)期间整个 DSH 进程卡顿 | 曾在 pi-ai `0.87.1` 上观测到逐 delta 重解析的固有开销(issue #9265 / PR #9461)。本插件不移植 DSH 的消费者侧补丁(ADR-0005);当前自带依赖已是 `~1.0
|
|
201
|
+
| 超长工具调用(多 MB 参数)期间整个 DSH 进程卡顿 | 曾在 pi-ai `0.87.1` 上观测到逐 delta 重解析的固有开销(issue #9265 / PR #9461)。本插件不移植 DSH 的消费者侧补丁(ADR-0005);当前自带依赖已是 `~1.3.0`,若仍复现则属上游行为,随其发版解决。 |
|
|
200
202
|
|
|
201
203
|
## 开发
|
|
202
204
|
|
package/lib/client.js
CHANGED
|
@@ -562,7 +562,7 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id) + "]")
|
|
|
562
562
|
style.textContent = ".d7lz0W_root{color:var(--dsw-alias-label-primary);flex-direction:column;gap:1.25rem;display:flex}.d7lz0W_title{margin:0;font-size:1.05rem}.d7lz0W_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.8rem}.d7lz0W_warn{color:var(--dsw-alias-state-warn-primary);margin:0;font-size:.8rem}.d7lz0W_ok{color:var(--dsw-alias-state-success-primary);font-size:.8rem}.d7lz0W_block{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:.6rem;flex-direction:column;gap:.5rem;padding:.85rem;display:flex}.d7lz0W_row{flex-wrap:wrap;align-items:center;gap:.5rem;display:flex}.d7lz0W_row>strong{margin-right:auto}.d7lz0W_input{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);min-width:10rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;flex:14rem;padding:.35rem .5rem;font-size:.85rem}.d7lz0W_button{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;padding:.35rem .7rem;font-size:.8rem}.d7lz0W_button:disabled{color:var(--dsw-alias-state-idle-primary);cursor:default}.d7lz0W_number{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:5rem;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}.d7lz0W_select{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-base);width:auto;max-width:100%;color:var(--dsw-alias-label-primary);font:inherit;border-radius:.35rem;padding:.25rem .4rem;font-size:.8rem}.d7lz0W_list{flex-direction:column;display:flex}.d7lz0W_item{border-top:1px solid var(--dsw-alias-border-l1);align-items:flex-start;gap:.5rem;padding:.45rem .15rem;display:flex}.d7lz0W_item input[type=checkbox]{accent-color:var(--dsw-alias-brand-primary);margin-top:.15rem}.d7lz0W_itemBody{flex-direction:column;gap:.15rem;min-width:0;display:flex}.d7lz0W_itemMain{flex-wrap:wrap;align-items:baseline;gap:.6rem;display:flex}.d7lz0W_itemMeta{color:var(--dsw-alias-label-secondary);flex-wrap:wrap;gap:.75rem;font-size:.75rem;display:flex}.d7lz0W_itemModalities{color:var(--dsw-alias-label-secondary);font-size:.75rem}.d7lz0W_name{color:var(--dsw-alias-label-primary)}.d7lz0W_mono{color:var(--dsw-alias-label-secondary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.d7lz0W_badge{color:var(--dsw-alias-brand-primary)}";
|
|
563
563
|
document.head.appendChild(style);
|
|
564
564
|
}
|
|
565
|
-
var section_default = { "
|
|
565
|
+
var section_default = { "button": "d7lz0W_button", "itemMeta": "d7lz0W_itemMeta", "mono": "d7lz0W_mono", "select": "d7lz0W_select", "hint": "d7lz0W_hint", "itemMain": "d7lz0W_itemMain", "ok": "d7lz0W_ok", "number": "d7lz0W_number", "title": "d7lz0W_title", "name": "d7lz0W_name", "warn": "d7lz0W_warn", "itemBody": "d7lz0W_itemBody", "item": "d7lz0W_item", "itemModalities": "d7lz0W_itemModalities", "block": "d7lz0W_block", "root": "d7lz0W_root", "badge": "d7lz0W_badge", "input": "d7lz0W_input", "row": "d7lz0W_row", "list": "d7lz0W_list" };
|
|
566
566
|
|
|
567
567
|
// src/client/Section.tsx
|
|
568
568
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -1335,7 +1335,7 @@ if (!document.querySelector("style[data-plugin-css=" + JSON.stringify(id2) + "]"
|
|
|
1335
1335
|
style.textContent = ".mMNkkW_root{align-items:center;display:inline-flex;position:relative}.mMNkkW_trigger{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;white-space:nowrap;border-radius:999px;padding:.35rem .6rem;font-size:.8rem;line-height:1}.mMNkkW_trigger:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.mMNkkW_panel{z-index:20;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-overlay);width:18rem;color:var(--dsw-alias-label-primary);border-radius:.6rem;flex-direction:column;gap:.6rem;padding:.75rem .85rem;display:flex;position:absolute;bottom:calc(100% + .5rem);right:0;box-shadow:0 8px 24px #0000002e}.mMNkkW_window{flex-direction:column;gap:.25rem;display:flex}.mMNkkW_row{justify-content:space-between;gap:.5rem;font-size:.85rem;display:flex}.mMNkkW_hint{color:var(--dsw-alias-label-secondary);margin:0;font-size:.75rem}.mMNkkW_progress{width:100%;height:.35rem;accent-color:var(--dsw-alias-brand-primary)}.mMNkkW_limited{color:var(--dsw-alias-state-warn-primary);font-size:.75rem}.mMNkkW_warning{border:1px solid var(--dsw-alias-state-warn-primary);color:var(--dsw-alias-label-primary);border-radius:.4rem;padding:.4rem .5rem;font-size:.75rem}.mMNkkW_retry{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;border-radius:.35rem;align-self:flex-start;padding:.25rem .5rem;font-size:.75rem}.mMNkkW_local{border-top:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:.2rem;padding-top:.5rem;display:flex}";
|
|
1336
1336
|
document.head.appendChild(style);
|
|
1337
1337
|
}
|
|
1338
|
-
var pill_default = { "root": "mMNkkW_root", "
|
|
1338
|
+
var pill_default = { "progress": "mMNkkW_progress", "root": "mMNkkW_root", "hint": "mMNkkW_hint", "trigger": "mMNkkW_trigger", "panel": "mMNkkW_panel", "window": "mMNkkW_window", "local": "mMNkkW_local", "retry": "mMNkkW_retry", "warning": "mMNkkW_warning", "limited": "mMNkkW_limited", "row": "mMNkkW_row" };
|
|
1339
1339
|
|
|
1340
1340
|
// src/client/UsagePill.tsx
|
|
1341
1341
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
package/lib/index.js
CHANGED
|
@@ -421,7 +421,13 @@ function readOnlineMetadata(body, sources) {
|
|
|
421
421
|
throw new Error(`configured protocol "${sources.overrides[id]}" is not one of anthropic-messages, openai-completions, openai-responses`);
|
|
422
422
|
}
|
|
423
423
|
const decision = decideProtocol(id, {
|
|
424
|
-
|
|
424
|
+
// Guarded, not asserted: pi-ai's builtin catalog is wider than this
|
|
425
|
+
// plugin's three protocols — 1.3.0 labels `gemini-4-argon-contributor`
|
|
426
|
+
// as `google-generative-ai`. Casting it straight to `WireProtocol`
|
|
427
|
+
// let an unimplementable protocol enter as `builtin`, the most
|
|
428
|
+
// trustworthy source, and the model then failed only once a stream
|
|
429
|
+
// was attempted.
|
|
430
|
+
...asWireProtocol(exact?.api) === void 0 ? {} : { builtin: asWireProtocol(exact?.api) },
|
|
425
431
|
...protocolOfNpm(metadata["provider"] === void 0 ? providerNpm : record(metadata["provider"])["npm"] ?? providerNpm) === void 0 ? {} : { online: protocolOfNpm(record(metadata["provider"])["npm"] ?? providerNpm) },
|
|
426
432
|
...override === void 0 ? {} : { override }
|
|
427
433
|
});
|
|
@@ -511,6 +517,9 @@ function harnessApiKeyAuth() {
|
|
|
511
517
|
}
|
|
512
518
|
};
|
|
513
519
|
}
|
|
520
|
+
function unsupportedBuiltinApi(api) {
|
|
521
|
+
return api === void 0 || asWireProtocol(api) !== void 0 ? void 0 : api;
|
|
522
|
+
}
|
|
514
523
|
function buildProvider(baseURL, models) {
|
|
515
524
|
return createProvider({
|
|
516
525
|
id: PROVIDER_ID,
|
|
@@ -638,6 +647,11 @@ var OpencodeGoCatalog = class {
|
|
|
638
647
|
unavailable.set(id, reason);
|
|
639
648
|
continue;
|
|
640
649
|
}
|
|
650
|
+
const unsupported = unsupportedBuiltinApi(builtin.get(id)?.api);
|
|
651
|
+
if (unsupported !== void 0) {
|
|
652
|
+
unavailable.set(id, `its wire protocol "${unsupported}" is not implemented by this plugin`);
|
|
653
|
+
continue;
|
|
654
|
+
}
|
|
641
655
|
facts.set(id, this.withDocumentedProtocol(this.inferredFacts(id, builtin)));
|
|
642
656
|
}
|
|
643
657
|
if (unavailable.size > 0) {
|
|
@@ -675,14 +689,15 @@ var OpencodeGoCatalog = class {
|
|
|
675
689
|
/** Facts for an id no source describes, from the ladder and the route defaults. */
|
|
676
690
|
inferredFacts(id, builtin) {
|
|
677
691
|
const exact = builtin.get(id);
|
|
678
|
-
const
|
|
692
|
+
const builtinApi = asWireProtocol(exact?.api);
|
|
693
|
+
const api = builtinApi ?? inferFamily(id);
|
|
679
694
|
const contextWindow = exact !== void 0 ? exact.contextWindow : this.options.defaults.contextWindow;
|
|
680
695
|
const maxTokens = exact !== void 0 ? exact.maxTokens : this.options.defaults.maxTokens;
|
|
681
696
|
return {
|
|
682
697
|
id,
|
|
683
698
|
name: exact?.name ?? id,
|
|
684
699
|
api,
|
|
685
|
-
protocolSource:
|
|
700
|
+
protocolSource: builtinApi === void 0 ? "inferred" : "builtin",
|
|
686
701
|
contextWindow,
|
|
687
702
|
maxInputTokens: void 0,
|
|
688
703
|
maxTokens,
|
|
@@ -2083,7 +2098,7 @@ function createUpdateChecker(deps) {
|
|
|
2083
2098
|
}
|
|
2084
2099
|
|
|
2085
2100
|
// src/update/version.ts
|
|
2086
|
-
var PLUGIN_VERSION = true ? "0.1.
|
|
2101
|
+
var PLUGIN_VERSION = true ? "0.1.36" : "0.0.0-dev";
|
|
2087
2102
|
|
|
2088
2103
|
// src/update/service.ts
|
|
2089
2104
|
import { TypertRemoteService as TypertRemoteService2 } from "@deepseek-ai/dsh-typert-protocol";
|
|
@@ -29,6 +29,7 @@ import { fetchModelIds } from "./gateway.js";
|
|
|
29
29
|
import { fetchGoDocument, GO_DOC_URLS } from "./go-doc.js";
|
|
30
30
|
import { readBoundedJson } from "./json-response.js";
|
|
31
31
|
import { readOnlineMetadata, toPiModel } from "./metadata.js";
|
|
32
|
+
import { asWireProtocol } from "./protocol.js";
|
|
32
33
|
export { PROVIDER_ID, DISPLAY_NAME, DEFAULT_BASE_URL, CONSOLE_BASE_URL } from "./constants.js";
|
|
33
34
|
export { readModelIds, fetchModelIds } from "./gateway.js";
|
|
34
35
|
export { readOnlineMetadata, toPiModel, modelBaseURL } from "./metadata.js";
|
|
@@ -59,6 +60,18 @@ function harnessApiKeyAuth() {
|
|
|
59
60
|
},
|
|
60
61
|
};
|
|
61
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* The installed catalog's protocol, when this plugin cannot serve it.
|
|
65
|
+
*
|
|
66
|
+
* `Model<Api>['api']` is pi-ai's wider union; this plugin mounts exactly the
|
|
67
|
+
* three in `WIRE_PROTOCOLS`. The check exists because the catalog is wider
|
|
68
|
+
* than the plugin and grows on its own release cadence.
|
|
69
|
+
* @param api - the raw `api` string the installed catalog states.
|
|
70
|
+
* @returns the unusable protocol, or undefined when there is nothing to refuse.
|
|
71
|
+
*/
|
|
72
|
+
function unsupportedBuiltinApi(api) {
|
|
73
|
+
return api === undefined || asWireProtocol(api) !== undefined ? undefined : api;
|
|
74
|
+
}
|
|
62
75
|
function buildProvider(baseURL, models) {
|
|
63
76
|
return createProvider({
|
|
64
77
|
id: PROVIDER_ID,
|
|
@@ -205,6 +218,18 @@ export class OpencodeGoCatalog {
|
|
|
205
218
|
unavailable.set(id, reason);
|
|
206
219
|
continue;
|
|
207
220
|
}
|
|
221
|
+
// The installed catalog may name a protocol this plugin cannot mount.
|
|
222
|
+
// pi-ai 1.3.0 labels `gemini-4-argon-contributor` as
|
|
223
|
+
// `google-generative-ai`, which `buildProvider` has no entry for, and
|
|
224
|
+
// the string used to reach the model list through an unchecked cast.
|
|
225
|
+
// Listing it as usable would defer the failure to the first stream —
|
|
226
|
+
// the one outcome this plugin refuses to ship — so it is refused here,
|
|
227
|
+
// exactly like a malformed record.
|
|
228
|
+
const unsupported = unsupportedBuiltinApi(builtin.get(id)?.api);
|
|
229
|
+
if (unsupported !== undefined) {
|
|
230
|
+
unavailable.set(id, `its wire protocol "${unsupported}" is not implemented by this plugin`);
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
208
233
|
// No source describes this id. The gateway's own provider default
|
|
209
234
|
// (`@ai-sdk/openai-compatible`) makes Chat Completions the best available
|
|
210
235
|
// guess, and the route defaults size it; the settings surface marks it as
|
|
@@ -245,14 +270,17 @@ export class OpencodeGoCatalog {
|
|
|
245
270
|
/** Facts for an id no source describes, from the ladder and the route defaults. */
|
|
246
271
|
inferredFacts(id, builtin) {
|
|
247
272
|
const exact = builtin.get(id);
|
|
248
|
-
|
|
273
|
+
// Guarded for the same reason `assemble` refuses these ids up front: the
|
|
274
|
+
// installed catalog states protocols this plugin cannot mount.
|
|
275
|
+
const builtinApi = asWireProtocol(exact?.api);
|
|
276
|
+
const api = builtinApi ?? inferFamily(id);
|
|
249
277
|
const contextWindow = exact !== undefined ? exact.contextWindow : this.options.defaults.contextWindow;
|
|
250
278
|
const maxTokens = exact !== undefined ? exact.maxTokens : this.options.defaults.maxTokens;
|
|
251
279
|
return {
|
|
252
280
|
id,
|
|
253
281
|
name: exact?.name ?? id,
|
|
254
282
|
api,
|
|
255
|
-
protocolSource:
|
|
283
|
+
protocolSource: builtinApi === undefined ? 'inferred' : 'builtin',
|
|
256
284
|
contextWindow,
|
|
257
285
|
maxInputTokens: undefined,
|
|
258
286
|
maxTokens,
|
|
@@ -188,7 +188,13 @@ export function readOnlineMetadata(body, sources) {
|
|
|
188
188
|
throw new Error(`configured protocol "${sources.overrides[id]}" is not one of anthropic-messages, openai-completions, openai-responses`);
|
|
189
189
|
}
|
|
190
190
|
const decision = decideProtocol(id, {
|
|
191
|
-
|
|
191
|
+
// Guarded, not asserted: pi-ai's builtin catalog is wider than this
|
|
192
|
+
// plugin's three protocols — 1.3.0 labels `gemini-4-argon-contributor`
|
|
193
|
+
// as `google-generative-ai`. Casting it straight to `WireProtocol`
|
|
194
|
+
// let an unimplementable protocol enter as `builtin`, the most
|
|
195
|
+
// trustworthy source, and the model then failed only once a stream
|
|
196
|
+
// was attempted.
|
|
197
|
+
...asWireProtocol(exact?.api) === undefined ? {} : { builtin: asWireProtocol(exact?.api) },
|
|
192
198
|
...protocolOfNpm(metadata['provider'] === undefined ? providerNpm : record(metadata['provider'])['npm'] ?? providerNpm) === undefined
|
|
193
199
|
? {}
|
|
194
200
|
: { online: protocolOfNpm(record(metadata['provider'])['npm'] ?? providerNpm) },
|
package/lib/types/config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Configuration for one `dshopencodego` mount.
|
|
3
3
|
*
|
|
4
|
-
* DSH
|
|
4
|
+
* DSH hands the plugin *live references* for every declared field, so a
|
|
5
5
|
* profile edit reaches the next operation without a restart. This plugin
|
|
6
6
|
* targets that generation only: there is no settings-document path, no
|
|
7
7
|
* `installSection` fallback, and no plain-value codec.
|
|
@@ -84,7 +84,7 @@ export interface OpencodeGoConfig {
|
|
|
84
84
|
* overrides, and the schema's own defaults fill the rest.
|
|
85
85
|
*/
|
|
86
86
|
export declare const PlainConfig: z<Partial<OpencodeGoConfig>, OpencodeGoConfig>;
|
|
87
|
-
/**
|
|
87
|
+
/** The loader retains these references when profile fields change. */
|
|
88
88
|
export type LiveConfig = {
|
|
89
89
|
[K in keyof OpencodeGoConfig]-?: {
|
|
90
90
|
get(): OpencodeGoConfig[K];
|
package/lib/types/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Configuration for one `dshopencodego` mount.
|
|
3
3
|
*
|
|
4
|
-
* DSH
|
|
4
|
+
* DSH hands the plugin *live references* for every declared field, so a
|
|
5
5
|
* profile edit reaches the next operation without a restart. This plugin
|
|
6
6
|
* targets that generation only: there is no settings-document path, no
|
|
7
7
|
* `installSection` fallback, and no plain-value codec.
|
|
@@ -30,7 +30,7 @@ import { toPiAssistant } from "./replay.js";
|
|
|
30
30
|
function flattenText(message) {
|
|
31
31
|
return message.content.filter(block => block.type === 'text').map(block => block.text).join('');
|
|
32
32
|
}
|
|
33
|
-
/** DSH
|
|
33
|
+
/** DSH carries tool results under their own role. */
|
|
34
34
|
function toolMessage(message) {
|
|
35
35
|
return message.role === 'tool' ? message : undefined;
|
|
36
36
|
}
|
|
@@ -28,9 +28,9 @@ export function mapUsage(usage) {
|
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* The account-quota failure class, written out rather than imported:
|
|
31
|
-
* `dsh-llm` exports it as `ACCOUNT_QUOTA_EXCEEDED_CODE
|
|
32
|
-
* the
|
|
33
|
-
*
|
|
31
|
+
* `dsh-llm` exports it as `ACCOUNT_QUOTA_EXCEEDED_CODE`, and the spelling is
|
|
32
|
+
* the stable protocol value the host routes on, so spelling it here keeps the
|
|
33
|
+
* route correct on every host this plugin supports.
|
|
34
34
|
*/
|
|
35
35
|
const ACCOUNT_QUOTA_CODE = 'ACCOUNT_QUOTA';
|
|
36
36
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dan-ai-studio/dshopencodego",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.36",
|
|
4
4
|
"description": "OpenCode Go provider for DeepSeek Harness: live gateway catalog, per-conversation session header, usage",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"engines": {
|
|
17
17
|
"node": "^22.19.0 || >=24.0.0",
|
|
18
|
-
"dsh": ">=0.
|
|
18
|
+
"dsh": ">=0.2.0-rc.1 <0.3.0"
|
|
19
19
|
},
|
|
20
20
|
"main": "./lib/index.js",
|
|
21
21
|
"types": "./lib/types/index.d.ts",
|
|
@@ -68,27 +68,27 @@
|
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"@deepseek-ai/schemastery": "~3.18.5-alpha.2",
|
|
71
|
-
"@earendil-works/pi-ai": "~1.0
|
|
71
|
+
"@earendil-works/pi-ai": "~1.3.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"@deepseek-ai/cordis": "4.0.
|
|
75
|
-
"@deepseek-ai/dsh-api-remotes": ">=0.
|
|
76
|
-
"@deepseek-ai/dsh-attachment": ">=0.
|
|
77
|
-
"@deepseek-ai/dsh-brand": ">=0.
|
|
78
|
-
"@deepseek-ai/dsh-client-locale": ">=0.
|
|
79
|
-
"@deepseek-ai/dsh-client-store": ">=0.
|
|
80
|
-
"@deepseek-ai/dsh-client-ui-conversation": ">=0.
|
|
81
|
-
"@deepseek-ai/dsh-client-ui-model-selection": ">=0.
|
|
82
|
-
"@deepseek-ai/dsh-client-ui-renderer": ">=0.
|
|
83
|
-
"@deepseek-ai/dsh-client-ui-settings": ">=0.
|
|
84
|
-
"@deepseek-ai/dsh-client-ui-slots": ">=0.
|
|
85
|
-
"@deepseek-ai/dsh-credentials": ">=0.
|
|
86
|
-
"@deepseek-ai/dsh-fs": ">=0.
|
|
87
|
-
"@deepseek-ai/dsh-launch-environment": ">=0.
|
|
88
|
-
"@deepseek-ai/dsh-llm": ">=0.
|
|
89
|
-
"@deepseek-ai/dsh-timeout": ">=0.
|
|
90
|
-
"@deepseek-ai/dsh-typert-protocol": ">=0.
|
|
91
|
-
"@deepseek-ai/dsh-typert-registry": ">=0.
|
|
74
|
+
"@deepseek-ai/cordis": "4.0.4 || 4.0.5-alpha.1 || 4.0.5-alpha.2",
|
|
75
|
+
"@deepseek-ai/dsh-api-remotes": ">=0.2.0-rc.1 <0.3.0",
|
|
76
|
+
"@deepseek-ai/dsh-attachment": ">=0.2.0-rc.1 <0.3.0",
|
|
77
|
+
"@deepseek-ai/dsh-brand": ">=0.2.0-rc.1 <0.3.0",
|
|
78
|
+
"@deepseek-ai/dsh-client-locale": ">=0.2.0-rc.1 <0.3.0",
|
|
79
|
+
"@deepseek-ai/dsh-client-store": ">=0.2.0-rc.1 <0.3.0",
|
|
80
|
+
"@deepseek-ai/dsh-client-ui-conversation": ">=0.2.0-rc.1 <0.3.0",
|
|
81
|
+
"@deepseek-ai/dsh-client-ui-model-selection": ">=0.2.0-rc.1 <0.3.0",
|
|
82
|
+
"@deepseek-ai/dsh-client-ui-renderer": ">=0.2.0-rc.1 <0.3.0",
|
|
83
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.2.0-rc.1 <0.3.0",
|
|
84
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.2.0-rc.1 <0.3.0",
|
|
85
|
+
"@deepseek-ai/dsh-credentials": ">=0.2.0-rc.1 <0.3.0",
|
|
86
|
+
"@deepseek-ai/dsh-fs": ">=0.2.0-rc.1 <0.3.0",
|
|
87
|
+
"@deepseek-ai/dsh-launch-environment": ">=0.2.0-rc.1 <0.3.0",
|
|
88
|
+
"@deepseek-ai/dsh-llm": ">=0.2.0-rc.1 <0.3.0",
|
|
89
|
+
"@deepseek-ai/dsh-timeout": ">=0.2.0-rc.1 <0.3.0",
|
|
90
|
+
"@deepseek-ai/dsh-typert-protocol": ">=0.2.0-rc.1 <0.3.0",
|
|
91
|
+
"@deepseek-ai/dsh-typert-registry": ">=0.2.0-rc.1 <0.3.0"
|
|
92
92
|
},
|
|
93
93
|
"peerDependenciesMeta": {
|
|
94
94
|
"@deepseek-ai/dsh-api-remotes": {
|