Skip to content

Commit 8f12201

Browse files
authored
πŸ€– fix: exclude auto from agent cycling, hide hints, fix color flash (#2635)
## Summary Four targeted fixes for the agent picker's `Ctrl+.` cycle shortcut and associated UI hints. ## Background - **Cycling includes "auto"** β€” `Ctrl+.` cycles through all `uiSelectable` agents including "auto". Since auto is a meta-mode (not a concrete agent), it should only be toggled explicitly via the picker switch. - **Auto ignores nothing** β€” When "auto" is selected, `Ctrl+.` still works (cycling away from auto) and both the `?` tooltip and the bottom-of-chat shortcut hint still show the "Cycle/change agents" hint. All should be suppressed. - **Color flash** β€” The picker pill animates `border-color` over 150ms via `transition-all`, but the textarea border snaps instantly (no transition). The mismatch produces a visible color flash during agent switches. ## Implementation 1. **`cycleToNextAgent` (`AgentContext.tsx`)** β€” Early-return when active agent is `"auto"` AND auto is available in the discovered agent list. Filter out `"auto"` from the cycle list so it's never a destination. Stale persisted "auto" still allows keyboard recovery. 2. **`AgentHelpTooltip` (`AgentModePicker.tsx`)** β€” Added `isAuto` prop; conditionally hides the "Cycle agents" hint when auto is selected. 3. **Chat input shortcut hints (`ChatInput/index.tsx`)** β€” Conditionally hides the `⌘. - change agent` bottom hint when auto mode is active. 4. **Picker pill transition (`AgentModePicker.tsx`)** β€” Changed `transition-all` β†’ `transition-[background-color]` so only hover-bg animates; border-color now snaps instantly to match the textarea. --- _Generated with `mux` β€’ Model: `anthropic:claude-opus-4-6` β€’ Thinking: `xhigh` β€’ Cost: `$2.30`_ <!-- mux-attribution: model=anthropic:claude-opus-4-6 thinking=xhigh costs=2.30 -->
1 parent d14e21f commit 8f12201

3 files changed

Lines changed: 37 additions & 13 deletions

File tree

β€Žsrc/browser/components/AgentModePicker.tsxβ€Ž

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ function normalizeAgentId(value: unknown): string {
9090
return typeof value === "string" && value.trim().length > 0 ? value.trim().toLowerCase() : "";
9191
}
9292

93-
const AgentHelpTooltip: React.FC = () => (
93+
const AgentHelpTooltip: React.FC<{ isAuto: boolean }> = (props) => (
9494
<Tooltip>
9595
<TooltipTrigger asChild>
9696
<HelpIndicator>?</HelpIndicator>
@@ -101,8 +101,12 @@ const AgentHelpTooltip: React.FC = () => (
101101
<br />
102102
Open picker: {formatKeybind(KEYBINDS.TOGGLE_AGENT)}
103103
<br />
104-
Cycle agents: {formatKeybind(KEYBINDS.CYCLE_AGENT)}
105-
<br />
104+
{!props.isAuto && (
105+
<>
106+
Cycle agents: {formatKeybind(KEYBINDS.CYCLE_AGENT)}
107+
<br />
108+
</>
109+
)}
106110
Quick select: {formatNumberedKeybind(0).replace("1", "1-9")} (when open)
107111
<br />
108112
<br />
@@ -362,7 +366,7 @@ export const AgentModePicker: React.FC<AgentModePickerProps> = (props) => {
362366
}}
363367
style={activeStyle}
364368
className={cn(
365-
"text-foreground hover:bg-hover flex items-center gap-1.5 rounded-sm border-[0.5px] px-1.5 py-0.5 text-[11px] font-medium transition-all duration-150",
369+
"text-foreground hover:bg-hover flex items-center gap-1.5 rounded-sm border-[0.5px] px-1.5 py-0.5 text-[11px] font-medium transition-[background-color] duration-150",
366370
activeClassName
367371
)}
368372
>
@@ -389,7 +393,7 @@ export const AgentModePicker: React.FC<AgentModePickerProps> = (props) => {
389393

390394
{/* Tooltip is hover-only; hide it on touch + narrow layouts to avoid overlap. */}
391395
<div className="hidden [@container(min-width:420px)]:[@media(hover:hover)_and_(pointer:fine)]:block">
392-
<AgentHelpTooltip />
396+
<AgentHelpTooltip isAuto={isAuto} />
393397
</div>
394398

395399
{isPickerOpen && (

β€Žsrc/browser/components/ChatInput/index.tsxβ€Ž

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,15 @@ const ChatInputInner: React.FC<ChatInputProps> = (props) => {
446446
const { open } = useSettings();
447447
const { selectedWorkspace, beginWorkspaceCreation, updateWorkspaceDraftSection } =
448448
useWorkspaceContext();
449-
const { agentId, currentAgent } = useAgent();
449+
const { agentId, currentAgent, agents } = useAgent();
450+
451+
// Keep auto-mode checks aligned with AgentModePicker behavior.
452+
const normalizedAgentId =
453+
typeof agentId === "string" && agentId.trim().length > 0
454+
? agentId.trim().toLowerCase()
455+
: WORKSPACE_DEFAULTS.agentId;
456+
const autoAvailable = agents.some((entry) => entry.uiSelectable && entry.id === "auto");
457+
const isAutoAgent = normalizedAgentId === "auto" && autoAvailable;
450458

451459
// Use current agent's uiColor, or neutral border until agents load
452460
const focusBorderColor = currentAgent?.uiColor ?? "var(--color-border-light)";
@@ -2430,10 +2438,12 @@ const ChatInputInner: React.FC<ChatInputProps> = (props) => {
24302438
<span className="font-mono">{formatKeybind(KEYBINDS.CYCLE_MODEL)}</span>
24312439
<span> - change model</span>
24322440
</span>
2433-
<span>
2434-
<span className="font-mono">{formatKeybind(KEYBINDS.CYCLE_AGENT)}</span>
2435-
<span> - change agent</span>
2436-
</span>
2441+
{!isAutoAgent && (
2442+
<span>
2443+
<span className="font-mono">{formatKeybind(KEYBINDS.CYCLE_AGENT)}</span>
2444+
<span> - change agent</span>
2445+
</span>
2446+
)}
24372447
</div>
24382448
)}
24392449

β€Žsrc/browser/contexts/AgentContext.tsxβ€Ž

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,19 @@ function AgentProviderWithState(props: {
231231
const activeAgentId = coerceAgentId(
232232
isProjectScope ? (scopedAgentId ?? globalDefaultAgentId) : scopedAgentId
233233
);
234-
const currentIndex = selectableAgents.findIndex((a) => a.id === activeAgentId);
235-
const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % selectableAgents.length;
236-
const nextAgent = selectableAgents[nextIndex];
234+
235+
// Auto mode: ignore the cycle shortcut when auto is a live agent
236+
// (stale persisted "auto" not in list β†’ allow cycling to recover)
237+
const autoAvailable = selectableAgents.some((a) => a.id === "auto");
238+
if (activeAgentId === "auto" && autoAvailable) return;
239+
240+
// Never cycle into "auto" β€” it's toggled explicitly via the picker switch
241+
const cyclableAgents = selectableAgents.filter((a) => a.id !== "auto");
242+
if (cyclableAgents.length < 2) return;
243+
244+
const currentIndex = cyclableAgents.findIndex((a) => a.id === activeAgentId);
245+
const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % cyclableAgents.length;
246+
const nextAgent = cyclableAgents[nextIndex];
237247
if (nextAgent) {
238248
setAgentId(nextAgent.id);
239249
}

0 commit comments

Comments
Β (0)