Repository navigation
feat(web-shell): add model-specific reasoning controls #8675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 41 commits
971a719
3412461
b832da2
23c34f9
8470c6c
ba86188
6792c84
14ab3ac
44695cc
1a891fb
def62ea
1c8f52d
49c8740
8c5cd8a
0b9a2ec
8859771
d7bb54a
5de46a2
9eb2be2
c5069b1
edb1992
f9b97e5
272d2e7
db34907
628ff58
1320418
e685b99
ba84526
f62a6e5
85a497d
14ae1e7
f54c14c
0c28a88
fd1f436
3a3e964
eaeeb71
d9cafef
630c79a
537080a
0973de8
004bc55
b3f6319
3bf0acd
f4a4592
8cb1088
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # Model reasoning controls registry | ||
|
|
||
| ## Goal | ||
|
|
||
| Expose model-specific Thinking and reasoning-effort controls without teaching | ||
| clients about individual model ids. A built-in Core registry declares which | ||
| controls each exact bare model id supports and their defaults. | ||
|
|
||
| `qwen3.8-max` supports `low`, `medium`, and `xhigh`; its default is | ||
| `xhigh`. `qwen3.8-max-preview`, runtime snapshots, and aliases are | ||
| deliberately excluded. | ||
|
|
||
| ## Design | ||
|
|
||
| The registry independently declares optional `thinking` and `effort` | ||
| capabilities. An effort registration contains its ordered supported tiers and | ||
| default. The first registration is `qwen3.8-max`: Thinking defaults on and | ||
| Effort supports `low`, `medium`, and `xhigh`, defaulting to `xhigh`. | ||
|
|
||
| These defaults are not UI-only. When a registered model has no stored | ||
| preference and no provider-provided reasoning state, resolution writes the | ||
| defaults into the generation config, so every surface (CLI, daemon, ACP, | ||
| channels) sends `reasoning: { effort: 'xhigh' }` to `qwen3.8-max` instead of | ||
| omitting the field and leaving the tier to the server's default. | ||
|
|
||
| The ACP session `configOptions` snapshot is the source of truth for live | ||
| sessions. The agent dynamically advertises the registered `thought_level` | ||
| options for the active model: | ||
|
|
||
| - `thinking`: `on` or `off` | ||
| - `effort`: `low`, `medium`, or `xhigh` | ||
|
|
||
| Changes travel through a daemon session config-option mutation and are echoed | ||
| as ACP `config_option_update` notifications. Web clients update their cached | ||
| connection state from both the attach snapshot and live notifications. | ||
| The ACP session also observes Core model changes, so model switches initiated | ||
| by slash commands or workspace reloads re-apply the active model's preferences | ||
| and publish the same config and model notifications as the session API. | ||
|
|
||
| The daemon's workspace model catalog carries the same optional capability | ||
| metadata so a composer can render controls before a session exists. Older | ||
| daemons omit both the capability metadata and `session_reasoning_control`, so | ||
| clients retain the model-only picker. | ||
|
|
||
| Persisted values live in `model.reasoningPreferences`, keyed by exact bare | ||
| model id. Each entry can store `thinkingEnabled` and `effort`. Missing or | ||
| invalid values use the registry defaults and never inherit the global | ||
| `model.reasoningEffort`; the global setting remains unchanged for unregistered | ||
| models. Turning thinking off does not erase the tier. TUI `/effort` keeps its | ||
| five-tier picker but normalizes a selection to the registered model's supported | ||
| subset before storing it. | ||
|
|
||
| Before a live session exists, WebShell merges the selected model's preference | ||
| into the map through the workspace settings API. Once attached, it uses the | ||
| session mutation so the current session and future sessions stay in sync. A | ||
| failed post-write settings reload is surfaced as an update error rather than | ||
| leaving the composer on stale state. | ||
|
|
||
| ## UI behavior | ||
|
|
||
| The existing model chip remains the only entry point. For a model with | ||
| reasoning controls, the popover's first level renders each registered section | ||
| independently (Thinking, then Effort) and moves the searchable model list | ||
| behind a second-level "Model" submenu; models without reasoning controls keep | ||
| the flat searchable list. This supports Thinking-only, Effort-only, and | ||
| combined models. Effort rows remain visible but disabled while Thinking is off | ||
| when both controls exist. | ||
| Changing an option keeps the popover open. During an active response the | ||
| controls remain available; the new value applies to the next request. | ||
|
|
||
| Older daemons that do not advertise `session_reasoning_control` keep the | ||
| existing model-only popover. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -365,6 +365,7 @@ describe('qwen serve — capabilities envelope', () => { | |
| 'workspace_file_read_cursor', | ||
| 'workspace_file_write', | ||
| 'session_approval_mode_control', | ||
| 'session_reasoning_control', | ||
| 'workspace_tool_toggle', | ||
|
Comment on lines
+368
to
369
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verified — no code change required. The 中文说明已核实——无需代码改动。 |
||
| 'workspace_skill_toggle', | ||
| 'workspace_skill_batch_toggle', | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.