dsh-packycode-api 1.4.8 → 1.4.10

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,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.4.10
4
+
5
+ - **Auto review works again on DSH 0.2.2.** DSH 0.2.2-rc.2 changed the official reviewer's model request: the system prompt is still `REVIEW_POLICY`, but the user message is now the environment followed by one JSON Session item per message, with the pending tool call last, instead of 0.2.1's one message holding four labelled sections. The plugin recognized only the old layout, so on 0.2.2 it passed every review through to the session model: a chosen Jev or DeepSeek Flash reviewer was never used, and a session model that rejects `temperature` failed the review with `Unsupported parameter: temperature` (GPT-6.1 Terra and GPT-5.6 Sol do; DeepSeek accepts it). The plugin now recognizes the official reviewer by its fixed policy prompt, reads both layouts, and fails a review it cannot read instead of silently passing it through. Jev's state is built from the 0.2.2 items too (the environment, `user-instruction` and other roles, tool schemas, and the pending call with its arguments and schema), and its authorization question names both role spellings.
6
+ - **The route drops the review's `temperature`.** Some models behind the gateway reject the official request's `temperature: 0` outright, and a review's answer does not depend on sampling. The route removes it from official review requests only (recognized by `purpose: 'auto-review'` or the fixed policy prompt), so the `session` reviewer also works on those models; ordinary turns keep their temperature.
7
+ - Validation, 2026-11-13:
8
+ - **Offline:** 576 tests (new: 0.2.2's request is recognized and read into its environment, items and pending call; Jev's state is built from it; the controller answers it with `jev-1.14.0` and re-addresses it to DeepSeek Flash; an unreadable layout fails closed instead of passing through; the route strips temperature from both 0.2.1- and 0.2.2-shaped review requests and keeps it on ordinary turns), both rebuilt bundles and the versioned tarball.
9
+ - **Live, `scripts/live-check.mjs` with the test key:** 0.2.1 and 0.2.2 review requests were answered by `jev-1.14.0` (allow: 1.8 s and 2.6 s; deny: 1.3 s and 1.5 s) and by DeepSeek Flash (allow: 1.8 s and 2.4 s; deny: 1.9 s and 1.7 s), all eight decisions correct. All other catalog models answered except `gemini-4-argon`, which the gateway failed upstream with `Publisher model ...` before this change's code ran; key rotation, the rejected-key classification, the RPC projections and the Claude CLI route were unchanged.
10
+ - **Not checked:** the desktop app's own 0.2.2 review flow end to end (its request is reproduced from the 0.2.2-rc.2 source), and the settings card in the desktop app.
11
+
12
+ ## 1.4.9
13
+
14
+ - **Auto review asks `jev-1.14.0`.** PackyCode retired the `jev-latest` alias: on 2026-11-13 `/api/pricing` lists `jev-1.14.0` and `jev-1.13.0` in `typesafe-officially` and no `jev-latest`, and a `/v1/systemone` request naming `jev-latest` is refused before any upstream (`400 model_not_found`, `当前令牌未覆盖供应商`), while `jev-1.14.0` answered in about 1.3 s. The reviewer, the classifier descriptor whose group coverage the settings read, the denial reasons and every failure sentence now use `jev-1.14.0`.
15
+ - **A saved `jev-latest` choice keeps working.** Taking the alias out of the Config schema would make the plugin's Config fail to parse for anyone who had picked it. The schema keeps it as a hidden value, and the preference reader maps it to `jev-1.14.0` (`RETIRED_AUTO_REVIEW_MODELS` in `src/auto-review.js`). The card offers only the versioned reviewer and refuses the alias on write.
16
+ - Validation, 2026-11-13:
17
+ - **Offline:** 570 tests (new: a saved `jev-latest` parses through the plugin Config, stays out of the offered choices, reads as `jev-1.14.0` in the preference, the status and the `llm/stream` listener, and is refused on write; Jev's request body, denial reason and coverage sentence name `jev-1.14.0`; the classifier descriptor, the client's coverage line and the settings card use it), both rebuilt bundles and the versioned tarball.
18
+ - **Live, `scripts/live-check.mjs` with the test key:** the group reading reached `jev-1.14.0`. The official review request was answered by `jev-1.14.0` with allow → allow (low risk) in 0.46 s and deny → deny (high risk) in 0.47 s, and by DeepSeek Flash with 1.28 s and 1.50 s. All fourteen catalog models answered through the route, and key rotation, the rejected-key classification, the RPC projections and the Claude CLI route were unchanged. A direct `/v1/systemone` request named `jev-1.14.0` answered; one naming `jev-latest` was refused.
19
+ - **Not checked:** the settings card in the desktop app (its rendering is covered by the built-bundle test, not by a look at the app). The id is pinned, so the next time PackyCode retires a Jev version the constant needs the same change.
20
+
3
21
  ## 1.4.8
4
22
 
