diff --git a/packages/tui/src/component/prompt/autocomplete.tsx b/packages/tui/src/component/prompt/autocomplete.tsx index bb35ea31d293..970720572e9f 100644 --- a/packages/tui/src/component/prompt/autocomplete.tsx +++ b/packages/tui/src/component/prompt/autocomplete.tsx @@ -44,7 +44,7 @@ export type AutocompleteOption = { path?: string absolute?: string destructive?: { id: string; confirm: string; run: () => void } - kind?: "skill" + kind?: "skill" | "agent" | "reference" queueable?: boolean } @@ -405,41 +405,13 @@ export function Autocomplete(props: { return { options: [], failed: false, query: "", resolved: false } }) - const mcpResources = createMemo(() => { - if (store.visible !== "reference") return [] - - const options: AutocompleteOption[] = [] - const width = props.anchor().width - 4 - - for (const res of data.location.mcp.resource.list(location.current) ?? []) { - options.push({ - display: Locale.truncateMiddle(res.name, width), - // Match the name only; matching the URI caused unrelated fuzzy hits. - value: res.name, - description: res.description, - onSelect: () => { - insertPart(res.name, { - type: "file", - value: { - uri: res.uri, - name: res.name, - description: res.description, - mention: { start: 0, end: 0, text: "" }, - }, - }) - }, - }) - } - - return options - }) - const agents = createMemo(() => { return (data.location.agent.list() ?? []) .filter((agent) => !agent.hidden && agent.mode !== "primary") .map( (agent): AutocompleteOption => ({ display: "@" + agent.id, + kind: "agent", onSelect: () => { insertPart(agent.id, { type: "agent", @@ -475,6 +447,7 @@ export function Autocomplete(props: { .map( (reference): AutocompleteOption => ({ display: "@" + reference.name, + kind: "reference", description: ` ${reference.source.type === "git" ? reference.source.repository : reference.source.path}`, onSelect: () => { insertPart(reference.name, { @@ -580,7 +553,7 @@ export function Autocomplete(props: { const fileOptions: AutocompleteOption[] = store.visible === "reference" ? fileSearch.options : [] const nonFileOptions: AutocompleteOption[] = store.visible === "reference" - ? [...skillOptions(), ...referenceAliasesValue, ...agentsValue, ...mcpResources()] + ? [...skillOptions(), ...referenceAliasesValue, ...agentsValue] : store.index === 0 ? [...commandsValue] : [] @@ -882,6 +855,11 @@ export function Autocomplete(props: { return "No matching files, agents, or references" }) const emptyError = createMemo(() => store.visible === "reference" && !files.loading && visibleFiles().failed) + const labels = { + skill: "skill", + agent: "agent", + reference: "reference", + } return ( {(option, index) => { const destructive = () => option().destructive + const label = () => { + const kind = option().kind + return kind ? labels[kind] : undefined + } + const contentWidth = () => { + const text = label() + return Math.max(1, position().width - 4 - (text ? stringWidth(text) + 2 : 0)) + } const confirmingAction = () => { const action = destructive() return action !== undefined && action.id === confirming() @@ -944,17 +930,32 @@ export function Autocomplete(props: { : theme.text.default } flexShrink={0} + wrapMode="none" > - {confirmingAction() ? destructive()?.confirm : option().display} + {Locale.truncateMiddle( + confirmingAction() ? (destructive()?.confirm ?? "") : option().display, + contentWidth(), + )} {" " + option().description?.replace(/\s+/g, " ").trim()} + + + + {label()} + + ) }}