dsh-packycode-api 1.1.6 → 1.1.8

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.1.8
4
+
5
+ - **Diagnosed an installation that mounts nothing, and made it reportable.** A profile that once had this plugin installed from a local path keeps a `node_modules` inside the installed package directory; a later registry install rewrites the package's files and leaves that tree in place. DSH resolves a plugin's imports from inside the profile first, so the plugin kept loading the old copies — `@deepseek-ai/schemastery` 3.18.2 has no `Schema.volatile()`, the module threw while it was imported, and the Loader created no fiber for the row. `@deepseek-ai/dsh-client-modules` skips a fiber-less entry, so the browser bundle was never composed and the only symptom was a settings page with no PackyCode section, no model route, no RPC channel, and a clean host log. The diagnosis was confirmed on the affected desktop profile: the composed entry `{"id":"packycode-api","name":"dsh-packycode-api"}` is present, the 67-row boot graph carries no bundle for it, `POST /packycode-api/status` is unregistered, and importing the installed package from a copy reproduces `TypeError: schema.volatile is not a function`.
6
+ - **A missing `Schema.volatile()` now names its cause.** `live()` throws an actionable error naming the peer requirement, the shadowing package directory left by an earlier local install, and the recovery, instead of a bare `schema.volatile is not a function` that the host log buries.
7
+ - Added `scripts/install-check.mjs`: read-only, no network. It resolves every installed profile dependency the way DSH does, reports any host package (`@deepseek-ai/*`, `@earendil-works/*`) shadowed by a `node_modules` inside an installed package, names the `schemastery` release that breaks a row, flags an installed-but-unselected bundle and a web-search patch left pointing at a removed backend, prints the recovery steps, and exits 1 when it finds an error. `--profile`, `--home`, and `--json` are supported. A `link:` install, which resolves outside the profile where DSH intercepts peers, is deliberately not reported.
8
+ - Installation guidance: the local-checkout instructions now require the `link:` prefix and say why a bare path or `file:` copy is damaging, the update section says a `pnpm add` update cannot remove that leftover tree and that uninstall (`pnpm remove`) must come first, and the FAQ documents the symptom, the one-line check, and the recovery.
9
+ - Validation: 295 tests passed, both bundles rebuilt and the tarball generated. The new checks were exercised against a fixture profile (clean, shadowed below and at the volatile release, `link:`, unselected bundle, dangling search patch, non-host nested tree, missing manifest) and against the affected desktop profile, where the script reports the shadowed tree and exits 1.
10
+
11
+ ## 1.1.7
12
+
13
+ - Fixed HTTP 405 from the settings RPC after a first hot install. The shipped Connection getter retains its own row's context, which need not inject `webServer`; the browser channel now registers with this plugin's `connection` / `webServer` injection scope as its explicit owner. Native Connection admission, authentication and RPC envelopes remain in use. The explicit-owner entry is internal to the shipped service, so other Connection implementations retain the public `rpc.handle` contract.
14
+ - Removed the bundle override of the protected `connection` row. First installation now mounts the plugin's own channel without rebuilding that row or restarting DSH; unloading or losing the optional webserver scope removes the channel. Installation instructions now describe the restart-free first install.
15
+ - Added real Connection / Cordis HTTP regressions for the 0.1.5 and 0.2.0-rc.2 hosts, covering first install, authenticated settings access, uninstall/reinstall and optional webserver availability. The 0.2 test host uses a separate development fixture with matching host dependencies.
16
+ - Validation: 284 tests passed, both bundles rebuilt and the tarball generated. The six HTTP lifecycle/authentication checks also passed against the built host bundle, without restarting the fixture's existing server or Connection service.
17
+
3
18
  ## 1.1.6
4
19
 
