dsh-model-switch 0.4.32 → 0.4.34
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 +19 -1
- package/lib/auto-review-BLtwr83V.js +738 -0
- package/lib/auto-review-BoF2_YtP.js +745 -0
- package/lib/auto-review.js +2 -718
- package/lib/client.js +5 -2
- package/lib/compaction.js +1 -1
- package/lib/index.js +8 -2
- package/lib/session-route-D1zoZgf3.js +258 -0
- package/lib/session-title.js +1 -1
- package/lib/subagent-runtime.js +1 -1
- package/lib/types/auto-review.d.ts +13 -0
- package/lib/types/client/locales.d.ts +1 -0
- package/lib/types/host-runtime.d.ts +7 -0
- package/lib/types/runtime-capabilities.d.ts +12 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,21 @@
|
|
|
1
|
+
## v0.4.34
|
|
2
|
+
|
|
3
|
+
The「停用失败:dsh: warning: 1 entry did not activate auto-review … permission: preset "auto" is already registered」toast is gone: every official-row activation now gets the registration yielded first, and this row releases the slot in the first synchronous step of its own teardown.
|
|
4
|
+
|
|
5
|
+
- **P0 root cause: the yield was one-shot (`src/auto-review-takeover.ts`).** The `loader/patch-context` listener kept an `handled` set so "a repeated patch-context does not loop" — but that guard also **skipped the yield from the second activation on**. The loader calls `_patchContext([])` right before every `registry.plugin` mount (confirmed in the loader source: `Entry._init()` = import → `_patchContext([])` → `registry.plugin`), and a plugin-manager enable goes through `Entry.update({ disabled: false }) → init()` — so the re-activating official row's `registerAuto` ran while this row still held the slot, failed with `preset "auto" is already registered`, and the manager reported the whole operation as 「停用失败」. `Entry.update({ disabled: true })` never emits `partial-dispose`, so the set was never cleared and the suppression was permanent. The guard is gone: **every** activation of the official row yields synchronously before the loader continues (`releaseForTakeover` is idempotent), and the existing per-entry single-flight reclaim keeps repeated triggers on one cycle, so this cannot loop. Two regression tests pin it: a second activation yields again, and non-official rows stay out of the way.
|
|
6
|
+
- **Release first on our own teardown (`src/auto-review.ts`).** Disposing the gate fiber now releases the Auto registration in its **first synchronous step** (the loader does not await fiber disposal, and the official row's re-activation in the same recompose must find the slot free), and a last-registered effect releases it again as the teardown's first step — belt-and-braces for registrations claimed without a gate fiber (a direct `reclaimRegistration()`).
|
|
7
|
+
- **Live reproduction and verification.** Reproduced on the real desktop Host through the web UI before fixing: enabling「自动授权审查」with `dsh-model-switch` active **failed twice** (the switch silently reverted), and the very same operation succeeded with `dsh-model-switch` disabled — the seam conflict isolated by a single variable. `pnpm run check` green (55 test files / **496** tests + pack gate). Post-fix web-UI regression covers enable/disable cycles with the official row active: no toasts, no warnings, no failed activations.
|
|
8
|
+
- **Diagnosis recorded (the reported "运行失败" was not this plugin).** The turn-28 outage was a **model-request transport failure** (`Connection error.` / `TRANSPORT`, provider `apigoto`, five fast rejections in 8 s) — the same failure class this deployment has seen on provider accounts before (10-13 `ark` ×10, 10-15 `xiaomi` ×29). A web-UI A/B with this plugin **on and off** ran 5/5 model requests clean in both states (and the naming call alongside), and this repo has no code path that touches the request transport (no `llm/stream` listener, no fetch/global patch). The 17:49 recovery after disabling plugins is confounded: the permission preset flipped `auto → danger-full-access` in the same minute, which also removes the per-tool-call review traffic against the same account.
|
|
9
|
+
|
|
10
|
+
## v0.4.33
|
|
11
|
+
|
|
12
|
+
The reviewer takeover now reports its own health to the settings page instead of only writing a Host log line.
|
|
13
|
+
|
|
14
|
+
- **Runtime-capability field (`src/runtime-capabilities.ts`, `src/host-runtime.ts`).** `autoReview` joins the capability snapshot: `{ available: true }` while this row holds the official reviewer route, `{ available: false, reason: 'auto-review-takeover' }` once it does not. The value comes from a live record (`autoReviewStatus` in `src/auto-review.ts`) updated on every claim, on the lost-seam path, and by the tool-call safety net — which also counts the calls it allowed unreviewed, so the card can say how much review was skipped.
|
|
15
|
+
- **Settings card warning (`src/client/ModelSwitchSettings.tsx`, `src/client/locales.ts`).** The「自动审查」section renders `autoReviewTakeoverNote` while the route is held and `autoReviewTakeoverWarning` otherwise (zh + en: tool calls keep running, those calls are unreviewed, restart DSH to converge). What used to be a Host-only log line is now visible where the human configures the route.
|
|
16
|
+
- **Verification.** `pnpm run check` green (55 test files / 494 tests + pack gate). The safety net's test now also asserts the allowed-call counter the snapshot reads, so the card's data path is covered end to end (host record → capability snapshot → card text selected by `available`).
|
|
17
|
+
- **Lab reproduction of the reported outage (released artifact).** The published `dsh-model-switch@0.4.33` was installed in the lab profile (`DSH_HOME=~/.dsh-lab`) with the official `auto-review` row **force-enabled** in the profile patch, the Host was booted on 3082, and the web UI was driven over CDP (a dedicated Edge instance, the user's own browser untouched). A first real tool call completed in 8 s with the actual directory listing. **Without restarting the Host**, `dsh plugin --profile lab remove dsh-model-switch` + `add dsh-model-switch@0.4.33` performed the hot swap and the profile patch toggled the official row off and back on (two runtime recompositions); a second real tool call then completed in 7 s with the file list, and the page contained **no** `inactive context` / `cannot get required service` / `body was not executed` / `Auto review of tool` failure. This is the disable → remove → install → enable sequence that used to require a DSH restart.
|
|
18
|
+
|
|
1
19
|
## v0.4.32
|
|
2
20
|
|
|
3
21
|
A hot install could still break every tool call: replacing the plugin (disable → remove → install → enable, **without a DSH restart**) leaves the official `auto-review` row serving while this row's takeover is still trying to displace it, and its unshielded probe fails each call. This release makes that window non-fatal and shortens it.
|
|
@@ -6,7 +24,7 @@ A hot install could still break every tool call: replacing the plugin (disable
|
|
|
6
24
|
- **The takeover budget matches a real disposal (`src/auto-review-takeover.ts`).** 20×10 ms (~200 ms) → 60×50 ms (~3 s), plus `TAKEOVER_LATE_RETRY_DELAYS_MS` = 500/1000/1500 ms: three bounded re-claims after the loop gives up, because `Entry.update({ disabled: true })` starts the displaced fiber's teardown and the loader does not await it. A disposal that unmounts a gate, restores permission presets and unwinds fibers outlasted the old budget, which is exactly the reported hot-swap window. Timers are cleared with the row.
|
|
7
25
|
- **Actionable failure log.** The lost-seam error now says both what happens next ("the reviewer path is shielded instead of failing tool calls") and what the human can do ("Restart DSH to converge the reviewer row — a hot install cannot always displace the official row in time").
|
|
8
26
|
- **Docs.** `docs/seam-gap.md` records the two remaining gaps: no public seam lets a plugin **replace a bundled capability row at runtime** (only disable-and-reclaim through the loader), and the loader cannot address a row nested in a preset's `config.plugins` — the official bundle row is top-level today, but a future nesting would need a config-level bridge like 0.4.27's preset bridge.
|
|
9
|
-
- **Verification.** `pnpm run check` green (55 test files / 494 tests + pack gate). New coverage: the net allows the call and reports exactly once when the seam is broken, stays inert while this row holds the route, rethrows a reviewer quota error, and classifies an inject failure apart from a denial. The late-retry schedule is bounded by the row's lifetime. **
|
|
27
|
+
- **Verification.** `pnpm run check` green (55 test files / 494 tests + pack gate). New coverage: the net allows the call and reports exactly once when the seam is broken, stays inert while this row holds the route, rethrows a reviewer quota error, and classifies an inject failure apart from a denial. The late-retry schedule is bounded by the row's lifetime. **Lab evidence, released artifact:** the published `dsh-model-switch@0.4.32` was installed into the lab profile (`DSH_HOME=~/.dsh-lab`, dependency pinned to the registry version) and booted on 3082 with the official `auto-review` row **force-enabled** in the profile patch — the Host started, served its token URL, and reported no failed activation, so the takeover and the new budget converge at startup on the immutable artifact. **Still not reproduced:** the *runtime* toggle (enabling the official row while the Host is already serving) together with a real tool call — plugin logs do not reach stdout in web mode, so that needs the Host API or a browser-driven session.
|
|
10
28
|
|
|
11
29
|
## v0.4.31
|
|
12
30
|
|