dsh-model-switch 0.4.22 → 0.4.24
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 +23 -0
- package/PRODUCT.md +7 -6
- package/README.md +43 -15
- package/README.zh.md +43 -15
- package/cordis.patch.yml +15 -1
- package/docs/screenshots/settings-subagent.png +0 -0
- package/lib/auto-review.js +8 -0
- package/lib/client.js +510 -810
- package/lib/compaction.js +51 -18
- package/lib/index.js +25 -96
- package/lib/provider-group-CsZi7H29.js +94 -0
- package/lib/session-route-h9SAqajc.js +172 -0
- package/lib/session-title.js +217 -0
- package/lib/subagent-runtime.js +20 -17
- package/lib/types/auto-review.d.ts +8 -0
- package/lib/types/client/ModelSwitchSettings.d.ts +9 -6
- package/lib/types/client/derived-config-form.d.ts +14 -0
- package/lib/types/client/locales.d.ts +10 -9
- package/lib/types/client/main-row-controller.d.ts +16 -35
- package/lib/types/client/picker/ComposerPicker.d.ts +1 -3
- package/lib/types/client/picker/PlanReviewCard.d.ts +0 -6
- package/lib/types/client/picker/locales.d.ts +0 -8
- package/lib/types/client/picker/provider-group-watch.d.ts +48 -0
- package/lib/types/client-contract.d.ts +8 -9
- package/lib/types/compaction.d.ts +25 -4
- package/lib/types/host-runtime.d.ts +1 -11
- package/lib/types/host-settings.d.ts +6 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/picker/plan-review.d.ts +2 -10
- package/lib/types/provider-group.d.ts +20 -36
- package/lib/types/session-route.d.ts +111 -0
- package/lib/types/session-title.d.ts +104 -0
- package/lib/types/subagent-runtime.d.ts +14 -3
- package/package.json +24 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
## v0.4.24
|
|
2
|
+
|
|
3
|
+
Three coordinated changes: session naming gains a configurable model; provider groups (and the Default Subagent route) become per-session derived policy instead of a write, fixing sessions on different providers overwriting or redirecting each other's auxiliary routes; and every settings row save becomes one atomic revision-fenced mutation, fixing the save-while-running freeze, half-written provider/model pairs, and the ambiguous ⚠ marker.
|
|
4
|
+
|
|
5
|
+
- **New: session-naming model card.** The settings page now configures the model behind DSH's automatic session titles. Off (both fields empty) is the official behavior — naming follows the session's own model; On pins a provider/model. The route is **read through on every naming request**, so a saved change applies to the very next title with no restart, and a naming request already in flight is never interrupted by a save. Each request resolves the session's provider group first, then the flat pair, then the session's own model, and the official implementation records the exact pair used in the session's own `session/title-llm-request` event — the durable record and the real request can never disagree. The plugin replaces the official `session-title-llm` row (the seam allows one registered naming provider per context) and mirrors the cadence that row declared; because a `disabled` row is not an instantiated loader entry, a profile where the displaced row cannot be inspected mirrors the shipped first-prompt cadence rather than dropping model-backed naming.
|
|
6
|
+
- **Provider groups are derived, not written (cross-session overwrite fixed).** Previously a provider switch *wrote* the group's routes into the shared deployment-wide fields, so two sessions on different providers could overwrite or redirect each other's auxiliary routes — a real cross-session hazard. Now a group saved for provider X merely applies to the sessions whose own provider is X: the Host resolves **group pair → flat deployment-wide pair → official default** per session and per request, and switching a session's provider writes NOTHING. The group editor therefore covers exactly the session-naming and subagent routes; auto review and compaction stay deployment-wide cards (the official auto-review gate exposes no session identity at its interception point, and the official compaction transaction durably records the provider/model that wrote its summary — both recorded in `docs/seam-gap.md`). The stored configuration format is unchanged and no migration runs: an older entry may still carry its compaction/auto-review fields, and they are ignored.
|
|
7
|
+
- **Subagent routing follows the delegating session.** A spawn that names no provider, model, or effort is routed with the delegating session's derived route (its provider group's subagent pair and effort, else the fixed card), so sessions on different providers route their own spawns. A caller that names a route is never overridden, and a provider whose capability is not `agentOptions` (for example a one-shot process adapter) is never reinterpreted as an Agent-capable route; with nothing pinning, the request stays untouched — official inherit (parent live request, then creation snapshot).
|
|
8
|
+
- **Compaction stays deployment-wide by design, with a supported per-route alternative.** The official compaction transaction durably records the provider/model that wrote the summary, so rewriting the summarization call per session would make that record false. A deployment that needs route-scoped summarization uses the official exact-target `modelPolicies` array on the profile's `compaction-basic` row config — each entry matches one exact routed conversation target and overrides its policy including the summarization pair, and this plugin forwards that row config verbatim (YAML example in the READMEs).
|
|
9
|
+
- **Atomic settings writes (freeze / half-pair / ⚠ fixed).** Every row save is now ONE atomic, revision-fenced mutation through the official ConfigForm `mutate`: a refused write can no longer leave a half-written provider/model pair. A draft the user edited survives external snapshot updates; a conflict is reported with a reload path instead of silently losing either side; and a write that never settles is reported after 30 seconds instead of freezing the page on "保存中…". The ⚠ marker now means only "this value is not in the current provider catalog".
|
|
10
|
+
- **The switch-time compaction guard is never dropped.** The send-time guard is installed *before* the previous one retires, and a refused registration is reported while the live guard stays in place, so a failed refresh can no longer leave a session without switch-time protection for its remaining steps.
|
|
11
|
+
- **Documentation.** The settings-page inventory is documented as shipped — Subagent, Web search, Image generation, Auto review, Compaction, and Session naming route cards plus the Provider groups card — in `README.md`, `README.zh.md`, and `PRODUCT.md`, with the two deployment-wide justifications and the `modelPolicies` alternative recorded in `docs/seam-gap.md`.
|
|
12
|
+
|
|
13
|
+
- **Verification.** `pnpm run check` green (`tsc` + `tsdown`, 53 test files / 425 tests, pack gate). Reverse verification: inverting the group-vs-deployment precedence turns the resolver spec red, removing the draft's pristine guard turns the external-snapshot spec red, and restoring the retire-then-install guard order turns the guard-lifecycle spec red — each green again after restore. Lab 3082 smoke: the naming card's save arrives as ONE `settings/mutate` carrying both `titleProvider` and `titleModel`, the group editor lists exactly the naming and subagent rows, and session naming was checked in both modes — card off produced a model-generated title within seconds, the card pinned to the keyless `deepseek-official` route produced no title across three sessions, and the same card pinned to a working route produced a model-generated title within seconds, which is the differential that shows the pinned route is the one the naming request uses. Residual: the `session/title-llm-request` field itself was not read (the session store's concatenated zstd frames could not be walked offline, and the trace view did not render the event), so the route match rests on that differential; compaction and auto review remain deployment-wide by design (`docs/seam-gap.md`).
|
|
14
|
+
|
|
15
|
+
## v0.4.23
|
|
16
|
+
|
|
17
|
+
Three coordinated changes: the Main-default card is removed entirely; provider groups now apply on every switch surface of the seat session; and the subagent summary distinguishes a pinned effort from a provider default.
|
|
18
|
+
|
|
19
|
+
- **Removed: the Main model card and its protection.** The settings page no longer configures the deployment default — the provider/model/effort card, `saveMain`, the `agent-default-model` client contract (`MAIN_DEFAULT_CONFIG_ID`, `MainSettingsView`, `MainSettingsConflictError`), the Host-side `mainDefaultPort`/`currentMainSelection`/`saveMainSelection` surface (and the runtime's `agentDefaultModel` inject), and the whole pre-switch capture / revision-fenced restore module (`main-default-restore.ts`, removed with its spec) are gone. The picker switch itself is now never gated on settings state (the previous writable-Main admission guard, including the non-loopback `settings.*` notices and the Plan Review card's settings-blocking path, is deleted). **Behavior and migration:** the plugin neither reads nor writes the deployment default; like a native TUI switch, a picker switch lets the Host's own default write take effect, so a new session starts on whatever was last used. To pin a fixed default, use DSH's own **Settings → Models** page. Remaining capability switches (auto review, compaction, subagent) seed their On state from the catalog head instead of Main, and the group editor's row-enable seeds from that capability's live route with the same catalog-head fallback. `PlanCommitOutcome` is now `{ committed }` only (plugin-internal, ships together).
|
|
20
|
+
- **Provider groups watch the session, not just the plugin.** A new watcher (`provider-group-watch.ts`, one per seat session, shared by both slot faces) observes the official model-selection directory projection — whose only `model/selection` emitter is the `session.selectModel` RPC — so the target provider's saved group now applies whenever **this session's model provider** changes, whether the switch came from this plugin's picker, the TUI, or another client. Semantics are unchanged: a provider without a group, a model-only change within one provider, and the subscription baseline write nothing; applies are serialized with coalescing to the latest target; a failed apply logs `dsh-model-switch: provider group apply failed` and never disturbs the switch. Residual boundary: the watcher exists only for sessions open in this Web UI. Settings copy reworded from "主模型切换" to "会话模型切换" (zh/en).
|
|
21
|
+
- **Subagent summary effort wording.** The Default Subagent route card now shows 「已固定 · High」 (locale `effortPinned` / `Pinned`) when an effort is stored and 「Provider 默认 · High」 when the route follows the provider default, with the effort rendered through the catalog's localized name (same lookup the picker uses) instead of the raw id. Previously every fixed route read "Provider 默认 · …" regardless.
|
|
22
|
+
- Verification: `pnpm run check` green (`tsc` + `tsdown`, 52 test files / 370 tests, pack gate); reverse verification — restoring the picker's inline group apply turns the watcher integration red, breaking the watcher baseline/coalescing turns exactly its unit spec red; lab 3082 smoke: the settings page shows no Main card, a picker provider switch still applies the stored group, a second browser tab switching the same session drives the first tab's cards to follow, the subagent summary reads 「已固定 · High」 when pinned and 「Provider 默认 · …」 when unset, group-less providers leave routes untouched, and switching is no longer blocked by settings state.
|
|
23
|
+
|
|
1
24
|
## v0.4.22
|
|
2
25
|
|
|
3
26
|
One addition: per-provider capability groups — save the compaction, subagent, and review routes together for a provider, and apply that group automatically when the main model's provider changes.
|
package/PRODUCT.md
CHANGED
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
## Routes
|
|
6
6
|
|
|
7
|
-
- **
|
|
8
|
-
- **Default Subagent:** one optional
|
|
7
|
+
- **Session model:** the active conversation's provider, model, and optional effort, switched through the official Model Directory and session-local by nature. The deployment default for new sessions belongs to DSH itself: the Host persists the last session switch as the default, and since 0.4.23 this plugin no longer configures, restores, or protects it (its Main-default card was removed; a fixed default is configured on DSH's own Models page).
|
|
8
|
+
- **Default Subagent:** one optional deployment-wide provider/model/effort plus optional per-provider group pins, derived into the route a spawn receives. A child spawn that names no provider, model, or effort is routed with the DELEGATING session's derived route: the group saved for that session's provider (subagent pair and effort), else the fixed card pair in `fixed` mode. When the setting is off, stored `follow-main` is read as unset and Model Switch injects nothing; Official inherit (parent live request, then creation snapshot) and the official Allowlist remain DSH's. A spawn that already supplies provider, model, or effort is never overridden, and a provider whose capability is not `agentOptions` (for example a one-shot process adapter) is never reinterpreted as an Agent-capable route. The default is not an Allowlist and need not be a member of one. Local spawn, fork, continuable, and workflow children use this policy unless the spawn already supplies provider, model, or effort. Remote Codex/Claude children are outside unified routing.
|
|
9
9
|
- **Search Router:** does not register or replace `web_search`. Model Switch registers one public `WebSearchProvider` with id `model-switch`; the existing official `web_search` continues through `ctx.web`, whose configured search provider must be `model-switch`. The thin provider selects the configured backend adapter and model at execution time and returns the official `WebSearchResult` unchanged. v0.2.0 supports Codex Search only. `web_fetch` and its configured provider remain unchanged.
|
|
10
10
|
- **Vision:** excluded. Model Switch exposes no Vision setting, does not shadow `read_image`, and does not preprocess chat attachments.
|
|
11
11
|
- **Image Router:** owns a new, uniquely named stable `generate_image` tool. It selects the configured Codex or Grok adapter/model at execution time, rejects backend-incompatible fields, and returns normalized image metadata. Existing provider-specific image tools remain available as rollback paths.
|
|
12
|
-
- **Composer Picker:** replaces the composer model seat with a suffix-grouped Model / Effort / Context / Fast / Thinking picker and submits through the official Model Directory. Variant changes preserve an effort only when the target catalog row supports it, otherwise they use the target default or omit effort. Picker changes are session-local. A submitted prompt reserves the selected runtime immediately (composer submitting, pending first turn, or running). Native Antigravity keeps its models and effort; DSH keeps LLM-provider choices and disables Agent providers. After a successful native binding, other groups stay disabled. Cancel without a binding releases the reservation; existing DSH history still cannot convert onto an External Agent.
|
|
13
|
-
- **Plan Review:** intercepts the official `plan-review` composer takeover with a header execution-model picker and right-aligned Discuss in chat / Reject / Set as goal and run / Confirm actions. Confirm commits the selected model before answering; a refused commit leaves the review pending and retryable
|
|
12
|
+
- **Composer Picker:** replaces the composer model seat with a suffix-grouped Model / Effort / Context / Fast / Thinking picker and submits through the official Model Directory. Variant changes preserve an effort only when the target catalog row supports it, otherwise they use the target default or omit effort. Picker changes are session-local. A submitted prompt reserves the selected runtime immediately (composer submitting, pending first turn, or running). Native Antigravity keeps its models and effort; DSH keeps LLM-provider choices and disables Agent providers. After a successful native binding, other groups stay disabled. Cancel without a binding releases the reservation; existing DSH history still cannot convert onto an External Agent. The deployment default write a Host performs alongside a Session switch is left to DSH (since 0.4.23 the plugin no longer restores a pre-switch default).
|
|
13
|
+
- **Plan Review:** intercepts the official `plan-review` composer takeover with a header execution-model picker and right-aligned Discuss in chat / Reject / Set as goal and run / Confirm actions. Confirm commits the selected model before answering; a refused commit leaves the review pending and retryable. Reject carries optional human feedback as the answer's own `custom` text, which plan mode reports to the model. **Set as goal and run** arms this Plan as the session's goal through the released `remote.goals.create` — replacing an unfinished goal with `get` + `clear` first so the new Plan receives a fresh round cap — and only then answers, so `dsh-goal-round-driver` carries the Plan after plan mode exits. The goal is set before the answer, a refusal keeps the review pending and retryable, and a deployment that mounts no goal service disables the action with an explicit reason; the plugin stores no goal state, schedules no rounds, and owns no part of the goal domain. The card body carries only the official two-part summary (first line, first paragraph); the full plan opens in the right sidebar through ui-plan's registered preview opener, which this card drives because a composer-takeover entry cannot declare the official actions slot. Discuss in chat withdraws the takeover through the Host's own verb — `dismiss()` where the Host publishes it, `cancel()` on the older generation — and names the Host when neither seam exists, so a settled review is never a dead end. The same runtime reservation applies.
|
|
14
|
+
- **Session naming:** the model behind DSH's automatic session titles, off by default — both fields empty means naming follows the session's own model, which is the official behavior. On pins a deployment-wide provider/model that each session re-resolves per request: provider group → flat pair → the session's own model. The route is read through on every naming request, so a save applies to the very next request with no restart and never interrupts an in-flight request; the exact pair used is recorded in the session's own `session/title-llm-request` event by the official naming implementation, so the record and the request always agree. The plugin replaces the official `session-title-llm` row (one registered naming provider per context) and mirrors the cadence that row declared; naming cadence and title policy remain DSH's.
|
|
14
15
|
|
|
15
16
|
Model choices are capability-driven. Invalid, unavailable, or unsupported selections remain visible to configuration surfaces and fail loudly at use; routing never silently falls back.
|
|
16
17
|
|
|
@@ -20,11 +21,11 @@ Official `agent-presets` stay in the process. A nested `ctx.plugin(AgentPresets)
|
|
|
20
21
|
|
|
21
22
|
## Settings and lifecycle
|
|
22
23
|
|
|
23
|
-
The settings surface aggregates public Settings namespaces, reads and mutates with optimistic revisions, and saves rows independently. Changing a
|
|
24
|
+
The settings surface aggregates public Settings namespaces, reads and mutates with optimistic revisions, and saves rows independently. Changing a fixed Subagent model applies only the target catalog row's default effort, so an effort never leaks across providers or models. The Subagent card is a RouteCard with an instant on/off for the Default Subagent route; turning it off keeps the last provider/model on disk. Switch compaction is a B-row in the Send protection group (发送保护), default on, written immediately. The Auto review card is a RouteCard with an instant switch defaulting **off = reviews follow the session model**; turning it on pins the catalog head as an editable starting point. The Compaction card mirrors it: default **off = official default = compaction follows the conversation target model**; turning it on pins the catalog head as an editable starting point, and the pinned pair drives `/compact` and official automatic compaction alike. The Session naming card mirrors them again: default **off = official default = naming follows the session's own model**, and every naming request re-reads the resolved route. The settings page hosts six route cards — Subagent, Web search, Image generation, Auto review, Compaction, and Session naming — plus the Provider groups card. Provider groups store one session-naming/subagent route group per provider in the shared `model-switch` namespace as a DERIVED policy, never a write: each session and each request resolves those two routes from its own provider — group pair → flat deployment-wide pair → official default — so switching a session's provider writes nothing and two sessions on different providers can no longer overwrite or redirect each other's auxiliary routes; the group editor covers exactly those two routes, auto review and compaction stay deployment-wide cards, and the stored format is unchanged (an older entry's compaction/auto-review fields are ignored; no migration). Every row save is one atomic, revision-fenced official ConfigForm mutation: a refused write leaves no half-written provider/model pair, an edited draft survives external snapshot updates, a conflict is reported with a reload path, a write that never settles is reported after 30 seconds instead of freezing the page, and the ⚠ marker means only "this value is not in the current provider catalog". There is no Main-default editing surface: the Host persists the deployment default from the last session switch, and a fixed default belongs to DSH's own Models page. Search and image routes are out of scope for groups. Every registration, watcher, and dynamic tool generation has clean disposal. All visible copy lives in zh/en locale dictionaries.
|
|
24
25
|
|
|
25
26
|
## Exclusions
|
|
26
27
|
|
|
27
|
-
Send-time context protection (check, and compact with the previous model when a sent message would exceed the target window) is in scope. The Auto reviewer route override rides a name-matched replacement of the experimental auto-review row and changes only the review request's provider/model. The compaction summarization route override rides a name-matched replacement of the official compaction-basic engine and changes only the summarization request's provider/model, forwarding the row's own engine config unchanged. Because the Web surface runs session compaction inside each agent preset's isolated compaction group and profile patches cannot address rows inside a preset's plugins list, the plugin replaces the shipped preset rows wholesale (the Web preset editor's own save mechanism) to swap that group's engine; the copies are re-synced per DSH release during the existing compatibility verification, and a deployment that edits presets in the Web editor owns the merge from its own wholesale row. Model Switch does not own global compaction policy, titles, fetch routing, fallback, load balancing, provider credentials, CLI/API, configuration history, or DSH Core edits. Coordinated changes are limited to Model Switch and self-maintained provider plugins. Installing this package replaces a standalone `dsh-composer-picker` install; keep only one composer model seat.
|
|
28
|
+
Send-time context protection (check, and compact with the previous model when a sent message would exceed the target window) is in scope. The Auto reviewer route override rides a name-matched replacement of the experimental auto-review row and changes only the review request's provider/model. The compaction summarization route override rides a name-matched replacement of the official compaction-basic engine and changes only the summarization request's provider/model, forwarding the row's own engine config unchanged. Both auxiliary routes stay deployment-wide by design. The official compaction transaction durably records the provider/model that wrote the summary, so rewriting the summarization call per session would make that record false — the supported per-route alternative is the official exact-target `modelPolicies` array on the profile's `compaction-basic` row config (each entry matches one exact routed conversation target and overrides its compaction policy, including the summarization pair), which this plugin forwards verbatim. The official auto-review gate builds its `GenerateOptions` with no `sessionId`/`purpose` and closes over the single context it was applied with, so its interception point carries no session identity and a review cannot be attributed to a session. Both gaps, and the seams they would need, are recorded in `docs/seam-gap.md`. Because the Web surface runs session compaction inside each agent preset's isolated compaction group and profile patches cannot address rows inside a preset's plugins list, the plugin replaces the shipped preset rows wholesale (the Web preset editor's own save mechanism) to swap that group's engine; the copies are re-synced per DSH release during the existing compatibility verification, and a deployment that edits presets in the Web editor owns the merge from its own wholesale row. Model Switch does not own global compaction policy, titles, fetch routing, fallback, load balancing, provider credentials, CLI/API, configuration history, or DSH Core edits. Coordinated changes are limited to Model Switch and self-maintained provider plugins. Installing this package replaces a standalone `dsh-composer-picker` install; keep only one composer model seat.
|
|
28
29
|
|
|
29
30
|
Official `settings.section` has no icon field. The Settings nav glyph is a label-matched DOM swap, the same published pattern as usage-monitor, until an official icon seam exists. The Plan Review takeover uses priority -5, and the composer model seat uses priority -10.
|
|
30
31
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文](README.zh.md)
|
|
4
4
|
|
|
5
|
-
Choose one explicit route for
|
|
5
|
+
Choose one explicit route for the active session, Subagents, Web Search, image generation, Plan execution, and automatic session naming in DeepSeek Harness. Model Switch uses public DSH services and provider-owned adapters; it does not patch DSH Core or manage provider credentials.
|
|
6
6
|
|
|
7
7
|
<p align="center"><img src="docs/screenshots/composer-picker.png" alt="Composer Picker with Model, Effort, Context, and Fast controls" width="314"></p>
|
|
8
8
|
|
|
@@ -12,9 +12,9 @@ The picker retains keyboard focus when changing panes or closing search, without
|
|
|
12
12
|
|
|
13
13
|
| Route | Behavior |
|
|
14
14
|
| --- | --- |
|
|
15
|
-
|
|
|
16
|
-
| Subagent |
|
|
17
|
-
| Composer Picker | Changes only the active session and submits the exact catalog model id.
|
|
15
|
+
| Session model | The active conversation's provider/model/effort, changed by the Composer Picker or Plan Review only. The deployment default (new sessions) is DSH's own; the picker never writes it. |
|
|
16
|
+
| Subagent | When a spawn names no provider, model, or effort: the delegating session's derived route — its provider group's subagent pair, else the fixed card's pair; with neither, official inherit (parent live request, then creation snapshot). A spawn that names a route is never overridden; workflow overrides remain authoritative. |
|
|
17
|
+
| Composer Picker | Changes only the active session and submits the exact catalog model id. |
|
|
18
18
|
| Plan Review | Chooses the execution model before the Plan approval response is sent. |
|
|
19
19
|
| Web Search | Keeps official `web_search`; after deployment opt-in, routes through the selected, dynamically declared provider search adapter. |
|
|
20
20
|
| Image generation | Provides one stable `generate_image` tool routed through a selected Codex or Grok adapter. |
|
|
@@ -25,16 +25,21 @@ Idle blank sessions may pick an External Agent. Submission, pending-first-turn,
|
|
|
25
25
|
|
|
26
26
|
The existing 3082 lab replay probe is `node scripts/check-lab-runtime-lock.mjs [native|runtime-absent|plugin-absent]`. It checks the dedicated QA conversation under the already-established condition; it does not disable plugins, select a model, or send a turn. `node scripts/check-lab-native-execution.mjs` verifies the saved guard rejection, restored native continuation, DeepSeek-parent/Antigravity-child completion, and restoration of temporary subagent preferences through public history streams.
|
|
27
27
|
|
|
28
|
-
## Configure
|
|
28
|
+
## Configure Subagents and capability routes
|
|
29
29
|
|
|
30
|
-
Open **Settings → Model Switch**.
|
|
31
|
-
Official DSH `0.1.7-alpha.2` makes ConfigForms memory-only in non-loopback browsers. This page shows an unavailable message there; open Settings on the Host loopback URL instead. The composer picker refuses model changes in that mode because the published `session.selectModel` also persists the deployment default, which cannot be safely restored without a writable Main ConfigForm. Remote editing and session-only selection require an upstream authenticated ConfigForm seam and a session-only selection API; this plugin does not bypass the official policy.
|
|
30
|
+
Open **Settings → Model Switch**. The page hosts six route cards — Subagent, Web search, Image generation, Auto review, Compaction, and Session naming — plus the Provider groups card. Subagents may follow the delegating session's derived route or a fixed provider, model, and effort.
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
Since 0.4.23 this plugin no longer configures or protects the deployment default ("Main model"). That default is DSH's own: the Host persists the last session switch as the default (including switches made through this plugin's picker or the TUI), exactly like native switching — so a new session starts on whatever was last used. To pin a fixed default, use DSH's own **Settings → Models** page. Official DSH makes ConfigForms memory-only in non-loopback browsers, so the Settings page shows an unavailable message there; open Settings on the Host loopback URL instead. As a side effect of the removal, model switching is never blocked by settings state (previously the picker waited for a writable Main ConfigForm).
|
|
33
|
+
|
|
34
|
+
Changing the fixed Subagent provider/model replaces the previous model's effort with the target model's default. Models without reasoning support receive no effort.
|
|
34
35
|
|
|
35
36
|

|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
Official inherit resolves the active parent request first, then the Host's own session default. A derived or fixed route is injected before the official Subagent descriptor is created, and only when the spawn names no provider, model, or effort — a caller that names a route is never overridden, and a provider whose capability is not `agentOptions` (for example a one-shot process adapter) is never reinterpreted as an Agent-capable route. DSH 0.1.2-alpha.4 carries provider, model, and fixed reasoning effort in that descriptor.
|
|
39
|
+
|
|
40
|
+
### Saving settings
|
|
41
|
+
|
|
42
|
+
Every row save is one atomic, revision-fenced mutation through the official ConfigForm `mutate`: a refused write either commits the whole row or nothing, so it can no longer leave a half-written provider/model pair. A draft you edited survives external snapshot updates (another tab's save, the capability poll); a revision conflict is reported with a reload path instead of silently losing either side; and a write that never settles is reported after 30 seconds rather than freezing the page on "Saving…". The ⚠ marker next to a value means exactly one thing: this value is not in the current provider catalog.
|
|
38
43
|
|
|
39
44
|
## How custom models appear in the Picker
|
|
40
45
|
|
|
@@ -75,7 +80,7 @@ To support a combined selection, the provider must publish the combined row. Pub
|
|
|
75
80
|
|
|
76
81
|
## Plan Review
|
|
77
82
|
|
|
78
|
-
Plan Review owns an execution-model draft separate from
|
|
83
|
+
Plan Review owns an execution-model draft separate from the session's current route. **Confirm** first commits that model to the active session, then answers the pending Plan review. A refused commit leaves the review pending and retryable. **Reject** and **Discuss in chat** do not execute the Plan.
|
|
79
84
|
|
|
80
85
|
**Reject** sends the option the asker offered, and any text typed in the card's feedback field as the answer's own `custom` text — plan mode reports that text back to the model as the reason to keep planning, so a rejection can carry what to change. **Discuss in chat** withdraws the takeover so the composer returns and the human speaks in their own words; it uses the Host's `dismiss()` where published and the older generation's `cancel()` otherwise, and names the Host when neither exists. Answering a settled review closes Confirm and Reject, while Discuss and the reload affordance stay reachable so the card always has a way back. Failures keep their wire code (`session/writer-held: …`) visible instead of a bare localized sentence.
|
|
81
86
|
|
|
@@ -91,19 +96,42 @@ When a sent message will use a different model or context-tier id than the last
|
|
|
91
96
|
|
|
92
97
|
## Auto review model
|
|
93
98
|
|
|
94
|
-
The official `@deepseek-ai/dsh-experimental-auto-review` (the per-call reviewer for the Auto permission preset) hardwires its review requests onto the session's own route. This plugin takes that row over through a `cordis.patch.yml` row replacement: the official row is disabled and `dsh-model-switch/auto-review` mounts the **same official `apply`** under a scoped child context whose `llm.stream` `provider/model` are rewritten to the reviewer model pinned in Settings. The "Auto review model" card defaults to off = reviews follow the session model; turning it on
|
|
99
|
+
The official `@deepseek-ai/dsh-experimental-auto-review` (the per-call reviewer for the Auto permission preset) hardwires its review requests onto the session's own route. This plugin takes that row over through a `cordis.patch.yml` row replacement: the official row is disabled and `dsh-model-switch/auto-review` mounts the **same official `apply`** under a scoped child context whose `llm.stream` `provider/model` are rewritten to the reviewer model pinned in Settings. The "Auto review model" card defaults to off = reviews follow the session model; turning it on pins the catalog head as an editable starting point, and saved changes apply to the very next review. When the optional auto-review bundle never started with the profile the row stays unmounted and the Auto preset keeps its official off state; an official row already active elsewhere is reported explicitly instead of producing a second `registerAuto`. The reviewer route is deliberately deployment-wide: the official gate builds its review request with no session identity and closes over the one context it was applied with, so no public seam can attribute a review to a session — the per-session route it would need is recorded in `docs/seam-gap.md`.
|
|
95
100
|
|
|
96
101
|
## Compaction model
|
|
97
102
|
|
|
98
|
-
Official compaction — `/compact` and DSH's automatic compaction — summarizes history with the conversation's target model by default. The "Compaction model" card (default off) pins that summarization route instead: turning it on
|
|
103
|
+
Official compaction — `/compact` and DSH's automatic compaction — summarizes history with the conversation's target model by default. The "Compaction model" card (default off) pins that summarization route instead: turning it on pins the catalog head as an editable starting point, and saved changes apply to the very next compaction. Leaving both fields empty returns to the official default. Saving while a compaction is running may interrupt it; it retries next time.
|
|
104
|
+
|
|
105
|
+
The pair stays deployment-wide by design: the official compaction transaction durably records the provider/model that wrote the summary, so rewriting the summarization call per session would make that record false. For route-scoped summarization the supported alternative is the official exact-target `modelPolicies` array on the profile's `compaction-basic` row config: each entry matches one exact routed conversation target and overrides its compaction policy — including the summarization pair — for that target, and this plugin forwards the row's own config verbatim (the card's pair is overlaid only when both fields are set):
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
- id: compaction-basic
|
|
109
|
+
name: '@deepseek-ai/dsh-compaction-basic'
|
|
110
|
+
config:
|
|
111
|
+
modelPolicies:
|
|
112
|
+
- provider: deepseek
|
|
113
|
+
model: deepseek-chat
|
|
114
|
+
summarizationProvider: deepseek
|
|
115
|
+
summarizationModel: deepseek-reasoner
|
|
116
|
+
```
|
|
99
117
|
|
|
100
118
|
How the route reaches the engine depends on where the deployment runs its agent plane. The Web surface moves compaction into each agent preset's isolated `compaction` group, and profile patches cannot address rows inside a preset's `plugins` list — so this plugin replaces each shipped preset row wholesale (the same id-targeted mechanism the Web preset editor saves with) and swaps that group's official `compaction-basic` for `model-switch-compaction`, which mounts the **same official `BasicCompactionEngine`** with only `summarizationProvider`/`summarizationModel` overlaid (either field alone is ignored). Surfaces that compose the agent process-wide (the TUI) use the top-level row replacement instead. Two consequences: a DSH release that edits those presets needs the copies re-synced (this plugin's per-release verification covers it), and a deployment that edits presets in the Web editor writes its own wholesale row that then owns the merge.
|
|
101
119
|
|
|
102
120
|
Known issue (upstream; recorded in `docs/seam-gap.md`): while the working set stays above the official engine's pressure threshold, automatic compaction can fire on every step and keep re-attempting ranges whose summaries fail the engine's own "summary must be smaller" guard — a visible loop of automatic compactions that this plugin does not control (verified in a session A/B with the plugin enabled and disabled). Mitigations on the forwarded row config: `auto: false` (keeps `/compact`), a higher `thresholdRatio`, a smaller mounted tool schema, or a pinned compaction model whose summaries are leaner.
|
|
103
121
|
|
|
122
|
+
## Session naming model
|
|
123
|
+
|
|
124
|
+
DSH names new sessions automatically; the profile's official naming row decides the cadence (right after the first prompt, or on every prompt). The "Session naming model" card picks the model those naming requests use. **Off — both fields empty — is the official behavior: naming follows the session's own model.** On pins a provider/model as an editable starting point.
|
|
125
|
+
|
|
126
|
+
The route is read through on every naming request: a saved change applies to the very next title with no restart, and a naming request already in flight is never interrupted by a save. Each request resolves its route in order — the session's provider group's naming pair, then the card's flat pair, then the session's own model. The request runs through the official naming implementation, which records the exact provider/model in the session's own `session/title-llm-request` event, so the durable record and the real request always agree. The plugin replaces the official `session-title-llm` row instead of forking the naming logic (the seam allows one registered naming provider per context) and mirrors the cadence that row declared; a profile with no official naming row keeps DSH's deterministic fallback title.
|
|
127
|
+
|
|
104
128
|
## Provider groups
|
|
105
129
|
|
|
106
|
-
The "Provider groups" card stores one route group per provider — the
|
|
130
|
+
The "Provider groups" card stores one route group per provider — the session-naming and subagent routes saved together — and a group saved for provider X applies to the sessions whose own provider is X. Groups are **derived, not written**: switching a session's provider writes nothing, so two sessions on different providers can no longer overwrite or redirect each other's auxiliary routes (before 0.4.24 a switch *wrote* the group into the shared fields, and one session's switch could steer another session's naming and subagent requests).
|
|
131
|
+
|
|
132
|
+
Every request derives its own route from durable state: the session's provider (its model selection — a just-made pending selection counts — else its latest logged request route), then the group pair for that provider, then the flat deployment-wide pair, then the official default (the session's own model for naming; official inherit for subagents, where the fixed card applies only in `fixed` mode). Because nothing is written, this works for sessions this browser never opened and for switches made from the TUI or another client, with no watcher and no residual boundary; a session with no observable provider simply resolves to the deployment default. A switch to a provider without a group changes nothing, and a switch within one provider re-resolves to the same routes.
|
|
133
|
+
|
|
134
|
+
The group editor therefore covers exactly these two routes: auto review and compaction stay deployment-wide cards (see the two sections above for why), and search and image routes are out of scope. The stored configuration format is unchanged — an older group entry that still carries compaction or auto-review fields is accepted as-is and those fields are ignored, so no migration runs. In the editor, a provider's draft seeds from the currently derived routes the first time you configure it, each row's off state means "no pin — fall through to the card, then the official default", and **Delete group** removes the provider's entry entirely (clearing the stored field when the last group goes).
|
|
107
135
|
|
|
108
136
|
## What Model Switch does not change
|
|
109
137
|
|
|
@@ -112,8 +140,8 @@ The "Provider groups" card stores one route group per provider — the compactio
|
|
|
112
140
|
- Provider login, credentials, or provider settings cards
|
|
113
141
|
- Official Agent Presets
|
|
114
142
|
- Existing provider-specific image tools
|
|
115
|
-
-
|
|
116
|
-
- Global compaction policy,
|
|
143
|
+
- The deployment default model (DSH persists the last session switch itself, same as native TUI switching)
|
|
144
|
+
- Global compaction policy, naming cadence (only the naming model is configurable), or DSH Core
|
|
117
145
|
|
|
118
146
|
## Installation
|
|
119
147
|
|
package/README.zh.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 中文
|
|
4
4
|
|
|
5
|
-
在 DeepSeek Harness
|
|
5
|
+
在 DeepSeek Harness 中为当前会话、Subagent、Web Search、图像生成、Plan 执行和自动会话命名配置明确路由。Model Switch 只使用 DSH 公开服务和 Provider 自有 Adapter;不修改 DSH Core,也不管理 Provider 登录凭证。
|
|
6
6
|
|
|
7
7
|
<p align="center"><img src="docs/screenshots/composer-picker.png" alt="包含 Model、Effort、Context 和 Fast 的 Composer Picker" width="314"></p>
|
|
8
8
|
|
|
@@ -12,9 +12,9 @@ Picker 在切换页面或关闭搜索时保留键盘焦点,不覆盖搜索框
|
|
|
12
12
|
|
|
13
13
|
| 路由 | 行为 |
|
|
14
14
|
| --- | --- |
|
|
15
|
-
|
|
|
16
|
-
| Subagent |
|
|
17
|
-
| Composer Picker | 只修改当前会话,并提交 catalog 中的原始 model id
|
|
15
|
+
| 会话模型 | 当前对话的 provider/model/effort,只由 Composer Picker 或 Plan Review 修改。部署默认模型(新建会话)归 DSH 自己管理;选择器从不写它。 |
|
|
16
|
+
| Subagent | 子代理 spawn 未指定 provider/model/effort 时:使用委派会话自身推导出的路由——其供应商组的子代理对,其次是固定卡片的对;两者都没有则为官方继承(先父请求实时路由,再创建时快照)。显式指定路由的 spawn 永远不会被覆盖;Workflow 显式覆盖始终优先。 |
|
|
17
|
+
| Composer Picker | 只修改当前会话,并提交 catalog 中的原始 model id。 |
|
|
18
18
|
| Plan Review | 在发送 Plan 审核确认前,先提交执行模型。 |
|
|
19
19
|
| Web Search | 保留官方 `web_search`;部署显式启用后,通过 Provider 动态声明的独立搜索适配器路由。 |
|
|
20
20
|
| 图像生成 | 提供一个稳定的 `generate_image` 工具,通过选定的 Codex 或 Grok Adapter 路由。 |
|
|
@@ -23,16 +23,21 @@ Picker 在切换页面或关闭搜索时保留键盘焦点,不覆盖搜索框
|
|
|
23
23
|
|
|
24
24
|
空闲的空白会话可以选择 External Agent。提交中、等待首个 turn 以及运行期间,从请求开始就锁定所选执行运行时,不等待首 token 或原生绑定:Antigravity 保留其模型和 effort 选择;DSH 保留 LLM provider 选择,但禁用 Agent provider。会话一旦有过用户消息,Composer 和 Plan Review 仍显示 Agent 角色行但将其禁用,除非该会话已经绑定原生运行时。当前会话成功打开 Antigravity 原生会话后,Picker 会在该会话内禁用其他 provider,同时保留 Antigravity 模型与 effort 控件。DSH 全局 Picker 锁仍拥有最高优先级。
|
|
25
25
|
|
|
26
|
-
## 配置
|
|
26
|
+
## 配置 Subagent 与能力路由
|
|
27
27
|
|
|
28
|
-
打开 **设置 → Model Switch
|
|
29
|
-
官方 DSH `0.1.7-alpha.2` 在非本机浏览器将 ConfigForms 设为仅内存模式,页面会明确显示不可用;请在 Host 的 127.0.0.1 页面打开设置。此模式下 Picker 也拒绝模型切换:已发布的 `session.selectModel` 会同时写入全局默认模型,但只读 Main 表单无法安全恢复。远端编辑与真正仅会话的切换需要上游提供受鉴权的 ConfigForm 通道及仅会话的选择接口;本插件不会绕过官方策略。
|
|
28
|
+
打开 **设置 → Model Switch**。设置页共有六张路由卡片——Subagent、Web 搜索、图像生成、自动审查、压缩、会话命名——外加「供应商配置组」卡片。子代理可以使用委派会话推导出的路由,也可以使用固定的 provider、model 和 effort。
|
|
30
29
|
|
|
31
|
-
|
|
30
|
+
自 0.4.23 起本插件不再配置、也不再保护部署默认模型(原「主模型」卡片)。默认模型归 DSH 自己:Host 会把最后一次会话切换写成默认值(包括经本插件选择器或 TUI 的切换),与原生切换行为一致——新会话从"上次用过的模型"开始。需要固定默认值时,请使用 DSH 自带的 **设置 → 模型** 页面。官方 DSH 在非本机浏览器将 ConfigForms 设为仅内存模式,设置页会明确显示不可用;请在 Host 的 127.0.0.1 页面打开设置。移除主卡片的附带收益:模型切换从此不再依赖设置可写状态(此前选择器要等 Main 表单可写才允许切换)。
|
|
31
|
+
|
|
32
|
+
切换固定 Subagent 的 provider/model 时,会用目标模型的默认 effort 替换旧模型的 effort;目标模型不支持推理时不传 effort。
|
|
32
33
|
|
|
33
34
|

