Add a thinking-level (reasoning effort) picker to the chat composer#45
Merged
Conversation
Adds a composer toolbar dropdown to change the per-session thinking level (off / low / medium / high / xhigh / max), mirroring the existing model picker. The thinkingLevel / onThinkingLevelChange props were already plumbed to FreeFormInput and persisted by both the draft and active chat pages; only the UI trigger was missing. Frontend-only: renders a Radix dropdown and calls the existing onThinkingLevelChange prop. No new i18n keys — level names/descriptions reuse the existing thinking.* keys and the trigger tooltip reuses settings.ai.thinking. Includes a CDP e2e assertion (e2e/assertions/thinking-level-picker.assert.ts) that opens the picker, asserts all six levels are listed with the active one marked, selects a different level, and asserts the trigger label updates. Closes #44
This was referenced Jul 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #44
What & why
Comparable desktop apps let you dial reasoning effort right from the composer —
Claude Code Desktop ships a dedicated effort menu (
⌘⇧E) next to its modelmenu. OpenWork supports six per-session thinking levels (
off/low/medium/high/xhigh/max) but had no way to change the level from thechat composer — the only control was Settings → AI, which sets a per-workspace
default for new chats. Raising effort for a single hard task meant leaving the
conversation, editing settings, and starting over.
The composer already had the neighbor for it (the model picker), and the
plumbing was already in place:
thinkingLevel/onThinkingLevelChangearethreaded from
ChatPage/DraftChatPage→ChatDisplay→ChatInputZone→InputContainer→FreeFormInput, and both pages already persist the value. Onlythe UI trigger was missing.
This adds a thinking-level picker to the composer toolbar, immediately before
the model picker and mirroring it:
(tooltip "Thinking"),
level, and on select calls the already-wired
onThinkingLevelChange(level)— sothe choice persists exactly like a model change,
compactMode(same rule the model picker uses).Frontend-only. It renders a Radix dropdown (the same
StyledDropdownMenu*primitives the model picker uses) and calls the existing
onThinkingLevelChangeprop — the value already flows to the runtime today, so there is no backend /
qwen-code change. No new i18n keys: level names/descriptions reuse the existing
thinking.*keys and the trigger tooltip reusessettings.ai.thinking.Changes
components/app-shell/input/FreeFormInput.tsx— the thinking-level dropdown(new
thinkingDropdownOpenstate; destructure the previously-unusedonThinkingLevelChangeprop; render the picker fromTHINKING_LEVELS).e2e/assertions/thinking-level-picker.assert.ts— new CDP assertion (below).Verification
bun run typecheck:all— introduces no new errors. Delta vsmainiszero; the only errors are the same pre-existing ones unrelated to this change
(
auto-update.ts, asettings-default-thinkingtest tuple, and two test filesimporting
vitest). None are in the file this PR touches.bun test— identical tomain:3578 pass / 56 failon both thisbranch and
mainin the same environment (the 56 failures are pre-existing:BrowserCDP, pet/RPC registration profiles, i18n sorted-parity checks, etc.).This change adds zero new failures.
bun run lint:i18n:parity— OK (6 locales, 1542 keys each). No new keys.bun run build:renderer, where this change lives) — ✅ buildscleanly.
CDP e2e assertion (
thinking-level-picker.assert.ts)The assertion drives the real built app over CDP: it waits for the ready AppShell,
asserts the composer renders the thinking-level trigger, opens the menu and asserts
all six levels are listed with exactly one marked selected (matching the trigger
label), then selects a different level and asserts the menu closes and the
trigger label updates to the chosen level — proving the picker actually changes
the session's thinking level, not merely displays a list.
Part of the autonomous desktop-feature loop (
loop-bot).