diff --git a/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts b/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts index c94042618c9db..647ac002a13a4 100644 --- a/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts +++ b/src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts @@ -203,6 +203,16 @@ class AgentCompletions extends Disposable { const agents = this.chatAgentService.getAgents() .filter(a => a.locations.includes(widget.location)); + // When the input is only `/`, items are sorted by sortText. + // When typing, filterText is used to score and sort. + // The same list is refiltered/ranked while typing. + const getFilterText = (agent: IChatAgentData, command: string) => { + // This is hacking the filter algorithm to make @terminal /explain match worse than @workspace /explain by making its match index later in the string. + // When I type `/exp`, the workspace one should be sorted over the terminal one. + const dummyPrefix = agent.id === 'github.copilot.terminal' ? `0000` : ``; + return `${chatSubcommandLeader}${dummyPrefix}${agent.name}.${command}`; + }; + const justAgents: CompletionItem[] = agents .filter(a => !a.isDefault) .map(agent => { @@ -218,7 +228,7 @@ class AgentCompletions extends Disposable { insertText: `${agentLabel} `, range: new Range(1, 1, 1, 1), kind: CompletionItemKind.Text, - sortText: `${chatSubcommandLeader}${agent.id}`, + sortText: `${chatSubcommandLeader}${agent.name}`, command: { id: AssignSelectedAgentAction.ID, title: AssignSelectedAgentAction.ID, arguments: [{ agent, widget } satisfies AssignSelectedAgentActionArgs] }, }; }); @@ -230,13 +240,13 @@ class AgentCompletions extends Disposable { const withSlash = `${chatSubcommandLeader}${c.name}`; return { label: { label: withSlash, description: agentLabel, detail: isDupe ? ` (${agent.publisherDisplayName})` : undefined }, - filterText: `${chatSubcommandLeader}${agent.name}${c.name}`, + filterText: getFilterText(agent, c.name), commitCharacters: [' '], insertText: `${agentLabel} ${withSlash} `, detail: `(${agentLabel}) ${c.description ?? ''}`, range: new Range(1, 1, 1, 1), kind: CompletionItemKind.Text, // The icons are disabled here anyway - sortText: `${chatSubcommandLeader}${agent.id}${c.name}`, + sortText: `${chatSubcommandLeader}${agent.name}${c.name}`, command: { id: AssignSelectedAgentAction.ID, title: AssignSelectedAgentAction.ID, arguments: [{ agent, widget } satisfies AssignSelectedAgentActionArgs] }, } satisfies CompletionItem; })))