diff --git a/src/renderer/src/components/settings/QuickCommandsPane.test.ts b/src/renderer/src/components/settings/QuickCommandsPane.test.ts index ac0689d9259..41af6d410ad 100644 --- a/src/renderer/src/components/settings/QuickCommandsPane.test.ts +++ b/src/renderer/src/components/settings/QuickCommandsPane.test.ts @@ -1,5 +1,9 @@ import { describe, expect, it } from 'vitest' -import { shouldOpenQuickCommandAddIntent } from './QuickCommandsPane' +import { + getAvailableQuickCommandHostId, + shouldOpenQuickCommandAddIntent, + shouldShowQuickCommandsRefreshError +} from './QuickCommandsPane' describe('QuickCommandsPane add-command intent', () => { it('opens the add flow once for each new intent signal', () => { @@ -10,3 +14,33 @@ describe('QuickCommandsPane add-command intent', () => { expect(shouldOpenQuickCommandAddIntent(2, 1)).toBe(true) }) }) + +describe('QuickCommandsPane host state', () => { + it('falls back to the local host when the selected remote host disappears', () => { + expect( + getAvailableQuickCommandHostId('runtime:removed', [ + { id: 'local' }, + { id: 'runtime:available' } + ]) + ).toBe('local') + }) + + it('keeps the selected host while it remains available', () => { + expect( + getAvailableQuickCommandHostId('runtime:available', [ + { id: 'local' }, + { id: 'runtime:available' } + ]) + ).toBe('runtime:available') + }) + + it('surfaces refresh failures only when cached commands remain usable', () => { + expect(shouldShowQuickCommandsRefreshError(true, { error: 'offline', ready: true })).toBe(true) + expect(shouldShowQuickCommandsRefreshError(true, { error: 'offline', ready: false })).toBe( + false + ) + expect(shouldShowQuickCommandsRefreshError(false, { error: 'offline', ready: true })).toBe( + false + ) + }) +}) diff --git a/src/renderer/src/components/settings/QuickCommandsPane.tsx b/src/renderer/src/components/settings/QuickCommandsPane.tsx index 1f98b1af361..55aef0a05a1 100644 --- a/src/renderer/src/components/settings/QuickCommandsPane.tsx +++ b/src/renderer/src/components/settings/QuickCommandsPane.tsx @@ -46,6 +46,22 @@ export function shouldOpenQuickCommandAddIntent( return Boolean(addCommandIntentSignal && consumedAddIntentSignal !== addCommandIntentSignal) } +export function getAvailableQuickCommandHostId( + selectedHostId: ExecutionHostId, + hostOptions: readonly { id: ExecutionHostId }[] +): ExecutionHostId { + return hostOptions.some((host) => host.id === selectedHostId) + ? selectedHostId + : LOCAL_EXECUTION_HOST_ID +} + +export function shouldShowQuickCommandsRefreshError( + commandsAreCurrent: boolean, + runtimeCommands: { error: string | null; ready: boolean } | undefined +): boolean { + return commandsAreCurrent && runtimeCommands?.ready === true && Boolean(runtimeCommands.error) +} + export function QuickCommandsPane({ settings, addCommandIntentSignal @@ -97,6 +113,12 @@ export function QuickCommandsPane({ const [scopeSelection, setScopeSelection] = useState | null>(null) const [scopePopoverOpen, setScopePopoverOpen] = useState(false) + const availableHostId = getAvailableQuickCommandHostId(selectedHostId, hostOptions) + if (availableHostId !== selectedHostId) { + setSelectedHostId(availableHostId) + setScopeSelection(null) + } + const hostRepos = useMemo( () => selectedEnvironmentId @@ -227,7 +249,9 @@ export function QuickCommandsPane({
- +