dsh-packycode-api 1.2.10 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.en.md +36 -55
- package/README.md +35 -54
- package/SECURITY.md +6 -8
- package/lib/client.js +4 -212
- package/lib/index.js +1746 -5080
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.3.0
|
|
4
|
+
|
|
5
|
+
- **Claude runs directly inside the plugin.** Opus, Sonnet and Haiku now use the native Anthropic Messages HTTP route with DSH tools, attachments, permissions, plan mode and durable history. Claude session titles use Haiku over HTTP. No Claude Code installation, login or subprocess is required.
|
|
6
|
+
- **Remove the old CLI subsystem.** Removed the runner, installer, delegation tool, local MCP bridges, CLI settings/RPC/UI and obsolete exports. Existing standalone Claude Code installations are untouched, and images saved by older plugin versions remain viewable.
|
|
7
|
+
- **Preserve native tool execution.** Offered bash/read/write/edit/glob/grep tools declare the CLI-compatible spellings, with other tools using bounded MCP names. Responses map back only to tools offered for that request; arguments, call IDs, validation and permissions remain under DSH. This fixes repeated `unknown tool "Bash"` calls without granting unoffered tools.
|
|
8
|
+
- **Unambiguous working directories.** The legacy cwd sentence is rewritten only when it matches the initiating session's metadata. The exact path is a standalone JSON string and is also explained in shell workdir defaults. Current-project commands are guided to relative paths. Legitimate final dots, Unicode, spaces and Windows drive/UNC/extended paths remain intact; commands and history are never rewritten.
|
|
9
|
+
- **Complete streaming and signed replay.** Responses finish at the protocol terminal frame without waiting for HTTP EOF, split CRLF delimiters survive network chunking, and empty signed thinking blocks survive persisted tool history. Model effort and output limits stay unchanged; thinking display follows the verified client defaults.
|
|
10
|
+
- **Client-policy failures stay separate from invalid keys.** The already-authorized/test-message refusal has its own category and does not disable credentials. Specific captured Haiku/Sonnet tool-context anomalies may repeat the exact request once before streaming begins; ordinary refusals, rate limits and accepted streams do not trigger this guard. This is bounded compatibility handling, not a repair of the gateway's internal policy.
|
|
11
|
+
- Retains 1.2.10's OpenAI upstream-server-error classification and 1.2.11's Gemini signature handling and release-artifact handoff.
|
|
12
|
+
- Validation, 2026-10-17: 395 offline tests, both rebuilt bundles and the versioned package passed. All three Claude models passed text, native tool roundtrip, image input and Chinese title checks (12 checks / 15 model requests, all HTTP 200 with successful stream completion and business validation). The all-model route, in-memory key-rotation and RPC checks passed; Grok completed its stream with a refusal of the exact-marker prompt. Working-directory and PowerShell request regressions retain simulated tool results and are not a Windows desktop execution test. Earlier failed probes remain in local evidence, and the stopped scheduled observation is not a completed six-hour reliability run.
|
|
13
|
+
|
|
14
|
+
## 1.2.11
|
|
15
|
+
|
|
16
|
+
- **Gemini tool continuations send no real thought signature.** Gemini 4 Argon long tasks ended in HTTP 400 `Invalid thought signature.` (`packy_upstream_error`) after DSH's retries. PackyCode support attributes this to its native Gemini route not handling the signature field in tool calls. It advises against resending through that route and recommends that clients ignore the field. Requests for both Gemini models now replace every thought signature with Google's documented `skip_thought_signature_validator`, which also fills the first function call of each step whose response came back unsigned. Only the signature field changes: the protocol (`google-generative-ai`), base URL, model IDs, thinking levels and DSH's stored replay state are unchanged, and no request is routed elsewhere. Google notes that skipped signatures can weaken reasoning continuity across tool steps. Flash keeps its one resend after an HTTP 400 signature refusal; such a refusal still never disables or rotates a key.
|
|
17
|
+
- Validation, 2026-10-16: 458 offline tests (one new; four failed without the change), both rebuilt bundles and the versioned tarball. Live, only the signature field changed between runs.
|
|
18
|
+
- Before: a 14-step Argon tool chain at low effort got 2 `Corrupted thought signature` refusals in 17 requests. A captured request was still accepted after pruning a tool result, editing call arguments or editing the user text, so DSH's history rewriting does not cause the refusals.
|
|
19
|
+
- After: 95 long-chain requests through the built route, carrying up to 26 skip-signed parts and no real signature, all returned HTTP 200 with no refusal. The runs covered Argon at low (14 steps plus a second turn), Argon at high (8 steps), Flash at low (12 steps plus a second turn), and Argon and Flash at high (24 steps plus a second turn each). Every answer was correct.
|
|
20
|
+
- `scripts/gemini-tool-check.mjs` passed 3/3 rounds at high for both models with no resend. `scripts/live-check.mjs` passed for every HTTP model, key rotation and the RPC projections. No DSH restart.
|
|
21
|
+
- **The release job receives the published tarball.** The v1.2.10 tag run published to npm, then its hand-off step found no tarball: `actions/upload-artifact@v4` skips files under a dot directory such as `.artifacts/` unless `include-hidden-files` is set. The release job was therefore skipped, and the v1.2.10 Release was made by hand with the tarball npm serves (its SHA-512 matched `dist.integrity`). The hand-off now sets `include-hidden-files: true`; its glob still matches only the published tarball.
|
|
22
|
+
|
|
3
23
|
## 1.2.10
|
|
4
24
|
|
|
5
25
|
- **OpenAI's transient server error is retried instead of failing the turn.** On the Codex group, a `gpt-6.1-sol` turn sometimes ended in 本轮运行失败 "An error occurred while processing your request. You can retry your request, or contact us through our help center at help.openai.com if the error persists." with `PI_AI_ERROR`. The gateway had already answered HTTP 200 and started the stream when the upstream failed: an SSE `error` event carrying a 503 `server_error`, then `response.failed`, before any output. The OpenAI SDK raises that without an HTTP status, so DSH's adapter, which reads a failure's category from status words, filed it as `PI_AI_ERROR`, a code no retry policy re-runs. The same failure sent as an HTTP 500 is `SERVER` and was already retried. The route now files OpenAI's `server_error` (its sentence, or pi-ai's `server_error:` prefix) as `SERVER` when the adapter left it unclassified, on prepared and direct calls alike, so the route's existing policy (up to 20 retries with backoff) resends the request. Only the code changes: if every retry fails, the upstream sentence still reaches the user, after up to about three minutes, as for an HTTP 500. The key stays enabled and is not rotated. The official Codex client also retries this failure (`ApiError::Retryable`).
|
package/README.en.md
CHANGED
|
@@ -29,7 +29,7 @@ The `PackyCode` model group ships with the plugin. No YAML edits and no separate
|
|
|
29
29
|
| **Keys used in order** | An exhausted or rejected key is disabled and the next usable key takes over; the failed step is retried on that key |
|
|
30
30
|
| **Keys chosen by group** | Each key lists its PackyCode groups and the models they reach; when the active key's groups cannot reach the selected model (no `cc` group for Claude, say), that turn runs on a stored key whose groups can |
|
|
31
31
|
| **Visible balance** | Settings lists each key's remaining, used, limit, reset period, and a usage bar, plus a total of those keys. The composer shows the active key's remaining balance |
|
|
32
|
-
| **Claude
|
|
32
|
+
| **Claude inside the plugin** | All three Claude models use HTTP Messages with DSH tools, permissions and conversation history; no local CLI is needed |
|
|
33
33
|
| **Web search through PackyCode** | Optional: DSH's `web_search` searches through PackyCode, with a DeepSeek or GPT backend, for every request or for PackyCode models only |
|
|
34
34
|
| **Image generation and editing** | Separate image keys, GPT Image 2 / 2.5 Flare / 2.5 Sunburst, model and quality settings, reference edits and original PNG storage; generation and editing verified against the gateway |
|
|
35
35
|
| **Credentials stay on the machine** | Keys live in the DSH credential file. The browser receives labels, state, and balances only |
|
|
@@ -38,7 +38,6 @@ The `PackyCode` model group ships with the plugin. No YAML edits and no separate
|
|
|
38
38
|
<img width="575" height="522" alt="截屏2026-10-15 10 34 49" src="https://github.com/user-attachments/assets/3cf4d090-a4f9-49fe-9ab3-3aab21d6e909" />
|
|
39
39
|
<img width="257" height="309" alt="截屏2026-10-15 10 37 21" src="https://github.com/user-attachments/assets/621cd800-17a2-42f6-8dfe-c1b4be09af61" />
|
|
40
40
|
|
|
41
|
-
|
|
42
41
|
## Install
|
|
43
42
|
|
|
44
43
|
You need **DeepSeek Harness** and a **PackyCode (PackyAPI) API key**. For DSH setup, see the [official instructions](https://github.com/deepseek-ai/deepseek-harness#run). No API key yet? You can register with PackyCode and apply for one through [this invite link](https://www.packyapi.ai/register?aff=Im3l).
|
|
@@ -48,10 +47,10 @@ You need **DeepSeek Harness** and a **PackyCode (PackyAPI) API key**. For DSH se
|
|
|
48
47
|
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
48
|
|
|
50
49
|
```text
|
|
51
|
-
dsh-packycode-api@1.
|
|
50
|
+
dsh-packycode-api@1.3.0
|
|
52
51
|
```
|
|
53
52
|
|
|
54
|
-
Choose the **official** install source, then click **Install**. `1.
|
|
53
|
+
Choose the **official** install source, then click **Install**. `1.3.0` was the latest release when this was written; the [npm page](https://www.npmjs.com/package/dsh-packycode-api) shows the current one.
|
|
55
54
|
|
|
56
55
|
> **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
56
|
|
|
@@ -65,14 +64,14 @@ Open **Settings → PackyCode**. Paste the API key under **Add a key**. A label
|
|
|
65
64
|
|
|
66
65
|
### 3. Select a model
|
|
67
66
|
|
|
68
|
-
Choose a model from the `PackyCode` group.
|
|
67
|
+
Choose a model from the `PackyCode` group. All nine models use the plugin’s HTTP route. Your key’s groups must cover the selected model.
|
|
69
68
|
|
|
70
69
|
<details>
|
|
71
70
|
<summary>Verify the install / other profiles / a local checkout</summary>
|
|
72
71
|
|
|
73
72
|
The **Plugins** page shows the installed state and version, and is also where you enable, disable, or uninstall.
|
|
74
73
|
|
|
75
|
-
**For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.
|
|
74
|
+
**For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.3.0`. Do not use it for `desktop` — the CLI refuses it (`profile "desktop" is managed exclusively by the Electron application`).
|
|
76
75
|
|
|
77
76
|
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
77
|
|
|
@@ -86,11 +85,11 @@ A profile without a browser can still use the model route. It just has no settin
|
|
|
86
85
|
|
|
87
86
|
**Switch keys.** Keys are used in the order they were added. **Use this key** picks the preferred key, effective from the next turn; **Rename** changes its label (at most 60 characters, empty names are refused); **Re-enable** puts a disabled key back after a top-up or replacement.
|
|
88
87
|
|
|
89
|
-
**See groups.** Under **Accounts and keys**, each key lists its PackyCode groups (hover for the group's description) and which models they reach: ✓ yes, ◐ partly, ✕ no. The groups come from the gateway itself (its refusal of a model id it cannot route names the token's groups; nothing is billed), matched against PackyCode's public model-group table. Claude
|
|
88
|
+
**See groups.** Under **Accounts and keys**, each key lists its PackyCode groups (hover for the group's description) and which models they reach: ✓ yes, ◐ partly, ✕ no. The groups come from the gateway itself (its refusal of a model id it cannot route names the token's groups; nothing is billed), matched against PackyCode's public model-group table. Check Claude group coverage per model; do not assume `cc-sale` serves all three models; GPT needs `codex` / `codex-sale`; DeepSeek needs `deepseek-officially` / `deepseek-sale`.
|
|
90
89
|
|
|
91
90
|
**Read the balance.** The total at the top of **Accounts and keys** is the remaining, used, and limit of **the keys listed here**, not the bill for every token on the PackyCode account. A key that could not be read is left out of the total and counted in a note; a key whose read failed this time but succeeded before keeps showing its last balance with the time it was read (the composer shows it as `≈US$…`) until DSH restarts. The composer shows the active key's remaining balance only while a PackyCode model is selected. **Refresh** bypasses the roughly 60-second cache. The default model host is `https://cf.api.fan` and the balance host is `https://www.packyapi.ai`; both can be changed under **Advanced: endpoints**. The old default, `https://www.packyapi.com`, is DNS-poisoned on mainland networks and answers `fetch failed` without a proxy; even when settings still name it, `.ai` is tried first.
|
|
92
91
|
|
|
93
|
-
**Use Claude.**
|
|
92
|
+
**Use Claude.** Select any Claude model directly; no CLI installation is needed. Reasoning effort is sent to the model. DSH owns the history, attachments, tool loop, plan mode and permissions.
|
|
94
93
|
|
|
95
94
|
**Web search.** DSH's `web_search` calls DeepSeek's official API by default (billed to `DEEPSEEK_API_KEY`). **Settings → PackyCode → Web search** can route it through PackyCode instead:
|
|
96
95
|
|
|
@@ -107,17 +106,7 @@ A profile without a browser can still use the model route. It just has no settin
|
|
|
107
106
|
|
|
108
107
|
PackyCode has no dedicated search endpoint: one search is one model call with a server-side search tool, billed to the keys stored here. An exhausted or rejected key rotates exactly as on the model route.
|
|
109
108
|
|
|
110
|
-
**Claude
|
|
111
|
-
|
|
112
|
-
```text
|
|
113
|
-
Claude Code CLI → temporary local MCP web_search → selected PackyCode DeepSeek/GPT backend
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
- **Backend selection applies to CLI; routing selection only applies to DSH.** Even with Off/Do not take over selected, CLI searches use the selected backend, not DSH's default. A backend change applies to the next search.
|
|
117
|
-
- Ordinary Claude requests still need a Claude-group key. Search needs a plugin-stored key covering DeepSeek or GPT; it can be another key. Failures are returned to the CLI, with no invented success or automatic switch to another backend.
|
|
118
|
-
- Read-only/edit modes auto-approve only this specific read-only MCP search tool, without adding shell or file-write privileges. User/managed denials still apply. CLI `--allowedTools` is an additive auto-approval list, not an exclusive tool whitelist; existing other permissions are preserved.
|
|
119
|
-
- At most 8 searches per invocation, 2 concurrently, 2000 characters per query and 8 sources per result, with a 60-second end-to-end search deadline. Title generation allocates no MCP server or search grant.
|
|
120
|
-
- Reasoning reports `▸ 网页搜索:PackyCode DeepSeek(MCP,原生 WebSearch 已禁用)` (or GPT). The temporary server binds only `127.0.0.1`; its private config contains an independent one-run capability, never a search API key. CLI completion/cancellation/timeout/plugin unload revokes it and removes the private config, leaving existing user MCP configurations untouched.
|
|
109
|
+
**Claude search.** Claude uses DSH’s `web_search` with the routing choices above and the same stored-key rules as other native models.
|
|
121
110
|
|
|
122
111
|
<details>
|
|
123
112
|
<summary>How web search is wired into DSH</summary>
|
|
@@ -136,8 +125,8 @@ Claude Code CLI → temporary local MCP web_search → selected PackyCode DeepSe
|
|
|
136
125
|
<summary>When a key is rotated</summary>
|
|
137
126
|
|
|
138
127
|
- **Rotates and disables the current key:** the gateway reports exhausted quota, or it rejects the key (HTTP 401 / invalid token). The harness retries the failed step, which is what actually sends it on the next key.
|
|
139
|
-
- **Passes over a key by its groups, without disabling it:** when the group reading shows the active key cannot reach this turn's model and another stored key can, the turn runs on that key (
|
|
140
|
-
- **Does not rotate:** rate limits (429); a 400 that this gateway uses for a dead upstream channel; and a 403 that means the group accepts only the vendor's official client.
|
|
128
|
+
- **Passes over a key by its groups, without disabling it:** when the group reading shows the active key cannot reach this turn's model and another stored key can, the turn runs on that key (an explicit Claude Code delegation says so in its reasoning: “当前 Key「A」的分组不能用 …,本轮改用 Key「B」”). The active key stays active for every other model. Only evidence counts: a key whose groups are not read yet is used as before.
|
|
129
|
+
- **Does not rotate:** rate limits (429); a 400 that this gateway uses for a dead upstream channel; and a 403 that means the group accepts only the vendor's official client. The separate 403 saying the client is already authorized and should not send connectivity test messages is classified as `GATEWAY_TEST_MESSAGE`. It explains the refusal without disabling the key. Only Haiku tool context may replay it once under the bounds below.
|
|
141
130
|
- When every stored key is disabled, the request fails and says so. There is no fallback credential.
|
|
142
131
|
|
|
143
132
|
</details>
|
|
@@ -150,7 +139,7 @@ The image card shows each image key's remaining/used quota, limits when supplied
|
|
|
150
139
|
|
|
151
140
|
Choose the image model and quality, then click **Create image** in a PackyCode conversation or explicitly request `packycode_image_generate`. Attach references and describe changes to use `/v1/images/edits`; new images use `/v1/images/generations`. The image model is independent of the conversation model and other image plugins can coexist.
|
|
152
141
|
|
|
153
|
-
|
|
142
|
+
Claude generates and edits images through DSH’s `packycode_image_generate`, with the same separate image key, preferences and balance cache as other models. Saved images from older CLI-backed sessions remain viewable without regeneration.
|
|
154
143
|
|
|
155
144
|
**Image visible in tool details but unavailable in the final answer:** a standalone main-chat gallery remains visible when reasoning/tool details are collapsed, including PTC child calls. Reopening an existing conversation restores the gallery from its saved attachments without regenerating or spending image quota. An old invalid Markdown image link to a host path does not affect this gallery.
|
|
156
145
|
|
|
@@ -174,9 +163,9 @@ Live checks on 2026-10-15 passed generation and editing at `low` on all three en
|
|
|
174
163
|
| `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 |
|
|
175
164
|
| `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` |
|
|
176
165
|
| `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` |
|
|
177
|
-
| `claude-opus-5-5` |
|
|
166
|
+
| `claude-opus-5-5` | HTTP, Anthropic Messages, images and native tools | Cannot be off; `low` / `medium` / `high` / `xhigh` / `max` | Claude-group coverage reported in Settings |
|
|
178
167
|
| `claude-sonnet-5-5` | Same | Same | Same |
|
|
179
|
-
| `claude-haiku-5-5` | Same;
|
|
168
|
+
| `claude-haiku-5-5` | Same; also generates Claude session titles | Same | Same |
|
|
180
169
|
|
|
181
170
|
A model in the list does not mean the current token group allows it. When changing groups, do not drop the group that serves the model you still want.
|
|
182
171
|
|
|
@@ -184,36 +173,34 @@ All nine models in the current catalog declare text and image input. DeepSeek Fl
|
|
|
184
173
|
|
|
185
174
|
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).
|
|
186
175
|
|
|
187
|
-
**
|
|
176
|
+
**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.
|
|
188
177
|
|
|
189
178
|
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.
|
|
190
179
|
|
|
191
180
|
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.
|
|
192
181
|
|
|
193
182
|
<details>
|
|
194
|
-
<summary>Protocol, group
|
|
195
|
-
|
|
196
|
-
-
|
|
197
|
-
-
|
|
198
|
-
- The
|
|
199
|
-
-
|
|
200
|
-
-
|
|
201
|
-
-
|
|
202
|
-
-
|
|
203
|
-
-
|
|
204
|
-
-
|
|
205
|
-
- The
|
|
206
|
-
-
|
|
207
|
-
-
|
|
208
|
-
-
|
|
209
|
-
- The `claude_code` tool can delegate one task to the local CLI while the session model is `gpt-6.1-sol`, `gpt-6-astra`, or `deepseek-flash`. The requested `mode` cannot exceed what the session preset allows. While the session is in plan mode the delegation plans too, and returns the plan text to the parent model.
|
|
210
|
-
- An effort level the model does not support is rejected before the request is sent. Do not edit a model's effort map casually.
|
|
183
|
+
<summary>Protocol, group and client compatibility</summary>
|
|
184
|
+
|
|
185
|
+
- All nine models use HTTP inside the plugin. Claude keeps `anthropic-messages`, with a base URL without `/v1`; the SDK appends `/v1/messages`. Model ids, protocols, context limits and effort mappings are unchanged.
|
|
186
|
+
- Claude requests use the live-verified CLI-compatible headers, bearer authentication, session metadata and identity system prefix while preserving DSH instructions, tool schemas, images and signed replay. The compatibility version is pinned to `2.1.295`; no local CLI is detected or started for a model turn.
|
|
187
|
+
- The bearer comes only from the plugin’s stored key chosen for the model. No CLI login, external configuration, ambient key or alternate provider is used.
|
|
188
|
+
- This compatibility envelope does not remove the gateway’s group restrictions. The key still needs Claude coverage. Client-policy refusals are explained without disabling a key or falling back to a CLI. Server changes may invalidate the envelope; see [PackyCode group policy](https://docs.packyapi.ai/docs/token/).
|
|
189
|
+
- Identical Haiku and Sonnet tool requests have been both refused with the captured client-anomaly 403 and accepted. The plugin waits one second and repeats the unchanged request once for that response. Haiku also covers the captured already-authorized/test-message 403, sharing the same one-replay limit. A second refusal remains visible. Opus, plain text, ordinary official-CLI-only refusals, 429s and accepted streams do not trigger this replay. Records retain the original failures; this does not establish a repair of the gateway's internal classifier.
|
|
190
|
+
- 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.
|
|
191
|
+
- 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. 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.
|
|
192
|
+
- 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.
|
|
193
|
+
- Native Claude turns retain the full DSH tool loop, permissions and plan mode, using host search and image tools. Claude titles use Haiku over HTTP; Astra titles still use Sol.
|
|
194
|
+
- The old `claude_code` delegation tool, CLI runner, detection/installation UI, configuration fields and local MCP bridges have been removed. Old `claudeCliPath`, `claudeCliMode` and `claudeCliCwd` settings no longer affect requests. Separately installed Claude Code remains untouched.
|
|
195
|
+
- Codex Responses requests still need `prompt_cache_key`; the plugin supplies a missing session identity. Other Responses families omit it.
|
|
196
|
+
- 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 and Chinese titles, validating the business answers. `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.
|
|
197
|
+
- For continuous dialogs, use `node scripts/claude-conversation-check.mjs --model claude-haiku-5-5 --rounds 3 --key-label <label> --output .artifacts/claude-conversation.json`. One plugin adapter handles independent sessions; each group retains six user turns and full tool history, validates arithmetic, final JSON and unexpected characters, and stops on a failure without discarding evidence. Requests default to 65 seconds and 2048 output tokens. Diagnostic overrides use `--timeout-ms` (5000–300000) and `--max-tokens` (1024–128000). `--capture-wire` records the synthetic business requests, non-authentication headers and partial stream events for exact replay, without keys. Reports include scenario and adapter lifecycle, configured limits, response-header latency and total response time. These options do not alter the plugin's runtime settings.
|
|
211
198
|
|
|
212
199
|
</details>
|
|
213
200
|
|
|
214
201
|
## Update and uninstall
|
|
215
202
|
|
|
216
|
-
**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 from the **Plugins** page works too, again with the version in the package name (for example `dsh-packycode-api@1.
|
|
203
|
+
**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 from the **Plugins** page works too, again with the version in the package name (for example `dsh-packycode-api@1.3.0`); without it you may get a version that is merely the newest one published at least 24 hours ago.
|
|
217
204
|
|
|
218
205
|
**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.
|
|
219
206
|
|
|
@@ -229,7 +216,7 @@ ls ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/node_modules
|
|
|
229
216
|
|
|
230
217
|
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.
|
|
231
218
|
|
|
232
|
-
Recovery: **uninstall** the plugin on the **Plugins** page, **install** it again with the version in the package name (for example `dsh-packycode-api@1.
|
|
219
|
+
Recovery: **uninstall** the plugin on the **Plugins** page, **install** it again with the version in the package name (for example `dsh-packycode-api@1.3.0`), 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.
|
|
233
220
|
|
|
234
221
|
**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:
|
|
235
222
|
|
|
@@ -243,25 +230,25 @@ Recovery: quit and reopen the desktop application, and the old version works. Th
|
|
|
243
230
|
|
|
244
231
|
**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.
|
|
245
232
|
|
|
246
|
-
**Claude
|
|
233
|
+
**Claude reports an official-client-only or client-anomaly refusal?** This is a gateway client-policy refusal, not proof of an invalid key. Check the selected model’s group coverage under **Accounts and keys** and in PackyCode’s model catalog, then collect diagnostics if a covered model is still refused. The plugin does not disable the key, switch providers or start a CLI for this refusal.
|
|
247
234
|
|
|
248
235
|
**The balance does not match the account bill?** Settings totals only the keys stored here, not other tokens on the same PackyCode account. A key that failed to read is noted separately and is not treated as zero.
|
|
249
236
|
|
|
250
237
|
**The balance reads `fetch failed` from `https://www.packyapi.com`?** That host, the default through 1.0.4, is DNS-poisoned on mainland networks and only answers through a proxy, so it works on and off. The default is now `https://www.packyapi.ai`. The model list is built into the plugin and never queried from PackyCode, so it is unaffected.
|
|
251
238
|
|
|
252
|
-
**A Claude model
|
|
239
|
+
**A Claude model stays on “thinking”?** Check DSH errors or diagnostics. HTTP 429/503 means gateway queueing or throttling and follows the host retry policy; client-policy refusals are explained directly. Native model turns never start a local CLI.
|
|
253
240
|
|
|
254
241
|
**A rate limit disabled the key?** It should not. HTTP 429 does not rotate. Exhausted quota or HTTP 401 does; after a top-up, click **Re-enable**.
|
|
255
242
|
|
|
256
243
|
**Installing from the Plugins page fails with `ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION`?** By default pnpm accepts only versions published at least 24 hours ago and checks the whole profile lockfile. (Entering only this plugin's bare name does not raise this error; it silently installs an older version that has passed 24 hours instead, see **Install the plugin**.) The package it names is often another plugin that was just updated, not this one. Retry once it is 24 hours old, or add the reported `name@version` under `minimumReleaseAgeExclude` in the profile's `pnpm-workspace.yaml`. Once this plugin is installed, **Update plugin** in Settings is not subject to that check.
|
|
257
244
|
|
|
258
|
-
**
|
|
245
|
+
**Do I still need the previously installed Claude Code?** This plugin no longer runs, installs or delegates to a CLI. Claude models use HTTP directly. Keep Claude Code if you use it separately; this plugin does not modify its installation or configuration.
|
|
259
246
|
|
|
260
247
|
**Replies stop at the output token limit (已达到输出 token 上限), or requests keep failing — how do I report it?** Open **Settings → PackyCode → Diagnostics**, pick the session (the 20 most recent, newest first, labelled with their folder name), click **Generate diagnostics** and then **Copy**, and paste the text into an [Issue](https://github.com/BaronCyrus/dsh-packycode-api/issues) or send it to the plugin author. It holds settings and numbers only: the plugin version, the session id and start time, each key's position and groups (no labels, no keys), each request's model, reasoning effort and output limit, the latest steps' token usage and finish reasons, and retry and failure codes (messages redacted and shortened). It contains no conversation text, file paths or keys. Where copying is unavailable, the text is selected instead; press ⌘C or Ctrl+C.
|
|
261
248
|
|
|
262
249
|
## Security and scope
|
|
263
250
|
|
|
264
|
-
This is a community plugin, not affiliated with or endorsed by DeepSeek or PackyCode. Model requests go to the PackyCode host you configured. Keeping credentials out of browser responses does not mean inference is local. Claude
|
|
251
|
+
This is a community plugin, not affiliated with or endorsed by DeepSeek or PackyCode. Model requests go to the PackyCode host you configured. Keeping credentials out of browser responses does not mean inference is local. Claude also uses the plugin’s native HTTP route.
|
|
265
252
|
|
|
266
253
|
Keys stay in the local DSH credential file (`~/.dsh/.credentials.yaml`, owner-only as enforced by DSH). They are not written into settings, logs, or the transcript. Balance requests run only on the host, with a timeout and redirects refused.
|
|
267
254
|
|
|
@@ -278,13 +265,7 @@ pnpm run check
|
|
|
278
265
|
|
|
279
266
|
`pnpm run check` runs every test, rebuilds, and writes a tarball under `.artifacts/`. `lib/` is a committed build; regenerate it with `pnpm run build` after editing `src/`, and do not hand-edit it.
|
|
280
267
|
|
|
281
|
-
`node scripts/live-check.mjs` checks the live gateway through the same route the plugin registers: balance and groups, one answer per HTTP model, a rotation rehearsal, and the failure classification, printing only the key's last four characters. `--with-
|
|
282
|
-
|
|
283
|
-
`node scripts/cli-search-check.mjs` runs the real CLI against a local test gateway and MCP bridge; Claude responses and search data are mocked by default, with no quota consumed. It checks all three permission modes, native-search exclusion and temporary-resource cleanup. `--live --backend deepseek` or `--live --backend gpt` sends the read-only mode's one search to the real backend (edit/full remain mocked). This does not verify actual Claude upstream turns or a running DSH integration.
|
|
284
|
-
|
|
285
|
-
`node scripts/cli-image-check.mjs` checks the real official CLI generating an image, editing its result, and persisting both through DSH's message assembler. Default model/image responses are local fixtures, covering read-only/edit/full/plan/title modes and temporary-config cleanup. `--live` makes one real Sunburst low-quality generation and one edit using the stored image key, while Claude replies remain local fixtures. `--with-claude` additionally uses a real Claude upstream turn (Haiku by default), consuming conversation quota too. Outputs go under `.artifacts/`; neither option starts DSH or claims a running desktop conversation was tested.
|
|
286
|
-
|
|
287
|
-
`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.
|
|
268
|
+
`node scripts/live-check.mjs` checks the live gateway through the same route the plugin registers: balance and groups, one answer per HTTP model, a rotation rehearsal, and the failure classification, printing only the key's last four characters. `--with-search` runs one search per backend; the default run spends a small amount of quota.
|
|
288
269
|
|
|
289
270
|
`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.
|
|
290
271
|
|