fix(vscode): avoid stale autocomplete abort controllers

This commit is contained in:
Mark IJbema
2026-06-24 08:17:42 +02:00
parent 8dc96eff6a
commit 92cd9d2838
2 changed files with 22 additions and 8 deletions
@@ -582,6 +582,12 @@ export class AutocompleteInlineCompletionProvider implements vscode.InlineComple
suffix: string,
languageId: string,
): Promise<void> {
// Defense-in-depth: credentials may become invalid between the provider gate and the actual
// debounced execution. In that case, do not attempt an LLM call at all.
if (!hasValidCredentials(this.connectionService)) {
return
}
// Abort only the request superseded within this file/notebook scope.
this.fimAbortControllers.get(scope)?.abort()
const controller = new AbortController()
@@ -596,12 +602,6 @@ export class AutocompleteInlineCompletionProvider implements vscode.InlineComple
provider: getAutocompleteModelById(this.contextProvider.modelId).provider,
}
// Defense-in-depth: credentials may become invalid between the provider gate and the actual
// debounced execution. In that case, do not attempt an LLM call at all.
if (!hasValidCredentials(this.connectionService)) {
return
}
try {
// Curry processSuggestion with request context
const curriedProcessSuggestion = (text: string) =>
@@ -2,13 +2,13 @@ import { describe, expect, it } from "bun:test"
import * as vscode from "vscode"
import { AutocompleteInlineCompletionProvider } from "../../src/services/autocomplete/classic-auto-complete/AutocompleteInlineCompletionProvider"
function createProvider() {
function createProvider(state = "connected") {
;(vscode.window as any).onDidChangeActiveTextEditor = () => ({ dispose: () => {} })
;(vscode.window as any).onDidChangeTextEditorSelection = () => ({ dispose: () => {} })
return new AutocompleteInlineCompletionProvider(
{} as any,
"kilo/mistralai/codestral-2508",
{ getConnectionState: () => "connected" } as any,
{ getConnectionState: () => state } as any,
() => {},
() => ({ enableAutoTrigger: true }),
"/repo",
@@ -109,4 +109,18 @@ describe("autocomplete FIM abort scope", () => {
await Promise.all([first, second])
provider.dispose()
})
it("does not retain controllers when credentials are invalid", async () => {
const provider = createProvider("disconnected")
;(provider as any).fimPromptBuilder = {
getFromFIM: () => {
throw new Error("should not fetch")
},
}
await provider.fetchAndCacheSuggestion("scope-a", prompt(), "", "", "python")
expect((provider as any).fimAbortControllers.size).toBe(0)
provider.dispose()
})
})