dsh-packycode-api 1.4.2 → 1.4.4

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,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.4.4
4
+
5
+ - **DeepSeek V4 Pro joins the catalog** ([#4](https://github.com/BaronCyrus/dsh-packycode-api/issues/4)). `deepseek-v4-pro` takes DeepSeek Flash's route: `openai-responses` at `https://cf.api.fan/v1`, 1,000,000 context and 384,000 output, with Flash's efforts (`off` as `reasoning.effort: "none"`, `low`, `high`, `max`), per DeepSeek's [models and pricing page](https://api-docs.deepseek.com/quick_start/pricing/) and [API reference](https://api-docs.deepseek.com/api/create-chat-completion). PackyCode's `/api/pricing` lists it in `deepseek-officially` and `deepseek-sale` with `openai-response` among its endpoints, at 4.5 times Flash's input rate. It sits after Flash in the picker, and the settings panel counts it under DeepSeek. pi-ai's own DeepSeek catalog pins `low` unsupported for V4 Pro; DeepSeek documents `low` for both models, and through PackyCode V4 Pro answered it as its own level.
6
+ - **V4 Pro takes text only.** DeepSeek documents image input for Flash alone, and PackyCode's gateway drops an image sent to V4 Pro without an error: the model then spent 2,807 reasoning tokens on a picture it never got and answered "Unknown". The catalog declares `['text']`, so DSH's composer does not attach images to it, and DSH's LLM runtime sends an image already in the session (after a switch from Flash, say) as its one-line "image omitted" note. Its session titles go to Flash, which every group serving V4 Pro serves too.
7
+ - Validation, 2026-10-28:
8
+ - **Offline:** 536 tests (new: V4 Pro's catalog entry, efforts and resolved metadata; each effort, and `off` as `none`, sent through the route without the GPT cache key or `strict`; through DSH's `LlmRuntime`, an image in a V4 Pro session reaches the gateway as DSH's note and is never read; V4 Pro titles on Flash), both rebuilt bundles and the versioned tarball. `scripts/live-check.mjs --with-vision` now refuses a text-only `--model` before any request.
9
+ - **Live, direct to `/v1/responses` with the test key (`deepseek-officially` among its groups):** `none`, `low`, `high` and `max` were each echoed back, `none` with 0 reasoning tokens; `low` and `high` differed in input tokens (36 and 115 for the same prompt), so `low` is not answered as `high`. `max_output_tokens` up to 393,216 was accepted and 393,217 refused with 400, as for Flash. Without `strict`, V4 Pro left the optional sandbox fields of DSH's bash tool out in 4 of 4 calls, as Flash does.
10
+ - **Live, through the built route:** `off`, `low`, `high` and `max` each sent its effort (`off` as `none`) and answered `ok`; `minimal`, `medium` and `xhigh` were refused before any request. An `echo` tool call continued to `ok` at `high`, `off` and `max`, with the turn's reasoning replayed and 256–384 prefix tokens cached without a cache key. A DSH title request ran on Flash ("十月发货单整理与缺货标注"). A red image in a V4 Pro session, through DSH's `LlmRuntime`, was not read or sent, and the model said it could not see an image. `scripts/live-check.mjs` passed: all eleven models answered, and the key's groups read as reaching each of them. Key rotation, the rejected-key classification, both auto reviewers and the RPC projections were unchanged. Not checked in the desktop app.
11
+ - **Gemini 4 Argon leaves the catalog.** PackyCode stopped serving `gemini-4-argon` on 2026-10-27. It answered at about 06:00Z, and before 07:00Z the gateway refused it, first with `分组 gemini-slb 下模型 gemini-4-argon 无可用渠道(distributor)`, then with `当前令牌未覆盖供应商`. The public `/api/pricing` no longer lists it, while `gemini-3.8-flash` stays in `gemini-slb`. The picker now offers ten models, the settings panel's Gemini line counts Flash only, and `scripts/gemini-tool-check.mjs` takes only Flash.
12
+ - **A session still set to Argon** now gets DSH's `UNKNOWN_MODEL` (`pi-ai provider "packycode" has no configured model "gemini-4-argon"`) instead of the gateway's refusal, and needs another model; both READMEs say so in their FAQ. A stored model selection that names Argon is ignored like any unknown id. Flash keeps its native handling unchanged: `thinkingLevel`, the skip signature and its one resend.
13
+ - Validation, 2026-10-27:
14
+ - **Offline:** 534 tests (new: a session still set to Argon is refused as `UNKNOWN_MODEL` before any credential is read; the per-model native Gemini tests now run for Flash only, and the replay guard's non-Flash case uses a placeholder Gemini id), both rebuilt bundles and the versioned tarball.
15
+ - **Live, with the test key (`gemini-slb` among its groups):** at 07:17Z `/api/pricing` listed `gemini-3.8-flash`, `gemini-3.5-flash`, `gemini-3-flash-preview`, `gemini-3.1-pro-preview` and `gemini-3-pro-preview` in `gemini-slb`, and no `gemini-4-argon`, and the gateway still refused Argon. `scripts/live-check.mjs` passed: all ten models answered, and the key's groups read as reaching each of them. Key rotation, the rejected-key classification, both auto reviewers and the RPC projections were unchanged. Gemini 3.8 Flash continued a native tool call to `ok` 2 of 2 times at `low` and once at `high`, each continuation accepted on its first send, and it named a red and a blue image. Both live scripts now refuse `--model gemini-4-argon` before any request. Not checked in the desktop app.
16
+
17
+ ## 1.4.3
18
+
19
+ - **GPT tool calls no longer fill DSH's sandbox escalation fields.** On GPT-6.1 Terra users saw tool calls fail with `Error: invalid justification: expected a non-empty sentence`. The plugin sent DSH's tools to GPT without `strict`, and PackyCode's GPT route treats such a tool as strict, so the model filled every optional parameter. DSH's `sandbox_permissions` came back as `workspace-write`, the first value of its enum, with an empty or stock `justification`, next to invented values such as `timeoutMs: 1000`. DSH's edit and write refuse `sandbox_permissions` with an empty justification, and bash does too when the requested mode is not the session's own. All four GPT models did this, also before 1.4.2. DeepSeek Flash and Grok 4.7 leave optional parameters out with or without `strict`.
20
+ - **The GPT models now declare pi-ai's `supportsStrictMode`**, so pi-ai sends `strict: false` on each tool, as the official Codex client does. The parameter schemas are sent as DSH wrote them. No DSH tool asks for strict sampling (only pi-ai itself mentions `constrainedSampling`), so no tool switches to a strict schema.
21
+ - Validation, 2026-10-27:
22
+ - **Offline:** 537 tests (new: through the route every GPT model sends DSH's tools with `strict: false` and unchanged parameters, while DeepSeek and Grok send no `strict`; the test fails without the fix), both rebuilt bundles and the versioned tarball.
23
+ - **Live, the cause:** DSH 0.2.1-rc.3's own bash, read, write and edit specs, compiled with DSH's `parameterSchemaSpecToJsonSchema`, went through the 1.4.2 route. Terra filled `sandbox_permissions: "workspace-write"` with an empty `justification` in 15 of 15 calls, GPT-6.1 Sol in 9 of 9, and DSH's own check refused one Terra `edit` with exactly this message. Sent directly with the same bash tool, every GPT model filled `justification` in every call with `strict` omitted (Terra 4 of 4, the other three 2 of 2 each) and in none with `strict: false`. DeepSeek Flash and Grok 4.7 filled it in none either way.
24
+ - **Live, the fix:** through the built route with the same specs, Terra and GPT-6.1 Sol made 9 calls each, `edit` and `write` included, with no escalation field and none refused. After DSH's sandbox denial and its retry hint, both still retried with `sandbox_permissions: "danger-full-access"` and a reason in the user's language, 3 of 3 rounds each. Terra's `echo` tool call still continued to `ok` at `high` and with reasoning off. In `scripts/live-check.mjs` ten models answered, all four GPT models among them, and key rotation, the rejected-key classification, both auto reviewers and the RPC projections were unchanged. `gemini-4-argon` failed with the gateway's own refusal (`分组 gemini-slb 下模型 gemini-4-argon 无可用渠道`, then `当前令牌未覆盖供应商`): PackyCode's `/api/pricing` stopped listing it that day, between two runs, so this change is not the cause. Not checked in the desktop app.
25
+
3
26
  ## 1.4.2
4
27
 
5
28
  - **GPT-6.1 Terra joins the catalog.** `gpt-6.1-terra` takes GPT-6.1 Sol's route: `openai-responses` at `https://cf.api.fan/v1`, text and image input, 1,050,000 context and 128,000 output, per OpenAI's [model page](https://developers.openai.com/api/docs/models/gpt-6.1-terra), which also says tool calls need Responses. PackyCode's `/api/pricing` lists it for `codex` and `codex-sale`, not `azure-officially`, at half GPT-6.1 Sol's rate. It sits after GPT-6.1 Sol in the picker, and the settings panel counts it under GPT. Its session titles stay on Terra, which costs less than Sol.
package/README.en.md CHANGED
@@ -48,10 +48,10 @@ You need **DeepSeek Harness** and a **PackyCode (PackyAPI) API key**. For DSH se
48
48
  Open the desktop application's **Plugins** page, click **Add plugin**, and enter the package name **with a version** as the **package name or address**:
49
49
 
50
50
  ```text
51
- dsh-packycode-api@1.4.2
51
+ dsh-packycode-api@1.4.4
52
52
  ```
53
53
 
54
- Choose the **official** install source, then click **Install**. `1.4.2` was the latest release when this was written; the [npm page](https://www.npmjs.com/package/dsh-packycode-api) shows the current one.
54
+ Choose the **official** install source, then click **Install**. `1.4.4` was the latest release when this was written; the [npm page](https://www.npmjs.com/package/dsh-packycode-api) shows the current one.
55
55
 
56
56
  > **Always include the version.** With a bare `dsh-packycode-api`, the install prompt shows the newest version on npm, but DSH's bundled pnpm by default installs only versions published at least 24 hours ago, so you can end up several releases behind with no sign of it in the prompt. With an exact version, pnpm installs that version and adds it to the profile's `minimumReleaseAgeExclude` itself. Afterwards, check **Current version** under **Settings → PackyCode → Plugin version**.
57
57
 
@@ -72,7 +72,7 @@ Choose a model from the `PackyCode` group. Of the eleven models, Claude runs thr
72
72
 
73
73
  The **Plugins** page shows the installed state and version, and is also where you enable, disable, or uninstall.
74
74
 
75
- **For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.4.2`. Do not use it for `desktop` — the CLI refuses it (`profile "desktop" is managed exclusively by the Electron application`).
75
+ **For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.4.4`. Do not use it for `desktop` — the CLI refuses it (`profile "desktop" is managed exclusively by the Electron application`).
76
76
 
77
77
  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.
78
78
 
@@ -221,12 +221,12 @@ The card shows whether DSH's plugin is on, how many reviews this plugin answered
221
221
  | Model | How it runs | Effort | Token group |
222
222
  | --- | --- | --- | --- |
223
223
  | `deepseek-flash` | HTTP, Responses, images allowed | Can be off; `low` / `high` / `max` | `deepseek-officially`, `deepseek-sale` |
224
+ | `deepseek-v4-pro` (DeepSeek V4 Pro) | HTTP, Responses, text only; 1M context, 384K output | Same | Same |
224
225
  | `gpt-6.1-sol` | HTTP, Responses, images allowed | Cannot be off; `low` / `medium` / `high` / `xhigh` / `max` | `codex`, `codex-sale` |
225
226
  | `gpt-6.1-terra` (GPT-6.1 Terra) | Same | Can be off; `low` / `medium` / `high` / `xhigh` / `max` | Same |
226
227
  | `gpt-6-astra` | Same | Cannot be off; `low` / `medium` / `high` / `xhigh` / `max` | Same |
227
228
  | `gpt-5.6-sol` | Same | Same | Same |
228
229
  | `grok-4.7` (Grok 4.7) | HTTP, Responses, text/image input; 500K context | Cannot be off; `low` / `medium` / `high` / `xhigh` | The Grok coverage read from the gateway in Settings |
229
- | `gemini-4-argon` (Gemini 4 Argon) | HTTP, native Gemini streaming, text/image input; 1,048,576 context, 65,536 output | Cannot be off; `low` / `medium` / `high` | `gemini-slb` |
230
230
  | `gemini-3.8-flash` (Gemini 3.8 Flash) | HTTP, native Gemini streaming, text/image input; 1,048,576 input, 65,536 output | Cannot be off; `low` / `medium` / `high` | `gemini-slb` |
231
231
  | `claude-opus-5-5` | Anthropic Messages, images and native tools: this device's Claude Code CLI as the agent for `cc` keys, HTTP otherwise | Cannot be off; `low` / `medium` / `high` / `xhigh` / `max` | Claude-group coverage reported in Settings |
232
232
  | `claude-sonnet-5-5` | Same | Same | Same |
@@ -236,15 +236,15 @@ A model in the list does not mean the current token group allows it. When changi
236
236
 
237
237
  `jev-latest` (TypeSafe Jev) is not in the model picker: it is a decision model that answers classification questions and cannot hold a conversation, so it only serves [Auto review](#auto-review). The plugin calls `/v1/systemone` host-side; it needs a key in the `typesafe-officially` group, and each key's Jev entry under Accounts and keys shows whether it can.
238
238
 
239
- All eleven models in the current catalog declare text and image input. DeepSeek Flash follows the [official vision guide](https://api-docs.deepseek.com/guides/vision/); images are read through DSH's attachment service and sent with the Responses request.
239
+ Of the eleven models in the current catalog, all but DeepSeek V4 Pro declare text and image input. DeepSeek Flash follows the [official vision guide](https://api-docs.deepseek.com/guides/vision/); images are read through DSH's attachment service and sent with the Responses request. DeepSeek V4 Pro takes text only, per DeepSeek's [models and pricing page](https://api-docs.deepseek.com/quick_start/pricing/): DSH does not let you attach an image to it, and an image already in the session (say, one switched over from Flash) is sent as a one-line "image omitted" note. PackyCode's gateway does not refuse an image sent to V4 Pro; it drops it.
240
240
 
241
- Gemini capabilities and limits follow Google's model pages: [Gemini 4 Argon](https://ai.google.dev/gemini-api/docs/models/gemini-4-argon), [Gemini 3.8 Flash](https://ai.google.dev/gemini-api/docs/models/gemini-3.8-flash). Both models use the native Gemini protocol through `/v1beta/models/{model}:streamGenerateContent`, streaming text, thinking and tool calls; images are read through DSH's attachment service. Thinking levels are sent with `thinkingLevel`. Both routes use the single-stream output limit without automatic continuation beyond 65,536 tokens. Available endpoints and groups follow the [PackyAPI live model catalog](https://www.packyapi.com/api/pricing).
241
+ Gemini 3.8 Flash's capabilities and limits follow Google's [model page](https://ai.google.dev/gemini-api/docs/models/gemini-3.8-flash). It uses the native Gemini protocol through `/v1beta/models/{model}:streamGenerateContent`, streaming text, thinking and tool calls; images are read through DSH's attachment service. Thinking levels are sent with `thinkingLevel`. It uses the single-stream output limit without automatic continuation beyond 65,536 tokens. Available endpoints and groups follow the [PackyAPI live model catalog](https://www.packyapi.com/api/pricing). PackyCode stopped serving Gemini 4 Argon on 2026-10-27, and the plugin no longer lists it.
242
242
 
243
- **Gemini tool continuation and thought signatures:** PackyCode's native Gemini route does not handle thought signatures in tool calls correctly. It answers HTTP 400 `Invalid thought signature` / `Corrupted thought signature`, and resending the same request does not help (PackyCode support's answer). For Gemini 4 Argon and Gemini 3.8 Flash the plugin therefore sends none of the signatures the model returned. Wherever a signature is required, it sends Google's documented validator-skip value `skip_thought_signature_validator` ([Google's guide](https://ai.google.dev/gemini-api/docs/thought-signatures)). The protocol, endpoint and model stay the same, and DSH's replay record keeps the original signatures. Google notes that skipped signatures can weaken reasoning continuity across tool steps. Flash keeps its earlier safeguard: after an HTTP 400 signature refusal before any stream event, it waits one second and resends once. Such a 400 is never treated as a failed key.
243
+ **Gemini tool continuation and thought signatures:** PackyCode's native Gemini route does not handle thought signatures in tool calls correctly. It answers HTTP 400 `Invalid thought signature` / `Corrupted thought signature`, and resending the same request does not help (PackyCode support's answer). For Gemini 3.8 Flash the plugin therefore sends none of the signatures the model returned. Wherever a signature is required, it sends Google's documented validator-skip value `skip_thought_signature_validator` ([Google's guide](https://ai.google.dev/gemini-api/docs/thought-signatures)). The protocol, endpoint and model stay the same, and DSH's replay record keeps the original signatures. Google notes that skipped signatures can weaken reasoning continuity across tool steps. Flash keeps its earlier safeguard: after an HTTP 400 signature refusal before any stream event, it waits one second and resends once. Such a 400 is never treated as a failed key.
244
244
 
245
245
  Grok 4.7's context and reasoning levels follow the [official guide](https://docs.x.ai/developers/grok-4-7). There is no separate text-output limit; the plugin uses the context size as its numeric output ceiling, bounded by the remaining context per request.
246
246
 
247
- Only GPT Responses requests keep `prompt_cache_key`; other Responses models omit it by default. This gateway's Grok route reports a misleading `Incorrect API key provided` error when the field is present, and DeepSeek Flash hits its prefix cache without it.
247
+ Only GPT Responses requests keep `prompt_cache_key`; other Responses models omit it by default. This gateway's Grok route reports a misleading `Incorrect API key provided` error when the field is present, and DeepSeek Flash hits its prefix cache without it. GPT tool definitions also carry an explicit `strict: false`: PackyCode's GPT route treats a tool without `strict` as strict, which forces the model to fill every optional parameter (see the FAQ).
248
248
 
249
249
  GPT-6.1 Terra's context, output limit and effort levels follow OpenAI's [model page](https://developers.openai.com/api/docs/models/gpt-6.1-terra). It is the only GPT model whose reasoning can be off: with effort off it sends `reasoning.effort: "none"`, which the gateway passes through, and the answer comes back without reasoning. GPT-5.6 Sol's documentation lists `none` too, but through PackyCode it answers at `medium`, so it cannot be off.
250
250
 
@@ -261,7 +261,7 @@ DeepSeek Flash uses the gateway's Responses endpoint (`/api/pricing` lists `open
261
261
  - Claude streams finish at `message_stop` without waiting for the gateway to close the HTTP body, and CRLF delimiters remain intact across network chunks. Stream errors and cancellation still surface; waiting for response headers is not counted as success.
262
262
  - Offered DSH bash/read/write/edit/glob/grep tools use canonical CLI names such as `Bash` and `Read` over HTTP; other tools use MCP names. Through the CLI, DSH's tools are not sent to Claude Code. Only aliases declared for the current request regain their original names before DSH dispatch; unknown names never grant execution. Arguments, call IDs, results and signed history remain intact. Thinking display follows the CLI defaults: `omitted` for Haiku and `updates` with its required beta for Sonnet and Opus. Reasoning effort and output limits remain unchanged, signatures on empty thinking blocks survive replay, and explicit display options take precedence.
263
263
  - When the legacy working-directory sentence agrees with the initiating session metadata, Claude receives the exact path as a separate JSON string. Sentence punctuation stays outside the path; real trailing dots, Windows drive/UNC paths, spaces and backslashes remain intact. Commands are never trimmed or rewritten. Shell guidance prefers the current directory or `workdir`, preserving PowerShell syntax for Windows tools.
264
- - Claude turns on both routes retain the full DSH tool loop, permissions and plan mode, using host search and image tools. Claude titles use Haiku on the same route as the conversation; GPT-6 Astra and GPT-5.6 Sol titles use GPT-6.1 Sol.
264
+ - Claude turns on both routes retain the full DSH tool loop, permissions and plan mode, using host search and image tools. Claude titles use Haiku on the same route as the conversation; GPT-6 Astra and GPT-5.6 Sol titles use GPT-6.1 Sol, and DeepSeek V4 Pro titles use DeepSeek Flash.
265
265
  - The 1.2 `claudeCliMode` / `claudeCliCwd` settings do not return: Claude Code's permissions follow the session's DSH permission preset, and its working directory is the session's. The tool named `claude_code` is now the mirror tool that shows Claude Code's tool calls in cc sessions; only the plugin uses it, and it is not the 1.2 delegation tool. `claudeCliPath` applies again and names the CLI (empty means the usual install places, then PATH). 1.3.4's `claudeTransport` is removed, and a value left in a profile is ignored. Separately installed Claude Code is only modified when you click **Update Claude Code CLI** in the CLI card.
266
266
  - Codex Responses requests still need `prompt_cache_key`; the plugin supplies a missing session identity. Other Responses families omit it.
267
267
  - After building, `node scripts/claude-check.mjs` checks all three Claude models on order totals, support triage, replenishment, read-only inventory tool roundtrips, product color labels, Chinese titles and plan mode (read-only lookup → plan submitted with `exit_plan_mode` → approval), validating the business answers; `--transport cli` runs the cc route's checks instead (`scripts/claude-agent-check.mjs`): in a scratch directory Claude Code reads a file and computes, edits one (approved), deletes one (refused), plans and then implements after review, asks a question, reads an image and names a session, and the files and answers are checked, with the gateway's client-anomaly and anti-abuse refusals counted. `node scripts/claude-stability.mjs --start --hours 6 --key-label <label>` starts a deadline- and request-budget-limited window. Invoke the same script on a schedule to sample again; `--status` reads the record. Each round records its build and scenario version. A test-message policy refusal fails that check while the other scheduled checks continue; real credential or quota failures still stop the window. Checks never change stored credentials or start DSH.
@@ -271,9 +271,9 @@ DeepSeek Flash uses the gateway's Responses endpoint (`/api/pricing` lists `open
271
271
 
272
272
  ## Update and uninstall
273
273
 
274
- > **Upgrading from 1.3.2 or earlier:** install `dsh-packycode-api@1.4.2` on the Plugins page instead of clicking **Update plugin** in the old settings card. The old button bypasses pnpm's release-age policy: if the version it installs is less than 24 hours old, the profile refuses every other plugin install until that version is 24 hours old. After the install and a restart, the button is the fixed one, and later updates can use it.
274
+ > **Upgrading from 1.3.2 or earlier:** install `dsh-packycode-api@1.4.4` on the Plugins page instead of clicking **Update plugin** in the old settings card. The old button bypasses pnpm's release-age policy: if the version it installs is less than 24 hours old, the profile refuses every other plugin install until that version is 24 hours old. After the install and a restart, the button is the fixed one, and later updates can use it.
275
275
 
276
- **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. The install keeps pnpm's release-age policy instead of overriding it: by default pnpm installs the version at once and records it in the profile's `minimumReleaseAgeExclude`; under a stricter pnpm policy the button says when the update can run. The newer version is read from npm, while pnpm downloads it from the profile's own install source: right after a release that source (a regional mirror in particular) may not have it yet, and the button asks you to update again in a few minutes; when the source cannot be reached, it asks you to check the network or proxy. 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 from the **Plugins** page works too, again with the version in the package name (for example `dsh-packycode-api@1.4.2`); without it you may get a version that is merely the newest one published at least 24 hours ago.
276
+ **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. The install keeps pnpm's release-age policy instead of overriding it: by default pnpm installs the version at once and records it in the profile's `minimumReleaseAgeExclude`; under a stricter pnpm policy the button says when the update can run. The newer version is read from npm, while pnpm downloads it from the profile's own install source: right after a release that source (a regional mirror in particular) may not have it yet, and the button asks you to update again in a few minutes; when the source cannot be reached, it asks you to check the network or proxy. 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 from the **Plugins** page works too, again with the version in the package name (for example `dsh-packycode-api@1.4.4`); without it you may get a version that is merely the newest one published at least 24 hours ago.
277
277
 
278
278
  **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.
279
279
 
@@ -289,7 +289,7 @@ ls ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/node_modules
289
289
 
290
290
  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.
291
291
 
292
- Recovery: **uninstall** the plugin on the **Plugins** page, **install** it again with the version in the package name (for example `dsh-packycode-api@1.4.2`), 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.
292
+ Recovery: **uninstall** the plugin on the **Plugins** page, **install** it again with the version in the package name (for example `dsh-packycode-api@1.4.4`), 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.
293
293
 
294
294
  **Right after a first install, every card in Settings shows `transport failure for /packycode-api/…: HTTP 405`?** The installed version is 1.1.6 or earlier, usually because only the bare package name was entered: the install prompt shows the newest version, but pnpm installs the newest one published at least 24 hours ago (see **Install the plugin**). Those older versions can register their settings channel only after DSH restarts and rebuilds its `connection` service. So right after a first install `/packycode-api` does not exist yet, requests fall through to the static page, and it answers 405; the model route and the settings panel itself load normally. From 1.1.7 on, a first install needs no restart. Check which version was installed:
295
295
 
@@ -303,6 +303,10 @@ Recovery: quit and reopen the desktop application, and the old version works. Th
303
303
 
304
304
  **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.
305
305
 
306
+ **A GPT model's file edit fails with `invalid justification: expected a non-empty sentence`?** This affected 1.4.2 and earlier; update to 1.4.3. PackyCode's GPT route treats a tool without `strict` as strict, so the model had to fill every optional parameter. It sent DSH's sandbox escalation pair as `sandbox_permissions: "workspace-write"` with an empty `justification`, and DSH's edit and write refused the call. From 1.4.3 GPT tool definitions carry an explicit `strict: false`. The model usually finishes the step another way, and existing sessions need nothing.
307
+
308
+ **A session says `pi-ai provider "packycode" has no configured model "gemini-4-argon"`?** PackyCode stopped serving Gemini 4 Argon on 2026-10-27: the gateway refuses it, and the plugin removed it from its catalog. Pick another model for that session in the model picker.
309
+
306
310
  **Claude reports an official-client-only or client-anomaly refusal?** This is a gateway client-policy refusal, not proof of an invalid key. See whether the key is marked “Claude via HTTP” or “via official CLI”: a `cc` key always uses the CLI, and other groups use HTTP. The cc group judges whether a request comes from Claude Code itself; from 1.4.0 cc sessions are carried out by Claude Code and are normally accepted. If one is still refused, resend it; if it keeps happening, send the gateway's own words from the error (with the request id) to PackyCode support, or use a `cc-sale` / `cc-expensive` / `claude-officially` key. Updating the Claude Code CLI does not help with this refusal. The plugin does not disable the key or switch providers.
307
311
 
308
312
  **“Claude Code CLI is not available”?** The key is in `cc`, which needs the CLI on this device. When the message says the key's groups are not read yet, the group reading failed for now (common on an unstable network or proxy): resend shortly, and a key outside `cc` moves to HTTP once its groups are read. Under **Settings → PackyCode → Claude Code CLI** click Install, or run `npm install -g @anthropic-ai/claude-code --allow-scripts=@anthropic-ai/claude-code` and click Check again; set `claudeCliPath` for an unusual location. Otherwise use a `cc-sale` / `cc-expensive` key.
package/README.md CHANGED
@@ -48,10 +48,10 @@
48
48
  打开桌面应用的**插件**页,点击**添加插件**,在**包名或地址**中填入**带版本号**的包名:
49
49
 
50
50
  ```text
51
- dsh-packycode-api@1.4.2
51
+ dsh-packycode-api@1.4.4
52
52
  ```
53
53
 
54
- 在**安装源**中选择**官方源**,然后点击**安装**。`1.4.2` 是写这份说明时的最新版,当前最新版本号以 [npm 页面](https://www.npmjs.com/package/dsh-packycode-api) 为准。
54
+ 在**安装源**中选择**官方源**,然后点击**安装**。`1.4.4` 是写这份说明时的最新版,当前最新版本号以 [npm 页面](https://www.npmjs.com/package/dsh-packycode-api) 为准。
55
55
 
56
56
  > **一定要带版本号。** 只填 `dsh-packycode-api` 时,安装前的提示显示的是 npm 上的最新版,但 DSH 自带的 pnpm 默认只安装发布满 24 小时的版本,实际装上的可能是好几个版本之前的旧版,而安装提示里看不出这一点。填写精确版本时,pnpm 会直接安装这个版本,并自动把它加入 profile 的 `minimumReleaseAgeExclude`。装好后可以在 **设置 → PackyCode → 插件版本** 核对「当前版本」。
57
57
 
@@ -72,7 +72,7 @@ dsh-packycode-api@1.4.2
72
72
 
73
73
  桌面应用的**插件**页可以看到已安装状态与版本,也可以在那里启用、停用或卸载。
74
74
 
75
- **仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.4.2`。不要对 `desktop` 使用它 —— CLI 会直接拒绝(`profile "desktop" is managed exclusively by the Electron application`)。
75
+ **仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.4.4`。不要对 `desktop` 使用它 —— CLI 会直接拒绝(`profile "desktop" is managed exclusively by the Electron application`)。
76
76
 
77
77
  本地开发要加 `link:` 前缀:`dsh plugin --profile <name> add link:/path/to/dsh-packycode-api`。**不要直接写路径(或 `file:`)** —— 那样的安装会把整个仓库目录(连同 `node_modules`)复制进 profile,之后它会在 profile 内部挡住 DSH 自带的包,插件看起来像没装,见「常见问题」。已经那样装过的话,先卸载再按上面的方式重装。
78
78
 
@@ -221,12 +221,12 @@ DSH 自带一个实验性插件「自动授权审查」,默认关闭。开启
221
221
  | 模型 | 怎么调用 | 推理档位 | 适合的令牌分组 |
222
222
  | --- | --- | --- | --- |
223
223
  | `deepseek-flash` | HTTP,Responses,可带图 | 可关;`low` / `high` / `max` | `deepseek-officially`、`deepseek-sale` |
224
+ | `deepseek-v4-pro`(DeepSeek V4 Pro) | HTTP,Responses,只收文字;1M 上下文,384K 输出 | 同上 | 同上 |
224
225
  | `gpt-6.1-sol` | HTTP,Responses,可带图 | 不能关;`low` / `medium` / `high` / `xhigh` / `max` | `codex`、`codex-sale` |
225
226
  | `gpt-6.1-terra`(GPT-6.1 Terra) | 同上 | 可关;`low` / `medium` / `high` / `xhigh` / `max` | 同上 |
226
227
  | `gpt-6-astra` | 同上 | 不能关;`low` / `medium` / `high` / `xhigh` / `max` | 同上 |
227
228
  | `gpt-5.6-sol` | 同上 | 同上 | 同上 |
228
229
  | `grok-4.7`(Grok 4.7) | HTTP,Responses,可带图;500k 上下文 | 不能关;`low` / `medium` / `high` / `xhigh` | 以设置页从网关读取的 Grok 分组覆盖为准 |
229
- | `gemini-4-argon`(Gemini 4 Argon) | HTTP,Gemini 原生流式,可带图;1,048,576 上下文,65,536 输出 | 不能关;`low` / `medium` / `high` | `gemini-slb` |
230
230
  | `gemini-3.8-flash`(Gemini 3.8 Flash) | HTTP,Gemini 原生流式,可带图;1,048,576 输入,65,536 输出 | 不能关;`low` / `medium` / `high` | `gemini-slb` |
231
231
  | `claude-opus-5-5` | Anthropic Messages,可带图和原生工具:`cc` 分组由本机 Claude Code CLI 当 agent,其它分组走 HTTP | 不能关;`low` / `medium` / `high` / `xhigh` / `max` | 以设置页读取的 Claude 分组覆盖为准 |
232
232
  | `claude-sonnet-5-5` | 同上 | 同上 | 同上 |
@@ -236,15 +236,15 @@ DSH 自带一个实验性插件「自动授权审查」,默认关闭。开启
236
236
 
237
237
  `jev-latest`(TypeSafe Jev)不在模型选择器里:它是只回答分类问题的决策模型,不能对话,只用于[自动审查](#自动审查)。插件在宿主侧直接调用 `/v1/systemone`,需要 Key 在 `typesafe-officially` 分组;「账户与 Key」里每个 Key 的「Jev」一项会显示能否使用。
238
238
 
239
- 当前目录中的 11 个模型都声明了文字和图像输入。DeepSeek Flash 的识图能力按 [官方图像理解文档](https://api-docs.deepseek.com/zh-cn/guides/vision/) 配置;图片通过 DSH 附件服务读取,再随 Responses 请求发送。
239
+ 当前目录的 11 个模型中,除 DeepSeek V4 Pro 外都声明了文字和图像输入。DeepSeek Flash 的识图能力按 [官方图像理解文档](https://api-docs.deepseek.com/zh-cn/guides/vision/) 配置;图片通过 DSH 附件服务读取,再随 Responses 请求发送。DeepSeek V4 Pro 按 [官方模型与价格页](https://api-docs.deepseek.com/zh-cn/quick_start/pricing/) 只收文字:DSH 不让给它附图,会话里已有的图片(比如从 Flash 切过来的会话)会换成一行「图片已省略」的说明再发送。PackyCode 网关收到发给 V4 Pro 的图片不报错,而是直接丢掉。
240
240
 
241
- Gemini 的能力与限制来自 Google 官方模型页:[Gemini 4 Argon](https://ai.google.dev/gemini-api/docs/models/gemini-4-argon)、[Gemini 3.8 Flash](https://ai.google.dev/gemini-api/docs/models/gemini-3.8-flash)。两款模型统一使用 Gemini 原生协议,通过 `/v1beta/models/{model}:streamGenerateContent` 流式返回文字、思考和工具调用,图片仍由 DSH 附件服务读取。思考档位通过 `thinkingLevel` 传入。两者均使用单次流式输出上限,不执行超过 65,536 token 的自动续写。可用端点与分组以 [PackyAPI 实时模型目录](https://www.packyapi.com/api/pricing) 为准。
241
+ Gemini 3.8 Flash 的能力与限制来自 Google 官方[模型页](https://ai.google.dev/gemini-api/docs/models/gemini-3.8-flash)。它使用 Gemini 原生协议,通过 `/v1beta/models/{model}:streamGenerateContent` 流式返回文字、思考和工具调用,图片仍由 DSH 附件服务读取。思考档位通过 `thinkingLevel` 传入。它使用单次流式输出上限,不执行超过 65,536 token 的自动续写。可用端点与分组以 [PackyAPI 实时模型目录](https://www.packyapi.com/api/pricing) 为准。PackyCode 自 2026-10-27 起不再提供 Gemini 4 Argon,插件已从目录中移除它。
242
242
 
243
- **Gemini 工具续聊的思维签名:** PackyCode 的 Gemini 原生通道在工具调用场景下不能正确处理思维签名,会返回 HTTP 400 `Invalid thought signature` / `Corrupted thought signature`,原样重发也无济于事(PackyCode 客服的答复)。因此插件对 Gemini 4 Argon 和 Gemini 3.8 Flash 不再回传模型返回的签名,而是按 [Google 文档](https://ai.google.dev/gemini-api/docs/thought-signatures) 在需要签名的位置填入跳过校验的值 `skip_thought_signature_validator`。协议、端点和模型都不变,DSH 的回放记录仍保留原始签名。Google 提示跳过签名可能削弱多步工具调用之间的推理连贯性。Flash 仍保留原有兜底:HTTP 400 签名拒绝且尚未输出任何流事件时,等待 1 秒原样重发一次。这类 400 不会被当作 Key 失效。
243
+ **Gemini 工具续聊的思维签名:** PackyCode 的 Gemini 原生通道在工具调用场景下不能正确处理思维签名,会返回 HTTP 400 `Invalid thought signature` / `Corrupted thought signature`,原样重发也无济于事(PackyCode 客服的答复)。因此插件对 Gemini 3.8 Flash 不再回传模型返回的签名,而是按 [Google 文档](https://ai.google.dev/gemini-api/docs/thought-signatures) 在需要签名的位置填入跳过校验的值 `skip_thought_signature_validator`。协议、端点和模型都不变,DSH 的回放记录仍保留原始签名。Google 提示跳过签名可能削弱多步工具调用之间的推理连贯性。Flash 仍保留原有兜底:HTTP 400 签名拒绝且尚未输出任何流事件时,等待 1 秒原样重发一次。这类 400 不会被当作 Key 失效。
244
244
 
245
245
  Grok 4.7 的上下文与推理档位来自 [官方文档](https://docs.x.ai/developers/grok-4-7)。官方没有单独限制文字输出长度;插件将输出上限设为上下文大小,并按每次请求的剩余上下文收紧。
246
246
 
247
- Responses 请求只有 GPT 模型保留 `prompt_cache_key`,其他 Responses 模型默认省略。当前网关的 Grok 路由会将这个字段误报成 `Incorrect API key provided`;DeepSeek Flash 不带它也能命中前缀缓存。
247
+ Responses 请求只有 GPT 模型保留 `prompt_cache_key`,其他 Responses 模型默认省略。当前网关的 Grok 路由会将这个字段误报成 `Incorrect API key provided`;DeepSeek Flash 不带它也能命中前缀缓存。GPT 的工具定义还会显式带上 `strict: false`:PackyCode 的 GPT 通道把没写 `strict` 的工具当作严格模式,模型会被迫填满所有可选参数(见「常见问题」)。
248
248
 
249
249
  GPT-6.1 Terra 的上下文、输出上限和推理档位来自 [OpenAI 模型页](https://developers.openai.com/api/docs/models/gpt-6.1-terra)。它是唯一可以关闭推理的 GPT 模型:关闭时发送 `reasoning.effort: "none"`,网关原样转发,返回时不带思考。GPT-5.6 Sol 的文档虽然也列出 `none`,经 PackyCode 却按 `medium` 回答,所以不能关。
250
250
 
@@ -261,7 +261,7 @@ DeepSeek Flash 走网关的 Responses 接口(`/api/pricing` 列出 `openai-res
261
261
  - Claude 流收到 `message_stop` 后即可完成,不再等网关关闭 HTTP 连接;跨分片的 CRLF 换行保持完整。流内错误与取消仍会返回,未收到响应头的等待也不会被当作成功。
262
262
  - DSH 的 bash/read/write/edit/glob/grep 在 HTTP 请求中使用已声明的 CLI 标准名称(如 `Bash`、`Read`),其它工具使用 MCP 命名;经 CLI 时 DSH 的工具不发给 Claude Code。回到 DSH 时仅还原本次实际提供的工具名称,未知名称不会获得执行权限。工具参数、调用 id、结果和历史签名不变。思考展示采用 CLI 默认:Haiku 为 `omitted`,Sonnet / Opus 为 `updates`(附带相应 beta)。所选推理强度和输出上限不变,空思考块的签名仍完整回传;明确指定的显示模式优先。
263
263
  - Claude 请求中的旧工作目录句式会在与当前会话元数据一致时转换为单独的 JSON 路径,避免把提示语的句号复制进路径。真实目录名中的点、Windows 盘符、UNC、空格和反斜杠保持不变;命令参数不会被自动修剪。命令工具优先使用当前目录或 `workdir`,Windows 的 PowerShell 工具保持其原有语法。
264
- - 两条通道的 Claude 对话都保留完整 DSH 工具循环、权限及计划模式;网页搜索和生图使用宿主工具。会话标题由 `claude-haiku-5-5` 生成(与对话走同一条通道);GPT-6 Astra 与 GPT-5.6 Sol 的标题交给 GPT-6.1 Sol。
264
+ - 两条通道的 Claude 对话都保留完整 DSH 工具循环、权限及计划模式;网页搜索和生图使用宿主工具。会话标题由 `claude-haiku-5-5` 生成(与对话走同一条通道);GPT-6 Astra 与 GPT-5.6 Sol 的标题交给 GPT-6.1 Sol,DeepSeek V4 Pro 的标题交给 DeepSeek Flash。
265
265
  - 1.2.x 的 `claudeCliMode`、`claudeCliCwd` 设置不再恢复:Claude Code 的权限由会话的 DSH 权限预设决定,工作目录就是会话目录。名为 `claude_code` 的工具现在是 cc 会话里显示 Claude Code 工具调用的镜像工具,只由插件使用,不是 1.2.x 的委派工具。`claudeCliPath` 重新生效,用于指定 CLI 位置(留空则按常见安装位置和 PATH 查找)。1.3.4 的 `claudeTransport` 已移除,profile 里残留的值会被忽略。除非你在 CLI 卡片里点「更新 Claude Code CLI」,用户独立安装的 Claude Code 不会被改动。
266
266
  - Codex 的 Responses 请求仍需要 `prompt_cache_key`;插件补上缺失的会话标识,其它 Responses 模型省略该字段。
267
267
  - 构建后可用 `node scripts/claude-check.mjs` 验证三个 Claude 模型的订单核算、工单归类、库存补货、只读库存查询工具回传、商品色卡标注、中文标题和计划模式(只读查询 → `exit_plan_mode` 提交计划 → 审批),并核对业务答案;加 `--transport cli` 则改跑 cc 通道的检查(`scripts/claude-agent-check.mjs`):在临时目录里让 Claude Code 自己读文件计算、改文件(授权批准)、删文件(授权拒绝)、计划审阅后实施、提问、看图和起标题,核对文件和答案,并统计网关的「客户端异常」和「反滥用」拒绝次数。`node scripts/claude-stability.mjs --start --hours 6 --key-label <备注名>` 开始有截止时间和请求上限的采样;定时执行同一脚本继续采样,用 `--status` 查看记录。业务场景版本和每轮构建分别记录;测试消息拒绝将对应检查记为失败,其余预定检查继续,真实凭据或额度错误仍会停止整个窗口。测试不改变已保存的凭据,也不启动 DSH。
@@ -271,9 +271,9 @@ DeepSeek Flash 走网关的 Responses 接口(`/api/pricing` 列出 `openai-res
271
271
 
272
272
  ## 更新与卸载
273
273
 
274
- > **从 1.3.2 或更早版本升级:** 请在插件页填写 `dsh-packycode-api@1.4.2` 安装,不要点旧版设置页里的「更新插件」。旧按钮安装时会绕过 pnpm 的发布冷却期:装到的版本如果发布还不满 24 小时,这个 profile 在它满 24 小时之前就装不了其他插件。装好并重启后,按钮就换成了修好的版本,以后直接点即可。
274
+ > **从 1.3.2 或更早版本升级:** 请在插件页填写 `dsh-packycode-api@1.4.4` 安装,不要点旧版设置页里的「更新插件」。旧按钮安装时会绕过 pnpm 的发布冷却期:装到的版本如果发布还不满 24 小时,这个 profile 在它满 24 小时之前就装不了其他插件。装好并重启后,按钮就换成了修好的版本,以后直接点即可。
275
275
 
276
- **更新:** 打开 **设置 → PackyCode**,有新版本时点「更新插件」。它会在当前 profile 目录里用 DSH 自带的 pnpm 安装精确版本,并读回 `package.json` 确认版本落地。安装遵守 pnpm 的发布冷却策略,不会绕过它:默认情况下 pnpm 会直接装上这个版本,并把它记进 profile 的 `minimumReleaseAgeExclude`;如果你给 pnpm 配了更严格的策略,按钮会提示什么时候可以更新。新版本号是从 npm 读到的,pnpm 却从 profile 配置的安装源下载:刚发布的版本,安装源(尤其是国内镜像)可能还没同步到,这时按钮会提示过几分钟再更新;连不上安装源时,会提示检查网络或代理。本地 `link:` 开发安装不会出现这个按钮。完成后完全退出并重新打开桌面应用。只刷新页面不会重载 Host。也可以在**插件**页重新安装,同样要填写带版本号的包名(例如 `dsh-packycode-api@1.4.2`),否则装上的可能是发布满 24 小时的旧版。
276
+ **更新:** 打开 **设置 → PackyCode**,有新版本时点「更新插件」。它会在当前 profile 目录里用 DSH 自带的 pnpm 安装精确版本,并读回 `package.json` 确认版本落地。安装遵守 pnpm 的发布冷却策略,不会绕过它:默认情况下 pnpm 会直接装上这个版本,并把它记进 profile 的 `minimumReleaseAgeExclude`;如果你给 pnpm 配了更严格的策略,按钮会提示什么时候可以更新。新版本号是从 npm 读到的,pnpm 却从 profile 配置的安装源下载:刚发布的版本,安装源(尤其是国内镜像)可能还没同步到,这时按钮会提示过几分钟再更新;连不上安装源时,会提示检查网络或代理。本地 `link:` 开发安装不会出现这个按钮。完成后完全退出并重新打开桌面应用。只刷新页面不会重载 Host。也可以在**插件**页重新安装,同样要填写带版本号的包名(例如 `dsh-packycode-api@1.4.4`),否则装上的可能是发布满 24 小时的旧版。
277
277
 
278
278
  **从本地路径安装切回官方源时,必须先卸载。** 「更新」是 `pnpm add`,它只重写包目录里的文件,不会删除更早一次本地路径安装留在包目录内的 `node_modules`;那份旧依赖会继续挡住 DSH 自带的包,插件行加载失败且看不出原因。「卸载」执行的是 `pnpm remove`,会删掉整个包目录,重装才是干净的。用 `node scripts/install-check.mjs` 可以确认当前 profile 是否处于这个状态。
279
279
 
@@ -289,7 +289,7 @@ ls ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/node_modules
289
289
 
290
290
  有输出就是残留:从 npm 安装的包不会自带 `node_modules`,这一份通常来自更早一次「本地路径」安装(`file:` 或直接写路径,而不是 `link:`)。它位于 profile 目录内部,而 DSH 解析插件导入时优先使用 profile 内的副本,所以插件拿到的仍是那份旧依赖 —— 例如 `@deepseek-ai/schemastery` 3.18.2 没有 `Schema.volatile()`,模块在导入阶段就抛错。导入失败时 Loader 不会为这一行创建 fiber,客户端 bundle 也不会被组合,于是模型路由、RPC 通道和设置页全都不会出现。
291
291
 
292
- 修复:到**插件**页**卸载**本插件,再用带版本号的包名重新**安装**(例如 `dsh-packycode-api@1.4.2`),然后完全退出并重新打开桌面应用。卸载执行的是 `pnpm remove`,会删掉整个包目录;直接重装或点「更新」只重写文件,不会清掉这份残留。也可以手动删掉上面那个 `node_modules` 再重启。
292
+ 修复:到**插件**页**卸载**本插件,再用带版本号的包名重新**安装**(例如 `dsh-packycode-api@1.4.4`),然后完全退出并重新打开桌面应用。卸载执行的是 `pnpm remove`,会删掉整个包目录;直接重装或点「更新」只重写文件,不会清掉这份残留。也可以手动删掉上面那个 `node_modules` 再重启。
293
293
 
294
294
  **首次安装后,设置页每张卡片都显示 `transport failure for /packycode-api/…: HTTP 405`?** 实际装上的是 1.1.6 或更早的版本,通常是因为安装时只填了包名:安装提示显示的是最新版,pnpm 实际装的却是发布满 24 小时的旧版(见「安装插件」)。这些旧版要等 DSH 重启、重建它的 `connection` 服务之后,才能注册设置通道。所以首次安装后 `/packycode-api` 通道还不存在,请求落到静态页面,返回 405;模型路由和设置页本身照常加载。1.1.7 起首次安装不需要重启。先确认装上的版本:
295
295
 
@@ -301,6 +301,10 @@ grep '"version"' ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/package.
301
301
 
302
302
  **某个模型不可用,但 Key 是有效的?** 看「账户与 Key」里这个 Key 的分组和 ✓ / ✕:分组不覆盖这个模型时,换一个分组合适的 Key,或在 PackyCode 控制台给 Key 加上对应分组。存了分组合适的 Key 时,插件会自动用它跑这个模型。分组拒绝不会停用 Key。
303
303
 
304
+ **GPT 模型改文件时报 `invalid justification: expected a non-empty sentence`?** 这是 1.4.2 及更早版本的问题,更新到 1.4.3 即可。PackyCode 的 GPT 通道把没写 `strict` 的工具当作严格模式,模型被迫填满所有可选参数,把 DSH 的沙箱提权参数填成 `sandbox_permissions: "workspace-write"` 加空的 `justification`,DSH 的 edit / write 于是拒绝这次调用。1.4.3 起 GPT 的工具定义显式带上 `strict: false`。模型通常会换一种方式完成这一步,已有会话不需要处理。
305
+
306
+ **会话报 `pi-ai provider "packycode" has no configured model "gemini-4-argon"`?** PackyCode 自 2026-10-27 起不再提供 Gemini 4 Argon,网关拒绝这个模型,插件也从目录中移除了它。在模型选择器里给这个会话换一个模型即可。
307
+
304
308
  **Claude 报「只接受官方 Claude Code CLI」或「客户端存在异常」?** 这是网关的客户端政策拒绝,不等于 Key 失效。看这个 Key 下方标的是「Claude 经 HTTP」还是「经官方 CLI」:`cc` 分组的 Key 总是走 CLI,其它分组走 HTTP。cc 分组按请求内容判断是不是 Claude Code 自己在工作;1.4.0 起 cc 会话由 Claude Code 自己完成,正常不会被拒。偶尔仍被拒时重发一次;反复出现时,把错误里的网关原文(含 request id)发给 PackyCode 客服,或改用 `cc-sale` / `cc-expensive` / `claude-officially` 分组的 Key。更新 Claude Code CLI 不能解决这个拒绝。插件不会因此禁用 Key 或切换提供商。
305
309
 
306
310
  **提示「本机没有可用的 Claude Code CLI」?** 当前 Key 在 `cc` 分组,需要本机 CLI。提示里写着「插件还没读到当前 Key 的分组」时,是分组读取暂时失败(网络或代理不稳时常见):稍后重发即可,不在 `cc` 分组的 Key 读到分组后会自动改走 HTTP。到 **设置 → PackyCode → Claude Code CLI** 点「安装」,或在终端执行 `npm install -g @anthropic-ai/claude-code --allow-scripts=@anthropic-ai/claude-code` 后点「重新检测」;装在非常规位置时可在配置里填 `claudeCliPath`。不想装的话,换用 `cc-sale` / `cc-expensive` 分组的 Key。
package/lib/client.js CHANGED
@@ -1951,7 +1951,7 @@ window.__ModuleLoader__.load({
1951
1951
  };
1952
1952
  /** The catalog's models by family, for the "reaches" line under each key. */
1953
1953
  const MODEL_FAMILIES = [
1954
- ["DeepSeek", ["deepseek-flash"]],
1954
+ ["DeepSeek", ["deepseek-flash", "deepseek-v4-pro"]],
1955
1955
  ["GPT", [
1956
1956
  "gpt-6.1-sol",
1957
1957
  "gpt-6.1-terra",
@@ -1959,7 +1959,7 @@ window.__ModuleLoader__.load({
1959
1959
  "gpt-5.6-sol"
1960
1960
  ]],
1961
1961
  ["Grok", ["grok-4.7"]],
1962
- ["Gemini", ["gemini-4-argon", "gemini-3.8-flash"]],
1962
+ ["Gemini", ["gemini-3.8-flash"]],
1963
1963
  ["Claude", [
1964
1964
  "claude-opus-5-5",
1965
1965
  "claude-sonnet-5-5",
package/lib/index.js CHANGED
@@ -1078,9 +1078,10 @@ const DEFAULT_REASONING_LEVEL = "high";
1078
1078
  * model does not support is refused before the request is sent: Claude Opus
1079
1079
  * 5.5 (platform.claude.com effort docs), GPT-6.1 Sol, GPT-6.1 Terra, GPT-6
1080
1080
  * Astra and GPT-5.6 Sol `reasoning.effort` (developers.openai.com model
1081
- * pages), DeepSeek thinking mode (`low|high|max` effort, or off), Grok 4.7
1082
- * (docs.x.ai/developers/grok-4-7), and Gemini 4 Argon
1083
- * (ai.google.dev/gemini-api/docs/models/gemini-4-argon and docs/openai).
1081
+ * pages), DeepSeek thinking mode (`low|high|max` effort, or off, for Flash
1082
+ * and V4 Pro alike), Grok 4.7
1083
+ * (docs.x.ai/developers/grok-4-7), and Gemini 3.8 Flash
1084
+ * (ai.google.dev/gemini-api/docs/models/gemini-3.8-flash).
1084
1085
  *
1085
1086
  * @module dsh-packycode-api/catalog
1086
1087
  */
@@ -1095,6 +1096,16 @@ const RESPONSES_BASE = `${DEFAULT_API_HOST}/v1`;
1095
1096
  const MESSAGES_BASE = DEFAULT_API_HOST;
1096
1097
  const GEMINI_BASE = `${DEFAULT_API_HOST}/v1beta`;
1097
1098
  /**
1099
+ * PackyCode's GPT route treats a function tool that names no `strict` as
1100
+ * strict, so the model fills every optional parameter. DSH's sandbox
1101
+ * escalation pair then came back as `workspace-write` with an empty
1102
+ * justification, which DSH's edit and write refuse. Declaring strict-mode
1103
+ * support makes pi-ai send `strict: false` on each tool, as the official
1104
+ * Codex client does; the schemas stay as DSH wrote them. DeepSeek and Grok
1105
+ * leave optional parameters out either way.
1106
+ */
1107
+ const GPT_COMPAT = Object.freeze({ supportsStrictMode: true });
1108
+ /**
1098
1109
  * pi-ai thinking-level maps. A level pinned to `null` is unsupported; an
1099
1110
  * absent key keeps pi-ai's own default for that level, which is how `off`
1100
1111
  * stays available for DeepSeek: pi-ai's Responses API then sends
@@ -1141,7 +1152,7 @@ const GROK_LEVELS = Object.freeze({
1141
1152
  ...ALWAYS_THINKING_LEVELS,
1142
1153
  max: null
1143
1154
  });
1144
- /** Gemini 4 Argon and 3.8 Flash support low | medium | high, with no off. */
1155
+ /** Gemini 3.8 Flash supports low | medium | high, with no off. */
1145
1156
  const GEMINI_LEVELS = Object.freeze({
1146
1157
  ...ALWAYS_THINKING_LEVELS,
1147
1158
  xhigh: null,
@@ -1161,6 +1172,19 @@ const PACKYCODE_MODELS = Object.freeze([
1161
1172
  maxTokens: 384e3,
1162
1173
  thinkingLevelMap: DEEPSEEK_LEVELS
1163
1174
  }),
1175
+ Object.freeze({
1176
+ id: "deepseek-v4-pro",
1177
+ name: "DeepSeek V4 Pro",
1178
+ api: "openai-responses",
1179
+ provider: PROVIDER,
1180
+ baseUrl: RESPONSES_BASE,
1181
+ reasoning: true,
1182
+ input: Object.freeze(["text"]),
1183
+ cost: NO_COST,
1184
+ contextWindow: 1e6,
1185
+ maxTokens: 384e3,
1186
+ thinkingLevelMap: DEEPSEEK_LEVELS
1187
+ }),
1164
1188
  Object.freeze({
1165
1189
  id: "gpt-6.1-sol",
1166
1190
  name: "GPT-6.1 Sol",
@@ -1172,7 +1196,8 @@ const PACKYCODE_MODELS = Object.freeze([
1172
1196
  cost: NO_COST,
1173
1197
  contextWindow: 105e4,
1174
1198
  maxTokens: 128e3,
1175
- thinkingLevelMap: ALWAYS_THINKING_LEVELS
1199
+ thinkingLevelMap: ALWAYS_THINKING_LEVELS,
1200
+ compat: GPT_COMPAT
1176
1201
  }),
1177
1202
  Object.freeze({
1178
1203
  id: "gpt-6.1-terra",
@@ -1185,7 +1210,8 @@ const PACKYCODE_MODELS = Object.freeze([
1185
1210
  cost: NO_COST,
1186
1211
  contextWindow: 105e4,
1187
1212
  maxTokens: 128e3,
1188
- thinkingLevelMap: TERRA_LEVELS
1213
+ thinkingLevelMap: TERRA_LEVELS,
1214
+ compat: GPT_COMPAT
1189
1215
  }),
1190
1216
  Object.freeze({
1191
1217
  id: "gpt-6-astra",
@@ -1198,7 +1224,8 @@ const PACKYCODE_MODELS = Object.freeze([
1198
1224
  cost: NO_COST,
1199
1225
  contextWindow: 105e4,
1200
1226
  maxTokens: 128e3,
1201
- thinkingLevelMap: ALWAYS_THINKING_LEVELS
1227
+ thinkingLevelMap: ALWAYS_THINKING_LEVELS,
1228
+ compat: GPT_COMPAT
1202
1229
  }),
1203
1230
  Object.freeze({
1204
1231
  id: "gpt-5.6-sol",
@@ -1211,7 +1238,8 @@ const PACKYCODE_MODELS = Object.freeze([
1211
1238
  cost: NO_COST,
1212
1239
  contextWindow: 105e4,
1213
1240
  maxTokens: 128e3,
1214
- thinkingLevelMap: ALWAYS_THINKING_LEVELS
1241
+ thinkingLevelMap: ALWAYS_THINKING_LEVELS,
1242
+ compat: GPT_COMPAT
1215
1243
  }),
1216
1244
  Object.freeze({
1217
1245
  id: "grok-4.7",
@@ -1227,19 +1255,6 @@ const PACKYCODE_MODELS = Object.freeze([
1227
1255
  thinkingLevelMap: GROK_LEVELS,
1228
1256
  compat: Object.freeze({ supportsLongCacheRetention: false })
1229
1257
  }),
1230
- Object.freeze({
1231
- id: "gemini-4-argon",
1232
- name: "Gemini 4 Argon",
1233
- api: "google-generative-ai",
1234
- provider: PROVIDER,
1235
- baseUrl: GEMINI_BASE,
1236
- reasoning: true,
1237
- input: Object.freeze(["text", "image"]),
1238
- cost: NO_COST,
1239
- contextWindow: 1048576,
1240
- maxTokens: 65536,
1241
- thinkingLevelMap: GEMINI_LEVELS
1242
- }),
1243
1258
  Object.freeze({
1244
1259
  id: "gemini-3.8-flash",
1245
1260
  name: "Gemini 3.8 Flash",
@@ -7654,7 +7669,7 @@ function guardGeminiReplay(open, { model, context, signal, wait = waitForRetry }
7654
7669
  //#endregion
7655
7670
  //#region src/gemini-api.js
7656
7671
  /** Gemini's native API, including level-based thinking on older pi-ai hosts. */
7657
- const GEMINI_MODELS = ["gemini-4-argon", "gemini-3.8-flash"];
7672
+ const GEMINI_MODELS = ["gemini-3.8-flash"];
7658
7673
  /**
7659
7674
  * Google's documented thought signature for a function call whose real one
7660
7675
  * cannot be sent: the API skips signature validation for it.
@@ -7708,10 +7723,10 @@ const skipped = (payload) => ({
7708
7723
  contents: skipThoughtSignatures(payload.contents)
7709
7724
  });
7710
7725
  /**
7711
- * pi-ai 0.85 treats Argon as a budget-based model, and defaults Flash to
7712
- * MINIMAL when reasoning is omitted. Both models support LOW/MEDIUM/HIGH,
7713
- * default to MEDIUM and cannot disable thinking. Keep the native SDK stream,
7714
- * credentials and tools; correct that config and send no real signature.
7726
+ * pi-ai 0.85 defaults Flash to MINIMAL when reasoning is omitted. Flash
7727
+ * supports LOW/MEDIUM/HIGH, defaults to MEDIUM and cannot disable thinking.
7728
+ * Keep the native SDK stream, credentials and tools; correct that config and
7729
+ * send no real signature.
7715
7730
  */
7716
7731
  function createGeminiApi() {
7717
7732
  const api = googleGenerativeAIApi();
@@ -7983,6 +7998,7 @@ const REQUEST_LIMITS = Object.freeze({
7983
7998
  });
7984
7999
  /** Short titles use a smaller model in the same supplier/key group. */
7985
8000
  const TITLE_MODELS = Object.freeze({
8001
+ "deepseek-v4-pro": "deepseek-flash",
7986
8002
  "gpt-6-astra": "gpt-6.1-sol",
7987
8003
  "gpt-5.6-sol": "gpt-6.1-sol",
7988
8004
  "claude-opus-5-5": "claude-haiku-5-5",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-packycode-api",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "description": "Use PackyCode API keys in DeepSeek Harness with multi-protocol models, image generation and editing, separate key rings, and balance display",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",