From 3492bebe44960899c05d076a057c091729121d49 Mon Sep 17 00:00:00 2001 From: luca cappa Date: Fri, 27 Mar 2026 17:40:34 -0700 Subject: [PATCH] minimize the calls to lm.selectChatModels --- .../Providers/CopilotHoverProvider.ts | 44 ++++++++++++++++--- Extension/src/LanguageServer/extension.ts | 10 +++-- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/Extension/src/LanguageServer/Providers/CopilotHoverProvider.ts b/Extension/src/LanguageServer/Providers/CopilotHoverProvider.ts index b04b8e302..b04e17cd3 100644 --- a/Extension/src/LanguageServer/Providers/CopilotHoverProvider.ts +++ b/Extension/src/LanguageServer/Providers/CopilotHoverProvider.ts @@ -26,10 +26,45 @@ export class CopilotHoverProvider implements vscode.HoverProvider { private cancelledDocument: vscode.TextDocument | undefined; private cancelledPosition: vscode.Position | undefined; private content: string | undefined; + private chatModel: vscode.LanguageModelChat | undefined; + // Flag to avoid querying the LanguageModelChat repeatedly if no model is found + private checkedChatModel: boolean = false; constructor(client: DefaultClient) { this.client = client; } + public async getCachedChatModel(): Promise { + if (this.checkedChatModel) { + return this.chatModel; + } + + const vscodelm = getVSCodeLanguageModel(); + if (vscodelm) { + try { + const [model] = await vscodelm.selectChatModels(modelSelector); + if (!model) { + telemetry.logLanguageServerEvent('CopilotHoverNoModelSelected', { remoteName: vscode.env.remoteName || 'local' }); + } else { + this.chatModel = model; + } + } catch (e: any) { + const exceptionType = e?.name || e?.constructor?.name || typeof e; + telemetry.logLanguageServerEvent('CopilotHoverSelectModelFailed', { + remoteName: vscode.env.remoteName || 'local', + exceptionType: String(exceptionType) + }); + } + } + this.checkedChatModel = true; + return this.chatModel; + } + + public async refreshCachedChatModel(): Promise { + this.chatModel = undefined; + this.checkedChatModel = false; + return this.getCachedChatModel(); + } + public async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise { await this.client.ready; @@ -43,12 +78,9 @@ export class CopilotHoverProvider implements vscode.HoverProvider { } // Ensure the user has access to Copilot. - const vscodelm = getVSCodeLanguageModel(); - if (vscodelm) { - const [model] = await vscodelm.selectChatModels(modelSelector); - if (!model) { - return undefined; - } + const model = await this.getCachedChatModel(); + if (!model) { + return undefined; } const newHover = this.isNewHover(document, position); diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 2c072eff3..f4d3417b2 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -17,7 +17,7 @@ import { TargetPopulation } from 'vscode-tas-client'; import * as which from 'which'; import { logAndReturn } from '../Utility/Async/returns'; import * as util from '../common'; -import { isWindows, modelSelector } from '../constants'; +import { isWindows } from '../constants'; import { instrument } from '../instrumentation'; import { getCrashCallStacksChannel } from '../logger'; import { PlatformInformation } from '../platform'; @@ -1471,8 +1471,12 @@ async function onCopilotHover(): Promise { let chatResponse: vscode.LanguageModelChatResponse | undefined; try { - // Select the chat model. - const [model] = await vscodelm.selectChatModels(modelSelector); + // Select the chat model (refresh from cache). + const model = await copilotHoverProvider.refreshCachedChatModel(); + if (!model) { + await reportCopilotFailure(copilotHoverProvider, hoverDocument, hoverPosition, "Copilot model not available."); + return; + } chatResponse = await model.sendRequest( messages,