|
|
34
35
|
|
|
35
|
-
|
|
36
|
+
官方继承先读取当前父请求,再读取 Host 自身的会话默认模型。推导或固定的路由会在官方 Subagent descriptor 创建前注入,且仅当 spawn 未指定 provider、model 或 effort——显式指定路由的 spawn 永远不会被覆盖,能力不是 `agentOptions` 的 provider(例如一次性进程适配器)也不会被重新解释为可路由的 Agent。DSH 0.1.2-alpha.4 会在该 descriptor 中携带 provider、model 和固定 reasoning effort。
|
|
37
|
+
|
|
38
|
+
### 保存设置
|
|
39
|
+
|
|
40
|
+
每一行的保存都是**一次**原子的、带版本围栏的官方 ConfigForm `mutate`:写入被拒绝时要么整行生效、要么什么都不写,不会再留下只写了一半的 provider/model 对。你编辑中的草稿不会被外部快照更新(另一标签页的保存、能力轮询)覆盖;版本冲突会明确报告并提供重新加载路径,而不是悄悄丢掉任何一方;30 秒内始终没有落定的写入会明确报错,而不是让页面卡在「保存中…」。值旁边的 ⚠ 标记现在只有一个含义:该值不在当前 Provider 目录中。
|
|
36
41
|
|
|
37
42
|
## 自定义模型如何出现在 Picker
|
|
38
43
|
|
|
@@ -73,7 +78,7 @@ Model Switch 按 provider,以及剥离以下后缀后的 model id 对 Catalog
|
|
|
73
78
|
|
|
74
79
|
## Plan Review
|
|
75
80
|
|
|
76
|
-
Plan Review
|
|
81
|
+
Plan Review 拥有独立于会话当前路由的执行模型草稿。**确认执行**会先把该模型提交到当前会话,再回答待处理的 Plan 审核。提交被拒绝时,审核保持待处理并允许重试。**拒绝**和**去聊天里说**不会执行 Plan。
|
|
77
82
|
|
|
78
83
|
**拒绝**会发送提问方给出的选项,并把卡片反馈框里的文字作为答复自身的 `custom` 文本一并提交 —— plan 模式会把它作为"继续规划"的理由回报给模型,所以打回时可以带上要改什么。**去聊天里说**会撤下这张卡、把输入框还给你,用你自己的话说明;它在 Host 提供 `dismiss()` 时用它,在旧代际用 `cancel()`,两者都没有时明确指出这一点。审核一旦落定,**确认执行**与**拒绝**关闭,而**去聊天里说**与"重新加载"始终可达,卡片不会变成死路。失败会保留线上错误码(如 `session/writer-held: …`),而不是只给一句本地化文案。
|
|
79
84
|
|
|
@@ -89,19 +94,42 @@ Plan Review 拥有独立于 Main 的执行模型草稿。**确认执行**会先
|
|
|
89
94
|
|
|
90
95
|
## 自动审查模型(Auto review)
|
|
91
96
|
|
|
92
|
-
官方 `@deepseek-ai/dsh-experimental-auto-review`(Auto 权限预设的逐调用审查)把审查请求固定在会话自身的路由上。本插件通过 `cordis.patch.yml` 的行替换接管这一行:官方行被禁用,改挂 `dsh-model-switch/auto-review`,它在作用域子上下文里运行**同一份官方 `apply`**,只把 `llm.stream` 的 `provider/model` 改写为设置里固定的审查模型。设置页「自动审查模型」默认关闭 =
|
|
97
|
+
官方 `@deepseek-ai/dsh-experimental-auto-review`(Auto 权限预设的逐调用审查)把审查请求固定在会话自身的路由上。本插件通过 `cordis.patch.yml` 的行替换接管这一行:官方行被禁用,改挂 `dsh-model-switch/auto-review`,它在作用域子上下文里运行**同一份官方 `apply`**,只把 `llm.stream` 的 `provider/model` 改写为设置里固定的审查模型。设置页「自动审查模型」默认关闭 = 审查跟随当前会话模型;打开时以目录首位模型作为可再改的固定起点,保存后对下一次审查立即生效。审查未配置官方能力包(`@deepseek-ai/dsh-experimental-auto-review` 未随 profile 启动)时本行不挂载,Auto 预设保持官方的关闭状态;官方行若已在别处注册,本行明确报错而不产生第二个 `registerAuto`。审查路由刻意保持部署级:官方闸门构造审查请求时不带会话身份、且只闭包它被 apply 的那一个上下文,因此没有任何公开接缝能把一次审查归属到某个会话——它需要的按会话路由已记录在 `docs/seam-gap.md`。
|
|
93
98
|
|
|
94
99
|
## 压缩模型(Compaction model)
|
|
95
100
|
|
|
96
|
-
官方压缩——`/compact` 与 DSH
|
|
101
|
+
官方压缩——`/compact` 与 DSH 的自动压缩——默认使用会话当前的目标模型做摘要。「压缩模型」卡片(默认关闭)改为固定摘要路由:打开时以目录首位模型作为可再改的固定起点,保存后对下一次压缩立即生效。两个字段都留空即回到官方默认。保存时若恰有压缩进行中,可能被打断并在下次重试。
|
|
102
|
+
|
|
103
|
+
摘要模型的固定对刻意保持部署级:官方压缩事务会持久记录写下摘要的 provider/model,若按会话改写摘要调用,这条持久记录就会与实际使用的路由不符。需要按路由区分摘要的部署,官方支持的做法是在 profile 的 `compaction-basic` 行配置里使用精确目标的 `modelPolicies` 数组:每个条目精确匹配一个实际路由的会话目标模型,并只对该目标覆盖其压缩策略——包括摘要路由;本插件会原样转发该行配置(仅当卡片两个字段都填写时才覆盖全局摘要对):
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
- id: compaction-basic
|
|
107
|
+
name: '@deepseek-ai/dsh-compaction-basic'
|
|
108
|
+
config:
|
|
109
|
+
modelPolicies:
|
|
110
|
+
- provider: deepseek
|
|
111
|
+
model: deepseek-chat
|
|
112
|
+
summarizationProvider: deepseek
|
|
113
|
+
summarizationModel: deepseek-reasoner
|
|
114
|
+
```
|
|
97
115
|
|
|
98
116
|
路由如何到达压缩引擎取决于部署在哪一层组合 agent。Web 面把压缩放进每个 Agent 预设的隔离 `compaction` 组里,而 profile patch 无法寻址 preset `plugins` 列表内部的行——因此本插件整表替换各预设行(与 Web 预设编辑器保存修改用的是同一套 id 定位机制),把该组的官方 `compaction-basic` 换成 `model-switch-compaction`,由它挂载**同一份官方 `BasicCompactionEngine`**、只覆盖 `summarizationProvider`/`summarizationModel`(只填其一忽略)。进程级组合 agent 的面(如 TUI)则走顶层行替换。两个后果:DSH 发布若改动这些预设,随包副本需要同步(本插件的逐版本核对覆盖这一步);部署若用 Web 编辑器改预设,会写出自己的整表行、并从那之后自行负责合并。
|
|
99
117
|
|
|
100
118
|
已知问题(上游侧,见 `docs/seam-gap.md`):当工作集持续超过官方引擎的压力阈值时,自动压缩可能每步触发,并反复重试摘要过不了官方「摘要必须更小」守卫的小片段——表现为"不停自动压缩",本插件不控制该行为(已在同一会话做过插件开/关 A/B 对照)。可用的缓解(都在转发行配置上):`auto: false`(保留 `/compact`)、调高 `thresholdRatio`、减少挂载的工具 schema,或固定一个摘要更精炼的压缩模型。
|
|
101
119
|
|
|
120
|
+
## 会话命名模型(Session naming model)
|
|
121
|
+
|
|
122
|
+
DSH 会自动为新会话起名;命名的触发节奏由 profile 的官方命名行决定(首条提示后一次,或每条提示一次)。「会话命名模型」卡片选择这些命名请求使用的模型。**关闭——两个字段都留空——即官方行为:命名跟随会话自身的模型。** 打开时以目录首位模型作为可再改的固定起点。
|
|
123
|
+
|
|
124
|
+
路由在**每次命名请求时现读**:保存后对下一次起名立即生效、无需重启,且进行中的命名请求不会被保存打断。每次请求按顺序解析路由:该会话供应商组里的命名对,其次卡片的部署级对,其次会话自身的模型。请求经由官方命名实现发出,它会把实际使用的 provider/model 记录到该会话自己的 `session/title-llm-request` 事件里,因此持久记录与真实请求永远一致。本插件替换官方的 `session-title-llm` 行而不分叉命名逻辑(该接缝每个上下文只允许注册一个命名 provider),并镜像该行声明的节奏;profile 没有官方命名行时保持 DSH 的确定性兜底标题。
|
|
125
|
+
|
|
102
126
|
## 供应商配置组(Provider groups)
|
|
103
127
|
|
|
104
|
-
|
|
128
|
+
「供应商配置组」卡片为每个供应商保存一组路由——会话命名与子代理两条路由一起存;为供应商 X 保存的组,作用于自身供应商就是 X 的会话。组是**推导出来的,而不是写进去的**:切换某个会话的供应商不写任何东西,因此不同供应商上的两个会话再也不能互相覆盖、互相改写对方的辅助路由(0.4.24 之前切换会把组**写进**共享字段,一个会话的切换能改道另一个会话的命名与子代理请求)。
|
|
129
|
+
|
|
130
|
+
每次请求都从持久状态推导自己的路由:先取该会话的供应商(它的模型选择——刚做出、尚未被请求消费的 pending 选择优先——其次最近一次已记录的请求路由),再取该供应商的组对,再取部署级的平铺对,最后是官方默认(命名用会话自身模型;子代理用官方继承,且平铺卡片仅在 `fixed` 模式下生效)。因为什么都不写,本浏览器从未打开过的会话、以及来自 TUI 或其他客户端的切换同样生效——没有 watcher,也没有剩余边界;观察不到供应商的会话直接落到部署默认。切换到没有配置组的供应商不改变任何东西,同一供应商内部切换推导出的还是同一些路由。
|
|
131
|
+
|
|
132
|
+
因此组编辑器恰好只覆盖这两条路由:自动审查与压缩保持部署级卡片(原因见上面两节),搜索与图片路由不在范围内。存储格式不变——较早的组条目若还带着压缩/自动审查字段,会原样接受并忽略这些字段,无需迁移。编辑器里首次配置某供应商时,草稿从当前推导出的路由种子化;每行的关闭态表示"不固定——先落到卡片、再落到官方默认";「删除该组」彻底移除该供应商的条目(删掉最后一组时同时清掉存储字段)。
|
|
105
133
|
|
|
106
134
|
## Model Switch 不会改变什么
|
|
107
135
|
|
|
@@ -110,8 +138,8 @@ Plan Review 拥有独立于 Main 的执行模型草稿。**确认执行**会先
|
|
|
110
138
|
- Provider 登录、凭证或 Provider 设置卡
|
|
111
139
|
- 官方 Agent Presets
|
|
112
140
|
- 已有的 Provider 专属图像工具
|
|
113
|
-
-
|
|
114
|
-
-
|
|
141
|
+
- 部署默认模型本身(DSH 自己把最后一次会话切换写成默认值,与原生 TUI 切换一致)
|
|
142
|
+
- 全局压缩策略、命名节奏(只可配置命名模型)或 DSH Core
|
|
115
143
|
|
|
116
144
|
## 安装
|
|
117
145
|
|
package/cordis.patch.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# Replace independently packaged host modules only through public profile patches.
|
|
2
2
|
# Existing rows are disabled with their original name; replacements use unique ids.
|
|
3
3
|
# Do not replace agent-presets: a nested AgentPresets instance loads a second
|
|
4
4
|
# @deepseek-ai/dsh-scope identity, and session.create then fails as unscoped.
|
|
@@ -24,6 +24,16 @@
|
|
|
24
24
|
name: '@deepseek-ai/dsh-compaction-basic'
|
|
25
25
|
disabled: true
|
|
26
26
|
|
|
27
|
+
# The official naming provider derives the session-title route from the
|
|
28
|
+
# session's own logged route; Model Switch replaces it with its own row so the
|
|
29
|
+
# naming model stays configurable (one registered title provider per context).
|
|
30
|
+
# The row id is stable across both cadence packages, and the replacement row
|
|
31
|
+
# mounts whatever package the row declared, so a profile that restated this
|
|
32
|
+
# row as all-prompts keeps its cadence.
|
|
33
|
+
- id: session-title-llm
|
|
34
|
+
name: '@deepseek-ai/dsh-session-title-first-prompt-llm'
|
|
35
|
+
disabled: true
|
|
36
|
+
|
|
27
37
|
# The Web surface moves the agent plane (tools, compaction, delegation) into
|
|
28
38
|
# per-session agent presets: session /compact and official automatic compaction
|
|
29
39
|
# run against the compaction service inside each preset's isolated `compaction`
|
|
@@ -513,3 +523,7 @@
|
|
|
513
523
|
# The official compaction engine under the configurable summarization route.
|
|
514
524
|
- id: model-switch-compaction
|
|
515
525
|
name: 'dsh-model-switch/compaction'
|
|
526
|
+
|
|
527
|
+
# The official naming provider under the configurable naming route.
|
|
528
|
+
- id: model-switch-session-title
|
|
529
|
+
name: 'dsh-model-switch/session-title'
|
|
Binary file
|
package/lib/auto-review.js
CHANGED
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
* route configured the wrapper passes options through by identity, so the
|
|
11
11
|
* reviewer follows the session model exactly.
|
|
12
12
|
*
|
|
13
|
+
* The reviewer route is deliberately DEPLOYMENT-WIDE. The official gate builds
|
|
14
|
+
* its request with no session id and no purpose and closes over the single
|
|
15
|
+
* context it was applied with, so this plugin has no public way to tell which
|
|
16
|
+
* session a review serves; guessing one would attribute a review to the wrong
|
|
17
|
+
* session and make the recorded reviewer route false. The unsupported
|
|
18
|
+
* per-session reviewer route is recorded in `docs/seam-gap.md` with the public
|
|
19
|
+
* seam it would need.
|
|
20
|
+
*
|
|
13
21
|
* The official gate stays an opt-in capability: the row mounts it only when
|
|
14
22
|
* the profile actually started with the experimental-auto-review bundle.
|
|
15
23
|
* `cordis.patch.yml` disables the official row (one `registerAuto` per
|