dsh-expert-group 0.1.7 → 0.1.11

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.
Files changed (213) hide show
  1. package/README.en.md +64 -292
  2. package/README.md +59 -290
  3. package/assets/notification-whoosh.wav +0 -0
  4. package/client-bundle.js +23160 -20893
  5. package/client-conversation-adapters.js +433 -0
  6. package/client-expert-group-model-format.js +1258 -0
  7. package/client-expert-group-model-normalize.js +958 -0
  8. package/client-fanout-normalize.js +233 -0
  9. package/client-focus-return.js +263 -0
  10. package/client-model-config-host.js +371 -0
  11. package/client-model-config-paths.js +272 -0
  12. package/{client-model-config.js → client-model-config-rows.js} +108 -838
  13. package/client-model-section.js +656 -0
  14. package/client-model-views-a.js +619 -0
  15. package/client-model-views-b.js +428 -0
  16. package/client-native-status.js +786 -0
  17. package/client-nav-icon.js +213 -0
  18. package/client-plugin-detail.js +503 -0
  19. package/client-provider-card.js +488 -0
  20. package/client-session-delete-local-keys.js +303 -0
  21. package/client-session-delete-selection.js +789 -0
  22. package/client-session-delete-ui.js +874 -0
  23. package/client-session-delete-view.js +420 -0
  24. package/client-settings-main-a.js +1499 -0
  25. package/client-settings-main-b.js +1419 -0
  26. package/client-settings-normalize.js +1227 -0
  27. package/client-sidebar-actions.js +425 -0
  28. package/client-sidebar-auto-controller.js +1087 -0
  29. package/client-sidebar-entry.js +225 -0
  30. package/client-sidebar-install-expand.js +874 -0
  31. package/client-sidebar-install-layout.js +644 -0
  32. package/client-sidebar-install-resources.js +344 -0
  33. package/client-sidebar-install-target.js +661 -0
  34. package/client-sidebar-install-width.js +541 -0
  35. package/client-sidebar-overlay.js +197 -0
  36. package/client-sidebar-panel-cache.js +103 -0
  37. package/client-sidebar-panel-hooks-actions-recorder.js +418 -0
  38. package/client-sidebar-panel-hooks-actions.js +1240 -0
  39. package/client-sidebar-panel-hooks-effects.js +1235 -0
  40. package/client-sidebar-panel-hooks-state.js +1125 -0
  41. package/client-sidebar-panel-hooks-tabs.js +1058 -0
  42. package/client-sidebar-panel-state-a.js +253 -0
  43. package/client-sidebar-panel-state-b.js +209 -0
  44. package/client-sidebar-panel.js +935 -0
  45. package/client-sidebar-split-sync.js +337 -0
  46. package/client-sidebar-tab-state.js +632 -0
  47. package/client-sidebar-views-a.js +473 -0
  48. package/client-sidebar-views-b.js +471 -0
  49. package/client-sidebar-views-c.js +904 -0
  50. package/client-styles.js +168 -0
  51. package/client-subagent-metadata.js +868 -0
  52. package/client-text.js +170 -0
  53. package/client.js +23172 -7941
  54. package/cordis.patch.yml +10 -1
  55. package/fanout/contracts.js +331 -0
  56. package/fanout/errors.js +162 -0
  57. package/fanout/events.js +262 -0
  58. package/fanout/limits.js +458 -0
  59. package/fanout/persistence.js +277 -0
  60. package/fanout/provider-attribution.js +55 -0
  61. package/fanout/public-api.js +303 -0
  62. package/fanout/reclaim.js +236 -0
  63. package/fanout/restore.js +933 -0
  64. package/fanout/scheduler.js +1238 -0
  65. package/fanout/snapshot.js +219 -0
  66. package/fanout/state.js +206 -0
  67. package/fanout/store.js +942 -0
  68. package/fanout/task-commands.js +1500 -0
  69. package/fanout/validation.js +590 -0
  70. package/fanout-host.js +194 -1497
  71. package/fanout.js +75 -2981
  72. package/host/expert-child-composition.js +294 -0
  73. package/host/expert-group-projection.js +1254 -0
  74. package/host/expert-group-runtime.js +220 -1339
  75. package/host/expert-group-snapshot.js +879 -14
  76. package/host/expert-group-stage.js +601 -0
  77. package/host/expert-guards.js +357 -0
  78. package/host/expert-task-prompt.js +170 -0
  79. package/host/fanout-attribution.js +798 -0
  80. package/host/fanout-dispatch-route.js +240 -0
  81. package/host/fanout-event-log.js +439 -0
  82. package/host/fanout-lifecycle.js +872 -0
  83. package/host/fanout-ownership.js +688 -0
  84. package/host/fanout-persistence.js +601 -0
  85. package/host/fanout-restore.js +288 -0
  86. package/host/fanout-route-restore.js +46 -0
  87. package/host/fanout-runtime.js +366 -740
  88. package/host/image-transcode.js +36 -0
  89. package/host/index-admission-batches.js +194 -0
  90. package/host/index-agent-created.js +186 -0
  91. package/host/index-agent-disposed.js +128 -0
  92. package/host/index-agent-records.js +133 -0
  93. package/host/index-agent-request-error.js +216 -0
  94. package/host/index-agent-snapshot.js +247 -0
  95. package/host/index-assembly-agents.js +207 -0
  96. package/host/index-assembly-bootstrap.js +515 -0
  97. package/host/index-assembly-guards.js +412 -0
  98. package/host/index-assembly-orchestrator.js +127 -0
  99. package/host/index-assembly-rpc.js +159 -0
  100. package/host/index-assembly-session-delete-job.js +215 -0
  101. package/host/index-assembly-session-delete-rpc.js +344 -0
  102. package/host/index-assembly-session-delete.js +709 -0
  103. package/host/index-assembly-tools.js +495 -0
  104. package/host/index-assembly-wire.js +354 -0
  105. package/host/index-auto-recovery.js +1109 -0
  106. package/host/index-capability-report.js +187 -0
  107. package/host/index-connection-channel.js +292 -0
  108. package/host/index-effort-retire.js +250 -0
  109. package/host/index-expert-tools-admission.js +928 -0
  110. package/host/index-expert-tools-core.js +1002 -0
  111. package/host/index-expert-tools-fanout.js +1439 -0
  112. package/host/index-expert-tools-role.js +907 -0
  113. package/host/index-expert-tools-surface.js +333 -0
  114. package/host/index-fanout-rpc.js +280 -0
  115. package/host/index-finalize.js +1395 -0
  116. package/host/index-handoff.js +1498 -0
  117. package/host/index-image-claims.js +376 -0
  118. package/host/index-image-route.js +218 -0
  119. package/host/index-manual-dispatch.js +168 -0
  120. package/host/index-model-route.js +1475 -0
  121. package/host/index-prelude.js +199 -0
  122. package/host/index-recovery.js +1310 -0
  123. package/host/index-root-wait.js +959 -0
  124. package/host/index-rpc-action-core.js +1477 -0
  125. package/host/index-rpc-action-session.js +563 -0
  126. package/host/index-rpc-http.js +199 -0
  127. package/host/index-runtime-diagnostics.js +600 -0
  128. package/host/index-settings-storage.js +740 -0
  129. package/host/index-template-plan.js +418 -0
  130. package/host/index-template-store.js +101 -0
  131. package/host/index-toast.js +196 -0
  132. package/host/index-upload-normalize.js +86 -0
  133. package/host/index-usage-attribution.js +394 -0
  134. package/host/model-fallback-snapshot.js +179 -0
  135. package/host/notification-text.js +65 -0
  136. package/host/notifications.js +1 -1
  137. package/host/orchestrator-epoch.js +158 -0
  138. package/host/orchestrator-model.js +794 -0
  139. package/host/orchestrator-settings.js +332 -0
  140. package/host/orchestrator-write.js +226 -0
  141. package/host/peak-valley-route.js +434 -0
  142. package/host/peak-valley-settings.js +875 -0
  143. package/host/persistence-health.js +2 -1
  144. package/host/plugin-identity.js +68 -0
  145. package/host/recovery.js +30 -2
  146. package/host/route-diagnostics.js +96 -0
  147. package/host/route-receipt-fields.js +78 -0
  148. package/host/rpc-request-lifecycle.js +124 -0
  149. package/host/rpc-transport.js +3 -12
  150. package/host/runtime-diagnostics.js +230 -0
  151. package/host/send-message-shadow.js +263 -0
  152. package/host/session-delete-candidates.js +539 -0
  153. package/host/session-delete-cleanup.js +298 -0
  154. package/host/session-delete-closure.js +487 -0
  155. package/host/session-delete-contract.js +295 -0
  156. package/host/session-delete-convergence.js +1028 -0
  157. package/host/session-delete-events.js +94 -0
  158. package/host/session-delete-gate.js +317 -0
  159. package/host/session-delete-job.js +1247 -0
  160. package/host/session-delete-lock.js +629 -0
  161. package/host/session-delete-paths.js +259 -0
  162. package/host/session-delete-probe.js +445 -0
  163. package/host/session-delete-quarantine.js +437 -0
  164. package/host/session-delete-rpc.js +697 -0
  165. package/host/session-delete-store.js +253 -0
  166. package/host/session-override-store.js +165 -0
  167. package/host/settings-read-projection.js +448 -0
  168. package/host/settings-schema.js +358 -0
  169. package/host/settings-source.js +121 -21
  170. package/host/snapshot-cache.js +709 -0
  171. package/host/storage-binding.js +12 -1
  172. package/host/storage-domain-schema.js +257 -0
  173. package/host/system-toast.js +51 -31
  174. package/host/turn-continuation-guard.js +460 -0
  175. package/host/turn-wait.js +692 -80
  176. package/host/usage-ledger.js +602 -0
  177. package/host/usage-projection.js +835 -0
  178. package/index.js +333 -11341
  179. package/orchestrator.js +211 -68
  180. package/package.json +196 -14
  181. package/prompt-contracts.js +25 -6
  182. package/resource-budget.js +178 -37
  183. package/role-registry.js +24 -8
  184. package/rpc-host.js +4 -3
  185. package/shared/affected-paths.js +183 -0
  186. package/shared/capacity-errors.js +121 -0
  187. package/shared/delegation-cohort.js +405 -0
  188. package/shared/delegation-tracker.js +747 -0
  189. package/shared/error-codes.js +70 -0
  190. package/shared/feedback-identity.js +47 -0
  191. package/shared/i18n.js +367 -0
  192. package/shared/model-route.js +558 -0
  193. package/shared/native-text.js +110 -0
  194. package/shared/peak-valley-time.js +279 -0
  195. package/shared/pending-creation.js +113 -0
  196. package/shared/prompts.js +174 -0
  197. package/shared/protocol.js +169 -0
  198. package/shared/recovery-ledger.js +130 -0
  199. package/shared/retry-policy.js +456 -0
  200. package/shared/root-descendants.js +190 -0
  201. package/shared/route-snapshot.js +359 -0
  202. package/shared/session-generation.js +147 -0
  203. package/shared/status-dom.js +432 -0
  204. package/shared/structured-path.js +132 -0
  205. package/shared/structured.js +122 -0
  206. package/shared/turn-settlement.js +408 -0
  207. package/shared.js +241 -3430
  208. package/storage.js +83 -2
  209. package/client-expert-group-model.js +0 -456
  210. package/client-expert-group-sidebar.js +0 -9931
  211. package/client-notifications.js +0 -38
  212. package/scripts/assemble-client.mjs +0 -605
  213. package/scripts/build.mjs +0 -124