5
23
  - **Claude Fable 5.2 joins the catalog.** On 2026-11-11 `/api/pricing` lists `claude-fable-5-2` with the `anthropic` endpoint alone, in `cc`, `cc-sale`, `cc-expensive`, `claude-officially` and `aws-q`. It takes the route of the other Claude models: `anthropic-messages` at `https://cf.api.fan`, text and image input, 1,000,000 context and 128,000 output, first in the picker's Claude models. Anthropic's [Claude Fable 5.2 overview](https://platform.claude.com/docs/en/models/fable-5-2/overview) gives the 1M context window (its default and maximum) and 128K output, thinking that is always on and adaptive, `output_config.effort` `low` to `max` as the only depth control, and no `temperature`; so it offers `low` / `medium` / `high` / `xhigh` / `max` and cannot be turned off, like the 5.5 models. A key in `cc` runs it through the Claude Code CLI as the agent; the other Claude groups use HTTP, where it asks for progress-update thinking (`display: "updates"` with the `thinking-display-updates-2026-08-18` beta) as Opus and Sonnet 5.5 do. Its session titles run on `claude-haiku-5-5`. The settings page counts it in each key's Claude coverage, and `scripts/claude-check.mjs` and `scripts/claude-agent-check.mjs` include it; the six-hour `scripts/claude-stability.mjs` window still samples the three 5.5 models, which its request budget is sized for.
package/README.en.md CHANGED
@@ -32,7 +32,7 @@ The `PackyCode` model group ships with the plugin. No YAML edits and no separate
32
32
  | **Claude route by group** | The `cc` group only serves the official client, so Claude sessions on `cc` keys are carried out by this device's Claude Code itself, with its own system prompt and tools, while DSH shows every tool call and handles permissions, plan review and questions; `cc-sale`, `cc-expensive`, `claude-officially` and other groups use the plugin's HTTP route with DSH's own agent |
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.6 Flare / 2.6 Sunburst, model and quality settings, reference edits and original PNG storage; generation and editing verified against the gateway |
35
- | **Auto review on your model** | With DSH's built-in “Auto authorization review” switched on, the permission menu's Auto review can review each tool call with jev-latest or DeepSeek Flash; the rules and outcomes stay the official ones |
35
+ | **Auto review on your model** | With DSH's built-in “Auto authorization review” switched on, the permission menu's Auto review can review each tool call with jev-1.14.0 or DeepSeek Flash; the rules and outcomes stay the official ones |
36
36
  | **Credentials stay on the machine** | Keys live in the DSH credential file. The browser receives labels, state, and balances only |
37
37
 
38
38
  <img width="774" height="455" alt="截屏2026-10-15 10 34 28" src="https://github.com/user-attachments/assets/c5eaa535-dd1e-4e2f-be9f-c181404d4dd6" />
@@ -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.8
51
+ dsh-packycode-api@1.4.10
52
52
  ```
53
53
 
54
- Choose the **official** install source, then click **Install**. `1.4.8` 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.10` 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 thirteen models, Claude runs t
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.8`. 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.10`. 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
 
@@ -185,10 +185,12 @@ By default DSH reviews with the conversation's own model. This plugin leaves the
185
185
 
186
186
  | Reviewer | Notes | Group needed |
187
187
  | --- | --- | --- |
188
- | jev-latest (default) | TypeSafe's decision classifier: about 0.4 s per review, billed by input only; a denial names only the risk level | `typesafe-officially` |
188
+ | jev-1.14.0 (default) | TypeSafe's decision classifier: about 0.4 s per review, billed by input only; a denial names only the risk level | `typesafe-officially` |
189
189
  | DeepSeek Flash | About 2 s per review, and a denial says why | `deepseek-officially` / `deepseek-sale` |
190
190
  | Conversation model | Leave the review alone, as DSH does by default | — |
191
191
 
192
+ A saved `jev-latest` still works and reviews with `jev-1.14.0`.
193
+
192
194
  Steps:
193
195
 
194
196
  1. Switch on “Auto authorization review” on DSH's Plugins page in the sidebar.
@@ -202,21 +204,21 @@ The card shows whether DSH's plugin is on, how many reviews this plugin answered
202
204
 
203
205
  - DSH's reviewer sends one model request per review:
204
206
  - its fixed `REVIEW_POLICY` as the system prompt;
205
- - four JSON sections as the user message: ENVIRONMENT, PROJECT_INSTRUCTIONS, FILTERED_HISTORY, PENDING_ACTION;
206
- - and it expects one `{"risk","decision","reason"?}` object back.
207
+ - DSH 0.2.1 puts the review in one user message holding four JSON sections: ENVIRONMENT, PROJECT_INSTRUCTIONS, FILTERED_HISTORY, PENDING_ACTION; DSH 0.2.2 sends the environment first and then one JSON Session item per message, the pending tool call last. The plugin reads both layouts;
208
+ - and it expects one `{"risk","decision","reason"?}` object back. Its `temperature: 0` is dropped before a PackyCode model sees it: GPT-6.1 Terra and GPT-5.6 Sol reject it with `Unsupported parameter: temperature`, and the review's answer does not depend on sampling.
207
209
  - Every model request passes DSH's `llm/stream` waterfall. The plugin recognizes only this request there; conversation turns and everything else go on untouched.
208
210
  - **DeepSeek Flash** gets the same request, re-addressed to the PackyCode route; DSH still reads its answer.
209
- - **jev-latest** cannot write that object. The plugin passes the four sections and the official policy text to System One as the state and asks two questions: the risk, and whether you explicitly asked for this action.
211
+ - **jev-1.14.0** cannot write that object. The plugin passes the four sections and the official policy text to System One as the state and asks two questions: the risk, and whether you explicitly asked for this action.
210
212
  - It allows a call when the probability of "low risk, or medium risk you asked for" is at least 0.6 and that of high risk is below 0.2.
211
- - A denial says that jev-latest judged the call medium or high risk.
212
- - jev-latest has a small context, so a long history is cut starting from the oldest entries; your instructions are kept first.
213
- - What is reviewed, the rules, and what an allow or a denial does all stay DSH's. DSH refuses a call whose review failed (for example, no key reaches jev-latest), and the plugin keeps that.
213
+ - A denial says that jev-1.14.0 judged the call medium or high risk.
214
+ - jev-1.14.0 has a small context, so a long history is cut starting from the oldest entries; your instructions are kept first.
215
+ - What is reviewed, the rules, and what an allow or a denial does all stay DSH's. DSH refuses a call whose review failed (for example, no key reaches jev-1.14.0), and the plugin keeps that.
214
216
  - Measured on 37 scenarios with the official request format and the official parser: both reviewers matched all 35 scenarios that have a clear answer.
215
- - jev-latest's median was 0.35 s, DeepSeek Flash's 2.3 s.
216
- - If a later DSH changes the review request:
217
- - a request the plugin no longer recognizes goes on untouched, reviewed by the conversation model;
218
- - a format jev-latest cannot read fails that review, which shows in the card's counts.
219
- - The description under Auto review in the menu says the same model reviews; that is DSH's text. With jev-latest or DeepSeek Flash chosen, that model reviews.
217
+ - jev-1.14.0's median was 0.35 s, DeepSeek Flash's 2.3 s.
218
+ - If a later DSH changes the review request again:
219
+ - as long as the system prompt is still `REVIEW_POLICY`, the plugin still takes the request over; a layout it cannot read fails that review (so DSH refuses the call) instead of silently falling back to the conversation model;
220
+ - a format jev-1.14.0 cannot read fails that review, which shows in the card's counts.
221
+ - The description under Auto review in the menu says the same model reviews; that is DSH's text. With jev-1.14.0 or DeepSeek Flash chosen, that model reviews.
220
222
 
221
223
  </details>
222
224
 
@@ -241,7 +243,7 @@ The card shows whether DSH's plugin is on, how many reviews this plugin answered
241
243
 
242
244
  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.
243
245
 
244
- `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.
246
+ `jev-1.14.0` (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). PackyCode lists it by version and no longer offers the `jev-latest` alias, so the plugin sends `jev-1.14.0` itself. It calls `/v1/systemone` host-side and needs a key in the `typesafe-officially` group; each key's Jev entry under Accounts and keys shows whether it can.
245
247
 
246
248
  Of the thirteen 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.
247
249
 
@@ -280,9 +282,9 @@ DeepSeek Flash uses the gateway's Responses endpoint (`/api/pricing` lists `open
280
282
 
281
283
  ## Update and uninstall
282
284
 
283
- > **Upgrading from 1.3.2 or earlier:** install `dsh-packycode-api@1.4.8` 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.
285
+ > **Upgrading from 1.3.2 or earlier:** install `dsh-packycode-api@1.4.10` 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.
284
286
 
285
- **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.8`); without it you may get a version that is merely the newest one published at least 24 hours ago.
287
+ **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.10`); without it you may get a version that is merely the newest one published at least 24 hours ago.
286
288
 
287
289
  **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.
288
290
 
@@ -298,7 +300,7 @@ ls ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/node_modules
298
300
 
299
301
  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.
300
302
 
301
- 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.8`), 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.
303
+ 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.10`), 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.
302
304
 
303
305
  **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:
304
306
 
package/README.md CHANGED
@@ -32,7 +32,7 @@
32
32
  | **Claude 按分组选通道** | `cc` 分组只接受官方客户端,这些 Key 的 Claude 会话由本机 Claude Code 自己完成:它用自己的系统提示词和工具做事,DSH 显示每次工具调用,并负责授权、计划审阅和提问;`cc-sale`、`cc-expensive`、`claude-officially` 等分组走插件内 HTTP,由 DSH 自己的 agent 执行 |
33
33
  | **网页搜索可走 PackyCode** | 可选:DSH 的 `web_search` 改用 PackyCode 搜索,后端在 DeepSeek 与 GPT 之间切换;可只对 PackyCode 模型生效 |
34
34
  | **图片生成与编辑** | 独立图片 Key,支持 GPT Image 2 / 2.6 Flare / 2.6 Sunburst、型号与质量设置、参考图编辑和 PNG 原图保存;已通过网关生图与编辑实测 |
35
- | **自动审查可换模型** | 开启 DSH 自带的「自动授权审查」后,权限菜单里的「自动审查」可改用 jev-latest 或 DeepSeek Flash 审查每次工具调用,审查规则和处理方式保持官方原样 |
35
+ | **自动审查可换模型** | 开启 DSH 自带的「自动授权审查」后,权限菜单里的「自动审查」可改用 jev-1.14.0 或 DeepSeek Flash 审查每次工具调用,审查规则和处理方式保持官方原样 |
36
36
  | **凭据不离开本机** | Key 只存在 DSH 凭据文件里。浏览器只能看到备注、状态和余额,拿不到 Key |
37
37
 
38
38
  <img width="774" height="455" alt="截屏2026-10-15 10 34 28" src="https://github.com/user-attachments/assets/060c4192-00ea-40e6-9b85-bbec605b5c31" />
@@ -48,10 +48,10 @@
48
48
  打开桌面应用的**插件**页,点击**添加插件**,在**包名或地址**中填入**带版本号**的包名:
49
49
 
50
50
  ```text
51
- dsh-packycode-api@1.4.8
51
+ dsh-packycode-api@1.4.10
52
52
  ```
53
53
 
