Resolve mobile task agent selection before commit (#3261)

This commit is contained in:
Neil
2026-05-30 18:58:55 -07:00
committed by GitHub
parent 44a5c8ab22
commit 8d8dc9ae05
3 changed files with 106 additions and 36 deletions
+17 -36
View File
@@ -59,6 +59,7 @@ import {
filterWorkspaceAgents,
isWorkspaceAgentEnabled,
pickWorkspaceAgent,
resolveWorkspaceAgentSelection,
workspaceAgentLabel,
type WorkspaceAgentChoice
} from '../../../src/tasks/workspace-agent-selection'
@@ -4998,42 +4999,22 @@ export default function MobileTasksScreen() {
workspaceCreateTargetRepo
])
useEffect(() => {
if (!tasksSupported || !workspaceCreateDraft || workspaceAgentOverridden) return
setWorkspaceAgent(pickWorkspaceAgent(runtimeTaskSettings, workspaceDetectedAgentIds))
}, [
runtimeTaskSettings,
tasksSupported,
workspaceAgentOverridden,
workspaceCreateDraft,
workspaceDetectedAgentIds
])
useEffect(() => {
if (
!workspaceCreateDraft ||
!tasksSupported ||
workspaceDetectedAgentIds === null ||
!workspaceAgent ||
workspaceAgent === 'blank' ||
(workspaceDetectedAgentIds.has(workspaceAgent) &&
isWorkspaceAgentEnabled(workspaceAgent, runtimeTaskSettings.disabledTuiAgents))
) {
return
}
// Why: the drawer can open before SSH/local detection settles. If the user
// picked an agent that is not actually available on that host, fall back to
// the same detected-agent rule desktop uses instead of launching a bad CLI.
setWorkspaceAgent(pickWorkspaceAgent(runtimeTaskSettings, workspaceDetectedAgentIds))
setWorkspaceAgentOverridden(false)
}, [
runtimeTaskSettings,
tasksSupported,
workspaceAgent,
workspaceCreateDraft,
workspaceDetectedAgentIds,
runtimeTaskSettings.disabledTuiAgents
])
const workspaceAgentSelection = resolveWorkspaceAgentSelection({
selectionActive: tasksSupported && workspaceCreateDraft !== null,
settings: runtimeTaskSettings,
detectedAgentIds: workspaceDetectedAgentIds,
agent: workspaceAgent,
overridden: workspaceAgentOverridden
})
if (
workspaceAgentSelection.agent !== workspaceAgent ||
workspaceAgentSelection.overridden !== workspaceAgentOverridden
) {
// Why: the drawer can open before SSH/local detection settles. Resolve the
// visible agent before commit so users do not see an unavailable override.
setWorkspaceAgent(workspaceAgentSelection.agent)
setWorkspaceAgentOverridden(workspaceAgentSelection.overridden)
}
const resolvedWorkspaceAgent = useMemo(
() => workspaceAgent ?? pickWorkspaceAgent(runtimeTaskSettings, workspaceDetectedAgentIds),
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'
import {
normalizeWorkspaceAgent,
pickWorkspaceAgent,
resolveWorkspaceAgentSelection,
workspaceAgentLabel
} from './workspace-agent-selection'
@@ -54,4 +55,52 @@ describe('workspace agent selection', () => {
expect(normalizeWorkspaceAgent('__blank__')).toBe('blank')
expect(workspaceAgentLabel('codex')).toBe('Codex')
})
it('keeps automatic selection current while create selection is active', () => {
expect(
resolveWorkspaceAgentSelection({
selectionActive: true,
settings: { defaultTuiAgent: 'codex' },
detectedAgentIds: new Set(['claude', 'codex']),
agent: null,
overridden: false
})
).toEqual({ agent: 'codex', overridden: false })
})
it('preserves a valid user override', () => {
expect(
resolveWorkspaceAgentSelection({
selectionActive: true,
settings: { defaultTuiAgent: 'claude' },
detectedAgentIds: new Set(['claude', 'codex']),
agent: 'codex',
overridden: true
})
).toEqual({ agent: 'codex', overridden: true })
})
it('falls back when a user override is unavailable after detection settles', () => {
expect(
resolveWorkspaceAgentSelection({
selectionActive: true,
settings: { defaultTuiAgent: 'codex' },
detectedAgentIds: new Set(['claude']),
agent: 'codex',
overridden: true
})
).toEqual({ agent: 'claude', overridden: false })
})
it('does not repair inactive selection state', () => {
expect(
resolveWorkspaceAgentSelection({
selectionActive: false,
settings: { defaultTuiAgent: 'codex' },
detectedAgentIds: new Set(['codex']),
agent: null,
overridden: false
})
).toEqual({ agent: null, overridden: false })
})
})
@@ -15,6 +15,17 @@ type WorkspaceAgentSettings = {
disabledTuiAgents?: unknown
}
export type WorkspaceAgentSelectionState = {
agent: WorkspaceAgentChoice | null
overridden: boolean
}
type ResolveWorkspaceAgentSelectionArgs = WorkspaceAgentSelectionState & {
selectionActive: boolean
settings: WorkspaceAgentSettings
detectedAgentIds: Set<string> | null
}
export function workspaceAgentLabel(agent: WorkspaceAgentChoice): string {
return agent === 'blank' ? 'Blank Terminal' : MOBILE_TUI_AGENT_LABELS[agent]
}
@@ -55,3 +66,32 @@ export function filterWorkspaceAgents(agents: readonly TuiAgent[], disabled?: un
export function isWorkspaceAgentEnabled(agent: TuiAgent, disabled?: unknown): boolean {
return isMobileTuiAgentEnabled(agent, disabled)
}
export function resolveWorkspaceAgentSelection({
selectionActive,
settings,
detectedAgentIds,
agent,
overridden
}: ResolveWorkspaceAgentSelectionArgs): WorkspaceAgentSelectionState {
const current = { agent, overridden }
if (!selectionActive) {
return current
}
const pickedAgent = pickWorkspaceAgent(settings, detectedAgentIds)
if (!overridden) {
return agent === pickedAgent ? current : { agent: pickedAgent, overridden: false }
}
if (
detectedAgentIds === null ||
!agent ||
agent === 'blank' ||
(detectedAgentIds.has(agent) && isWorkspaceAgentEnabled(agent, settings.disabledTuiAgents))
) {
return current
}
return { agent: pickedAgent, overridden: false }
}