package/README.en.md CHANGED
@@ -1,330 +1,102 @@
1
1
  # dsh-expert-group
2
2
 
3
- **English** | [中文](README.md)
4
-
5
- This English edition is a translation of [README.md](README.md); if the two versions ever disagree, the Chinese version is authoritative.
6
-
7
- > The `dsh-expert-group` settings namespace stores the global providers, `defaults`, and notification preferences; session overrides and subagent snapshots belong to the plugin's own `dsh_expert_group` storage domain.
8
-
9
- An external **dual-face Cordis bundle** that can be installed into DSH (DeepSeek Harness). Its expert division of labour, per-role model and reasoning-depth routing, and background parallel delegation discipline are borrowed from the open-source **oh-my-opencode-slim** project
10
- (https://github.com/alvinunreal/oh-my-opencode-slim , MIT).
11
- It brings "per-role model and reasoning depth" expert subagents into DSH, and maintains the global models, reasoning depths, and notification preferences on the "dsh-expert-group" settings page in the Web UI.
12
- It also ports oh-my-opencode-slim's parent-agent orchestrator design: the root session breaks down, delegates, integrates, and verifies, while expert subagents keep their leaf-worker constraints.
13
-
14
- ## Capabilities
15
-
16
- - 5 expert subagent tools (enabled by default):
17
- - `explorer` — read-only codebase reconnaissance (file location, symbol/pattern mapping)
18
- - `librarian` — read-only research into external documentation / library APIs
19
- - `oracle` — read-only architecture decisions / hard debugging / code review
20
- - `designer` — UI/UX and visual implementation (can write)
21
- - `fixer` — implementation of already-decided plans, repetitive edits, migrations, and filling in tests, including large amounts of work in a single file (can write)
22
- - **Visual agent** `observer`: a read-only visual-analysis expert that interprets the real durable image attachments provided by the Host, including screenshots, UI mockups, charts, and PDF pages already rendered as images; it does not accept arbitrary local paths. Off by default in a bare Config; the current `cordis.patch.yml` explicitly turns the bundle override on. Image routing hands the Host-created `image/png` durable attachment ContentBlock directly to the Observer; the automatic image entry point only dispatches bounded, purely visual tasks, and the user's original task is still held by the parent agent, which synthesizes the visual report.
23
- - Plugin tools use short, conflict-free role tool names (`explorer`, `librarian`, and so on) registered on the current DSH's `ctx.tools`;
24
- the parent agent must not treat the Harness-level `subagent_<role>`, PTC's `run_code`, or the generic subagent entry point as a substitute for plugin delegation.
25
- - Every expert delegation is always a continuable subagent: by default it runs in the background and immediately returns the subagent id;
26
- `run_in_background: false` is accepted for compatibility only — like omitting it or passing `true`, it uses non-blocking admission and does not wait for the final result (errors / empty returns are still handled as "automatic recovery").
27
- - **No built-in default models**: after a fresh install every role is empty, so you must choose and save models from those already configured in DSH on the "dsh-expert-group" settings page; a role without a model reports a clear message when it is invoked.
28
- - Models and reasoning depths are validated through `llm.listProviders/listModels` + `resolveCallConfig`, and only models that have been added in settings are accepted.
29
- - **Dynamic settings write capability**: the plugin does not import `@deepseek-ai/dsh-settings` at module-load time (the package declares a `>=0.2.1-rc.1` peer, so the host should provide a compatible version and the plugin does not additionally load that package). The target runtimes are `0.2.1-rc.1` / `0.2.1-rc.2` (that is, the RC2 contract host line above `>0.2.1-rc.1`); the plugin reads and writes profile entries through the describe/update/mutate surface of the host settings service, and DEG's own settings-commit endpoint performs semantic validation and revision conflict detection (the host no longer provides an owner validate hook).
30
- - The subagent's `reasoningEffort` is injected through the subagent `agent/request` waterfall, bypassing the limitation that `dsh-tool-subagent`'s
31
- `AgentOptions` does not expose that field yet.
3
+ [中文](README.md) | **English**
4
+
5
+ This project is a subagent plugin for DeepSeek Harness (dsh), in the spirit of omo-slim. The parent agent decomposes tasks, delegates to experts, merges the results, and verifies them; the plugin provides role-based experts with configurable models (every expert can have fallback models and peak/off-peak models), a task sidebar, model configuration, task notifications, and session deletion.
6
+
7
+ > This English edition is a translation of [README.md](README.md); if the two versions ever disagree, the Chinese version is authoritative.
32
8
 
33
9
  ## Installation
34
10
 
35
- The plugin is published to the public npm registry and can be installed directly with npm:
11
+ The plugin is published on the public npm registry and can be installed directly:
36
12
 
37
- ```bash
13
+ ```shell
38
14
  npm i dsh-expert-group
39
15
  ```
40
16
 
41
- You can also install it by package name on DSH's "Add plugin" page: enter `dsh-expert-group` in the input box, switch the install source on the right if needed, then click "Install".
42
-
43
- ![Screenshot of the DSH "Add plugin" dialog: the input box contains dsh-expert-group and the install source can be switched on the right](docs/assets/dsh-plugin-add-dialog.png)
44
-
45
- > This screenshot lives under the repository's `docs/assets/`. The npm package is published per the `files` allowlist in `package.json` and **does not include `docs/`**, so the image does not show up in a copy installed from npm; reading it in the repository works normally.
46
-
47
- Prerequisites: DSH version ≥ `0.2.1-rc.1`, a working DSH Web (`dsh web`), Node.js ≥ 22, and `pnpm` on PATH. Restart `dsh web` after installation for the plugin to take effect.
48
-
49
- The plugin ships no built-in default models per role: first configure models under DSH "Settings → Models", then choose models for each role and save them under "Settings → dsh-expert-group".
50
-
51
- ## Interface Overview
52
-
53
- DEG has exactly three visible surfaces in the DSH Web UI, independent of one another and non-overlapping:
54
-
55
- | Surface | Location | What it does | Details |
56
- | --- | --- | --- | --- |
57
- | **dsh-expert-group settings page** | Settings → `dsh-expert-group` | Maintains global providers, the default models and reasoning depths of the six expert roles, plus notification preferences, `Observer优先`(Observer priority), `任务管理`(Task management), `Auto`, and the per-role concurrency limit | [Settings page in detail](#settings-page-dsh-expert-group) |
58
- | **Expert Group task sidebar** | Right sidebar (the native right pane, or a standalone page when better-sidebar is installed) | Shows the task tree and run state of the current root session; use `>>` / `<<` to open or close a subagent session in the right sidebar; cancel / retry fan-out tasks | [Expert Group task sidebar](#expert-group-task-sidebar) |
59
- | **Run status line and system notifications** | Bottom-left of the main view / bottom-right of the Windows desktop | While running it shows run words such as `Orchestrator running` and `Explorer running`; when a task reaches a terminal state a Windows Toast notifies you | Web status hints |
60
-
61
- DEG has no model-callable notification tool, and it puts no model-configuration entry point in the session title bar or the right sidebar: global expert configuration is maintained only on the settings page, while in-session main-model overrides are still managed by the DSH Host itself.
62
-
63
- > The UI screenshots below were taken from the DSH desktop app and live under the repository's `docs/assets/`. The npm package is published per the `files` allowlist in `package.json` and **does not include `docs/`**, so these image links do not resolve in a copy installed from npm; reading them in the repository works normally.
64
-
65
- ## Settings Page (dsh-expert-group)
66
-
67
- The settings page is a standalone section that DEG registers through `settings.section` (label `dsh-expert-group`), and it calls `ctx.settings.configure({ auto: false })` to turn off the configuration page the host would otherwise generate — **every control that appears on the page is rendered by DEG itself**.
68
-
69
- The page as a whole uses **deferred saving**: every dropdown, checkbox, and number field only edits a draft, and nothing is persisted until you click "Save" in the footer; the only exception is the provider cards inside the "Model configuration" section, each of which holds its own draft with its own "Apply / Cancel". When the settings namespace is not writable the whole page stays read-only.
70
-
71
- The features below are described in top-to-bottom render order; implementation details and boundaries (data flow, revision fence, the seven-effort write rules, and so on) are covered in the "[Model Configuration](#model-configuration)" section later on.
72
-
73
- > To make public release possible, every UI screenshot in this document is redacted: provider route names, model names, Base URLs, and credential reference names appear as grey bars.
74
-
75
- ### 1. Page Header and Description
76
-
77
- ![Settings page title and description](docs/assets/settings/01-page-header.png)
78
-
79
- - The title is `dsh-expert-group`, and the subtitle reads verbatim `专家模型使用 DSH 当前已配置的 provider 和模型目录。`("Expert models use the providers and model catalog already configured in DSH.")
80
- - That sentence is the most important constraint on this page: **candidate providers and models come only from what has already been added under DSH "Settings → Models"**. DEG ships no built-in model catalog and will not accept models outside it.
81
-
82
- ### 2. The "Model Configuration" Section (Collapsed by Default)
83
-
84
- ![Model configuration section](docs/assets/settings/02-model-config-header.png)
85
-
86
- - The only collapsible area on the page, **collapsed by default**; while collapsed it does not read the provider catalog, and only expanding it issues the request.
87
- - The collapsed state is not persisted: refreshing the page returns it to collapsed.
88
- - The section's description text reads verbatim `与 DSH 内置模型设置页同一份数据流:provider 目录、凭据状态与模型目录都来自宿主公开接口,保存走正式 settings API 与 schema 校验。`("Same data flow as the DSH built-in model settings page: the provider catalog, credential status, and model catalog all come from public host interfaces, and saving goes through the official settings API and schema validation.")
89
- - The section **has no save button of its own**: each provider card has its own "Apply / Cancel", independent of saving the role table above.
90
- - When the host provides no model-configuration capability (no settings namespace view or remote service), the whole section is not rendered, and the rest of the page's controls keep working normally.
91
-
92
- ### 3. Provider Cards (Collapsed)
93
-
94
- ![Provider card list](docs/assets/settings/03-provider-cards.png)
95
-
96
- - Each card is one row: on the left is the provider display name (the route id is shown as well when it differs from the display name), followed by a green dot meaning the API Key is configured (both `title` and `aria-label` are `API Key 已配置`(API Key configured)); on the right are `删除`(Delete) and `编辑`(Edit).
97
- - `编辑` expands the card; `删除` deletes that provider and its configuration. This is the **only operation on the whole page with a confirmation step**; the confirmation text is `确定删除 provider「<显示名>」及其配置吗?`(Delete provider "<display name>" and its configuration?), and cancelling writes nothing.
98
- - Before deleting there is a role-linkage guard: if the deletion would make a default reasoning effort that some role is currently using disappear, the deletion is blocked and the affected roles are listed (see section 6).
99
-
100
- ### 4. Expanded Provider: API Key, Base URL, Protocol
101
-
102
- ![Expanded provider](docs/assets/settings/04-provider-fields.png)
103
-
104
- - **API Key**: `type=password`, write-only with no read-back, and no plaintext echo after saving. The input box has three placeholder states: `已配置(留空表示不修改)`(configured — leave blank to keep), `粘贴 API Key 后点应用`(paste an API Key, then click Apply), and `当前凭据只读`(the current credential is read-only).
105
- - **Credential reference**: shown as `凭据引用:<REF>(API Key 只写入 credentials 服务,保存后不回显明文)`(Credential reference: <REF> — the API Key is only written to the credentials service and is not echoed in plaintext after saving); when there is no reference it shows `未设置凭据引用`(no credential reference set). REF is derived from the provider route id — uppercased, non-alphanumeric characters replaced with `_`, and `_API_KEY` appended, so the route `my-gateway` yields `MY_GATEWAY_API_KEY`; when the profile explicitly sets `apiKeyEnv`, that value wins.
106
- - **Base URL**: placeholder `留空表示使用适配器默认端点`(leave blank to use the adapter's default endpoint); leaving it blank deletes the field and falls back to the adapter's default endpoint. Inside the card only empty / non-empty is checked, with no format validation (strict format validation happens in the "Add custom provider" card).
107
- - **Protocol**: the first dropdown entry is always `适配器默认`(adapter default), and selecting it deletes the `api` field; the remaining options are read dynamically from the union type of `providers.<route>.api` in the **host namespace schema** — which protocols exist is decided by the current DSH version, and the plugin does not hardcode a vocabulary.
108
-
109
- ### 5. Model Catalog: Adapter Default / User Override / Restore Default / Fetch Models
110
-
111
- ![Model catalog header](docs/assets/settings/05-model-catalog.png)
112
-
113
- - The label to the right of the `模型`(Models) heading has two states: `适配器默认(首次编辑时写入用户覆盖)`(adapter default — the first edit writes a user override) and `已按用户覆盖`(overridden by the user). Without a user override the adapter default catalog is shown read-only; only the first real edit writes a user override.
114
- - `恢复默认`(Restore default): submits `unset` for the user-layer `models`, that is, **deletes the user override** rather than writing an empty array.
115
- - `获取模型`(Fetch models): uses the draft (not yet saved) Base URL, protocol, and API Key to pull candidate models from the endpoint; on an empty result it reports `该端点没有返回任何模型`(the endpoint returned no models). The candidate list supports select all / deselect all, and when you click `采纳所选`(take the selection), **existing rows are not overwritten**.
116
- - When the model catalog is empty it reports `没有模型:留空表示沿用适配器内置目录`(no models — leaving this empty keeps the adapter's built-in catalog).
117
-
118
- ### 6. Model Entries
119
-
120
- ![Model entries](docs/assets/settings/06-model-entry.png)
121
-
122
- Each model contains two rows of fields:
123
-
124
- - **Model ID** and **Display name**: two text boxes whose placeholders are `模型 ID`(Model ID) and `显示名`(Display name). The ID is required and must be unique (validation messages `模型 ID 不能为空`(Model ID cannot be empty) / `模型 ID 重复(<id>)`(duplicate Model ID <id>)); a completely blank row is not written into the user override.
125
- - **Context window** and **Max output tokens**: placeholder `继承适配器默认`(inherit the adapter default), accepting forms such as `500K` / `128K` (K = 1000, M = 1000000); leaving them blank inherits. Non-positive integers are rejected (`上下文窗口必须是正整数`(context window must be a positive integer) / `最大输出 token 必须是正整数`(max output tokens must be a positive integer)).
126
- - **Reasoning efforts (multi-select)**: the fixed seven effort levels `off / minimal / low / medium / high / xhigh / max`, in the same order as DSH's pi-ai effort vocabulary, and **always shown regardless of whether the current catalog declares support**. On write, `off` is stored as an empty string and the other levels as the same lowercase string; when none of the seven is checked and there are no unknown keys, the `reasoningEfforts` field is deleted. Existing models restore their checks from `reasoningEfforts`; newly added models start with all seven unchecked.
127
- - **Input types**: the `text` and `image` checkboxes, of which **at least one must remain** — once only one is checked it is locked and can no longer be unchecked.
128
-
129
- This row also carries two cross-section constraints:
130
-
131
- - The seven effort levels on the card are **model capabilities** (which effort levels this model offers), whereas `defaults.<role>.reasoningEffort` is a **single choice per role**. If one save would delete or uncheck a level that a role currently uses as its default, the save is blocked and the affected roles are listed, with the message reading verbatim `无法保存:将删除的思考档位 <档位> 正被以下专家角色使用:<角色(档位)>。请先在这些角色的配置中改用其它档位,本页不会自动改写角色配置。`("Cannot save: the reasoning effort <effort> being deleted is currently used by the following expert roles: <role (effort)>. Please switch those roles to another effort level in their configuration first; this page will not rewrite role configuration automatically.")
132
- - The plugin **writes only the fields visible on the card** (`displayName`, `apiKeyEnv`, `baseURL`, `api`, `models`); hidden advanced fields such as `transport`, `retryPolicy`, and `compat` are neither displayed nor rebuilt nor deleted.
133
-
134
- ### 7. Model Actions: Add Model / Remove Model / Cancel / Apply
135
-
136
- ![Model action buttons](docs/assets/settings/07-model-actions.png)
137
-
138
- - `添加模型`(Add model): appends an empty model row (all seven levels unchecked, no input types).
139
- - **Remove model**: the `✕` button on the right of each row, whose accessible name is `删除模型 N`(Remove model N); **there is no confirmation step**.
140
- - `取消`(Cancel): discards this card's draft and returns to the saved state.
141
- - `应用`(Apply) (showing `应用中…`(Applying…) while in progress): local schema validation first → write the settings namespace → write the API Key only after that succeeds → re-read the provider catalog and credential status (the available efforts in the role table above refresh accordingly). A validation failure reports `设置校验未通过,已拒绝写入:<原因>`(settings validation did not pass, the write was rejected: <reason>).
142
- - **Revision conflict**: if the configuration is changed by another session or page after the card was opened, the submission is rejected and the card shows `配置冲突:本卡片的修改未提交。`(Configuration conflict: this card's changes were not submitted.) together with `重新打开(加载最新配置)`(Reopen and load the latest configuration); both the local re-check and the host rejection paths carry explicit text, so other people's changes are never silently overwritten.
143
-
144
- ### 8. Provider Actions: Add Provider / Add Custom Provider / Reload Provider Catalog
145
-
146
- ![Provider actions](docs/assets/settings/08-provider-actions.png)
147
-
148
- - `添加提供方`(Add provider): picks one route from the adapters the host already has and adds it to the profile; the button is disabled when there is nothing to add.
149
- - `添加自定义提供方`(Add custom provider): opens the custom card, with fields in the order route ID → display name → Base URL → protocol → API Key → models.
150
- - The route ID has its own validation: it must look like `/^[a-z][a-z0-9-]{0,62}[a-z0-9]$/`, and it rejects a name that duplicates an existing provider or collides with the same credential reference.
151
- - The Base URL must be http / https with a valid hostname; verbatim errors include `Base URL 只支持 http:// 或 https://`(the Base URL only supports http:// or https://) and `Base URL 必须包含主机名`(the Base URL must contain a hostname).
152
- - Submission has two phases: write the settings profile first, then write the API Key separately; if the latter fails it shows `provider 配置已保存,但 API Key 写入失败:<原因>`(the provider configuration has been saved, but writing the API Key failed: <reason>), and only the credential write can be retried.
153
- - `重新读取 provider 目录`(Reload provider catalog) (showing `读取中…`(Loading…) while in progress): re-fetches the provider catalog, credential status, and model catalog; this is the manual recovery entry point after a catalog anomaly or an external change.
154
- - When there is no configurable provider at all it shows the empty state `当前宿主没有可配置的 provider。`(this host has no configurable providers).
155
-
156
- ### 9. Notifications
157
-
158
- ![Notification settings](docs/assets/settings/09-notifications.png)
159
-
160
- | Control | Default | Values | Stored field |
161
- | --- | --- | --- | --- |
162
- | `通知弹窗`(Notification popup) (checkbox) | On | On / Off | `dsh-expert-group.notificationEnabled` |
163
- | `弹窗停留时间`(Popup duration) (dropdown) | `5s` | `5s / 10s / 30s / 60s / 5min / 10min / 永久`(forever) | `dsh-expert-group.notificationHoldMs` |
164
- | `通知音量`(Notification volume) (slider + number box) | `100` | `0 – 100`, step `1` | `dsh-expert-group.notificationVolume` |
165
-
166
- - Once `通知弹窗` is turned off, the Host **sends no notifications at all** and does not backfill them either; it only affects delivery and does not affect task snapshots, root-turn waiting, or recovery semantics.
167
- - A volume of `100` means no attenuation at all, with only the Windows master volume applying; the slider and the number box are two-way bound to the same value.
168
- - All three use deferred saving: after changing them you must click "Save" in the footer; invalid values fall back to the defaults (duration → `5s`, volume → `100`).
169
-
170
- ### 10. Unified Provider
171
-
172
- ![Unified provider](docs/assets/settings/10-unified-provider.png)
173
-
174
- - The displayed value is "the provider shared by the currently visible roles"; when it is mixed or nothing is selected it shows `无`(None), and the first entry `无` means "not unified".
175
- - Choosing a concrete provider: switches every visible role's provider to it in one step, and migrates models with the same name by **model display name**; models that cannot be matched are cleared, leaving that role with "a provider selected but no model selected".
176
- - Choosing `无`: only clears the top-level unified selection; it **does not** delete the provider any role already has.
177
- - It only rewrites the draft: the role table below refreshes in step before you click Save, and is given up if you do not; after that, manually changing the provider on any row makes the "unified" state fall back to mixed (showing `无` again).
178
-
179
- ### 11. Role Table
180
-
181
- ![Role table](docs/assets/settings/11-role-table.png)
182
-
183
- Six rows in a fixed order: **Explorer, Librarian, Oracle, Designer, Fixer, Observer**. The four columns mean:
184
-
185
- | Column | Where the available values come from | Placeholder when nothing is selected |
186
- | --- | --- | --- |
187
- | Expert | A role label button; clicking it opens that role's prompt editor | — |
188
- | Provider | Providers from the DSH model catalog | `未选择供应商`(No provider selected) |
189
- | Model | Models filtered by the selected provider | `先选择供应商`(Select a provider first) / `未选择模型`(No model selected) |
190
- | Reasoning depth | `模型默认`(Model default) plus the efforts declared by the selected model, based on that model's reasoning capability | `先选择模型`(Select a model first) / `模型无思考深度`(Model has no reasoning depth) |
191
-
192
- - When the current provider / model is no longer in the catalog, it stays visible as a disabled entry `<provider>(不可用)` / `<model>(不可用)`(unavailable), which makes stale configuration easy to spot.
193
- - Selecting a model automatically applies the `defaultEffort` declared by the catalog; selecting `模型默认` (an empty value) for reasoning depth deletes that role's `reasoningEffort` field.
194
- - The Observer row follows the host's meta projection: when the visual agent is not enabled the row is still in the table, but its three dropdowns are disabled.
195
- - Stored field paths: `dsh-expert-group.defaults.<role>.provider / .model / .reasoningEffort`.
196
- - Writes from the role table go through DEG's own commit endpoint (semantic validation + revision conflict detection) and do not reuse the configuration form's set / unset / mutate.
197
-
198
- ### 12. Bottom Management Options
199
-
200
- ![Bottom management options](docs/assets/settings/12-role-options.png)
201
-
202
- | Control | Default | Stored field | Description |
203
- | --- | --- | --- | --- |
204
- | `Observer优先`(Observer priority) | Off | `observerPreferred` | When enabled, image submission switches to the Observer-first route and requires the Observer model to explicitly support image, otherwise it reports `已开启 Observer优先,但 Observer 模型未明确支持 image;原始输入已保留。`(Observer priority is on, but the Observer model does not explicitly support image; the original input has been preserved.); the parent-agent prompt also switches to the Observer-first paragraph |
205
- | `任务管理`(Task management) | On | `taskManagementEnabled` | Controls whether DEG registers Expert Group in the sidebar: after turning it off and saving, it calls the disposer returned by the current install to release the registration (the native right pane and better-sidebar's default sidebar stay unchanged), and after turning it back on and saving it registers again; a missing field or a failed read is always treated as on |
206
- | `Auto` | Off | `autoOpenSubagentSidebar` | When enabled, it automatically opens the subagent's session page in the right pane while the subagent runs, and automatically retracts it once the subagent finishes and resources go idle; it only closes tabs that Auto itself opened during this run, and tabs the user opened manually are never auto-closed. When disabled you can open or close them manually with `>>` / `<<` |
207
- | `单个角色并发上限`(Per-role concurrency limit) | `10` | `roleConcurrencyLimit` | An integer in the range `1–64`. **It does not take effect immediately** and only applies after you click Save; invalid values are rejected by the Host (`设置 roleConcurrencyLimit 无效`, i.e. "setting roleConcurrencyLimit is invalid") |
208
-
209
- ### 13. Footer and Saving
210
-
211
- - The footer status line has only three values: `有未保存的修改`(Unsaved changes), `已保存`(Saved), and empty.
212
- - Buttons: `保存`(Save) (showing `保存中…`(Saving…) while saving) and `放弃修改`(Discard changes). Save errors are displayed as text above the footer, with no separate dialog.
213
- - Saving requires the settings namespace to be writable and the catalog to be ready; when it is read-only or not ready, saving is unavailable.
214
-
215
- ### Differences from the DSH Built-in "Models" Settings Page
216
-
217
- | Aspect | DSH built-in models page | DEG "Model configuration" section |
218
- | --- | --- | --- |
219
- | Visible fields | Includes hidden advanced YAML fields (`transport`, `retryPolicy`, `compat`, etc.) | Only the fields visible on the card; hidden fields are not displayed, rebuilt, or deleted |
220
- | Save granularity | Whole-page submission | Each provider card has its own "Apply / Cancel", and the section has no save button |
221
- | Write path | The host's generic settings write surface | Also goes through the host's `settings.mutate`; the model-catalog layer does not run DEG semantic validation |
222
- | Role configuration | — | Written through DEG's own settings-commit endpoint, with semantic validation and revision conflict detection |
223
-
224
- ## Parent Agent Configuration
225
-
226
- - `enableOrchestrator` is enabled by default: the root session receives the upstream orchestrator's workflow manager prompt and is responsible for breaking down tasks, choosing experts, integrating results, and verifying; subagents do not inherit that parent-agent section.
227
- - To turn it off: set `enableOrchestrator` to `false` in `cordis.patch.yml` and restart DSH; this only disables the parent-agent prompt and does not affect the plugin's role tools themselves.
228
- - This port does not override the root agent's `provider` / `model`; the main model and the UI model override continue to be managed by the DSH Host.
229
-
230
- ## Model Configuration
231
-
232
- > For the user-facing, control-by-control description with screenshots, see "[Settings page in detail](#settings-page-dsh-expert-group)" above; this section only records implementation details and boundaries.
233
-
234
- - **Global expert configuration is maintained only on the "dsh-expert-group" settings page**: providers, each expert's default model / reasoning depth, the notification toggle and volume, `Observer优先`, **Task management**, and **Auto** are all persisted to the plugin settings namespace.
235
- - The plugin no longer offers a right-side **Model configuration** panel, a better-sidebar "Expert models" tab, or a session title-bar entry point; model selection is still maintained only on the settings page. Task state is shown by the Expert Group sidebar described below.
236
- - The settings page's model candidates come only from DSH's current model catalog (the models already added under "Settings → Models"), and they are validated twice by the client and the Host before saving.
237
- - **The "Model configuration" section (collapsed by default)**: at the bottom of the settings page there is another section, also collapsed by default, that mirrors the visible capabilities of DSH's built-in model settings page — provider catalog, API Key (through the credentials service, write-only with no plaintext read-back), Base URL, protocol, adding / removing providers, fetching models, adding / removing models, model ID / display name, context window, max output tokens, input types, and the model catalog's "adapter default / user override / restore default". Its scope **excludes** the built-in page's hidden advanced YAML fields (`transport`, `retryPolicy`, `compat`, etc.): the card only writes the fields it can see, and those fields are neither displayed nor rebuilt.
238
- - **Saved separately from role configuration**: each provider card holds its own draft with its own "Apply / Cancel", and the section itself has no save button; the save button and behaviour of the role table above are completely unchanged. A submission is fenced by the namespace revision read when the card was opened: if the revision has already moved on outside (another session or page), the overwrite is refused, and the card shows a conflict notice together with a "Reopen" entry point.
239
- - **Seven reasoning efforts (multi-select)**: the advanced settings of every model entry contain seven checkboxes `off / minimal / low / medium / high / xhigh / max`, in the same order as DSH's pi-ai effort vocabulary, and they are always shown regardless of whether the current catalog declares support. Existing models restore their checks from `reasoningEfforts`; new models start with all seven unchecked. On save, `off` writes an empty string value and the other levels write the same lowercase string; only these seven visible keys are added or removed, while unknown keys that are not displayed are preserved; when none of the seven is checked and there are no unknown keys, the `reasoningEfforts` field is deleted.
240
-
241
- ## Expert Group Task Sidebar
242
-
243
- Expert Group is the task view that DEG registers in the right sidebar: it draws the complete task tree of **the root session the current session belongs to** — the parent agent is the root node, and ordinary experts, fan-out shards, and live run state all hang below it. It is a read-only view, and the only operations that write state are cancelling and retrying fan-out tasks.
244
-
245
- ![Expert Group sidebar overview](docs/assets/sidebar/01-overview.png)
17
+ You can also install it by package name from DSH's "Add plugin" page: enter `dsh-expert-group` (or an index) in the input box, switch the installation source on the right as needed, and click "Install".
246
18
 
247
- How it is registered depends on the host: without `dsh-better-sidebar` installed it registers a native DSH right-pane page and auto-opens it for each root session the first time; with it installed it registers only a standalone `expert-group` page with `ctx.betterSidebar`. If the user disables that page in better-sidebar, DEG neither opens it automatically nor falls back to registering the other kind of page.
19
+ <p align="center"><a href="https://github.com/NTOIOTN/dsh-expert-group/blob/master/docs/assets/dsh-plugin-add-dialog.png"><img src="https://github.com/NTOIOTN/dsh-expert-group/raw/master/docs/assets/dsh-plugin-add-dialog.png" alt="DSH Add plugin dialog: dsh-expert-group entered as the package name, with the installation source switch on the right"></a></p>
248
20
 
249
- ### The Four Node Types
21
+ ## Expert roles
250
22
 
251
- | Node | First-line title | When it appears |
252
- | --- | --- | --- |
253
- | Parent agent (root node) | The fixed Chinese text `主代理`(Parent agent) | Always present; the root's taskName / session id are not shown |
254
- | Ordinary expert | The short description of the latest dispatch | One node is created per expert delegation |
255
- | fan-out aggregate branch | `<角色> · <N> shards · running|ready` (`<角色>` is the role name) | One fan-out submission creates a parent node, and its shards are its child nodes |
256
- | Idle subagent group | `空闲子代理(N)`(Idle subagents (N)) | Appears when a ready ordinary expert or a settled fan-out parent task exists; collapsible |
23
+ | Role | Purpose | Default permission boundary |
24
+ | ----------- | -------------------------------------------------------------- | ---------------------------------------------- |
25
+ | `explorer` | Locate code, map symbols and existing patterns | Read-only |
26
+ | `librarian` | Research external documentation and library APIs | Read-only |
27
+ | `oracle` | Architecture trade-offs, hard problems, and code review | Read-only |
28
+ | `designer` | Implement user-visible UI/UX work | Writable, constrained by task paths |
29
+ | `fixer` | Implement well-scoped multi-file changes and add tests | Writable, constrained by task paths |
30
+ | `observer` | Analyze images, screenshots, charts, and PDFs | Read-only; vision support depends on the host |
257
31
 
258
- ### Three-Line Structure of a Task Row
32
+ ## Plugin settings
259
33
 
260
- Except for fan-out shards, every agent node has a fixed three lines, and their content does not depend on the collapsed state:
34
+ The settings page covers three areas: model configuration, plugin feature toggles, and expert subagent model configuration and management.
261
35
 
262
- ![Parent agent root node](docs/assets/sidebar/02-root-row.png)
36
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793167391173.png" alt="1793167391173"></p>
37
+ <p align="center"><sub>DEG plugin settings overview</sub></p>
263
38
 
264
- 1. **Task name**: the root node always shows `主代理`; expert nodes show the latest dispatch description; fan-out shard rows show `分片代号 任务名称`(shard code, then task name) (shard rows wrap by content instead of being ellipsized onto a single line). The full text doubles as the tooltip and the accessible label.
265
- 2. **Model metadata**: `角色 · provider · model · 思考深度`(role · provider · model · reasoning depth) (provider and model names in this document's screenshots are redacted). Missing values use the stable placeholders `未知供应商`(Unknown provider) / `未知模型`(Unknown model) / `默认`(Default).
266
- 3. **Status summary**: `标题 · 可继续|一次性 · 正在运行|当前未运行`(title · continuable | one-shot · running | not running), for example, verbatim `修复 DSH 运行状态文字 Animations · 正在运行`(fixing the DSH run-status text animations · running) and `你是 oracle 子代理。任务内容 · 可继续 · 当前未运行`(you are an oracle subagent. Task content · continuable · currently not running). The root node keeps only the dynamic title and the activity state and does not show the continuation mode.
39
+ ### Model configuration
267
40
 
268
- - `可继续`(Continuable) is shown only when the session catalog explicitly proves the subagent is continuable; anything unknown degrades to not continuable, and unknown is never described as continuable.
269
- - The state dot is DSH's native `primitives.StateDot` (`running` / `ready`); when the official component is missing it degrades to a static dot.
41
+ Same capabilities as DSH's built-in model settings page. This was originally built to configure image input and reasoning effort for custom providers; DSH's model settings now offer the same features, so configuring here has the same effect, and the data is shared and synced in both directions.
270
42
 
271
- ### Interaction
43
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793167502011.png" alt="1793167502011"></p>
44
+ <p align="center"><sub>Model configuration</sub></p>
272
45
 
273
- - Clicking the **task name** or the **third line**: the main view switches to that subagent session; when the host provides no workspace navigation capability the whole row stops being clickable, so no dead button is left behind.
274
- - Clicking the **chevron**: only collapses / expands that node (`aria-expanded`; titles `折叠`(Collapse) / `展开`(Expand)) without navigating.
275
- - Clicking **`>>` / `<<`**: affects only the right sidebar; see the next section.
276
- - A fan-out branch offers `取消父任务(未完成 N 个分片)`(Cancel parent task (N shards unfinished)) while active shards remain; a shard row offers `取消分片`(Cancel shard) in the active state and `重试分片`(Retry shard) in the retryable state. Destructive operations ask the host for confirmation first (for example `确认取消父任务?未完成 N 个分片。`(Cancel the parent task? N shards are unfinished.)); when the plugin cannot obtain confirmation capability the whole operation is not executed — it never runs silently.
46
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793169619722.png" alt="1793169619722"></p>
47
+ <p align="center"><sub>DEG plugin reasoning-effort and input-type settings</sub></p>
277
48
 
278
- ### State, Collapse, and Refresh
49
+ ### Plugin feature toggles
279
50
 
280
- - Expanded by default: running, waiting, failed, timed-out, and interrupted tasks; collapsed by default: idle, ready, successful, or cancelled tasks.
281
- - Manual collapse / expand choices are stored per **root session** in `sessionStorage`, and later state changes do not override the user's choice.
282
- - When idle it refreshes by bounded polling (about once every 2.5s); it does not re-render when the whole tree is unchanged, and real changes are never swallowed.
283
- - Only one root session is drawn: the cache is isolated per root, so switching sessions never shows the previous root's content on the new root.
284
- - The panel title is `Expert Group`; if the snapshot fails to load, the title bar shows `快照读取失败`(Snapshot load failed) and a `重试`(Retry) button; the first screen shows a skeleton when there is no cache, and an empty tree shows `暂无 Expert Group 任务`(No Expert Group tasks).
51
+ - **Task management**: enables the right-sidebar task management panel; on by default.
52
+ - **Auto**: enables automatic expansion and reclaim of subagent sessions in the right sidebar; off by default.
53
+ - **Sidebar entry**: adds a plugin settings entry to DSH's left sidebar; on by default.
54
+ - **Notification pop-ups**: calls system notifications when notification events fire; on by default.
55
+ - **Notification volume**: sets the notification volume; 100 by default.
56
+ - **Notification events**: selects which events trigger notifications; all selected by default.
285
57
 
286
- ### fan-out Aggregate Branch
58
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793167576121.png" alt="1793167576121"></p>
59
+ <p align="center"><sub>Plugin feature management</sub></p>
287
60
 
288
- ![fan-out aggregate branch and shards](docs/assets/sidebar/03-fanout-group.png)
61
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793167687070.png" alt="1793167687070"></p>
62
+ <p align="center"><sub>Right-sidebar task management panel</sub></p>
289
63
 
290
- ![fan-out shard row](docs/assets/sidebar/04-shard-row.png)
64
+ **Sidebar session model**: changes only the current session's model configuration.
291
65
 
292
- - The parent node's title is `<角色> · <N> shards · running|ready`, and its dot takes its colour from the canonical run state of the whole fan-out.
293
- - The first line of a shard row is `分片代号 任务名称`, followed by the same model metadata and status summary.
294
- - A shard whose latest attempt succeeded is displayed as successful (even if earlier attempts failed); cancel and retry always act on the **latest attempt's childId**.
295
- - While a cancel / retry request is in flight the button is disabled and marked `aria-busy`, so repeated clicks do not send a second request.
66
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793170346274.png" alt="1793170346274"></p>
67
+ <p align="center"><sub>Sidebar session model page</sub></p>
296
68
 
297
- ### Idle Subagent Group
69
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793167858911.png" alt="1793167858911"></p>
70
+ <p align="center"><sub>Left-sidebar plugin entry</sub></p>
298
71
 
299
- ![Idle subagent group](docs/assets/sidebar/05-idle-group.png)
72
+ ### Expert subagent model configuration and management
300
73
 
301
- Running experts and unsettled fan-outs stay in the main list; idle (ready) ordinary experts and fan-out parent tasks whose shards have all settled are collected into the collapsible group `空闲子代理(N)`, so that long task trees are not drowned by historical nodes. A settled fan-out keeps its shard tree and task operations after moving into the group. The group header is a container rather than an agent, so its dot is always ready; members inside the group each take their colour from their own actual state.
74
+ **Unified provider**: after selecting a provider from the dropdown, every expert in the list below is switched to that provider.
302
75
 
303
- ### `>>` and `<<`: Opening and Closing Subagent Sessions in the Right Sidebar
76
+ **Automatic fallback limit**: when an expert's primary model fails, it automatically falls back to the candidate models (no fallback happens if no candidates are configured), and it stops once the fallback limit is reached; the default limit is 2. For example, set Fixer's primary model to deepseek-v4.1-flash, candidate 1 to glm-5.3-flash, candidate 2 to minimax-m3.1-flash, and candidate 3 to gpt-6-luna. With a limit of 0, the request fails as soon as deepseek-v4.1-flash fails; with a limit of 2, it tries up to minimax-m3.1-flash and then stops.
304
77
 
305
- After every task name there is a 30×20px arrow button, and **the same button has two forms**:
78
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793168093919.png" alt="1793168093919"></p>
79
+ <p align="center"><sub>Expert model settings</sub></p>
306
80
 
307
- | Form | Meaning | Colour | Accessibility |
308
- | --- | --- | --- | --- |
309
- | `>>` | **Opens** this row's subagent session in the right sidebar | Amber (`state-warning-primary`, or `#f59e0b` when the token is missing) | `title` / `aria-label` is `在侧边栏打开 <任务名>`(Open <task name> in the sidebar); with toggle capability, `aria-pressed=false` and `data-open=false` |
310
- | `<<` | **Closes** this row's session, which is already open in the right sidebar | Cyan (`state-business-primary`, or `#22d3ee` when the token is missing) | `aria-label` is `在侧边栏关闭 <任务名>`(Close <task name> in the sidebar); `aria-pressed=true`, `data-open=true` |
81
+ - **Peak/off-peak mode**: opens the peak/off-peak settings page.
82
+ - **Enable peak/off-peak mode**: turns the mode on.
83
+ - **Peak periods**: two peak periods are added by default; they can be edited or deleted. Time outside the peak periods is off-peak.
84
+ - **Peak/off-peak models**: click "Peak" to configure the peak models and candidates, and "Off-peak" to configure the off-peak models and candidates.
311
85
 
86
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793168688030.png" alt="1793168688030"></p>
87
+ <p align="center"><sub>Peak/off-peak mode settings</sub></p>
312
88
 
313
- **`>>` (Open)**
89
+ **Note**: as shown below, once peak/off-peak mode is enabled, the model settings on the DEG plugin settings page follow the current period's configuration; editing them edits the current period's peak/off-peak models.
314
90
 
315
- - None of the render conditions may be missing: the host provides `sidebarRight.openResource`, this row's address resolves to a subagent session address, and the named arrow icon is available. If any one of them fails, **the button is not rendered** — an empty button, or a warning icon posing as an arrow, is misleading.
316
- - Clicking only opens the subagent session page in the right sidebar and **never switches the main view**; `preventDefault + stopPropagation` block both mouse bubbling and keyboard Enter / Space, so clicking the arrow does not also navigate to that subagent session.
317
- - The first open prefers DSH's public `split()` and uses the returned `paneId` to place the resource explicitly; only hosts without `split()` fall back to `preferNewPane: true`. When a subagent pane already exists it passes `paneId` explicitly and turns `preferNewPane` off, so multiple subagents never wrongly share the left pane with Expert Group.
318
- - If the host temporarily cannot open that address (the seat has not been minted yet), the thrown error is swallowed by the plugin: it affects neither the main view nor the other buttons on the same row.
91
+ <p align="center"><img src="https://raw.githubusercontent.com/NTOIOTN/dsh-expert-group/master/docs/assets/readme/1793168997228.png" alt="1793168997228"></p>
92
+ <p align="center"><sub>DEG plugin settings with peak/off-peak mode enabled</sub></p>
319
93
 
320
- **`<<` (Close)**
94
+ - **Observer priority**: off by default. When enabled, images sent by the parent agent are forwarded to the observer subagent for image analysis, which is useful when the parent agent's model cannot accept image input. The observer subagent's model must support image input.
95
+ - **Per-role concurrency limit**: maximum number of concurrent runs for a single role.
96
+ - **Default role timeout**: maximum runtime of a single subagent session.
321
97
 
322
- - It turns into `<<` only when all three capabilities are present — "`close` is available", "either `active()` or the public `openTabs` inventory can provide evidence that it is open", and "the named left-arrow icon is available" — and when this row's exact `tabId` **has already been recorded from evidence**; if any one of them is missing it falls back to a static `>>`, and it never shows a fake toggle that will not close anything when clicked.
323
- - Clicking closes only the one tab belonging to this row; it does not switch the main view, does not affect other rows, and performs no fuzzy matching.
324
- - When the user closes that tab in the right sidebar themselves, the plugin makes a **best-effort** observation through the right-pane DOM markers and `openTabs`: only after two consecutive confirmations that the target is gone does it reset the arrow to `>>`. Indeterminate states such as panel switching, focus changes, or unreadable DOM are never guessed as "closed" nor as "still open".
98
+ ## License and acknowledgements
325
99
 
326
- **Right sidebar width**
100
+ Released under the [MIT License](https://github.com/NTOIOTN/dsh-expert-group/blob/master/LICENSE). See [`THIRD_PARTY_NOTICES.md`](https://github.com/NTOIOTN/dsh-expert-group/blob/master/THIRD_PARTY_NOTICES.md) for the design inspirations and third-party materials.
327
101
 
328
- - When splitting for the first time from a single pane holding only Expert Group, the open transaction first temporarily widens the right sidebar to about 50%, and once the target tab is confirmed to have landed in the returned pane it keeps the 50% adjustable mode; if the split fails it restores the original 20% locked width.
329
- - Day-to-day opening / closing of tabs inside an existing subagent pane does not change the width.
330
- - After the first two panes form: Expert Group takes 40% of the right sidebar (about 20% of the viewport) and the subagent pane takes 60% of the right sidebar (about 30% of the viewport); once the last tracked pane closes, the default width of about 20% is restored.
102
+ Feel free to discuss problems and improvements via GitHub Issues; when submitting code, please include the test results for your change.