dsh-packycode-api 1.3.7 → 1.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.en.md +56 -6
- package/README.md +56 -6
- package/lib/client.js +191 -3
- package/lib/index.js +4372 -3629
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.3.8
|
|
4
|
+
|
|
5
|
+
- **DSH's official 自动审查 can review with jev-latest or DeepSeek Flash.** DSH ships an experimental "自动授权审查" plugin (`@deepseek-ai/dsh-experimental-auto-review`, row `auto-review`, off by default). Switched on, it adds 自动审查 to the composer's permission menu and reviews every tool call of a session in that mode with one hand-built `llm.stream` request on the session's own model. The plugin now listens on DSH's `llm/stream` waterfall, which every model request passes. It recognizes that request by its fixed `REVIEW_POLICY` system prompt and four-section message, and answers it with the reviewer chosen under Settings → PackyCode → 自动审查 (`autoReviewModel`: `jev-latest` by default, `deepseek-flash`, or `session` to leave it alone). What is reviewed, the policy, asking the user, final denials in children, and refusing a call whose review failed all stay the official plugin's. Every other request goes on untouched. The plugin registers no permission preset and no tool gate of its own.
|
|
6
|
+
- **DeepSeek Flash gets the official request itself**, re-addressed to `packycode/deepseek-flash`; the official reviewer reads its answer.
|
|
7
|
+
- **jev-latest answers through System One.** Jev cannot write the official JSON answer, so the four sections become its state together with the official policy text, bounded to about 24K characters for its 32K-token per-question limit (Chinese measured one token per character; the user's instructions are kept first). Two questions are asked: the risk (`high` / `medium` / `low`, worded as the official policy and with the conservative option first, because Jev leans to the first choice) and whether the user asked for exactly this action (a `noul` told to judge by effect). A call is allowed when P(low) + P(medium) × P(asked) ≥ 0.6 and P(high) < 0.2. The decision goes back as the official answer, a text block holding `{"risk","decision"}` with a Chinese `reason` naming jev-latest on a denial. A failed review ends the stream with an error, which the official reviewer turns into a refused call. `jev-latest` was answered by `jev-1.14.0`.
|
|
8
|
+
- **jev-latest joins the catalog as a classifier, not a chat model.** PackyCode lists it as the `systemone` endpoint (`POST /v1/systemone`) in the `typesafe-officially` group ("jev官方渠道"). DSH's pi-ai adapter only serves chat models, so `PACKYCODE_CLASSIFIER_MODELS` keeps it out of the picker, and the plugin calls it host-side with its own keys. Its group coverage is read like the chat models', and each key's reach line in Settings shows Jev. A review tries the keys in ring order, keys whose groups reach Jev first. An exhausted or rejected key moves aside as on the model route, a key outside the group is passed over, and one gateway 5xx or 429 is resent after 0.5 s.
|
|
9
|
+
- **Settings → PackyCode → 自动审查** shows whether DSH's plugin is on (and how to switch it on), the reviewer choice, the reviews the plugin answered since start (allowed / denied / failed) and the last one, and a warning when no stored key's groups reach the chosen reviewer. DSH's own copy under the menu entry still says the same model reviews; the card says which one does. Every review the plugin answers logs one line (`packycode-api: auto review allowed bash (jev-1.14.0, low risk, 352 ms)`), without arguments.
|
|
10
|
+
- The web search's key ordering moves to `key-chooser.js` so the reviewer shares it. `scripts/live-check.mjs` sends the official request about one ordinary call and one exfiltration to each reviewer and reads the answers with the official parser (vendored, with the official policy text, in `tests/fixtures/official-auto-review.mjs`).
|
|
11
|
+
- Validation, 2026-10-22: 510 offline tests (new: recognizing the official request and passing every other request through; reading its four sections; Jev's bounded state with the official policy, its decision rule and denial reasons; answers and failures read by the official reviewer's own parser; key order, coverage, quota rotation, the transient resend and cancellation; the listener's three choices, the re-addressed Flash request reaching the adapter on its second trip, the counts, status and preference; the `llm/stream` registration; the settings card), both rebuilt bundles and the versioned tarball. One full run failed two hot-install registration tests on their 5-second fixture timeout while the machine was loaded (load average 4.5); they pass alone and in the next full run. Live with a key in `typesafe-officially` and `deepseek-officially`: the official request for 37 scenarios (the 0.2.1-rc.2 policy text and message format, read back by its parser) matched all 35 with a definite answer for both reviewers; jev-latest took a median 0.35 s, DeepSeek Flash 2.3 s. End to end in a scratch DSH 0.2.1-rc.2 headless profile with `@deepseek-ai/dsh-experimental-auto-review` switched on, a session in 自动审查 on `gpt-6.1-sol`, and a request to force-push: with `jev-latest` Jev answered the review (no reasoning, `jev-latest 判定为中风险操作…`); with `deepseek-flash` the request reached `packycode/deepseek-flash`, which gave its own reason; with `session` `gpt-6.1-sol` reviewed it. Each time DSH asked for approval with its own `Auto review denied tool "bash": …` and, without an approval channel, refused the push. `scripts/live-check.mjs` passed every HTTP model, the rotation, the classification and the RPC projections, read the key as reaching `jev-latest`, and both reviewers allowed `pnpm test` and denied an upload of `~/.ssh/id_rsa`. Not yet checked in the desktop app.
|
|
12
|
+
|
|
3
13
|
## 1.3.7
|
|
4
14
|
|
|
5
15
|
- **The CLI card also offers the update when a newer Claude Code is out.** Until now **Update Claude Code CLI** only appeared for a CLI older than 2.1.259. The plugin now reads the newest release on the host, from `https://registry.npmjs.org/@anthropic-ai/claude-code/latest` (npm's `latest` and the native installer's `latest` channel named the same 2.1.303 when checked), with a 10-second timeout and redirects refused, at most once every 30 minutes, again after 2 minutes when it got no answer, and at once when **Check again** is clicked. A CLI that works but is behind gets a note naming the new version, the same button and the command it runs; the installed version keeps working, so it is not marked too old. Without an answer from npm no update is offered. The update itself is unchanged: `claude update` for the native installer, npm with `--allow-scripts` for an npm install. Its outcome is now judged for a CLI that already worked: a run that changed nothing while a newer version exists fails with the installer's own output (for example Homebrew's `brew upgrade claude-code`) instead of reading as "updated", a failed command that changed nothing reports that failure, and a clean run with the newest release unknown says the version is unchanged.
|
package/README.en.md
CHANGED
|
@@ -32,6 +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 requests on `cc` keys go through this device's Claude Code CLI; `cc-sale`, `cc-expensive`, `claude-officially` and other groups use the plugin's HTTP route. Either way DSH runs the tools and permissions, and plan mode, attachments and the full history behave the same |
|
|
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
|
+
| **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
36
|
| **Credentials stay on the machine** | Keys live in the DSH credential file. The browser receives labels, state, and balances only |
|
|
36
37
|
|
|
37
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" />
|
|
@@ -47,10 +48,10 @@ You need **DeepSeek Harness** and a **PackyCode (PackyAPI) API key**. For DSH se
|
|
|
47
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**:
|
|
48
49
|
|
|
49
50
|
```text
|
|
50
|
-
dsh-packycode-api@1.3.
|
|
51
|
+
dsh-packycode-api@1.3.8
|
|
51
52
|
```
|
|
52
53
|
|
|
53
|
-
Choose the **official** install source, then click **Install**. `1.3.
|
|
54
|
+
Choose the **official** install source, then click **Install**. `1.3.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
55
|
|
|
55
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**.
|
|
56
57
|
|
|
@@ -71,7 +72,7 @@ Choose a model from the `PackyCode` group. All ten models use the plugin’s HTT
|
|
|
71
72
|
|
|
72
73
|
The **Plugins** page shows the installed state and version, and is also where you enable, disable, or uninstall.
|
|
73
74
|
|
|
74
|
-
**For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.3.
|
|
75
|
+
**For non-desktop profiles only:** `dsh plugin --profile <name> add dsh-packycode-api@1.3.8`. Do not use it for `desktop` — the CLI refuses it (`profile "desktop" is managed exclusively by the Electron application`).
|
|
75
76
|
|
|
76
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.
|
|
77
78
|
|
|
@@ -166,6 +167,53 @@ After adding the image key, `node scripts/image-check.mjs --all --edit` checks a
|
|
|
166
167
|
|
|
167
168
|
Live checks on 2026-10-15 passed generation and editing at `low` on all three engines. Sunburst also passed both operations at `xhigh` and `max`, with matching quality values in the responses. All 10 requests succeeded without retries and returned 1024×1024 PNGs; visual inspection confirmed the requested color edits with composition preserved. Generate/edit times were about 43/48 seconds at xhigh and 84/91 seconds at max. These are built-client gateway checks; no desktop conversation was created to verify the full chat flow in this run. See the [protocol research and gateway results](docs/research/image-api.md) for scope and evidence.
|
|
168
169
|
|
|
170
|
+
### Auto review
|
|
171
|
+
|
|
172
|
+
DSH ships an experimental plugin, “Auto authorization review”, switched off by default. Switched on, it adds **Auto review** (marked EXP) to the permission menu under the composer (Read only / Workspace write / Full access). In a session set to Auto review, a model reviews every tool call first:
|
|
173
|
+
|
|
174
|
+
- A call it allows runs at once, without a sandbox.
|
|
175
|
+
- A call it denies asks for your approval; in a subagent it is refused outright.
|
|
176
|
+
- When the review itself fails, the call does not run.
|
|
177
|
+
|
|
178
|
+
By default DSH reviews with the conversation's own model. This plugin leaves the review logic alone and only swaps the reviewer model. Choose it under **Settings → PackyCode → Auto review**:
|
|
179
|
+
|
|
180
|
+
| Reviewer | Notes | Group needed |
|
|
181
|
+
| --- | --- | --- |
|
|
182
|
+
| 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` |
|
|
183
|
+
| DeepSeek Flash | About 2 s per review, and a denial says why | `deepseek-officially` / `deepseek-sale` |
|
|
184
|
+
| Conversation model | Leave the review alone, as DSH does by default | — |
|
|
185
|
+
|
|
186
|
+
Steps:
|
|
187
|
+
|
|
188
|
+
1. Switch on “Auto authorization review” on DSH's Plugins page in the sidebar.
|
|
189
|
+
2. Pick Auto review in the composer's permission menu and confirm the risk notice.
|
|
190
|
+
3. Choose the reviewer under Settings → PackyCode → Auto review.
|
|
191
|
+
|
|
192
|
+
The card shows whether DSH's plugin is on, how many reviews this plugin answered (allowed / denied / failed), and the last one. It warns when no key reaches the chosen reviewer.
|
|
193
|
+
|
|
194
|
+
<details>
|
|
195
|
+
<summary>How the review is taken over</summary>
|
|
196
|
+
|
|
197
|
+
- DSH's reviewer sends one model request per review:
|
|
198
|
+
- its fixed `REVIEW_POLICY` as the system prompt;
|
|
199
|
+
- four JSON sections as the user message: ENVIRONMENT, PROJECT_INSTRUCTIONS, FILTERED_HISTORY, PENDING_ACTION;
|
|
200
|
+
- and it expects one `{"risk","decision","reason"?}` object back.
|
|
201
|
+
- Every model request passes DSH's `llm/stream` waterfall. The plugin recognizes only this request there; conversation turns and everything else go on untouched.
|
|
202
|
+
- **DeepSeek Flash** gets the same request, re-addressed to the PackyCode route; DSH still reads its answer.
|
|
203
|
+
- **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.
|
|
204
|
+
- 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.
|
|
205
|
+
- A denial says that jev-latest judged the call medium or high risk.
|
|
206
|
+
- jev-latest has a small context, so a long history is cut starting from the oldest entries; your instructions are kept first.
|
|
207
|
+
- 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.
|
|
208
|
+
- Measured on 37 scenarios with the official request format and the official parser: both reviewers matched all 35 scenarios that have a clear answer.
|
|
209
|
+
- jev-latest's median was 0.35 s, DeepSeek Flash's 2.3 s.
|
|
210
|
+
- If a later DSH changes the review request:
|
|
211
|
+
- a request the plugin no longer recognizes goes on untouched, reviewed by the conversation model;
|
|
212
|
+
- a format jev-latest cannot read fails that review, which shows in the card's counts.
|
|
213
|
+
- 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.
|
|
214
|
+
|
|
215
|
+
</details>
|
|
216
|
+
|
|
169
217
|
## Models and groups
|
|
170
218
|
|
|
171
219
|
| Model | How it runs | Effort | Token group |
|
|
@@ -183,6 +231,8 @@ Live checks on 2026-10-15 passed generation and editing at `low` on all three en
|
|
|
183
231
|
|
|
184
232
|
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.
|
|
185
233
|
|
|
234
|
+
`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.
|
|
235
|
+
|
|
186
236
|
All ten models in the current catalog declare text and image input. DeepSeek Flash follows the [official vision guide](https://api-docs.deepseek.com/guides/vision/); images are read through DSH's attachment service and sent with the Responses request.
|
|
187
237
|
|
|
188
238
|
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).
|
|
@@ -216,9 +266,9 @@ DeepSeek Flash uses the gateway's Responses endpoint (`/api/pricing` lists `open
|
|
|
216
266
|
|
|
217
267
|
## Update and uninstall
|
|
218
268
|
|
|
219
|
-
> **Upgrading from 1.3.2 or earlier:** install `dsh-packycode-api@1.3.
|
|
269
|
+
> **Upgrading from 1.3.2 or earlier:** install `dsh-packycode-api@1.3.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.
|
|
220
270
|
|
|
221
|
-
**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. 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.
|
|
271
|
+
**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. 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.8`); without it you may get a version that is merely the newest one published at least 24 hours ago.
|
|
222
272
|
|
|
223
273
|
**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.
|
|
224
274
|
|
|
@@ -234,7 +284,7 @@ ls ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/node_modules
|
|
|
234
284
|
|
|
235
285
|
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.
|
|
236
286
|
|
|
237
|
-
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.
|
|
287
|
+
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.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.
|
|
238
288
|
|
|
239
289
|
**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:
|
|
240
290
|
|
package/README.md
CHANGED
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
| **Claude 按分组选通道** | `cc` 分组只接受官方客户端,这些 Key 的 Claude 请求由本机 Claude Code CLI 发出;`cc-sale`、`cc-expensive`、`claude-officially` 等分组走插件内 HTTP。两条通道都由 DSH 执行工具、审批权限,计划模式、附件和完整对话历史完全一致 |
|
|
33
33
|
| **网页搜索可走 PackyCode** | 可选:DSH 的 `web_search` 改用 PackyCode 搜索,后端在 DeepSeek 与 GPT 之间切换;可只对 PackyCode 模型生效 |
|
|
34
34
|
| **图片生成与编辑** | 独立图片 Key,支持 GPT Image 2 / 2.5 Flare / 2.5 Sunburst、型号与质量设置、参考图编辑和 PNG 原图保存;已通过网关生图与编辑实测 |
|
|
35
|
+
| **自动审查可换模型** | 开启 DSH 自带的「自动授权审查」后,权限菜单里的「自动审查」可改用 jev-latest 或 DeepSeek Flash 审查每次工具调用,审查规则和处理方式保持官方原样 |
|
|
35
36
|
| **凭据不离开本机** | Key 只存在 DSH 凭据文件里。浏览器只能看到备注、状态和余额,拿不到 Key |
|
|
36
37
|
|
|
37
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" />
|
|
@@ -47,10 +48,10 @@
|
|
|
47
48
|
打开桌面应用的**插件**页,点击**添加插件**,在**包名或地址**中填入**带版本号**的包名:
|
|
48
49
|
|
|
49
50
|
```text
|
|
50
|
-
dsh-packycode-api@1.3.
|
|
51
|
+
dsh-packycode-api@1.3.8
|
|
51
52
|
```
|
|
52
53
|
|
|
53
|
-
在**安装源**中选择**官方源**,然后点击**安装**。`1.3.
|
|
54
|
+
在**安装源**中选择**官方源**,然后点击**安装**。`1.3.8` 是写这份说明时的最新版,当前最新版本号以 [npm 页面](https://www.npmjs.com/package/dsh-packycode-api) 为准。
|
|
54
55
|
|
|
55
56
|
> **一定要带版本号。** 只填 `dsh-packycode-api` 时,安装前的提示显示的是 npm 上的最新版,但 DSH 自带的 pnpm 默认只安装发布满 24 小时的版本,实际装上的可能是好几个版本之前的旧版,而安装提示里看不出这一点。填写精确版本时,pnpm 会直接安装这个版本,并自动把它加入 profile 的 `minimumReleaseAgeExclude`。装好后可以在 **设置 → PackyCode → 插件版本** 核对「当前版本」。
|
|
56
57
|
|
|
@@ -71,7 +72,7 @@ dsh-packycode-api@1.3.7
|
|
|
71
72
|
|
|
72
73
|
桌面应用的**插件**页可以看到已安装状态与版本,也可以在那里启用、停用或卸载。
|
|
73
74
|
|
|
74
|
-
**仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.3.
|
|
75
|
+
**仅用于非 desktop profile:** `dsh plugin --profile <name> add dsh-packycode-api@1.3.8`。不要对 `desktop` 使用它 —— CLI 会直接拒绝(`profile "desktop" is managed exclusively by the Electron application`)。
|
|
75
76
|
|
|
76
77
|
本地开发要加 `link:` 前缀:`dsh plugin --profile <name> add link:/path/to/dsh-packycode-api`。**不要直接写路径(或 `file:`)** —— 那样的安装会把整个仓库目录(连同 `node_modules`)复制进 profile,之后它会在 profile 内部挡住 DSH 自带的包,插件看起来像没装,见「常见问题」。已经那样装过的话,先卸载再按上面的方式重装。
|
|
77
78
|
|
|
@@ -166,6 +167,53 @@ Claude 与其它模型一样,通过 DSH 的 `packycode_image_generate` 工具
|
|
|
166
167
|
|
|
167
168
|
2026-10-15 实测:三个型号均通过 `low` 生图与编辑;Sunburst 额外通过 `xhigh`、`max` 生图与编辑,两档响应的 quality 均与请求一致。合计 10 次成功请求,无重试,全部返回 1024×1024 PNG;编辑正确改色并保留构图。xhigh 生成/编辑约 43/48 秒,max 约 84/91 秒。这是已构建图片 client 的网关验证;本轮未新建 DSH 对话验证完整聊天流程。完整范围和记录见[协议核查与网关实测](docs/research/image-api.md)。
|
|
168
169
|
|
|
170
|
+
### 自动审查
|
|
171
|
+
|
|
172
|
+
DSH 自带一个实验性插件「自动授权审查」,默认关闭。开启后,输入框下方的权限菜单(「仅可查看 / 工作区内修改 / 完全权限」)会多出一项 **自动审查**(带 EXP 标记)。选了自动审查的会话里,每次工具调用前都先由模型审查:
|
|
173
|
+
|
|
174
|
+
- 放行的直接执行,不使用沙箱。
|
|
175
|
+
- 拒绝的改为请你批准;在子代理里则直接拒绝。
|
|
176
|
+
- 审查本身失败时,这次调用不执行。
|
|
177
|
+
|
|
178
|
+
官方默认用当前对话的模型审查。本插件不改官方的审查逻辑,只替换审查模型。在 **设置 → PackyCode → 自动审查** 里选:
|
|
179
|
+
|
|
180
|
+
| 审查模型 | 说明 | 需要的分组 |
|
|
181
|
+
| --- | --- | --- |
|
|
182
|
+
| jev-latest(默认) | TypeSafe 的决策分类模型,一次约 0.4 秒,只按输入计费;拒绝时只给出风险等级 | `typesafe-officially` |
|
|
183
|
+
| DeepSeek Flash | 一次约 2 秒,拒绝时写明原因 | `deepseek-officially` / `deepseek-sale` |
|
|
184
|
+
| 跟随对话模型 | 不接管,按官方默认审查 | — |
|
|
185
|
+
|
|
186
|
+
使用步骤:
|
|
187
|
+
|
|
188
|
+
1. 在 DSH 左侧「插件」页开启「自动授权审查」。
|
|
189
|
+
2. 在输入框的权限菜单里选「自动审查」,确认风险提示。
|
|
190
|
+
3. 在「设置 → PackyCode → 自动审查」选审查模型。
|
|
191
|
+
|
|
192
|
+
卡片会显示:官方插件是否已开启、本插件处理过多少次审查(放行 / 拒绝 / 失败)和最近一次结果。如果没有 Key 能调用所选模型,卡片会提示。
|
|
193
|
+
|
|
194
|
+
<details>
|
|
195
|
+
<summary>怎么接管的</summary>
|
|
196
|
+
|
|
197
|
+
- 官方审查器每次审查发出一个模型请求:
|
|
198
|
+
- 系统提示是它固定的 `REVIEW_POLICY`;
|
|
199
|
+
- 用户消息是四段 JSON:ENVIRONMENT、PROJECT_INSTRUCTIONS、FILTERED_HISTORY、PENDING_ACTION;
|
|
200
|
+
- 要求返回一个 `{"risk","decision","reason"?}` 对象。
|
|
201
|
+
- 所有模型请求都经过 DSH 的 `llm/stream` 流水线。本插件在这里只认这一种请求,对话等其它请求原样放过。
|
|
202
|
+
- **DeepSeek Flash**:同一个请求原样改发到 PackyCode 线路,结果仍由官方解析。
|
|
203
|
+
- **jev-latest**:它写不出 JSON。插件把四段内容和官方规则原文作为 System One 的 state,问两个问题:风险等级,以及你是否明确要求过这个操作。
|
|
204
|
+
- 放行条件:「低风险,或中风险且你要求过」的概率不低于 0.6,且高风险概率低于 0.2。
|
|
205
|
+
- 拒绝时,理由里写明是 jev-latest 判定的中风险或高风险。
|
|
206
|
+
- jev-latest 上下文较小,过长的历史会从最旧的开始截掉,你的指令优先保留。
|
|
207
|
+
- 看什么、按什么规则判、放行或拒绝后怎么处理,都由官方插件决定。官方对审查失败(例如 Key 调不了 jev-latest)的处理是拒绝这次调用,本插件不改变这一点。
|
|
208
|
+
- 实测方式:37 个场景,用官方的请求格式和官方解析器。其中 35 个有明确答案,两个模型都全部符合预期。
|
|
209
|
+
- jev-latest 中位 0.35 秒,DeepSeek Flash 中位 2.3 秒。
|
|
210
|
+
- 如果以后 DSH 改了审查请求的格式:
|
|
211
|
+
- 认不出这个请求时,原样放过,由对话模型审查;
|
|
212
|
+
- jev-latest 读不懂新格式时,这次审查失败,卡片计数里会看到。
|
|
213
|
+
- 菜单里「自动审查」的说明写的是「由同一模型审查」,那是 DSH 的文字。选了 jev-latest 或 DeepSeek Flash 时,实际由所选模型审查。
|
|
214
|
+
|
|
215
|
+
</details>
|
|
216
|
+
|
|
169
217
|
## 模型与分组
|
|
170
218
|
|
|
171
219
|
| 模型 | 怎么调用 | 推理档位 | 适合的令牌分组 |
|
|
@@ -183,6 +231,8 @@ Claude 与其它模型一样,通过 DSH 的 `packycode_image_generate` 工具
|
|
|
183
231
|
|
|
184
232
|
列表里看得到模型,不代表当前令牌分组一定放行。换分组时不要把对应分组一起去掉。
|
|
185
233
|
|
|
234
|
+
`jev-latest`(TypeSafe Jev)不在模型选择器里:它是只回答分类问题的决策模型,不能对话,只用于[自动审查](#自动审查)。插件在宿主侧直接调用 `/v1/systemone`,需要 Key 在 `typesafe-officially` 分组;「账户与 Key」里每个 Key 的「Jev」一项会显示能否使用。
|
|
235
|
+
|
|
186
236
|
当前目录中的 10 个模型都声明了文字和图像输入。DeepSeek Flash 的识图能力按 [官方图像理解文档](https://api-docs.deepseek.com/zh-cn/guides/vision/) 配置;图片通过 DSH 附件服务读取,再随 Responses 请求发送。
|
|
187
237
|
|
|
188
238
|
Gemini 的能力与限制来自 Google 官方模型页:[Gemini 4 Argon](https://ai.google.dev/gemini-api/docs/models/gemini-4-argon)、[Gemini 3.8 Flash](https://ai.google.dev/gemini-api/docs/models/gemini-3.8-flash)。两款模型统一使用 Gemini 原生协议,通过 `/v1beta/models/{model}:streamGenerateContent` 流式返回文字、思考和工具调用,图片仍由 DSH 附件服务读取。思考档位通过 `thinkingLevel` 传入。两者均使用单次流式输出上限,不执行超过 65,536 token 的自动续写。可用端点与分组以 [PackyAPI 实时模型目录](https://www.packyapi.com/api/pricing) 为准。
|
|
@@ -216,9 +266,9 @@ DeepSeek Flash 走网关的 Responses 接口(`/api/pricing` 列出 `openai-res
|
|
|
216
266
|
|
|
217
267
|
## 更新与卸载
|
|
218
268
|
|
|
219
|
-
> **从 1.3.2 或更早版本升级:** 请在插件页填写 `dsh-packycode-api@1.3.
|
|
269
|
+
> **从 1.3.2 或更早版本升级:** 请在插件页填写 `dsh-packycode-api@1.3.8` 安装,不要点旧版设置页里的「更新插件」。旧按钮安装时会绕过 pnpm 的发布冷却期:装到的版本如果发布还不满 24 小时,这个 profile 在它满 24 小时之前就装不了其他插件。装好并重启后,按钮就换成了修好的版本,以后直接点即可。
|
|
220
270
|
|
|
221
|
-
**更新:** 打开 **设置 → PackyCode**,有新版本时点「更新插件」。它会在当前 profile 目录里用 DSH 自带的 pnpm 安装精确版本,并读回 `package.json` 确认版本落地。安装遵守 pnpm 的发布冷却策略,不会绕过它:默认情况下 pnpm 会直接装上这个版本,并把它记进 profile 的 `minimumReleaseAgeExclude`;如果你给 pnpm 配了更严格的策略,按钮会提示什么时候可以更新。本地 `link:` 开发安装不会出现这个按钮。完成后完全退出并重新打开桌面应用。只刷新页面不会重载 Host。也可以在**插件**页重新安装,同样要填写带版本号的包名(例如 `dsh-packycode-api@1.3.
|
|
271
|
+
**更新:** 打开 **设置 → PackyCode**,有新版本时点「更新插件」。它会在当前 profile 目录里用 DSH 自带的 pnpm 安装精确版本,并读回 `package.json` 确认版本落地。安装遵守 pnpm 的发布冷却策略,不会绕过它:默认情况下 pnpm 会直接装上这个版本,并把它记进 profile 的 `minimumReleaseAgeExclude`;如果你给 pnpm 配了更严格的策略,按钮会提示什么时候可以更新。本地 `link:` 开发安装不会出现这个按钮。完成后完全退出并重新打开桌面应用。只刷新页面不会重载 Host。也可以在**插件**页重新安装,同样要填写带版本号的包名(例如 `dsh-packycode-api@1.3.8`),否则装上的可能是发布满 24 小时的旧版。
|
|
222
272
|
|
|
223
273
|
**从本地路径安装切回官方源时,必须先卸载。** 「更新」是 `pnpm add`,它只重写包目录里的文件,不会删除更早一次本地路径安装留在包目录内的 `node_modules`;那份旧依赖会继续挡住 DSH 自带的包,插件行加载失败且看不出原因。「卸载」执行的是 `pnpm remove`,会删掉整个包目录,重装才是干净的。用 `node scripts/install-check.mjs` 可以确认当前 profile 是否处于这个状态。
|
|
224
274
|
|
|
@@ -234,7 +284,7 @@ ls ~/.dsh/profiles/desktop/node_modules/dsh-packycode-api/node_modules
|
|
|
234
284
|
|
|
235
285
|
有输出就是残留:从 npm 安装的包不会自带 `node_modules`,这一份通常来自更早一次「本地路径」安装(`file:` 或直接写路径,而不是 `link:`)。它位于 profile 目录内部,而 DSH 解析插件导入时优先使用 profile 内的副本,所以插件拿到的仍是那份旧依赖 —— 例如 `@deepseek-ai/schemastery` 3.18.2 没有 `Schema.volatile()`,模块在导入阶段就抛错。导入失败时 Loader 不会为这一行创建 fiber,客户端 bundle 也不会被组合,于是模型路由、RPC 通道和设置页全都不会出现。
|
|
236
286
|
|
|
237
|
-
修复:到**插件**页**卸载**本插件,再用带版本号的包名重新**安装**(例如 `dsh-packycode-api@1.3.
|
|
287
|
+
修复:到**插件**页**卸载**本插件,再用带版本号的包名重新**安装**(例如 `dsh-packycode-api@1.3.8`),然后完全退出并重新打开桌面应用。卸载执行的是 `pnpm remove`,会删掉整个包目录;直接重装或点「更新」只重写文件,不会清掉这份残留。也可以手动删掉上面那个 `node_modules` 再重启。
|
|
238
288
|
|
|
239
289
|
**首次安装后,设置页每张卡片都显示 `transport failure for /packycode-api/…: HTTP 405`?** 实际装上的是 1.1.6 或更早的版本,通常是因为安装时只填了包名:安装提示显示的是最新版,pnpm 实际装的却是发布满 24 小时的旧版(见「安装插件」)。这些旧版要等 DSH 重启、重建它的 `connection` 服务之后,才能注册设置通道。所以首次安装后 `/packycode-api` 通道还不存在,请求落到静态页面,返回 405;模型路由和设置页本身照常加载。1.1.7 起首次安装不需要重启。先确认装上的版本:
|
|
240
290
|
|
package/lib/client.js
CHANGED
|
@@ -240,7 +240,28 @@ window.__ModuleLoader__.load({
|
|
|
240
240
|
searchOverridden: "基础搜索现在是 {base},不是 PackyCode:可能还在热加载,或被其他插件的补丁覆盖。",
|
|
241
241
|
searchUnavailable: "当前运行环境没有 DSH 网页搜索服务,搜索路由暂不生效。",
|
|
242
242
|
searchNotWritable: "当前 profile 不允许写入设置。",
|
|
243
|
-
searchUnknown: "未知"
|
|
243
|
+
searchUnknown: "未知",
|
|
244
|
+
reviewTitle: "自动审查",
|
|
245
|
+
reviewIntro: "DSH 自带的「自动授权审查」插件会在输入框的权限菜单里加入「自动审查」:每次工具调用前先让模型审查,放行的直接执行,拒绝的改为请你批准。它默认用当前对话的模型审查;本插件可以让它改用下面选择的模型,审查内容、规则和结果处理都保持官方原样。",
|
|
246
|
+
reviewChecking: "正在读取自动审查设置…",
|
|
247
|
+
reviewLoadFailed: "自动审查设置读取或保存失败",
|
|
248
|
+
reviewOfficialOn: "官方自动审查已开启",
|
|
249
|
+
reviewOfficialOff: "官方自动审查未开启",
|
|
250
|
+
reviewEnableHint: "还没有开启:在 DSH 左侧「插件」页找到「自动授权审查」并开启,然后在输入框的权限菜单里选「自动审查」。",
|
|
251
|
+
reviewModelTitle: "审查模型",
|
|
252
|
+
reviewModelJev: "jev-latest",
|
|
253
|
+
reviewModelFlash: "DeepSeek Flash",
|
|
254
|
+
reviewModelSession: "跟随对话模型",
|
|
255
|
+
reviewModelJevHint: "TypeSafe 的决策分类模型,一次约 0.4 秒,只按输入计费;拒绝时只给出风险等级。需要 Key 的分组包含 typesafe-officially。",
|
|
256
|
+
reviewModelFlashHint: "一次约 2 秒,拒绝时写明原因。需要 Key 的分组包含 deepseek-officially。",
|
|
257
|
+
reviewModelSessionHint: "不接管,按官方默认由当前对话的模型审查。",
|
|
258
|
+
reviewUncovered: "已保存的 Key 都不在 {model} 所需的分组里:审查会失败,官方会因此拒绝每次工具调用。请换一个审查模型,或添加分组包含它的 Key。",
|
|
259
|
+
reviewCounts: "本次启动以来本插件处理了 {reviewed} 次审查:放行 {allowed},拒绝 {denied},失败 {failed}。",
|
|
260
|
+
reviewLast: "最近一次:{tool} · {outcome} · {model} · {seconds} 秒",
|
|
261
|
+
reviewOutcomeAllowed: "放行",
|
|
262
|
+
reviewOutcomeDenied: "拒绝",
|
|
263
|
+
reviewOutcomeFailed: "失败",
|
|
264
|
+
reviewMenuNote: "权限菜单里「自动审查」的说明写的是「由同一模型审查」,那是 DSH 的文字;选了 jev-latest 或 DeepSeek Flash 时,实际由所选模型审查。审查失败时,官方会拒绝这次调用,不会执行。"
|
|
244
265
|
};
|
|
245
266
|
const en = {
|
|
246
267
|
nav: "PackyCode",
|
|
@@ -447,7 +468,28 @@ window.__ModuleLoader__.load({
|
|
|
447
468
|
searchOverridden: "The base search is {base}, not PackyCode: the reload may still be running, or another plugin’s patch overrides it.",
|
|
448
469
|
searchUnavailable: "This runtime has no DSH web search service; search routing has no effect.",
|
|
449
470
|
searchNotWritable: "This profile does not allow settings writes.",
|
|
450
|
-
searchUnknown: "unknown"
|
|
471
|
+
searchUnknown: "unknown",
|
|
472
|
+
reviewTitle: "Auto review",
|
|
473
|
+
reviewIntro: "DSH’s built-in “Auto authorization review” plugin adds Auto review to the composer’s permission menu: before each tool call a model reviews it; calls it allows run at once, calls it denies ask for your approval. It reviews with the conversation’s own model by default; this plugin can make it use the model chosen below, while what is reviewed, the rules and the outcomes stay exactly the official ones.",
|
|
474
|
+
reviewChecking: "Reading the auto review preference…",
|
|
475
|
+
reviewLoadFailed: "Could not read or save the auto review preference",
|
|
476
|
+
reviewOfficialOn: "Official auto review is on",
|
|
477
|
+
reviewOfficialOff: "Official auto review is off",
|
|
478
|
+
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.",
|
|
479
|
+
reviewModelTitle: "Reviewer",
|
|
480
|
+
reviewModelJev: "jev-latest",
|
|
481
|
+
reviewModelFlash: "DeepSeek Flash",
|
|
482
|
+
reviewModelSession: "Conversation model",
|
|
483
|
+
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.",
|
|
484
|
+
reviewModelFlashHint: "About 2 s per review, and a denial says why. Needs a key whose group includes deepseek-officially.",
|
|
485
|
+
reviewModelSessionHint: "Leave the review alone: the conversation’s own model reviews, as DSH does by default.",
|
|
486
|
+
reviewUncovered: "No stored key is in a group that serves {model}: reviews will fail, and DSH then refuses every tool call. Pick another reviewer, or add a key whose group includes it.",
|
|
487
|
+
reviewCounts: "Since this start the plugin answered {reviewed} reviews: {allowed} allowed, {denied} denied, {failed} failed.",
|
|
488
|
+
reviewLast: "Last: {tool} · {outcome} · {model} · {seconds} s",
|
|
489
|
+
reviewOutcomeAllowed: "allowed",
|
|
490
|
+
reviewOutcomeDenied: "denied",
|
|
491
|
+
reviewOutcomeFailed: "failed",
|
|
492
|
+
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."
|
|
451
493
|
};
|
|
452
494
|
//#endregion
|
|
453
495
|
//#region src/client-style.js
|
|
@@ -1882,6 +1924,8 @@ window.__ModuleLoader__.load({
|
|
|
1882
1924
|
const SEARCH_SETTLE_MS = 1500;
|
|
1883
1925
|
/** While the CLI installs, the panel polls its status this often. */
|
|
1884
1926
|
const INSTALL_POLL_MS = 2e3;
|
|
1927
|
+
/** The auto review counts are re-read this often while the page is open. */
|
|
1928
|
+
const REVIEW_POLL_MS = 5e3;
|
|
1885
1929
|
const CLAUDE_MODELS = [
|
|
1886
1930
|
"claude-opus-5-5",
|
|
1887
1931
|
"claude-sonnet-5-5",
|
|
@@ -1909,7 +1953,8 @@ window.__ModuleLoader__.load({
|
|
|
1909
1953
|
"claude-opus-5-5",
|
|
1910
1954
|
"claude-sonnet-5-5",
|
|
1911
1955
|
"claude-haiku-5-5"
|
|
1912
|
-
]]
|
|
1956
|
+
]],
|
|
1957
|
+
["Jev", ["jev-latest"]]
|
|
1913
1958
|
];
|
|
1914
1959
|
/**
|
|
1915
1960
|
* The one way this bundle talks to the host. The transport drops an
|
|
@@ -2589,6 +2634,145 @@ window.__ModuleLoader__.load({
|
|
|
2589
2634
|
]
|
|
2590
2635
|
});
|
|
2591
2636
|
}
|
|
2637
|
+
const REVIEW_OUTCOMES = {
|
|
2638
|
+
allowed: "reviewOutcomeAllowed",
|
|
2639
|
+
denied: "reviewOutcomeDenied",
|
|
2640
|
+
failed: "reviewOutcomeFailed"
|
|
2641
|
+
};
|
|
2642
|
+
const REVIEW_LABELS = {
|
|
2643
|
+
"jev-latest": "reviewModelJev",
|
|
2644
|
+
"deepseek-flash": "reviewModelFlash",
|
|
2645
|
+
session: "reviewModelSession"
|
|
2646
|
+
};
|
|
2647
|
+
const REVIEW_HINTS = {
|
|
2648
|
+
"jev-latest": "reviewModelJevHint",
|
|
2649
|
+
"deepseek-flash": "reviewModelFlashHint",
|
|
2650
|
+
session: "reviewModelSessionHint"
|
|
2651
|
+
};
|
|
2652
|
+
/** Which model DSH's official auto review uses; the official plugin owns the rest. */
|
|
2653
|
+
function AutoReviewCard({ call, t }) {
|
|
2654
|
+
const [state, setState] = react.useState();
|
|
2655
|
+
const [groups, setGroups] = react.useState();
|
|
2656
|
+
const [busy, setBusy] = react.useState(false);
|
|
2657
|
+
const [error, setError] = react.useState();
|
|
2658
|
+
const generation = react.useRef(0);
|
|
2659
|
+
const read = react.useCallback(() => {
|
|
2660
|
+
const current = ++generation.current;
|
|
2661
|
+
return call("auto-review/status").then((value) => {
|
|
2662
|
+
if (generation.current === current) setState(value);
|
|
2663
|
+
}).catch((failure) => {
|
|
2664
|
+
if (generation.current === current) setError(clearMessage(failure));
|
|
2665
|
+
});
|
|
2666
|
+
}, [call]);
|
|
2667
|
+
react.useEffect(() => {
|
|
2668
|
+
let live = true;
|
|
2669
|
+
read();
|
|
2670
|
+
call("groups").then((value) => {
|
|
2671
|
+
if (live) setGroups(value);
|
|
2672
|
+
}).catch(() => void 0);
|
|
2673
|
+
const timer = window.setInterval(read, REVIEW_POLL_MS);
|
|
2674
|
+
return () => {
|
|
2675
|
+
live = false;
|
|
2676
|
+
generation.current += 1;
|
|
2677
|
+
window.clearInterval(timer);
|
|
2678
|
+
};
|
|
2679
|
+
}, [call, read]);
|
|
2680
|
+
const update = (patch) => {
|
|
2681
|
+
if (busy || state?.writable !== true) return;
|
|
2682
|
+
setBusy(true);
|
|
2683
|
+
setError(void 0);
|
|
2684
|
+
generation.current += 1;
|
|
2685
|
+
call("auto-review/update", patch).then((value) => setState(value)).catch((failure) => setError(clearMessage(failure))).finally(() => setBusy(false));
|
|
2686
|
+
};
|
|
2687
|
+
const label = (id) => REVIEW_LABELS[id] === void 0 ? id : t(REVIEW_LABELS[id]);
|
|
2688
|
+
const model = state?.model;
|
|
2689
|
+
const enabled = state?.official?.enabled === true;
|
|
2690
|
+
const keys = groups?.keys ?? [];
|
|
2691
|
+
const uncovered = model !== void 0 && model !== "session" && keys.length > 0 && keys.every((entry) => entry.coverage?.[model] === false);
|
|
2692
|
+
const counts = state?.counts;
|
|
2693
|
+
const last = state?.last;
|
|
2694
|
+
const disabled = busy || state?.writable !== true;
|
|
2695
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Card, {
|
|
2696
|
+
title: t("reviewTitle"),
|
|
2697
|
+
aside: state !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2698
|
+
className: "pkc-chip",
|
|
2699
|
+
"data-tone": enabled ? "success" : "neutral",
|
|
2700
|
+
children: enabled ? t("reviewOfficialOn") : t("reviewOfficialOff")
|
|
2701
|
+
}),
|
|
2702
|
+
children: [
|
|
2703
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2704
|
+
className: "pkc-note",
|
|
2705
|
+
children: t("reviewIntro")
|
|
2706
|
+
}),
|
|
2707
|
+
state === void 0 && error === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2708
|
+
className: "pkc-note",
|
|
2709
|
+
role: "status",
|
|
2710
|
+
children: t("reviewChecking")
|
|
2711
|
+
}),
|
|
2712
|
+
state !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
2713
|
+
!enabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2714
|
+
className: "pkc-warn",
|
|
2715
|
+
children: t("reviewEnableHint")
|
|
2716
|
+
}),
|
|
2717
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2718
|
+
className: "pkc-setting",
|
|
2719
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2720
|
+
className: "pkc-label",
|
|
2721
|
+
children: t("reviewModelTitle")
|
|
2722
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Segmented, {
|
|
2723
|
+
label: t("reviewModelTitle"),
|
|
2724
|
+
value: model,
|
|
2725
|
+
disabled,
|
|
2726
|
+
onChange: (value) => update({ autoReviewModel: value }),
|
|
2727
|
+
options: (state.models ?? []).map((entry) => ({
|
|
2728
|
+
value: entry.id,
|
|
2729
|
+
label: label(entry.id)
|
|
2730
|
+
}))
|
|
2731
|
+
}), REVIEW_HINTS[model] !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2732
|
+
className: "pkc-note",
|
|
2733
|
+
children: t(REVIEW_HINTS[model])
|
|
2734
|
+
})] })]
|
|
2735
|
+
}),
|
|
2736
|
+
uncovered && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2737
|
+
className: "pkc-warn",
|
|
2738
|
+
children: fill(t("reviewUncovered"), { model: label(model) })
|
|
2739
|
+
}),
|
|
2740
|
+
counts !== void 0 && counts.reviewed > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2741
|
+
className: "pkc-status",
|
|
2742
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2743
|
+
className: "pkc-dot",
|
|
2744
|
+
"data-tone": counts.failed > 0 ? "warn" : "success"
|
|
2745
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2746
|
+
className: "pkc-meta",
|
|
2747
|
+
children: fill(t("reviewCounts"), counts)
|
|
2748
|
+
})]
|
|
2749
|
+
}),
|
|
2750
|
+
last !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2751
|
+
className: "pkc-meta",
|
|
2752
|
+
children: fill(t("reviewLast"), {
|
|
2753
|
+
tool: last.tool ?? "",
|
|
2754
|
+
outcome: t(REVIEW_OUTCOMES[last.outcome] ?? "reviewOutcomeFailed"),
|
|
2755
|
+
model: last.version ?? label(last.model),
|
|
2756
|
+
seconds: typeof last.ms === "number" ? (last.ms / 1e3).toFixed(1) : "?"
|
|
2757
|
+
})
|
|
2758
|
+
}),
|
|
2759
|
+
state.writable !== true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2760
|
+
className: "pkc-note",
|
|
2761
|
+
children: t("searchNotWritable")
|
|
2762
|
+
}),
|
|
2763
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2764
|
+
className: "pkc-note",
|
|
2765
|
+
children: t("reviewMenuNote")
|
|
2766
|
+
})
|
|
2767
|
+
] }),
|
|
2768
|
+
error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2769
|
+
className: "pkc-error",
|
|
2770
|
+
role: "alert",
|
|
2771
|
+
children: `${t("reviewLoadFailed")}: ${error}`
|
|
2772
|
+
})
|
|
2773
|
+
]
|
|
2774
|
+
});
|
|
2775
|
+
}
|
|
2592
2776
|
const INSTALL_FAILURES = {
|
|
2593
2777
|
"npm-missing": () => "cliNpmMissing",
|
|
2594
2778
|
permission: (cli) => cli.platform === "win32" ? "cliPermissionWindows" : "cliPermission",
|
|
@@ -3029,6 +3213,10 @@ window.__ModuleLoader__.load({
|
|
|
3029
3213
|
call,
|
|
3030
3214
|
t
|
|
3031
3215
|
}),
|
|
3216
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoReviewCard, {
|
|
3217
|
+
call,
|
|
3218
|
+
t
|
|
3219
|
+
}),
|
|
3032
3220
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(VersionCard, {
|
|
3033
3221
|
call,
|
|
3034
3222
|
t
|