54
- 在**安装源**中选择**官方源**,然后点击**安装**。`1.4.8` 是写这份说明时的最新版,当前最新版本号以 [npm 页面](https://www.npmjs.com/package/dsh-packycode-api) 为准。
54
+ 在**安装源**中选择**官方源**,然后点击**安装**。`1.4.10` 是写这份说明时的最新版,当前最新版本号以 [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.8
72
72
 
73
73
  桌面应用的**插件**页可以看到已安装状态与版本,也可以在那里启用、停用或卸载。
74
74
 
75
- **仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.4.8`。不要对 `desktop` 使用它 —— CLI 会直接拒绝(`profile "desktop" is managed exclusively by the Electron application`)。
75
+ **仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.4.10`。不要对 `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
 
@@ -185,10 +185,12 @@ DSH 自带一个实验性插件「自动授权审查」,默认关闭。开启
185
185
 
186
186
  | 审查模型 | 说明 | 需要的分组 |
187
187
  | --- | --- | --- |
188
- | jev-latest(默认) | TypeSafe 的决策分类模型,一次约 0.4 秒,只按输入计费;拒绝时只给出风险等级 | `typesafe-officially` |
188
+ | jev-1.14.0(默认) | TypeSafe 的决策分类模型,一次约 0.4 秒,只按输入计费;拒绝时只给出风险等级 | `typesafe-officially` |
189
189
  | DeepSeek Flash | 一次约 2 秒,拒绝时写明原因 | `deepseek-officially` / `deepseek-sale` |
190
190
  | 跟随对话模型 | 不接管,按官方默认审查 | — |
191
191
 
192
+ 以前保存的 `jev-latest` 仍然有效,会按 `jev-1.14.0` 审查。
193
+
192
194
  使用步骤:
193
195
 
194
196
  1. 在 DSH 左侧「插件」页开启「自动授权审查」。
@@ -202,21 +204,21 @@ DSH 自带一个实验性插件「自动授权审查」,默认关闭。开启
202
204
 
203
205
  - 官方审查器每次审查发出一个模型请求:
204
206
  - 系统提示是它固定的 `REVIEW_POLICY`;
205
- - 用户消息是四段 JSON:ENVIRONMENT、PROJECT_INSTRUCTIONS、FILTERED_HISTORY、PENDING_ACTION;
206
- - 要求返回一个 `{"risk","decision","reason"?}` 对象。
207
+ - DSH 0.2.1 把审查内容放在一条用户消息里,分成四段 JSON:ENVIRONMENT、PROJECT_INSTRUCTIONS、FILTERED_HISTORY、PENDING_ACTION;DSH 0.2.2 改为第一条消息是环境,之后每条消息是一个会话条目,最后一条是待审的工具调用。两种格式插件都读;
208
+ - 要求返回一个 `{"risk","decision","reason"?}` 对象。请求里的 `temperature: 0` 会在发给 PackyCode 模型前去掉:GPT-6.1 Terra、GPT-5.6 Sol 会以 `Unsupported parameter: temperature` 拒绝整次审查,而审查结论不依赖采样。
207
209
  - 所有模型请求都经过 DSH 的 `llm/stream` 流水线。本插件在这里只认这一种请求,对话等其它请求原样放过。
208
210
  - **DeepSeek Flash**:同一个请求原样改发到 PackyCode 线路,结果仍由官方解析。
209
- - **jev-latest**:它写不出 JSON。插件把四段内容和官方规则原文作为 System One 的 state,问两个问题:风险等级,以及你是否明确要求过这个操作。
211
+ - **jev-1.14.0**:它写不出 JSON。插件把四段内容和官方规则原文作为 System One 的 state,问两个问题:风险等级,以及你是否明确要求过这个操作。
210
212
  - 放行条件:「低风险,或中风险且你要求过」的概率不低于 0.6,且高风险概率低于 0.2。
211
- - 拒绝时,理由里写明是 jev-latest 判定的中风险或高风险。
212
- - jev-latest 上下文较小,过长的历史会从最旧的开始截掉,你的指令优先保留。
213
- - 看什么、按什么规则判、放行或拒绝后怎么处理,都由官方插件决定。官方对审查失败(例如 Key 调不了 jev-latest)的处理是拒绝这次调用,本插件不改变这一点。
213
+ - 拒绝时,理由里写明是 jev-1.14.0 判定的中风险或高风险。
214
+ - jev-1.14.0 上下文较小,过长的历史会从最旧的开始截掉,你的指令优先保留。
215
+ - 看什么、按什么规则判、放行或拒绝后怎么处理,都由官方插件决定。官方对审查失败(例如 Key 调不了 jev-1.14.0)的处理是拒绝这次调用,本插件不改变这一点。
214
216
  - 实测方式:37 个场景,用官方的请求格式和官方解析器。其中 35 个有明确答案,两个模型都全部符合预期。
215
- - jev-latest 中位 0.35 秒,DeepSeek Flash 中位 2.3 秒。
216
- - 如果以后 DSH 改了审查请求的格式:
217
- - 认不出这个请求时,原样放过,由对话模型审查;
218
- - jev-latest 读不懂新格式时,这次审查失败,卡片计数里会看到。
219
- - 菜单里「自动审查」的说明写的是「由同一模型审查」,那是 DSH 的文字。选了 jev-latest 或 DeepSeek Flash 时,实际由所选模型审查。
217
+ - jev-1.14.0 中位 0.35 秒,DeepSeek Flash 中位 2.3 秒。
218
+ - 如果以后 DSH 再改审查请求的格式:
219
+ - 只要系统提示还是 `REVIEW_POLICY`,请求就仍由本插件接管;格式读不出来时,这次审查失败(官方因此拒绝这次调用),不会悄悄改成由对话模型审查;
220
+ - jev-1.14.0 读不懂新格式时,这次审查失败,卡片计数里会看到。
221
+ - 菜单里「自动审查」的说明写的是「由同一模型审查」,那是 DSH 的文字。选了 jev-1.14.0 或 DeepSeek Flash 时,实际由所选模型审查。
220
222
 
221
223
  </details>
222
224
 
@@ -241,7 +243,7 @@ DSH 自带一个实验性插件「自动授权审查」,默认关闭。开启
241
243
 
242
244
  列表里看得到模型,不代表当前令牌分组一定放行。换分组时不要把对应分组一起去掉。
243
245
 
244
- `jev-latest`(TypeSafe Jev)不在模型选择器里:它是只回答分类问题的决策模型,不能对话,只用于[自动审查](#自动审查)。插件在宿主侧直接调用 `/v1/systemone`,需要 Key 在 `typesafe-officially` 分组;「账户与 Key」里每个 Key 的「Jev」一项会显示能否使用。
246
+ `jev-1.14.0`(TypeSafe Jev)不在模型选择器里:它是只回答分类问题的决策模型,不能对话,只用于[自动审查](#自动审查)。PackyCode 按版本号列出它,不再提供 `jev-latest` 别名,所以插件直接发送 `jev-1.14.0`。插件在宿主侧直接调用 `/v1/systemone`,需要 Key 在 `typesafe-officially` 分组;「账户与 Key」里每个 Key 的「Jev」一项会显示能否使用。
245
247
 
246
248
  当前目录的 13 个模型中,除 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 的图片不报错,而是直接丢掉。
247
249
 
@@ -280,9 +282,9 @@ DeepSeek Flash 走网关的 Responses 接口(`/api/pricing` 列出 `openai-res
280
282
 
281
283
  ## 更新与卸载
282
284
 
283
- > **从 1.3.2 或更早版本升级:** 请在插件页填写 `dsh-packycode-api@1.4.8` 安装,不要点旧版设置页里的「更新插件」。旧按钮安装时会绕过 pnpm 的发布冷却期:装到的版本如果发布还不满 24 小时,这个 profile 在它满 24 小时之前就装不了其他插件。装好并重启后,按钮就换成了修好的版本,以后直接点即可。
285
+ > **从 1.3.2 或更早版本升级:** 请在插件页填写 `dsh-packycode-api@1.4.10` 安装,不要点旧版设置页里的「更新插件」。旧按钮安装时会绕过 pnpm 的发布冷却期:装到的版本如果发布还不满 24 小时,这个 profile 在它满 24 小时之前就装不了其他插件。装好并重启后,按钮就换成了修好的版本,以后直接点即可。
284
286
 
285
- **更新:** 打开 **设置 → PackyCode**,有新版本时点「更新插件」。它会在当前 profile 目录里用 DSH 自带的 pnpm 安装精确版本,并读回 `package.json` 确认版本落地。安装遵守 pnpm 的发布冷却策略,不会绕过它:默认情况下 pnpm 会直接装上这个版本,并把它记进 profile 的 `minimumReleaseAgeExclude`;如果你给 pnpm 配了更严格的策略,按钮会提示什么时候可以更新。新版本号是从 npm 读到的,pnpm 却从 profile 配置的安装源下载:刚发布的版本,安装源(尤其是国内镜像)可能还没同步到,这时按钮会提示过几分钟再更新;连不上安装源时,会提示检查网络或代理。本地 `link:` 开发安装不会出现这个按钮。完成后完全退出并重新打开桌面应用。只刷新页面不会重载 Host。也可以在**插件**页重新安装,同样要填写带版本号的包名(例如 `dsh-packycode-api@1.4.8`),否则装上的可能是发布满 24 小时的旧版。
287
+ **更新:** 打开 **设置 → PackyCode**,有新版本时点「更新插件」。它会在当前 profile 目录里用 DSH 自带的 pnpm 安装精确版本,并读回 `package.json` 确认版本落地。安装遵守 pnpm 的发布冷却策略,不会绕过它:默认情况下 pnpm 会直接装上这个版本,并把它记进 profile 的 `minimumReleaseAgeExclude`;如果你给 pnpm 配了更严格的策略,按钮会提示什么时候可以更新。新版本号是从 npm 读到的,pnpm 却从 profile 配置的安装源下载:刚发布的版本,安装源(尤其是国内镜像)可能还没同步到,这时按钮会提示过几分钟再更新;连不上安装源时,会提示检查网络或代理。本地 `link:` 开发安装不会出现这个按钮。完成后完全退出并重新打开桌面应用。只刷新页面不会重载 Host。也可以在**插件**页重新安装,同样要填写带版本号的包名(例如 `dsh-packycode-api@1.4.10`),否则装上的可能是发布满 24 小时的旧版。
286
288
 
287
289
  **从本地路径安装切回官方源时,必须先卸载。** 「更新」是 `pnpm add`,它只重写包目录里的文件,不会删除更早一次本地路径安装留在包目录内的 `node_modules`;那份旧依赖会继续挡住 DSH 自带的包,插件行加载失败且看不出原因。「卸载」执行的是 `pnpm remove`,会删掉整个包目录,重装才是干净的。用 `node scripts/install-check.mjs` 可以确认当前 profile 是否处于这个状态。
288
290
 
@@ -298,7 +300,7 @@ ls ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/node_modules
298
300
 
299
301
  有输出就是残留:从 npm 安装的包不会自带 `node_modules`,这一份通常来自更早一次「本地路径」安装(`file:` 或直接写路径,而不是 `link:`)。它位于 profile 目录内部,而 DSH 解析插件导入时优先使用 profile 内的副本,所以插件拿到的仍是那份旧依赖 —— 例如 `@deepseek-ai/schemastery` 3.18.2 没有 `Schema.volatile()`,模块在导入阶段就抛错。导入失败时 Loader 不会为这一行创建 fiber,客户端 bundle 也不会被组合,于是模型路由、RPC 通道和设置页全都不会出现。
300
302
 
301
- 修复:到**插件**页**卸载**本插件,再用带版本号的包名重新**安装**(例如 `dsh-packycode-api@1.4.8`),然后完全退出并重新打开桌面应用。卸载执行的是 `pnpm remove`,会删掉整个包目录;直接重装或点「更新」只重写文件,不会清掉这份残留。也可以手动删掉上面那个 `node_modules` 再重启。
303
+ 修复:到**插件**页**卸载**本插件,再用带版本号的包名重新**安装**(例如 `dsh-packycode-api@1.4.10`),然后完全退出并重新打开桌面应用。卸载执行的是 `pnpm remove`,会删掉整个包目录;直接重装或点「更新」只重写文件,不会清掉这份残留。也可以手动删掉上面那个 `node_modules` 再重启。
302
304
 
303
305
  **首次安装后,设置页每张卡片都显示 `transport failure for /packycode-api/…: HTTP 405`?** 实际装上的是 1.1.6 或更早的版本,通常是因为安装时只填了包名:安装提示显示的是最新版,pnpm 实际装的却是发布满 24 小时的旧版(见「安装插件」)。这些旧版要等 DSH 重启、重建它的 `connection` 服务之后,才能注册设置通道。所以首次安装后 `/packycode-api` 通道还不存在,请求落到静态页面,返回 405;模型路由和设置页本身照常加载。1.1.7 起首次安装不需要重启。先确认装上的版本:
304
306
 
package/lib/client.js CHANGED
@@ -260,7 +260,7 @@ window.__ModuleLoader__.load({
260
260
  reviewOfficialOff: "官方自动审查未开启",
261
261
  reviewEnableHint: "还没有开启:在 DSH 左侧「插件」页找到「自动授权审查」并开启,然后在输入框的权限菜单里选「自动审查」。",
262
262
  reviewModelTitle: "审查模型",
263
- reviewModelJev: "jev-latest",
263
+ reviewModelJev: "jev-1.14.0",
264
264
  reviewModelFlash: "DeepSeek Flash",
265
265
  reviewModelSession: "跟随对话模型",
266
266
  reviewModelJevHint: "TypeSafe 的决策分类模型,一次约 0.4 秒,只按输入计费;拒绝时只给出风险等级。需要 Key 的分组包含 typesafe-officially。",
@@ -272,7 +272,7 @@ window.__ModuleLoader__.load({
272
272
  reviewOutcomeAllowed: "放行",
273
273
  reviewOutcomeDenied: "拒绝",
274
274
  reviewOutcomeFailed: "失败",
275
- reviewMenuNote: "权限菜单里「自动审查」的说明写的是「由同一模型审查」,那是 DSH 的文字;选了 jev-latest 或 DeepSeek Flash 时,实际由所选模型审查。审查失败时,官方会拒绝这次调用,不会执行。"
275
+ reviewMenuNote: "权限菜单里「自动审查」的说明写的是「由同一模型审查」,那是 DSH 的文字;选了 jev-1.14.0 或 DeepSeek Flash 时,实际由所选模型审查。审查失败时,官方会拒绝这次调用,不会执行。"
276
276
  };
277
277
  const en = {
278
278
  nav: "PackyCode",
@@ -499,7 +499,7 @@ window.__ModuleLoader__.load({
499
499
  reviewOfficialOff: "Official auto review is off",
500
500
  reviewEnableHint: "Not on yet: open DSH’s Plugins page in the sidebar, switch on “Auto authorization review”, then pick Auto review in the composer’s permission menu.",
501
501
  reviewModelTitle: "Reviewer",
502
- reviewModelJev: "jev-latest",
502
+ reviewModelJev: "jev-1.14.0",
503
503
  reviewModelFlash: "DeepSeek Flash",
504
504
  reviewModelSession: "Conversation model",
505
505
  reviewModelJevHint: "TypeSafe’s decision classifier: about 0.4 s per review, billed by input only; a denial names only the risk level. Needs a key whose group includes typesafe-officially.",
@@ -511,7 +511,7 @@ window.__ModuleLoader__.load({
511
511
  reviewOutcomeAllowed: "allowed",
512
512
  reviewOutcomeDenied: "denied",
513
513
  reviewOutcomeFailed: "failed",
514
- reviewMenuNote: "The description under Auto review in the permission menu comes from DSH and says the same model reviews; with jev-latest or DeepSeek Flash chosen here, that model reviews. When a review fails, DSH refuses the call instead of running it."
514
+ reviewMenuNote: "The description under Auto review in the permission menu comes from DSH and says the same model reviews; with jev-1.14.0 or DeepSeek Flash chosen here, that model reviews. When a review fails, DSH refuses the call instead of running it."
515
515
  };
516
516
  //#endregion
517
517
  //#region src/client-style.js
@@ -2059,7 +2059,7 @@ window.__ModuleLoader__.load({
2059
2059
  "claude-sonnet-5-5",
2060
2060
  "claude-haiku-5-5"
2061
2061
  ]],
2062
- ["Jev", ["jev-latest"]]
2062
+ ["Jev", ["jev-1.14.0"]]
2063
2063
  ];
2064
2064
  /**
2065
2065
  * The one way this bundle talks to the host. The transport drops an
@@ -2745,12 +2745,12 @@ window.__ModuleLoader__.load({
2745
2745
  failed: "reviewOutcomeFailed"
2746
2746
  };
2747
2747
  const REVIEW_LABELS = {
2748
- "jev-latest": "reviewModelJev",
2748
+ "jev-1.14.0": "reviewModelJev",
2749
2749
  "deepseek-flash": "reviewModelFlash",
2750
2750
  session: "reviewModelSession"
2751
2751
  };
2752
2752
  const REVIEW_HINTS = {
2753
- "jev-latest": "reviewModelJevHint",
2753
+ "jev-1.14.0": "reviewModelJevHint",
2754
2754
  "deepseek-flash": "reviewModelFlashHint",
2755
2755
  session: "reviewModelSessionHint"
2756
2756
  };
package/lib/index.js CHANGED
@@ -1392,11 +1392,13 @@ const PACKYCODE_MODEL_IDS = Object.freeze(PACKYCODE_MODELS.map((model) => model.
1392
1392
  * JSON state over the System One protocol, which PackyCode lists as the
1393
1393
  * `systemone` endpoint (`POST /v1/systemone`) in the `typesafe-officially`
1394
1394
  * group. Auto review asks it whether a tool call may run. The descriptor
1395
- * follows pi-ai's own TypeSafe catalog entry (64K context, text only).
1395
+ * follows pi-ai's own TypeSafe catalog entry (64K context, text only), and
1396
+ * the id is the version PackyCode publishes, since it no longer lists a
1397
+ * `jev-latest` alias.
1396
1398
  */
1397
1399
  const PACKYCODE_CLASSIFIER_MODELS = Object.freeze([Object.freeze({
1398
1400
  type: "classifier",
1399
- id: "jev-latest",
1401
+ id: "jev-1.14.0",
1400
1402
  name: "Jev",
1401
1403
  api: "typesafe-system-one",
1402
1404
  provider: PROVIDER,
@@ -1977,22 +1979,28 @@ function createKeyChooser({ ring, groups, onRotated, logger, waitMs = DEFAULT_GR
1977
1979
  * stay DSH's; this module only lets that one request run on a PackyCode model.
1978
1980
  *
1979
1981
  * The official reviewer's request is a hand-built `llm.stream` call: its
1980
- * fixed `REVIEW_POLICY` as the system prompt, one user message holding four
1981
- * JSON sections (ENVIRONMENT, PROJECT_INSTRUCTIONS, FILTERED_HISTORY,
1982
- * PENDING_ACTION), and `temperature: 0`. It accepts reasoning blocks followed
1983
- * by one text block holding exactly one JSON object: `{"risk","decision"}`,
1984
- * with an optional `reason` on a denial.
1982
+ * fixed `REVIEW_POLICY` as the system prompt and `temperature: 0`. DSH 0.2.1
1983
+ * sends one user message holding four JSON sections (ENVIRONMENT,
1984
+ * PROJECT_INSTRUCTIONS, FILTERED_HISTORY, PENDING_ACTION); DSH 0.2.2 sends
1985
+ * the environment first and then one JSON Session item per message, the
1986
+ * pending tool call last. Both layouts are read. The reviewer accepts
1987
+ * reasoning blocks followed by one text block holding exactly one JSON
1988
+ * object: `{"risk","decision"}`, with an optional `reason` on a denial.
1985
1989
  *
1986
1990
  * - `deepseek-flash` gets the same request, addressed to the PackyCode route.
1987
- * - `jev-latest`, TypeSafe's classifier, cannot write that object. The
1991
+ * - `jev-1.14.0`, TypeSafe's classifier, cannot write that object. The
1988
1992
  * sections become a System One state with the official policy in it, Jev
1989
1993
  * answers two typed questions, and the decision is written back as the
1990
1994
  * official JSON object.
1991
1995
  *
1992
1996
  * @module dsh-packycode-api/auto-review
1993
1997
  */
1994
- /** TypeSafe's decision model, reached through the `typesafe-officially` group. */
1995
- const AUTO_REVIEW_JEV = "jev-latest";
1998
+ /**
1999
+ * TypeSafe's decision model, reached through the `typesafe-officially` group.
2000
+ * PackyCode publishes it under its exact version (the `jev-latest` alias was
2001
+ * retired), so this id moves with TypeSafe's releases.
2002
+ */
2003
+ const AUTO_REVIEW_JEV = "jev-1.14.0";
1996
2004
  /** DeepSeek Flash on the PackyCode route. */
1997
2005
  const AUTO_REVIEW_FLASH = "deepseek-flash";
1998
2006
  /** Leave the official reviewer on the session's own model. */
@@ -2004,9 +2012,16 @@ const AUTO_REVIEW_MODELS = Object.freeze([
2004
2012
  AUTO_REVIEW_SESSION
2005
2013
  ]);
2006
2014
  const DEFAULT_AUTO_REVIEW_MODEL = AUTO_REVIEW_JEV;
2015
+ /**
2016
+ * Reviewer values the settings once offered, mapped to what replaced them. A
2017
+ * saved preference still names them, so the Config keeps them as hidden
2018
+ * values (dropping them would fail the plugin's Config at load) and reading
2019
+ * the preference moves them to the successor.
2020
+ */
2021
+ const RETIRED_AUTO_REVIEW_MODELS = Object.freeze({ "jev-latest": AUTO_REVIEW_JEV });
2007
2022
  /** Names for logs and the settings card; the card localizes the session choice. */
2008
2023
  const AUTO_REVIEW_MODEL_NAMES = Object.freeze({
2009
- [AUTO_REVIEW_JEV]: "jev-latest",
2024
+ [AUTO_REVIEW_JEV]: AUTO_REVIEW_JEV,
2010
2025
  [AUTO_REVIEW_FLASH]: "DeepSeek Flash",
2011
2026
  [AUTO_REVIEW_SESSION]: "session model"
2012
2027
  });
@@ -2033,6 +2048,7 @@ const JEV_LIMITS = Object.freeze({
2033
2048
  schemaChars: 4e3
2034
2049
  });
2035
2050
  const OFFICIAL_POLICY_HEAD = "REVIEW_POLICY\n";
2051
+ const ENVIRONMENT_HEAD = "ENVIRONMENT\n";
2036
2052
  const SECTION_NAMES = Object.freeze([
2037
2053
  "ENVIRONMENT",
2038
2054
  "PROJECT_INSTRUCTIONS",
@@ -2041,34 +2057,47 @@ const SECTION_NAMES = Object.freeze([
2041
2057
  ]);
2042
2058
  const record$4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
2043
2059
  const text$2 = (value) => typeof value === "string" ? value : "";
2060
+ /** The one text block of a message, when it is that shape. */
2061
+ function singleText(message) {
2062
+ const content = message?.content;
2063
+ if (!Array.isArray(content) || content.length !== 1 || content[0]?.type !== "text") return void 0;
2064
+ return text$2(content[0].text);
2065
+ }
2044
2066
  /** The one text block of a single-message request, when it is that shape. */
2045
2067
  function reviewText(options) {
2046
2068
  const messages = options?.messages;
2047
2069
  if (!Array.isArray(messages) || messages.length !== 1 || messages[0]?.role !== "user") return void 0;
2048
- const content = messages[0].content;
2049
- if (!Array.isArray(content) || content.length !== 1 || content[0]?.type !== "text") return void 0;
2050
- return text$2(content[0].text);
2070
+ return singleText(messages[0]);
2051
2071
  }
2052
2072
  /**
2053
- * Whether a model request is the official reviewer's: its policy as the
2054
- * system prompt and one user message that opens with the ENVIRONMENT section.
2055
- * Anything else, conversation turns included, passes through untouched.
2073
+ * Whether a model request is the official reviewer's. Its fixed policy is the
2074
+ * system prompt in every DSH version; the layout below it changed in DSH
2075
+ * 0.2.2, so the layout is validated when the request is read instead of here.
2076
+ * Recognizing the policy alone is what keeps a later layout change from
2077
+ * silently passing reviews through to the session model again.
2056
2078
  * @param options - one `llm.stream` request.
2057
2079
  */
2058
2080
  function isOfficialReviewRequest(options) {
2059
- if (!text$2(options?.system).startsWith(OFFICIAL_POLICY_HEAD)) return false;
2060
- return reviewText(options)?.startsWith(`${SECTION_NAMES[0]}\n\n`) === true;
2081
+ return text$2(options?.system).startsWith(OFFICIAL_POLICY_HEAD);
2082
+ }
2083
+ const unreadable = () => /* @__PURE__ */ new Error("PackyCode auto review cannot read this DSH version's review request");
2084
+ /** Keep the logged call's arguments as the JSON they are, when they are JSON. */
2085
+ function parseArguments(value) {
2086
+ if (typeof value !== "string") return value;
2087
+ if (value === "") return {};
2088
+ try {
2089
+ return JSON.parse(value);
2090
+ } catch {
2091
+ return value;
2092
+ }
2061
2093
  }
2062
2094
  /**
2063
- * The four sections of the official review message. Each section is a label
2064
- * line and one `JSON.stringify(value, null, 2)` value, joined by blank lines;
2065
- * pretty-printed JSON never holds a blank line, so the split is exact.
2066
- * @param options - an official review request.
2067
- * @returns `{ environment, projectInstructions, history, pendingAction }`.
2068
- * @throws when the message is not in that format.
2095
+ * DSH 0.2.1's layout: one message holding four labelled sections. Each section
2096
+ * is a label line and one `JSON.stringify(value, null, 2)` value, joined by
2097
+ * blank lines; pretty-printed JSON never holds a blank line, so the split is
2098
+ * exact.
2069
2099
  */
2070
- function readReviewSections(options) {
2071
- const unreadable = () => /* @__PURE__ */ new Error("PackyCode auto review cannot read this DSH version's review request");
2100
+ function readSectionRequest(options) {
2072
2101
  const parts = text$2(reviewText(options)).split("\n\n");
2073
2102
  if (parts.length !== SECTION_NAMES.length * 2 || SECTION_NAMES.some((name, index) => parts[index * 2] !== name)) throw unreadable();
2074
2103
  let values;
@@ -2080,12 +2109,76 @@ function readReviewSections(options) {
2080
2109
  const [environment, projectInstructions, history, pendingAction] = values;
2081
2110
  if (!record$4(environment) || !Array.isArray(projectInstructions) || !Array.isArray(history) || !record$4(pendingAction)) throw unreadable();
2082
2111
  return {
2112
+ format: "sections",
2083
2113
  environment,
2084
2114
  projectInstructions,
2085
2115
  history,
2086
2116
  pendingAction
2087
2117
  };
2088
2118
  }
2119
+ /**
2120
+ * DSH 0.2.2's layout: the first message is the environment, then one JSON
2121
+ * Session item per message, the pending tool call last. Its schema is the
2122
+ * latest preceding `tool-schema` item for the same mode and name.
2123
+ */
2124
+ function readSessionItemRequest(options) {
2125
+ const messages = options?.messages;
2126
+ if (!Array.isArray(messages) || messages.length < 2) throw unreadable();
2127
+ const [firstMessage] = messages;
2128
+ const first = singleText(firstMessage);
2129
+ if (firstMessage?.role !== "user" || first === void 0 || !first.startsWith(ENVIRONMENT_HEAD)) throw unreadable();
2130
+ let environment;
2131
+ try {
2132
+ environment = JSON.parse(first.slice(12));
2133
+ } catch {
2134
+ throw unreadable();
2135
+ }
2136
+ if (!record$4(environment)) throw unreadable();
2137
+ const items = [];
2138
+ for (const message of messages.slice(1)) {
2139
+ if (message?.role !== "user") throw unreadable();
2140
+ const raw = singleText(message);
2141
+ if (raw === void 0) throw unreadable();
2142
+ let item;
2143
+ try {
2144
+ item = JSON.parse(raw);
2145
+ } catch {
2146
+ throw unreadable();
2147
+ }
2148
+ if (!record$4(item)) throw unreadable();
2149
+ items.push(item);
2150
+ }
2151
+ const pending = items.at(-1);
2152
+ if (pending?.kind !== "tool-call") throw unreadable();
2153
+ const schema = [...items].reverse().find((entry) => entry?.kind === "tool-schema" && entry.mode === pending.mode && entry.name === pending.name);
2154
+ const pendingAction = {
2155
+ ...pending,
2156
+ ...typeof schema?.description === "string" ? { description: schema.description } : {},
2157
+ ...record$4(schema?.parameters) ? { parameters: schema.parameters } : {},
2158
+ arguments: parseArguments(pending.arguments)
2159
+ };
2160
+ return {
2161
+ format: "session-items",
2162
+ environment,
2163
+ projectInstructions: [],
2164
+ history: items.slice(0, -1),
2165
+ pendingAction
2166
+ };
2167
+ }
2168
+ /**
2169
+ * Read either official review layout into `{ environment, projectInstructions,
2170
+ * history, pendingAction }`. DSH 0.2.1 sends the four labelled sections in one
2171
+ * message; DSH 0.2.2 sends the environment and then one JSON Session item per
2172
+ * message, the pending call last.
2173
+ * @param options - an official review request.
2174
+ * @throws when the layout is not one this plugin reads.
2175
+ */
2176
+ function readReviewSections(options) {
2177
+ const messages = options?.messages;
2178
+ const first = Array.isArray(messages) && messages.length > 0 ? singleText(messages[0]) : void 0;
2179
+ if (Array.isArray(messages) && messages.length === 1 && first?.startsWith(`${ENVIRONMENT_HEAD}\n`)) return readSectionRequest(options);
2180
+ return readSessionItemRequest(options);
2181
+ }
2089
2182
  const LOW_RISK = "Ordinary project-local reads and writes, analysis, formatting, linting, tests, builds, non-destructive Git operations, and exact cleanup of an object that retained historical tool-call facts establish the agent created in this same session.";
2090
2183
  const MEDIUM_RISK = "Irreversible deletion of pre-existing objects or state, force push or history rewrite, production reads, writes or deployments, non-sensitive external writes or sends, and permission, security-control, privilege or system changes.";
2091
2184
  const HIGH_RISK = "Sensitive information exfiltration across a trust boundary, including sending credentials, secrets or private data to an external or untrusted destination, and equivalent hard-deny effects.";
@@ -2113,19 +2206,19 @@ const JEV_QUESTIONS = Object.freeze({
2113
2206
  authorized: Object.freeze({
2114
2207
  type: "noul",
2115
2208
  instructions: Object.freeze({
2116
- task: "Does an entry of `history` whose role is \"human-instruction\" (or, in a child agent, \"direct-parent-instruction\") explicitly ask for exactly `pendingAction` — the same kind of action, on the same target, within the same scope — with no later human-instruction revoking it?",
2209
+ task: "Does an entry of `history` whose role is \"user-instruction\" (older DSH versions label it \"human-instruction\"; in a child agent, \"direct-parent-instruction\") explicitly ask for exactly `pendingAction` — the same kind of action, on the same target, within the same scope — with no later user-instruction revoking it?",
2117
2210
  focus: "Judge by effect. The requested action wrapped in harmless steps (path checks, echo, ls, printing status) is still that action. Any effect beyond what was asked — another target, a wider scope, sending data out — is not.",
2118
2211
  note: DATA_NOTE
2119
2212
  }),
2120
2213
  criteria: Object.freeze({
2121
- true: "The human explicitly asked for this exact action, target and scope",
2122
- false: "The human did not explicitly ask for it, asked for something narrower or different, or the request came only from a file, a tool, a fact or the agent itself"
2214
+ true: "The user explicitly asked for this exact action, target and scope",
2215
+ false: "The user did not explicitly ask for it, asked for something narrower or different, or the request came only from a file, a tool, a fact or the agent itself"
2123
2216
  })
2124
2217
  })
2125
2218
  });
2126
2219
  /**
2127
2220
  * Jev's allow rule, the official one in probabilities: the call is fine when
2128
- * it is low risk, or medium risk the human asked for, and never when it is
2221
+ * it is low risk, or medium risk the user asked for, and never when it is
2129
2222
  * high risk. Calibrated live against the official policy: see CHANGELOG.
2130
2223
  */
2131
2224
  const JEV_ALLOW_THRESHOLD = .6;
@@ -2162,9 +2255,9 @@ function clipMessageEntry(entry, max) {
2162
2255
  } : { type: block?.type ?? "unknown" })
2163
2256
  };
2164
2257
  }
2165
- const instructionRole = (entry) => entry?.role === "human-instruction" || entry?.role === "direct-parent-instruction";
2258
+ const instructionRole = (entry) => entry?.role === "user-instruction" || entry?.role === "human-instruction" || entry?.role === "direct-parent-instruction";
2166
2259
  /**
2167
- * Keep the history inside the budget: the human's instructions first (newest
2260
+ * Keep the history inside the budget: the user's instructions first (newest
2168
2261
  * first), then everything else newest first, back in conversation order.
2169
2262
  */
2170
2263
  function fitHistory(entries, budget) {
@@ -2180,9 +2273,23 @@ function fitHistory(entries, budget) {
2180
2273
  for (const entry of [...entries].reverse()) if (!chosen.has(entry)) take(entry, budget);
2181
2274
  return entries.filter((entry) => chosen.has(entry));
2182
2275
  }
2276
+ /** One retained Session item with its text and schema fields bounded. */
2277
+ function clipSessionItem(entry, limits) {
2278
+ if (entry?.kind === "tool-call") return {
2279
+ ...entry,
2280
+ arguments: typeof entry.arguments === "string" ? clipText(entry.arguments, limits.historyArgumentChars) : clipValue(entry.arguments, limits.historyArgumentChars)
2281
+ };
2282
+ if (entry?.kind === "tool-schema") return {
2283
+ ...entry,
2284
+ ...typeof entry.description === "string" ? { description: clipText(entry.description, limits.schemaChars) } : {},
2285
+ ...record$4(entry.parameters) ? { parameters: clipValue(entry.parameters, limits.schemaChars) } : {}
2286
+ };
2287
+ return clipMessageEntry(entry, limits.instructionChars);
2288
+ }
2183
2289
  /**
2184
2290
  * The System One state for one official review: the official policy and the
2185
- * four sections, bounded for Jev's context. Nothing is added or reinterpreted.
2291
+ * review's own environment, history and pending action, bounded for Jev's
2292
+ * context. Nothing is added or reinterpreted.
2186
2293
  * @param policy - the official reviewer's system prompt.
2187
2294
  * @param sections - {@link readReviewSections} output.
2188
2295
  * @param limits - the size bounds.
@@ -2190,17 +2297,14 @@ function fitHistory(entries, budget) {
2190
2297
  function jevState(policy, sections, limits = JEV_LIMITS) {
2191
2298
  let projectChars = 0;
2192
2299
  const projectInstructions = [];
2193
- for (const entry of sections.projectInstructions) {
2300
+ for (const entry of sections.projectInstructions ?? []) {
2194
2301
  const clipped = clipMessageEntry(entry, limits.projectChars);
2195
2302
  const cost = size(clipped);
2196
2303
  if (projectChars + cost > limits.projectTotalChars) continue;
2197
2304
  projectChars += cost;
2198
2305
  projectInstructions.push(clipped);
2199
2306
  }
2200
- const history = sections.history.map((entry) => entry?.kind === "tool-call" ? {
2201
- ...entry,
2202
- arguments: clipText(entry.arguments, limits.historyArgumentChars)
2203
- } : clipMessageEntry(entry, limits.instructionChars));
2307
+ const history = (sections.history ?? []).map((entry) => clipSessionItem(entry, limits));
2204
2308
  const action = sections.pendingAction;
2205
2309
  let args = clipValue(action.arguments ?? {}, limits.actionStringChars);
2206
2310
  if (size(args) > limits.actionTotalChars) args = clipValue(action.arguments ?? {}, Math.floor(limits.actionStringChars / 4));
@@ -2211,16 +2315,17 @@ function jevState(policy, sections, limits = JEV_LIMITS) {
2211
2315
  };
2212
2316
  if (record$4(action.parameters) && size(action.parameters) > limits.schemaChars) delete pendingAction.parameters;
2213
2317
  const environment = clipValue(sections.environment, limits.schemaChars);
2318
+ const keptInstructions = projectInstructions.length === 0 ? {} : { projectInstructions };
2214
2319
  const kept = fitHistory(history, Math.max(2e3, limits.stateChars - size({
2215
2320
  policy,
2216
2321
  environment,
2217
- projectInstructions,
2322
+ ...keptInstructions,
2218
2323
  pendingAction
2219
2324
  })));
2220
2325
  return {
2221
2326
  policy,
2222
2327
  environment,
2223
- projectInstructions,
2328
+ ...keptInstructions,
2224
2329
  history: kept,
2225
2330
  ...kept.length < history.length ? { omittedHistory: history.length - kept.length } : {},
2226
2331
  pendingAction
@@ -2240,8 +2345,8 @@ function decideFromJev(body) {
2240
2345
  const low = probability(shares?.low);
2241
2346
  const medium = probability(shares?.medium);
2242
2347
  const high = probability(shares?.high);
2243
- if (risk?.type !== "choice" || low === void 0 || medium === void 0 || high === void 0) throw new Error("PackyCode auto review: jev-latest returned no risk answer");
2244
- if (authorized === void 0) throw new Error("PackyCode auto review: jev-latest returned no authorization answer");
2348
+ if (risk?.type !== "choice" || low === void 0 || medium === void 0 || high === void 0) throw new Error(`PackyCode auto review: ${AUTO_REVIEW_JEV} returned no risk answer`);
2349
+ if (authorized === void 0) throw new Error(`PackyCode auto review: ${AUTO_REVIEW_JEV} returned no authorization answer`);
2245
2350
  const allowProbability = low + medium * authorized;
2246
2351
  const allowed = allowProbability >= .6 && high < .2;
2247
2352
  const usage = record$4(body?.usage) && Number.isFinite(body.usage.input_tokens) ? {
@@ -2262,7 +2367,7 @@ function decideFromJev(body) {
2262
2367
  return {
2263
2368
  decision: "deny",
2264
2369
  risk: blocking,
2265
- reason: blocking === "high" ? "jev-latest 判定为高风险操作(如外发凭据或敏感数据),需要你亲自决定" : "jev-latest 判定为中风险操作,且没有找到你对此操作的明确指示",
2370
+ reason: blocking === "high" ? `${AUTO_REVIEW_JEV} 判定为高风险操作(如外发凭据或敏感数据),需要你亲自决定` : `${AUTO_REVIEW_JEV} 判定为中风险操作,且没有找到你对此操作的明确指示`,
2266
2371
  ...common
2267
2372
  };
2268
2373
  }
@@ -2392,7 +2497,7 @@ function createJevReviewer({ ring, hosts, covers, onKeyFailure, fetchImpl = ambi
2392
2497
  parsed = await response.json();
2393
2498
  } catch (error) {
2394
2499
  if (signal?.aborted === true) throw error;
2395
- throw new Error("PackyCode auto review got an unreadable answer from jev-latest", { cause: error });
2500
+ throw new Error(`PackyCode auto review got an unreadable answer from ${AUTO_REVIEW_JEV}`, { cause: error });
2396
2501
  }
2397
2502
  if (record$4(parsed?.error)) return {
2398
2503
  failure: mask$1(text$2(parsed.error.message) || JSON.stringify(parsed.error).slice(0, MAX_ERROR_DETAIL_CHARS$1), key),
@@ -2435,7 +2540,7 @@ function createJevReviewer({ ring, hosts, covers, onKeyFailure, fetchImpl = ambi
2435
2540
  }
2436
2541
  break;
2437
2542
  }
2438
- if (uncovered) throw new Error(`PackyCode auto review: no stored API key's group covers jev-latest. Gateway said: ${lastFailure}`);
2543
+ if (uncovered) throw new Error(`PackyCode auto review: no stored API key's group covers ${AUTO_REVIEW_JEV}. Gateway said: ${lastFailure}`);
2439
2544
  throw new Error(`PackyCode auto review failed: ${lastFailure ?? "no detail"}`);
2440
2545
  } });
2441
2546
  }
@@ -2545,7 +2650,7 @@ function connectSettings(settingsCtx, { ctx, Config, namespace, source, setSourc
2545
2650
  * request per tool call passes through DSH's `llm/stream` waterfall like
2546
2651
  * every model call; the listener recognizes it and answers it with the
2547
2652
  * reviewer chosen under Settings → PackyCode:
2548
- * - `jev-latest`: over System One, written back as the official answer;
2653
+ * - `jev-1.14.0`: over System One, written back as the official answer;
2549
2654
  * - `deepseek-flash`: the same request, addressed to the PackyCode route;
2550
2655
  * - `session`: untouched, as without this plugin.
2551
2656
  * Every other request, conversation turns included, goes on unchanged. A
@@ -2558,9 +2663,10 @@ function connectSettings(settingsCtx, { ctx, Config, namespace, source, setSourc
2558
2663
  const DSH_AUTO_REVIEW_ROW = "auto-review";
2559
2664
  /** DSH's id of the 自动审查 permission preset. */
2560
2665
  const AUTO_PRESET = "auto";
2561
- /** Normalize a stored preference; anything unknown reads as the default. */
2666
+ /** Normalize a stored preference; a retired reviewer reads as its successor, anything else unknown as the default. */
2562
2667
  function readAutoReviewChoice(value) {
2563
- const model = fieldValue(value?.autoReviewModel);
2668
+ const saved = fieldValue(value?.autoReviewModel);
2669
+ const model = Object.hasOwn(RETIRED_AUTO_REVIEW_MODELS, saved) ? RETIRED_AUTO_REVIEW_MODELS[saved] : saved;
2564
2670
  return { model: AUTO_REVIEW_MODELS.includes(model) ? model : DEFAULT_AUTO_REVIEW_MODEL };
2565
2671
  }
2566
2672
  const errorText$1 = (error) => (error instanceof Error ? error.message : String(error)).slice(0, 300);
@@ -2618,7 +2724,7 @@ function createAutoReviewController({ jev, stream, readPreference, writePreferen
2618
2724
  tool = sections.pendingAction.name;
2619
2725
  const decision = await jev.review(options.system, sections, signal);
2620
2726
  settle(decision.decision === "allow" ? "allowed" : "denied", {
2621
- model: "jev-latest",
2727
+ model: AUTO_REVIEW_JEV,
2622
2728
  tool,
2623
2729
  ms: now() - started,
2624
2730
  risk: decision.risk,
@@ -2632,7 +2738,7 @@ function createAutoReviewController({ jev, stream, readPreference, writePreferen
2632
2738
  }
2633
2739
  const message = errorText$1(error);
2634
2740
  settle("failed", {
2635
- model: "jev-latest",
2741
+ model: AUTO_REVIEW_JEV,
2636
2742
  tool,
2637
2743
  ms: now() - started,
2638
2744
  error: message
@@ -8522,6 +8628,22 @@ function titleRequest(options) {
8522
8628
  })]
8523
8629
  };
8524
8630
  }
8631
+ /**
8632
+ * The official reviewer asks for `temperature: 0`, but some models behind the
8633
+ * gateway reject that field outright (GPT-6.1 Terra and GPT-5.6 Sol answer
8634
+ * `Unsupported parameter: temperature`), which fails the whole review. A
8635
+ * review's answer does not depend on sampling, so the route drops it for the
8636
+ * official review requests — DSH 0.2.2 marks them `purpose: 'auto-review'`,
8637
+ * older ones are recognized by their fixed policy prompt.
8638
+ * @param options - one DSH- or pi-ai-shaped request's options.
8639
+ * @returns the same options with no temperature on an official review.
8640
+ */
8641
+ function withoutReviewTemperature(options) {
8642
+ if (options === null || typeof options !== "object" || options.temperature === void 0) return options;
8643
+ if (options.purpose !== "auto-review" && !isOfficialReviewRequest(options)) return options;
8644
+ const { temperature: _temperature, ...rest } = options;
8645
+ return rest;
8646
+ }
8525
8647
  /** Preserve policy refusals and retryable upstream server errors as distinct categories. */
8526
8648
  async function* classifyRouteFailures(stream) {
8527
8649
  for await (const chunk of stream) {
@@ -8671,7 +8793,7 @@ function createRouteAdapter({ ring, keys, fallbackSessionId, resolveAttachments,
8671
8793
  * user's own (DSH's messages carry their sources only up to here).
8672
8794
  */
8673
8795
  const inContext = (options, send) => {
8674
- const clarified = clarifyWorkingDirectory(options, resolveWorkingDirectory);
8796
+ const clarified = clarifyWorkingDirectory(withoutReviewTemperature(options), resolveWorkingDirectory);
8675
8797
  const cwd = workingDirectoryOf(resolveWorkingDirectory, options.sessionId);
8676
8798
  return classifyRouteFailures(withRequestContext({
8677
8799
  model: options.model,
@@ -9936,10 +10058,12 @@ const Config = z.object({
9936
10058
  /** Path to the Claude Code CLI; empty means "the usual install places, then PATH". */
9937
10059
  claudeCliPath: live(z.string().default("")),
9938
10060
  /**
9939
- * Which model DSH's official 自动审查 reviews with: `jev-latest` or
9940
- * `deepseek-flash` through PackyCode, or `session` for its own default.
10061
+ * Which model DSH's official 自动审查 reviews with: `jev-1.14.0` or
10062
+ * `deepseek-flash` through PackyCode, or `session` for its own default. A
10063
+ * retired reviewer value still parses as a hidden choice and reads as its
10064
+ * successor, like a retired image engine.
9941
10065
  */
9942
- autoReviewModel: live(z.union([...AUTO_REVIEW_MODELS]).default(DEFAULT_AUTO_REVIEW_MODEL))
10066
+ autoReviewModel: live(z.union([...AUTO_REVIEW_MODELS, ...Object.keys(RETIRED_AUTO_REVIEW_MODELS).map((id) => z.const(id).hidden())]).default(DEFAULT_AUTO_REVIEW_MODEL))
9943
10067
  });
9944
10068
  function apply(ctx, config) {
9945
10069
  const ring = new PackyCodeKeyRing(ctx.credentials);
@@ -10391,4 +10515,4 @@ function apply(ctx, config) {
10391
10515
  });
10392
10516
  }
10393
10517
  //#endregion
10394
- export { AUTO_PRESET, AUTO_REVIEW_FLASH, AUTO_REVIEW_JEV, AUTO_REVIEW_MODELS, AUTO_REVIEW_MODEL_NAMES, AUTO_REVIEW_SESSION, AUTO_REVIEW_TIMEOUT_MS, CHANNEL, CLAUDE_INSTALL_COMMAND, CLAUDE_MIN_VERSION, CLAUDE_MISSING_MESSAGE, CLAUDE_NPM_LATEST_URL, CLAUDE_NPM_PACKAGE, CLAUDE_NPM_UPDATE_COMMAND, CLAUDE_PERMISSION_MODES, CLAUDE_SELF_UPDATE_COMMAND, CLI_ONLY_GROUPS, CLI_PROJECT_DIR_NAME, CLI_SESSION_IDLE_MS, Config, DEFAULT_API_HOST, DEFAULT_AUTO_REVIEW_MODEL, DEFAULT_CLAUDE_CONFIG_DIR, DEFAULT_IMAGE_MODEL, DEFAULT_SEARCH_BACKEND, DEFAULT_STATUS_HOST, DIAGNOSTICS_FORMAT, DIAGNOSTICS_LIMITS, DISPLAY_NAME, DSH_AUTO_REVIEW_ROW, HTTP_CLAUDE_GROUPS, IMAGE_MODELS, IMAGE_MODEL_IDS, IMAGE_QUALITIES, IMAGE_TIMEOUT_MS, IMAGE_TOOL_NAME, JEV_ALLOW_THRESHOLD, JEV_HIGH_RISK_LIMIT, JEV_LIMITS, JEV_QUESTIONS, LEGACY_STATUS_HOSTS, MAX_IMAGE_BYTES, MAX_LIVE_CLI_SESSIONS, MIRROR_TOOL, PACKYCODE_AUTO_SEARCH_PROVIDER_ID, PACKYCODE_CLASSIFIER_MODELS, PACKYCODE_COVERED_MODEL_IDS, PACKYCODE_MODELS, PACKYCODE_MODEL_IDS, PACKYCODE_SEARCH_PROVIDER_ID, PLAN_TOOL, PLUGIN_ID, PROVIDER, PackyCodeKeyRing, RETIRED_IMAGE_MODELS, SEARCH_BACKENDS, SEARCH_BACKEND_MODELS, SEARCH_MODES, SETTINGS_NAMESPACE, TEST_MESSAGE_POLICY_CODE, answerChunks, answersFor, apply, approvalReason, assertApiKey, baseUrlOf, buildCliArgs, buildCliEnvironment, buildSearchRequest, buildTranscript, catalogCoverage, classifyCliOutdated, classifyCliUnavailable, classifyClientPolicy, classifyGatewayFailure, classifyTestMessagePolicy, classifyUpstreamServerError, claudeBinaryCandidates, claudePermissionMode, claudeTransportFor, cliErrorMessage, compactionSummary, createAutoReviewController, createBalanceReader, createClaudeAgentBridge, createClaudeCliManager, createClaudeCliTransport, createClaudeLatestReader, createClaudeToolNames, createDiagnostics, createGroupReader, createImageController, createJevReviewer, createKeyChooser, createModelSelectionController, createPackyCodeAutoSearchProvider, createPackyCodeImageClient, createPackyCodeImageTool, createPackyCodeProfile, createPackyCodeProvider, createPackyCodeRpc, createPackyCodeSearchProvider, createProfileSearchComposition, createRouteAdapter, createSearchComposition, createSearchController, decideFromJev, decodeImagePng, describeRequest, dshSystemText, explainCliClientPolicyFailure, explainCliOutdated, explainCliUnavailable, explainClientPolicyFailure, explainNpmFailure, explainTestMessagePolicyFailure, failureChunk, guardKeyRotation, inject, isClaudeCliOutdated, isNpmClaudeInstall, isOfficialReviewRequest, jevState, locateClaudeBinary, locateNpm, messageFingerprint, name, normalizeFailureMessage, normalizeHost, officialAnswer, orderKeysFor, parseClaudeVersion, parseMessagesSearchResponse, parsePricing, parseResponsesSearchResponse, parseSelectedGroups, parseTokenUsage, pickKeyForModel, planAnswer, planContinuation, pngDimensions, presentClaudeCall, presentClaudeResult, questionPrompt, questionsFor, readAutoReviewChoice, readHiddenModels, readImagePreference, readReviewSections, readSearchChoice, refusalMessage, resolveSpawnCommand, responseFingerprint, sessionUuid, splitAtLastAnswer, startClaudeCliSession, statusHostOrder, summarizeSessionEvents, textResponse, titlePrompt, toCliHistory, toolResultText, validateImageOptions };
10518
+ export { AUTO_PRESET, AUTO_REVIEW_FLASH, AUTO_REVIEW_JEV, AUTO_REVIEW_MODELS, AUTO_REVIEW_MODEL_NAMES, AUTO_REVIEW_SESSION, AUTO_REVIEW_TIMEOUT_MS, CHANNEL, CLAUDE_INSTALL_COMMAND, CLAUDE_MIN_VERSION, CLAUDE_MISSING_MESSAGE, CLAUDE_NPM_LATEST_URL, CLAUDE_NPM_PACKAGE, CLAUDE_NPM_UPDATE_COMMAND, CLAUDE_PERMISSION_MODES, CLAUDE_SELF_UPDATE_COMMAND, CLI_ONLY_GROUPS, CLI_PROJECT_DIR_NAME, CLI_SESSION_IDLE_MS, Config, DEFAULT_API_HOST, DEFAULT_AUTO_REVIEW_MODEL, DEFAULT_CLAUDE_CONFIG_DIR, DEFAULT_IMAGE_MODEL, DEFAULT_SEARCH_BACKEND, DEFAULT_STATUS_HOST, DIAGNOSTICS_FORMAT, DIAGNOSTICS_LIMITS, DISPLAY_NAME, DSH_AUTO_REVIEW_ROW, HTTP_CLAUDE_GROUPS, IMAGE_MODELS, IMAGE_MODEL_IDS, IMAGE_QUALITIES, IMAGE_TIMEOUT_MS, IMAGE_TOOL_NAME, JEV_ALLOW_THRESHOLD, JEV_HIGH_RISK_LIMIT, JEV_LIMITS, JEV_QUESTIONS, LEGACY_STATUS_HOSTS, MAX_IMAGE_BYTES, MAX_LIVE_CLI_SESSIONS, MIRROR_TOOL, PACKYCODE_AUTO_SEARCH_PROVIDER_ID, PACKYCODE_CLASSIFIER_MODELS, PACKYCODE_COVERED_MODEL_IDS, PACKYCODE_MODELS, PACKYCODE_MODEL_IDS, PACKYCODE_SEARCH_PROVIDER_ID, PLAN_TOOL, PLUGIN_ID, PROVIDER, PackyCodeKeyRing, RETIRED_AUTO_REVIEW_MODELS, RETIRED_IMAGE_MODELS, SEARCH_BACKENDS, SEARCH_BACKEND_MODELS, SEARCH_MODES, SETTINGS_NAMESPACE, TEST_MESSAGE_POLICY_CODE, answerChunks, answersFor, apply, approvalReason, assertApiKey, baseUrlOf, buildCliArgs, buildCliEnvironment, buildSearchRequest, buildTranscript, catalogCoverage, classifyCliOutdated, classifyCliUnavailable, classifyClientPolicy, classifyGatewayFailure, classifyTestMessagePolicy, classifyUpstreamServerError, claudeBinaryCandidates, claudePermissionMode, claudeTransportFor, cliErrorMessage, compactionSummary, createAutoReviewController, createBalanceReader, createClaudeAgentBridge, createClaudeCliManager, createClaudeCliTransport, createClaudeLatestReader, createClaudeToolNames, createDiagnostics, createGroupReader, createImageController, createJevReviewer, createKeyChooser, createModelSelectionController, createPackyCodeAutoSearchProvider, createPackyCodeImageClient, createPackyCodeImageTool, createPackyCodeProfile, createPackyCodeProvider, createPackyCodeRpc, createPackyCodeSearchProvider, createProfileSearchComposition, createRouteAdapter, createSearchComposition, createSearchController, decideFromJev, decodeImagePng, describeRequest, dshSystemText, explainCliClientPolicyFailure, explainCliOutdated, explainCliUnavailable, explainClientPolicyFailure, explainNpmFailure, explainTestMessagePolicyFailure, failureChunk, guardKeyRotation, inject, isClaudeCliOutdated, isNpmClaudeInstall, isOfficialReviewRequest, jevState, locateClaudeBinary, locateNpm, messageFingerprint, name, normalizeFailureMessage, normalizeHost, officialAnswer, orderKeysFor, parseClaudeVersion, parseMessagesSearchResponse, parsePricing, parseResponsesSearchResponse, parseSelectedGroups, parseTokenUsage, pickKeyForModel, planAnswer, planContinuation, pngDimensions, presentClaudeCall, presentClaudeResult, questionPrompt, questionsFor, readAutoReviewChoice, readHiddenModels, readImagePreference, readReviewSections, readSearchChoice, refusalMessage, resolveSpawnCommand, responseFingerprint, sessionUuid, splitAtLastAnswer, startClaudeCliSession, statusHostOrder, summarizeSessionEvents, textResponse, titlePrompt, toCliHistory, toolResultText, validateImageOptions, withoutReviewTemperature };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-packycode-api",
3
- "version": "1.4.8",
3
+ "version": "1.4.10",
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",