diff --git a/src/renderer/src/components/agent/AgentLaunchPickerMenu.search.test.tsx b/src/renderer/src/components/agent/AgentLaunchPickerMenu.search.test.tsx index 94c96fa30a1..daf9b9dfd7e 100644 --- a/src/renderer/src/components/agent/AgentLaunchPickerMenu.search.test.tsx +++ b/src/renderer/src/components/agent/AgentLaunchPickerMenu.search.test.tsx @@ -1,5 +1,5 @@ // @vitest-environment happy-dom -import { cleanup, render, screen } from '@testing-library/react' +import { cleanup, fireEvent, render, screen } from '@testing-library/react' import { afterEach, expect, it, vi } from 'vitest' import { useState, type ComponentProps } from 'react' import userEvent from '@testing-library/user-event' @@ -93,3 +93,48 @@ it('includes blank terminal in keyboard results and filters it for agent and mod await user.type(screen.getByRole('textbox'), 'astra{Enter}') expect(screen.getByLabelText('Selection').textContent).toBe('codex:astra') }) + +it('lists an agent named by the query before other agents’ model setups', () => { + const codex: AgentPickerEntry = { + agent: 'codex', + label: 'Codex', + rows: [{ agent: 'codex', kind: 'cli' }], + surfaces: ['terminal'], + defaultSurface: 'terminal', + terminal: {}, + structured: {}, + catalog: { origin: 'probe', fetchedAt: 1, models: [] } + } + const opencode: AgentPickerEntry = { + ...codex, + agent: 'opencode', + label: 'OpenCode', + rows: [{ agent: 'opencode', kind: 'cli' }], + catalog: { + origin: 'probe', + fetchedAt: 1, + models: [{ id: 'gpt-5-codex', label: 'GPT-5 Codex', isDefault: false, efforts: [] }] + } + } + const launch = vi.fn() + render( + + Open + + + + + ) + fireEvent.focus(screen.getByRole('textbox')) + fireEvent.change(screen.getByRole('textbox'), { target: { value: 'codex' } }) + const items = screen.getAllByRole('menuitem').map((item) => item.textContent) + expect(items[0]).toContain('Codex') + expect(items[0]).not.toContain('OpenCode') + expect(items.some((text) => text?.includes('OpenCode · GPT-5 Codex'))).toBe(true) + const highlighted = document.querySelectorAll('[data-search-default]') + expect(highlighted).toHaveLength(1) + expect(highlighted[0].textContent).toContain('Codex') + expect(highlighted[0].textContent).not.toContain('OpenCode') + fireEvent.keyDown(screen.getByRole('textbox'), { key: 'Enter' }) + expect(launch).toHaveBeenCalledWith({ agent: 'codex', kind: 'cli' }, undefined) +}) diff --git a/src/renderer/src/components/agent/AgentLaunchPickerMenu.tsx b/src/renderer/src/components/agent/AgentLaunchPickerMenu.tsx index a0b2ebfc6ba..31b1804db26 100644 --- a/src/renderer/src/components/agent/AgentLaunchPickerMenu.tsx +++ b/src/renderer/src/components/agent/AgentLaunchPickerMenu.tsx @@ -144,8 +144,10 @@ export function AgentLaunchPickerMenu({ // Why: Enter in the search picks the first enabled row, so show it highlighted like cmdk comboboxes. const enabled = (entry: AgentPickerEntry) => !disabled && entry.surfaces.length > 0 const showBlankTerminal = !!onSelectBlankTerminal && agentPickerBlankTerminalMatches(query) - const firstSetup = showBlankTerminal ? undefined : setups.find((setup) => enabled(setup.entry)) - const firstEntry = showBlankTerminal || firstSetup ? undefined : visible.find(enabled) + // Why: a query naming an agent ("codex") should surface that agent before other agents' model setups. + const firstEntry = showBlankTerminal ? undefined : visible.find(enabled) + const firstSetup = + showBlankTerminal || firstEntry ? undefined : setups.find((setup) => enabled(setup.entry)) const showSearchDefault = searchFocused && query.trim().length > 0 return (
@@ -212,6 +214,30 @@ export function AgentLaunchPickerMenu({ ) : null} + {visible.map((entry) => { + const source = draftForEntry?.(entry) + return ( + + ) + })} {setups.map((setup) => { const source = draftForEntry?.(setup.entry) return ( @@ -237,30 +263,6 @@ export function AgentLaunchPickerMenu({ /> ) })} - {visible.map((entry) => { - const source = draftForEntry?.(entry) - return ( - - ) - })} {!showBlankTerminal && !visible.length && !setups.length ? ( {t('auto.components.agent.AgentCombobox.579c768bde', 'No agents match your search.')}