5
20
  - Fixed the missing `image` input capability on `deepseek-flash`, following [DeepSeek's official vision guide](https://api-docs.deepseek.com/guides/vision/). DSH can now send image attachments through the existing Chat Completions route. Audited the two GPT models, Grok 4.7 and three Claude models against their vendor documentation; all six already declare image input.
package/README.en.md CHANGED
@@ -45,9 +45,9 @@ Open the desktop application's **Plugins** page, click **Add plugin**, and enter
45
45
  dsh-packycode-api
46
46
  ```
47
47
 
48
- Choose the **official** install source, then click **Install**. To pin a version, enter `dsh-packycode-api@1.1.6`.
48
+ Choose the **official** install source, then click **Install**. To pin a version, enter `dsh-packycode-api@1.1.8`.
49
49
 
50
- Then **manually restart the desktop application**. Refreshing the page does not reload the plugin inside the Host process.
50
+ A **first install requires no DSH restart**: open **Settings → PackyCode** and add a key immediately. When updating an already loaded older version, follow the restart guidance in the **Plugin version** card.
51
51
 
52
52
  ### 2. Add a key
53
53
 
@@ -64,9 +64,9 @@ Choose a model from the `PackyCode` group. `deepseek-flash`, `gpt-6.1-sol`, `gpt
64
64
 
65
65
  The **Plugins** page shows the installed state and version, and is also where you enable, disable, or uninstall.
66
66
 
67
- **For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.1.6`. Do not use it for `desktop` — the CLI refuses it (`profile "desktop" is managed exclusively by the Electron application`).
67
+ **For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.1.8`. Do not use it for `desktop` — the CLI refuses it (`profile "desktop" is managed exclusively by the Electron application`).
68
68
 
69
- A local checkout can be linked with `dsh plugin --profile <name> add link:/path/to/dsh-packycode-api`.
69
+ For a local checkout, keep the `link:` prefix: `dsh plugin --profile <name> add link:/path/to/dsh-packycode-api`. **Do not pass a bare path or `file:`** — that install copies the whole checkout, `node_modules` included, into the profile, where it then shadows the packages the DSH installation itself provides and the plugin looks uninstalled; see the FAQ. If you already installed that way, uninstall first and reinstall as above.
70
70
 
71
71
  A profile without a browser can still use the model route. It just has no settings panel and no composer balance.
72
72
 
@@ -179,10 +179,22 @@ Only GPT Responses requests keep `prompt_cache_key`; other Responses models omit
179
179
 
180
180
  **Update:** open **Settings → PackyCode** and, when a newer version is listed, click **Update plugin**. It installs that exact version into the owning profile with DSH's bundled pnpm and reads `package.json` back before reporting success. A local `link:` checkout does not get the button. Then quit and reopen the desktop application. A page refresh does not reload the Host. Reinstalling `dsh-packycode-api` from the **Plugins** page does the same job.
181
181
 
182
+ **Coming back from a local-path install, uninstall first.** An update is a `pnpm add`: it rewrites the files inside the package directory and leaves a `node_modules` that an earlier local-path install left there. That older tree keeps shadowing the packages the DSH installation provides, so the plugin row fails to load with no visible reason. **Uninstall** runs `pnpm remove`, which deletes the package directory outright — only a reinstall after that is clean. `node scripts/install-check.mjs` reports whether a profile is in that state.
183
+
182
184
  **Uninstall:** if you used PackyCode web search, first switch **Settings → PackyCode → Web search** back to the default. Then remove this plugin on the **Plugins** page and restart the desktop application. Otherwise `cordis.patch.yml` keeps a web entry naming a provider that no longer exists, and `web_search` fails with `configured web provider "packycode-api-auto" is not registered`; delete the block marked `dsh-packycode-api: web search provider` by hand to recover. Uninstalling does not remove other plugins, the profile, or the token in the PackyCode console.
183
185
 
184
186
  ## FAQ
185
187
 
188
+ **Installed, but Settings shows no PackyCode at all?** The plugin row failed to load at startup, and DSH only records that in the host log — the settings page shows no reason. Check with `node scripts/install-check.mjs` from this repository (read-only, no network); by hand, look for this directory:
189
+
190
+ ```sh
191
+ ls ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/node_modules
192
+ ```
193
+
194
+ Output means a leftover tree: a registry install ships no `node_modules`, so this one usually comes from an earlier local-path install (`file:`, or a bare path instead of `link:`). It sits inside the profile directory, and DSH resolves a plugin's imports from inside the profile first, so the plugin gets those old copies — for example `@deepseek-ai/schemastery` 3.18.2, which has no `Schema.volatile()`, so the module throws while it is imported. When an import fails the Loader creates no fiber for that row and no client bundle is composed either, so the model route, the RPC channel, and the settings panel all stay absent.
195
+
196
+ Recovery: **uninstall** the plugin on the **Plugins** page, **install** `dsh-packycode-api` again, then quit and reopen the desktop application. Uninstall runs `pnpm remove` and deletes the whole package directory; reinstalling or clicking **Update** only rewrites files and keeps the leftover tree. Deleting that `node_modules` by hand and restarting works too.
197
+
186
198
  **Web search says "no stored API key's group covers …"?** The search backend's model is not in your token groups (or the gateway currently routes it to another supplier). Pick the other backend under **Settings → PackyCode → Web search**, or add a key whose group covers it.
187
199
 
188
200
  **One model fails, but the key is valid?** Look at that key's groups and ✓ / ✕ under **Accounts and keys**. When its groups do not cover the model, use a key whose groups do, or add the group to the key in the PackyCode console. With such a key stored, the plugin runs that model on it automatically. A group refusal never disables a key.
@@ -226,6 +238,8 @@ pnpm run check
226
238
 
227
239
  `node scripts/cli-plan-check.mjs` checks plan mode with the real CLI and a local fake gateway: stdio handoff, concurrent plan ownership, invocation-only file fallback, stale-plan exclusion, actual denial limits and cleanup. It reads no real credentials, spends no quota and starts no DSH instance.
228
240
 
241
+ `node scripts/install-check.mjs` diagnoses an installed plugin that never appears: it reads one profile, lists any host package shadowed by a leftover `node_modules` inside an installed package (with versions) plus the recovery steps, and exits 1 when it finds one. `--profile <name>`, `--home <dir>`, and `--json` are available.
242
+
229
243
  Read [AGENTS.md](AGENTS.md) before agent-assisted changes or a release. Publishing is the [Publish workflow](.github/workflows/publish.yml), triggered by pushing a `v*` tag. Do not run `npm publish` locally.
230
244
 
231
245
  ## License
package/README.md CHANGED
@@ -49,9 +49,9 @@
49
49
  dsh-packycode-api
50
50
  ```
51
51
 
52
- 在**安装源**中选择**官方源**,然后点击**安装**。需要固定版本时填入 `dsh-packycode-api@1.1.6`。
52
+ 在**安装源**中选择**官方源**,然后点击**安装**。需要固定版本时填入 `dsh-packycode-api@1.1.8`。
53
53
 
54
- 完成后**手动重启桌面应用**。仅刷新页面不会重新加载 Host 里的插件。
54
+ 首次安装后**无需重启 DSH**,可直接打开**设置 → PackyCode** 添加 Key。更新已加载的旧版时,按「插件版本」卡片的重启提示操作。
55
55
 
56
56
  ### 2. 添加 Key
57
57
 
@@ -68,9 +68,9 @@ dsh-packycode-api
68
68
 
69
69
  桌面应用的**插件**页可以看到已安装状态与版本,也可以在那里启用、停用或卸载。
70
70
 
71
- **仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.1.6`。不要对 `desktop` 使用它 —— CLI 会直接拒绝(`profile "desktop" is managed exclusively by the Electron application`)。
71
+ **仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.1.8`。不要对 `desktop` 使用它 —— CLI 会直接拒绝(`profile "desktop" is managed exclusively by the Electron application`)。
72
72
 
73
- 本地开发可以用绝对路径:`dsh plugin --profile <name> add link:/path/to/dsh-packycode-api`。
73
+ 本地开发要加 `link:` 前缀:`dsh plugin --profile <name> add link:/path/to/dsh-packycode-api`。**不要直接写路径(或 `file:`)** —— 那样的安装会把整个仓库目录(连同 `node_modules`)复制进 profile,之后它会在 profile 内部挡住 DSH 自带的包,插件看起来像没装,见「常见问题」。已经那样装过的话,先卸载再按上面的方式重装。
74
74
 
75
75
  没有浏览器的 profile 也能走模型路由,只是看不到设置页和输入框额度。
76
76
 
@@ -183,10 +183,22 @@ Responses 请求只有 GPT 模型保留 `prompt_cache_key`,其他 Responses
183
183
 
184
184
  **更新:** 打开 **设置 → PackyCode**,有新版本时点「更新插件」。它会在当前 profile 目录里用 DSH 自带的 pnpm 安装精确版本,并读回 `package.json` 确认版本落地。本地 `link:` 开发安装不会出现这个按钮。完成后完全退出并重新打开桌面应用。只刷新页面不会重载 Host。也可以在**插件**页重新安装 `dsh-packycode-api`。
185
185
 
186
+ **从本地路径安装切回官方源时,必须先卸载。** 「更新」是 `pnpm add`,它只重写包目录里的文件,不会删除更早一次本地路径安装留在包目录内的 `node_modules`;那份旧依赖会继续挡住 DSH 自带的包,插件行加载失败且看不出原因。「卸载」执行的是 `pnpm remove`,会删掉整个包目录,重装才是干净的。用 `node scripts/install-check.mjs` 可以确认当前 profile 是否处于这个状态。
187
+
186
188
  **卸载:** 用过 PackyCode 网页搜索的话,先在 **设置 → PackyCode → 网页搜索** 切回「不接管」,再到**插件**页卸载本插件,然后重启桌面应用。否则 `cordis.patch.yml` 里会留下指向已卸载后端的 web 配置,`web_search` 会报 `configured web provider "packycode-api-auto" is not registered`;这时手动删掉带 `dsh-packycode-api: web search provider` 标记的那一段即可。卸载不会删除其它插件、整个 profile,也不会撤销 PackyCode 控制台里的令牌。
187
189
 
188
190
  ## 常见问题
189
191
 
192
+ **装好了,但设置里完全没有 PackyCode 这一项?** 说明插件行在启动时加载失败了 —— DSH 只在宿主日志里记录这件事,设置页不会显示原因。先用仓库里的 `node scripts/install-check.mjs` 查一次(只读,不发网络请求);手动检查则是看这个目录是否存在:
193
+
194
+ ```sh
195
+ ls ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/node_modules
196
+ ```
197
+
198
+ 有输出就是残留:从 npm 安装的包不会自带 `node_modules`,这一份通常来自更早一次「本地路径」安装(`file:` 或直接写路径,而不是 `link:`)。它位于 profile 目录内部,而 DSH 解析插件导入时优先使用 profile 内的副本,所以插件拿到的仍是那份旧依赖 —— 例如 `@deepseek-ai/schemastery` 3.18.2 没有 `Schema.volatile()`,模块在导入阶段就抛错。导入失败时 Loader 不会为这一行创建 fiber,客户端 bundle 也不会被组合,于是模型路由、RPC 通道和设置页全都不会出现。
199
+
200
+ 修复:到**插件**页**卸载**本插件,再重新**安装** `dsh-packycode-api`,然后完全退出并重新打开桌面应用。卸载执行的是 `pnpm remove`,会删掉整个包目录;直接重装或点「更新」只重写文件,不会清掉这份残留。也可以手动删掉上面那个 `node_modules` 再重启。
201
+
190
202
  **某个模型不可用,但 Key 是有效的?** 看「账户与 Key」里这个 Key 的分组和 ✓ / ✕:分组不覆盖这个模型时,换一个分组合适的 Key,或在 PackyCode 控制台给 Key 加上对应分组。存了分组合适的 Key 时,插件会自动用它跑这个模型。分组拒绝不会停用 Key。
191
203
 
192
204
  **Claude 报「PackyCode 的上游拒绝了这次 Claude Code CLI 请求」或「只接受官方 Claude Code CLI」?** 最常见的原因是这一轮用的 Key 没有 Claude 分组:PackyCode 对这种 Key 也会回这句话(或 400 `当前令牌未覆盖供应商`)。现在报错会直接写明「本轮使用的 Key「…」所在分组(…)不包含能用 claude-… 的分组」,并说明不需要更新 CLI。只有 Key 确实有 Claude 分组时仍被拒,才需要按报错里的提示检查 CLI 版本或联系 PackyCode。
@@ -230,6 +242,8 @@ Claude CLI 的 MCP 接口验证用 `node scripts/cli-search-check.mjs`:运行
230
242
 
231
243
  计划模式另用 `node scripts/cli-plan-check.mjs` 验证:真实 CLI 对接本地模拟网关,检查 stdio 计划提交、并发计划归属、本轮文件回退、旧计划隔离、实际拒绝次数上限和清理;不读取真实凭据、不消费额度、不启动 DSH。
232
244
 
245
+ 排查「装了却看不到插件」用 `node scripts/install-check.mjs`:它只读当前 profile,列出被包内残留 `node_modules` 挡住的宿主包(含版本)和对应的修复步骤,发现问题时以退出码 1 结束;`--profile <name>`、`--home <dir>` 可指定其它 profile,`--json` 输出结构化结果。
246
+
233
247
  使用 Agent 修改或发布时,先读 [AGENTS.md](AGENTS.md)。发布由推送 `v*` 标签触发 [Publish workflow](.github/workflows/publish.yml),不要在本机执行 `npm publish`。
234
248
 
235
249
  ## License
package/cordis.patch.yml CHANGED
@@ -5,19 +5,3 @@
5
5
  - insert:
6
6
  - id: packycode-api
7
7
  name: 'dsh-packycode-api'
8
-
9
- # Connection registers a plugin's RPC channel through `owner.webServer`, where
10
- # the owner is the Connection row's own fiber — not the caller's. The shipped
11
- # dsh-web-app row injects `webRuntime` alone, so that read is refused with
12
- # `cannot get property "webServer" without inject`, the channel never reaches
13
- # the web server, and the browser's calls answer HTTP 405 while the boot log
14
- # stays clean.
15
- #
16
- # An entry patch replaces the whole inject list, so name every service that
17
- # fiber actually touches: `credentials` is the module's own inject, `webRuntime`
18
- # carries the row's `trustedHosts: !!js ctx.webRuntime.trustedHosts`, and
19
- # `webServer` is what channel registration reads. The name guard leaves a
20
- # replacement Connection implementation untouched.
21
- - id: connection
22
- name: '@deepseek-ai/dsh-client-connection'
23
- inject: [credentials, webRuntime, webServer]
package/lib/index.js CHANGED
@@ -4933,10 +4933,19 @@ var PackyCodeKeyRing = class {
4933
4933
  */
4934
4934
  /**
4935
4935
  * Mark a preference editable without restarting the plugin. DSH 0.2 stores
4936
- * plugin preferences as volatile Config fields and writes only those. The
4937
- * peer dependency requires the schema version that implements `volatile()`.
4938
- */
4939
- const live = (schema) => schema.volatile();
4936
+ * plugin preferences as volatile Config fields and writes only those, so the
4937
+ * schema version that implements `volatile()` is a peer requirement.
4938
+ *
4939
+ * Name the cause when it is missing instead of letting a bare
4940
+ * `schema.volatile is not a function` reach the host log: the Loader creates
4941
+ * no fiber for a plugin whose module throws while it is imported, so DSH shows
4942
+ * nothing at all — no settings section, no model route, no RPC channel — and
4943
+ * the only explanation is that one log line.
4944
+ */
4945
+ const live = (schema) => {
4946
+ if (typeof schema?.volatile !== "function") throw new Error("PackyCode needs @deepseek-ai/schemastery ^3.18.4, which implements Schema.volatile(); the copy resolved for this plugin is older. A plugin installed from a registry has no node_modules of its own, so this usually means a stale dependency tree inside the installed package directory (for example <profile>/node_modules/dsh-packycode-api/node_modules, left by an earlier local-path install) is shadowing the DSH installation. Remove that directory, or uninstall the plugin and install it again, then restart DSH.");
4947
+ return schema.volatile();
4948
+ };
4940
4949
  /** Read a Config field that may arrive as a volatile reference. */
4941
4950
  const fieldValue = (value) => value !== null && typeof value === "object" && typeof value.get === "function" ? value.get() : value;
4942
4951
  /** A preference target nothing can write to yet. */
@@ -6915,15 +6924,16 @@ function apply(ctx, config) {
6915
6924
  modelSelection
6916
6925
  });
6917
6926
  /**
6918
- * Connection registers a channel through `owner.webServer`, read on its own
6919
- * row's fiber — which is why this plugin ships the `connection` inject patch
6920
- * in `cordis.patch.yml`. Without that service the read is refused, the
6921
- * channel never reaches the web server, and the browser answers HTTP 405
6922
- * while the boot log stays clean. A profile with neither service (a headless
6923
- * run) simply never runs this callback.
6927
+ * The shipped Connection getter retains its own service context, whose row
6928
+ * need not inject webServer. Register with our injected context explicitly:
6929
+ * a first hot install then mounts the channel without rebuilding Connection.
6930
+ * The native registry still owns admission and the wire protocol. Its
6931
+ * explicit-owner entry is internal, so retain the public RPC contract for
6932
+ * other Connection implementations. A headless profile can omit this scope.
6924
6933
  */
6925
6934
  ctx.inject(["connection", "webServer"], (connectionCtx) => {
6926
- ctx.effect(() => connectionCtx.connection.rpc.handle(CHANNEL, handler), "packycode-api: loopback account RPC");
6935
+ const service = connectionCtx.connection;
6936
+ connectionCtx.effect(() => typeof service.register === "function" ? service.register(connectionCtx, CHANNEL, handler) : service.rpc.handle(CHANNEL, handler), "packycode-api: loopback account RPC");
6927
6937
  });
6928
6938
  ctx.inject(["tools"], (toolsCtx) => {
6929
6939
  ctx.effect(() => toolsCtx.tools.register(createClaudeCodeTool({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-packycode-api",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "Use a PackyCode (PackyAPI) API key in DeepSeek Harness through a built-in multi-protocol model route with key rotation and balance display",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -82,13 +82,18 @@
82
82
  },
83
83
  "devDependencies": {
84
84
  "@deepseek-ai/cordis": "4.0.2",
85
+ "@deepseek-ai/dsh-brand": "0.1.5-rc.3",
86
+ "@deepseek-ai/dsh-client-connection": "0.1.5-rc.3",
85
87
  "@deepseek-ai/dsh-credentials": "0.1.5-rc.2",
88
+ "@deepseek-ai/dsh-invariants": "0.1.5-rc.3",
86
89
  "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
87
90
  "@deepseek-ai/dsh-llm-pi-ai": "0.1.5-rc.2",
91
+ "@deepseek-ai/dsh-scope": "0.1.5-rc.3",
88
92
  "@deepseek-ai/dsh-settings": "0.1.5-rc.2",
89
93
  "@deepseek-ai/dsh-tools": "0.1.5-rc.2",
90
94
  "@deepseek-ai/schemastery": "3.18.4",
91
95
  "@earendil-works/pi-ai": "0.85.1",
96
+ "packycode-host-v020-fixture": "file:tests/fixtures/host-v020",
92
97
  "react": "18.3.1",
93
98
  "tsdown": "0.22.2",
94
99
  "yaml": "2.9.1"