🤖 feat: unify reasoning picker between chat composer and Agents settings - #3887
🤖 feat: unify reasoning picker between chat composer and Agents settings#3887ibetitsmike wants to merge 24 commits into
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d5ff5f3db0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20edfe77ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a937067819
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1c3188ef10
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ca2bb19aa2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2a46665bad
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 122b930f99
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 801b461d7a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
The Agents settings page used a plain Select for reasoning that only listed thinking levels, so per-model features in the chat picker (Pro mode for the GPT-5.6 family, Fast mode for OpenAI/Grok frontier models) were impossible to configure there and the two controls drifted in styling. - Extract ThinkingSelectorControl: a controlled variant of the chat thinking picker owning policy resolution + route-aware Pro/Fast availability, with a "composer" (chat input) and "box" (settings form field) variant plus an optional Inherit row. ThinkingSelector is now a thin wrapper binding it to ThinkingContext, so future picker changes apply to both surfaces. - Add reasoningMode to AgentAiDefaultsEntry/SubagentAiDefaultsEntry (sparse: only explicit "pro" is persisted) and plumb it through normalizers, the TasksSection save path, workspace mode sync, task/workspace-turn resolution, ACP agent defaults, heartbeat/idle-compaction sends, and compaction override paths, mirroring thinkingLevel precedence. --- _Generated with `mux` • Model: `anthropic:claude-fable-5` • Thinking: `xhigh`_ <!-- mux-attribution: model=anthropic:claude-fable-5 thinking=xhigh -->
Remote UAT found the bottom agent row's menu opened below the settings fold with no auto-scroll.
…f per-field fallback Codex review: ACP mode switches, model changes, and thinking-level changes rebuilt persisted AI settings without reasoningMode, silently dropping pro; goal-continuation kickoff skipped model-less candidates entirely, ignoring reasoning-only agent defaults.
…tandard override of inherited pro Codex round 2: the plan-to-exec handoff ignored effectiveReasoningMode from resolveTaskAISettings (configured exec sub-agent/agent pro defaults never applied), and the Exec sub-agent row's pro toggle could not disable an inherited pro because turning it off deleted the already-absent override.
…clears reasoning override Codex round 3 follow-ons: setAgentReasoningMode deleted overrides that ACP's base-chain resolution then re-filled with an ancestor's pro, and the Inherit action retained an invisible explicit-standard reasoning override with no way to remove it.
Codex round 4: Dream's headless requests (raw streamText) never apply reasoningMode, so the card offered a toggle that could not affect them; and cards without a direct override displayed standard while ACP base-chain resolution ran pro, making the first toggle click a no-op.
…AppConfigStore Codex round 5: agent cards gated Pro on the ambient default model even when the base chain supplied a pro-capable one, hiding an active inherited pro; and every ThinkingSelectorControl instance opened its own config.getConfig fetch + onConfigChanged subscription via useRouting/useMinThinkingLevels (O(rows) fan-out on the Agents settings page). AppConfigStore mirrors ProvidersConfigStore: one fetch + one subscription per app session.
…es and creation Codex round 6: the desktop mode-switch resolver read only the direct agentAiDefaults entry (custom agents with base: exec never inherited an ancestor's pro), and the creation sync copied only model/thinking so a configured pro default missed the first turn of new workspaces. resolveConfiguredReasoningModeDefault mirrors ACP's base-chain walk and is shared by both paths.
… hide Pro on Name Workspace card Codex round 7: resolveTaskAISettings consulted only the target agent's own defaults before parent fallbacks, so Explore never inherited a pro configured on its Exec base (unlike Settings display and ACP resolution); and the Name Workspace card offered Pro even though name generation runs raw streamText (same headless class as Dream, now a shared exclusion set).
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Codex round 8: the sync approximation hardcoded every non-plan agent to inherit its reasoning default from exec; a custom sub-agent with base: plan (or a custom ancestor) now resolves its definition's actual chain at Task.create/createMany time (readAgentDefinition + resolveAgentInheritanceChain, ACP-parity fallback terminus), keeping the approximation only where definitions are unreadable or callers are sync (plan handoff targets literal exec, where the approximation is exact).
9355ea8 to
cdf18a5
Compare
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 038ab8f4fe
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…'s declared base Codex round 11: - resolveWorkspaceAiSettingsForAgent resolves model/thinking field-wise through DECLARED base chains alongside reasoningMode, so a custom agent inheriting GPT-5.6 + pro from its base persists both together instead of pro beside an Anthropic workspace model where gating drops it. The implicit unknown-agent fallback still contributes reasoningMode only, preserving desktop switches that keep the workspace's current model. - resolveWorkspaceAgentBaseChainIds no longer assumes agents named exec are the unmodified built-in: a project-scoped exec.md with base: plan now resolves Plan's defaults for goal kickoffs and heartbeats.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 848bf2e5bb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…beat model/thinking through declared chains Codex round 12: - /compact (applyCompactionOverrides) resolves compact's configured base chain (compact -> exec) for reasoningMode, so a saved Exec pro default reaches compaction as the Settings card displays. - Backend idle compaction gets the same chain-walk (same defect class: it consulted workspace exec settings but never config agentAiDefaults). - Heartbeats resolve model and thinking through the declared base chain alongside reasoningMode; resolving only some fields combined Plan's pro with Exec's Anthropic model, where gating drops pro.
|
@codex review |
…e in package.json (#3898 broke main: updater.ts derives feed repo from package.json repository URL)
…subagent; add pure AI-settings resolver Checkpoint 1 (Phases 1-2): one root config map with a sparse nested delegated profile, legacy root map reduced to a save-time downgrade projection, dual-map mirroring deleted from router/settings/mocks, and a pure field-wise resolver (model/thinking/reasoning) with chain traversal and table-driven tests.
…d resolver Task create/createMany, workspace turns, plan->exec handoff, and parent auto-resume all resolve model/thinking/reasoning via resolveNodeAgentAiSettings. Deletes resolveTaskReasoningMode, the workspace-turn inline ladder, and the handoff-specific reasoning patch; resolveDeclaredBaseChainIds is no longer used by taskService.
…rough the unified resolver - workspaceService: goal kickoff, idle compaction, and heartbeat send options resolve via resolveNodeAgentAiSettings (workspace bucket -> config -> definition/base chain -> legacy/activity fallbacks); deletes the three bespoke candidate ladders and resolveWorkspaceAgentBaseChainIds. - agentSession: auto-compaction resolves as agent compact via the pure resolver (now including the workspace compact bucket); startup crash recovery is documented as request replay; removed a duplicate pre-send thinking clamp. - dream and name_workspace resolve their model through the shared resolver (name_workspace defaults are now actually wired into candidates). - resolveDeclaredBaseChainIds deleted (no remaining consumers).
…hared resolver - ACP resolveAgentAiSettings is now a thin adapter (declared base chain from ORPC descriptors + implicit plan/exec fallback) over the pure resolver; target definition defaults now beat ancestor config per the unified order. - ACP /compact resolves as agent compact with the -m flag as the explicit tier, the workspace compact bucket, and live session settings as parent runtime; invalid -m values report an error instead of streaming a fallback. - Composer /compact resolves through the shared resolver (configured compact model now honored, matching idle/auto compaction). - CLI run/workflow -m flags normalize through normalizeModelInput and fail fast on invalid input.
…olver The fallback-base rule (plan -> plan, otherwise exec, reasoningMode only) was duplicated across four places: the unused common chain helper, the ACP adapter, the Node adapter, and the composer /compact call site. Adapters now pass declared ancestors only and the resolver appends the implicit fallback itself, so AgentAiAncestorLayer.declared disappears. Also drops the unused adjustments output block, collapses the three per-field precedence loops into one pickField helper, and reuses the resolver's selected shape for the ACP ResolvedAiSettings type.
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
… resolver resolveConfiguredAiDefaults hand-rolled the same declared-chain + implicit-fallback precedence the pure resolver owns. It now feeds agentAiDefaults and the declared ancestor layers into the resolver and uses value provenance (sources tier) to report only genuinely configured fields. Behavioral contract unchanged: all 19 resolveWorkspaceAiSettingsForAgent tests pass unmodified.
# Conflicts: # src/common/orpc/schemas/api.ts # src/desktop/updater.test.ts # src/node/orpc/router.ts
|
@codex review Head 852c1d8 adds the unified AI-settings resolver refactor on top of the reasoning-picker feature: canonical
|
… pro defaults UAT regression (rounds 3-5): with a configured exec Pro default, toggling a workspace to Standard was undone on reload or on switching back to the agent; background sync re-applied the configured Pro and the next send flipped the persisted bucket. An existing per-agent bucket now owns the reasoning choice outright (matching the backend targetWorkspaceBucketToLayer contract); configured defaults apply only when no bucket entry exists.
|
@codex review Head bbadd26 additionally fixes a UAT-found regression: an explicit workspace Standard reasoning choice was reverted to a configured Pro default on reload or agent switch-back. An existing per-agent workspace bucket entry now owns the reasoning choice in the frontend sync path, matching the backend targetWorkspaceBucketToLayer contract.
|
|
@claude review |
Summary
Unifies the reasoning picker between the chat composer and the Settings -> Agents cards, and replaces the ~10 scattered model/thinking/reasoning fallback ladders behind those surfaces with one shared field-wise resolver used by every execution path: interactive turns, sub-agent spawns, plan handoff, goals, heartbeats, compaction (
/compact, auto, ACP), title generation, memory consolidation, ACP sessions, and the CLI.Background
The chat composer and the per-agent settings cards previously had separate reasoning UIs with divergent semantics. Settings-configured reasoning defaults were ignored or inconsistently applied on several paths (task spawning, plan handoff, goal kickoff, heartbeats, desktop mode switches), and Pro availability was gated on the wrong model when an agent inherited its model from a base agent.
Under the hood, each of those paths carried its own ad hoc precedence ladder, and delegated (sub-agent) defaults lived in a second root config map (
subagentAiDefaults) that had to be mirrored againstagentAiDefaultswith an active migration marker. The ladders disagreed on ancestor inheritance and coupled fields together, so overriding a model at one layer could silently drop a thinking or reasoning preference from another.Implementation
UI unification:
ThinkingSelectorgains a box variant used by the Agents settings cards; both surfaces share option gating, keyboard handling, and Inherit semantics (choosing Inherit clears the stored override instead of persisting a copy).AppConfigStorecentralizes config fetches so pickers share one subscription; routing refreshes when config writes fail so the UI does not show a state that was never persisted.Single resolver:
src/common/utils/ai/resolveAgentAiSettings.tsis a pure field-wise resolver with one precedence order (explicit overrides -> target workspace bucket -> configured profile -> definition defaults -> declared ancestors -> parent runtime -> workspace/activity fallbacks -> system default). Each field resolves independently, invalid persisted values self-heal by falling through, and invalid explicit values throw. The implicit fallback base rule (plan -> plan, otherwise exec, contributing reasoning mode only) lives inside the resolver instead of being duplicated by every caller.resolveNodeAgentAiSettings(Node services, reads definition chains), the ACP adapter (ORPC descriptors), and the browser call sites (persisted config + workspace metadata).selected(the user's preference, what persistence stores) separately fromeffective(provider-safe values after alias normalization, thinking clamping/floors, and route-aware Pro gating), so temporary capability limits no longer overwrite saved preferences.Canonical config:
subagentAiDefaultscollapses into sparseagentAiDefaults[id].subagentprofiles. Config load folds legacy data into the nested shape; config save emits a one-way legacy projection for downgrade compatibility. TheexecSubagentDefaultsSplitmigration marker and the dual-map mirroring in the ORPC router are deleted.Also includes an unrelated one-line rider:
updater.test.tsfeed expectations updated fromrepo: "mux"torepo: "shux". Main was broken by #3898 (package.json repository URL renamed to coder/shux while the updater derives its feed repo from it), which failed every merge-queue run including this PR's; fixing it here repairs main via this squash merge.Validation
resolveAgentAiSettings.test.ts), plus behavioral tests across the resolution surfaces: base-chain inheritance and per-field fallback (taskService.test.ts,workspaceService.test.ts,workspaceGoalService.test.ts,acp.resolveAgentAiSettings.test.ts,acp.configOptions.test.ts), legacy config merge/projection round-trips (config.test.ts,agentAiDefaults.test.ts), Pro gating and Inherit-clears-override (workspaceModeAi.test.ts), picker UI flows (TasksSection.ui.test.tsx), routing refresh on failed writes (useRouting.test.ts).bun test src/desktop/updater.test.tspasses on the merged tree.Risks
Medium. Reasoning/model resolution touches every agent-spawn path; a regression would mis-select thinking level or model for sub-agents, heartbeats, or goal kickoff. Mitigations: the resolver is pure and table-tested against the documented precedence order, adapters fall back to resolver-internal defaults when definitions cannot be read, and invalid persisted config self-heals instead of erroring. The config schema change ships a save-time legacy projection so downgrading builds keep reading delegated defaults.
Generated with
Shux• Model:anthropic:claude-fable-5• Thinking:xhigh