Skip to content

Commit 5f92e6b

Browse files
authored
Merge pull request #3501 from Kilo-Org/feature/experimental-new-autocomplete
feat: Add experimental Continue.dev-based autocomplete as alternative to classic autocomplete
2 parents fab8e32 + 035a0de commit 5f92e6b

File tree

9 files changed

+123
-99
lines changed

9 files changed

+123
-99
lines changed

packages/types/src/kilocode/kilocode.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const ghostServiceSettingsSchema = z
1313
enableQuickInlineTaskKeybinding: z.boolean().optional(),
1414
enableSmartInlineTaskKeybinding: z.boolean().optional(),
1515
showGutterAnimation: z.boolean().optional(),
16+
useNewAutocomplete: z.boolean().optional(),
1617
provider: z.string().optional(),
1718
model: z.string().optional(),
1819
})

src/extension.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import { initializeI18n } from "./i18n"
4545
import { registerGhostProvider } from "./services/ghost" // kilocode_change
4646
import { registerMainThreadForwardingLogger } from "./utils/fowardingLogger" // kilocode_change
4747
import { getKiloCodeWrapperProperties } from "./core/kilocode/wrapper" // kilocode_change
48-
import { registerAutocompleteProvider } from "./services/autocomplete" // kilocode_change
4948

5049
/**
5150
* Built using https://github.com/microsoft/vscode-webview-ui-toolkit
@@ -322,8 +321,6 @@ export async function activate(context: vscode.ExtensionContext) {
322321
if (!kiloCodeWrapped) {
323322
// Only use autocomplete in VS Code
324323
registerGhostProvider(context, provider)
325-
// Experimental
326-
// registerAutocompleteProvider(context, provider)
327324
} else {
328325
// Only foward logs in Jetbrains
329326
registerMainThreadForwardingLogger(context)

src/services/autocomplete/index.ts

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/services/ghost/GhostServiceManager.ts

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { GhostModel } from "./GhostModel"
66
import { GhostStatusBar } from "./GhostStatusBar"
77
import { GhostCodeActionProvider } from "./GhostCodeActionProvider"
88
import { GhostInlineCompletionProvider } from "./classic-auto-complete/GhostInlineCompletionProvider"
9+
import { NewAutocompleteProvider } from "./new-auto-complete/NewAutocompleteProvider"
910
import { GhostServiceSettings, TelemetryEventName } from "@roo-code/types"
1011
import { ContextProxy } from "../../core/config/ContextProxy"
1112
import { ProviderSettingsManager } from "../../core/config/ProviderSettingsManager"
@@ -37,6 +38,7 @@ export class GhostServiceManager {
3738
// VSCode Providers
3839
public codeActionProvider: GhostCodeActionProvider
3940
public inlineCompletionProvider: GhostInlineCompletionProvider
41+
private newAutocompleteProvider: NewAutocompleteProvider | null = null
4042
private inlineCompletionProviderDisposable: vscode.Disposable | null = null
4143

4244
private ignoreController?: Promise<RooIgnoreController>
@@ -123,19 +125,37 @@ export class GhostServiceManager {
123125

124126
private async updateInlineCompletionProviderRegistration() {
125127
const shouldBeRegistered = this.settings?.enableAutoTrigger ?? false
128+
const useNewAutocomplete = this.settings?.useNewAutocomplete ?? false
126129

127-
if (shouldBeRegistered && !this.inlineCompletionProviderDisposable) {
128-
// Register the provider
129-
this.inlineCompletionProviderDisposable = vscode.languages.registerInlineCompletionItemProvider(
130-
"*",
131-
this.inlineCompletionProvider,
132-
)
133-
this.context.subscriptions.push(this.inlineCompletionProviderDisposable)
134-
} else if (!shouldBeRegistered && this.inlineCompletionProviderDisposable) {
135-
// Deregister the provider
130+
// First, dispose any existing registration
131+
if (this.inlineCompletionProviderDisposable) {
136132
this.inlineCompletionProviderDisposable.dispose()
137133
this.inlineCompletionProviderDisposable = null
138134
}
135+
136+
// Dispose new autocomplete provider if switching away from it
137+
if (!useNewAutocomplete && this.newAutocompleteProvider) {
138+
this.newAutocompleteProvider.dispose()
139+
this.newAutocompleteProvider = null
140+
}
141+
142+
if (shouldBeRegistered) {
143+
if (useNewAutocomplete) {
144+
// Initialize new autocomplete provider if not already created
145+
if (!this.newAutocompleteProvider) {
146+
this.newAutocompleteProvider = new NewAutocompleteProvider(this.context, this.cline)
147+
await this.newAutocompleteProvider.load()
148+
}
149+
// New autocomplete provider registers itself internally
150+
} else {
151+
// Register classic provider
152+
this.inlineCompletionProviderDisposable = vscode.languages.registerInlineCompletionItemProvider(
153+
"*",
154+
this.inlineCompletionProvider,
155+
)
156+
this.context.subscriptions.push(this.inlineCompletionProviderDisposable)
157+
}
158+
}
139159
}
140160

141161
public async disable() {
@@ -272,6 +292,15 @@ export class GhostServiceManager {
272292
return
273293
}
274294

295+
// Check if using new autocomplete
296+
const useNewAutocomplete = this.settings?.useNewAutocomplete ?? false
297+
298+
if (useNewAutocomplete) {
299+
// New autocomplete doesn't support manual code suggestion yet
300+
// Just return for now
301+
return
302+
}
303+
275304
// Ensure model is loaded
276305
if (!this.model.loaded) {
277306
await this.load()
@@ -416,7 +445,13 @@ export class GhostServiceManager {
416445

417446
public cancelRequest() {
418447
this.stopProcessing()
419-
this.inlineCompletionProvider.cancelRequest()
448+
// Check which provider is active and cancel appropriately
449+
const useNewAutocomplete = this.settings?.useNewAutocomplete ?? false
450+
if (useNewAutocomplete) {
451+
// New autocomplete doesn't have a cancel method yet
452+
} else {
453+
this.inlineCompletionProvider.cancelRequest()
454+
}
420455
}
421456

422457
/**
@@ -434,6 +469,12 @@ export class GhostServiceManager {
434469
this.inlineCompletionProviderDisposable = null
435470
}
436471

472+
// Dispose new autocomplete provider if it exists
473+
if (this.newAutocompleteProvider) {
474+
this.newAutocompleteProvider.dispose()
475+
this.newAutocompleteProvider = null
476+
}
477+
437478
this.disposeIgnoreController()
438479

439480
GhostServiceManager.instance = null // Reset singleton

src/services/autocomplete/AutocompleteModel.ts renamed to src/services/ghost/new-auto-complete/NewAutocompleteModel.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import {
66
ProviderSettings,
77
ProviderSettingsEntry,
88
} from "@roo-code/types"
9-
import { ApiHandler, buildApiHandler } from "../../api"
10-
import { ProviderSettingsManager } from "../../core/config/ProviderSettingsManager"
11-
import { OpenRouterHandler } from "../../api/providers"
12-
import { ApiStreamChunk } from "../../api/transform/stream"
13-
import { ILLM, LLMOptions } from "../continuedev/core/index.js"
14-
import { DEFAULT_AUTOCOMPLETE_OPTS } from "../continuedev/core/util/parameters.js"
15-
import Mistral from "../continuedev/core/llm/llms/Mistral"
16-
import OpenRouter from "../continuedev/core/llm/llms/OpenRouter"
17-
import KiloCode from "../continuedev/core/llm/llms/KiloCode"
9+
import { ApiHandler, buildApiHandler } from "../../../api"
10+
import { ProviderSettingsManager } from "../../../core/config/ProviderSettingsManager"
11+
import { OpenRouterHandler } from "../../../api/providers"
12+
import { ApiStreamChunk } from "../../../api/transform/stream"
13+
import { ILLM, LLMOptions } from "../../continuedev/core/index.js"
14+
import { DEFAULT_AUTOCOMPLETE_OPTS } from "../../continuedev/core/util/parameters.js"
15+
import Mistral from "../../continuedev/core/llm/llms/Mistral"
16+
import OpenRouter from "../../continuedev/core/llm/llms/OpenRouter"
17+
import KiloCode from "../../continuedev/core/llm/llms/KiloCode"
1818

1919
export const AUTOCOMPLETE_PROVIDER_MODELS = {
2020
mistral: "codestral-2501",
@@ -23,7 +23,7 @@ export const AUTOCOMPLETE_PROVIDER_MODELS = {
2323
bedrock: "mistral.codestral-2501-v1:0",
2424
} as const
2525

26-
export class AutocompleteModel {
26+
export class NewAutocompleteModel {
2727
private apiHandler: ApiHandler | null = null
2828
private profile: ProviderSettings | null = null
2929
public loaded = false
@@ -95,7 +95,7 @@ export class AutocompleteModel {
9595
*/
9696
public getILLM(): ILLM | null {
9797
if (!this.profile?.apiProvider) {
98-
console.warn("[AutocompleteModel] No profile loaded")
98+
console.warn("[NewAutocompleteModel] No profile loaded")
9999
return null
100100
}
101101

@@ -105,7 +105,7 @@ export class AutocompleteModel {
105105
// Extract provider-specific configuration
106106
const config = this.extractProviderConfig()
107107
if (!config) {
108-
console.warn(`[AutocompleteModel] Failed to extract config for provider: ${provider}`)
108+
console.warn(`[NewAutocompleteModel] Failed to extract config for provider: ${provider}`)
109109
return null
110110
}
111111

@@ -140,7 +140,7 @@ export class AutocompleteModel {
140140
// Create appropriate LLM instance based on provider
141141
return this.createLLMInstance(provider, llmOptions)
142142
} catch (error) {
143-
console.error(`[AutocompleteModel] Error creating ILLM for provider ${provider}:`, error)
143+
console.error(`[NewAutocompleteModel] Error creating ILLM for provider ${provider}:`, error)
144144
return null
145145
}
146146
}
@@ -164,7 +164,7 @@ export class AutocompleteModel {
164164
switch (provider) {
165165
case "mistral":
166166
if (!this.profile.mistralApiKey) {
167-
console.warn("[AutocompleteModel] Missing Mistral API key")
167+
console.warn("[NewAutocompleteModel] Missing Mistral API key")
168168
return null
169169
}
170170
return {
@@ -175,7 +175,7 @@ export class AutocompleteModel {
175175

176176
case "kilocode":
177177
if (!this.profile.kilocodeToken) {
178-
console.warn("[AutocompleteModel] Missing Kilocode token")
178+
console.warn("[NewAutocompleteModel] Missing Kilocode token")
179179
return null
180180
}
181181
return {
@@ -187,7 +187,7 @@ export class AutocompleteModel {
187187

188188
case "openrouter":
189189
if (!this.profile.openRouterApiKey) {
190-
console.warn("[AutocompleteModel] Missing OpenRouter API key")
190+
console.warn("[NewAutocompleteModel] Missing OpenRouter API key")
191191
return null
192192
}
193193
return {
@@ -199,11 +199,11 @@ export class AutocompleteModel {
199199
case "bedrock":
200200
// Bedrock uses AWS credentials, not a simple API key
201201
// For now, return null as it requires more complex setup
202-
console.warn("[AutocompleteModel] Bedrock provider not yet supported for autocomplete")
202+
console.warn("[NewAutocompleteModel] Bedrock provider not yet supported for autocomplete")
203203
return null
204204

205205
default:
206-
console.warn(`[AutocompleteModel] Unsupported provider: ${provider}`)
206+
console.warn(`[NewAutocompleteModel] Unsupported provider: ${provider}`)
207207
return null
208208
}
209209
}

src/services/autocomplete/AutocompleteProvider.ts renamed to src/services/ghost/new-auto-complete/NewAutocompleteProvider.ts

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,30 @@
11
import * as vscode from "vscode"
2-
import { AutocompleteModel } from "./AutocompleteModel"
3-
import {
4-
AUTOCOMPLETE_PROVIDER_MODELS,
5-
AutocompleteProviderKey,
6-
GhostServiceSettings,
7-
modelIdKeysByProvider,
8-
ProviderSettingsEntry,
9-
} from "@roo-code/types"
10-
import { ContextProxy } from "../../core/config/ContextProxy"
11-
import { ProviderSettingsManager } from "../../core/config/ProviderSettingsManager"
12-
import { ClineProvider } from "../../core/webview/ClineProvider"
13-
import { MinimalConfigProvider } from "../continuedev/core/autocomplete/MinimalConfig"
14-
import { VsCodeIde } from "../continuedev/core/vscode-test-harness/src/VSCodeIde"
15-
import { ContinueCompletionProvider } from "../continuedev/core/vscode-test-harness/src/autocomplete/completionProvider"
16-
import OpenRouter from "../continuedev/core/llm/llms/OpenRouter"
17-
18-
export class AutocompleteProvider {
2+
import { NewAutocompleteModel } from "./NewAutocompleteModel"
3+
import { GhostServiceSettings } from "@roo-code/types"
4+
import { ContextProxy } from "../../../core/config/ContextProxy"
5+
import { ProviderSettingsManager } from "../../../core/config/ProviderSettingsManager"
6+
import { ClineProvider } from "../../../core/webview/ClineProvider"
7+
import { MinimalConfigProvider } from "../../continuedev/core/autocomplete/MinimalConfig"
8+
import { VsCodeIde } from "../../continuedev/core/vscode-test-harness/src/VSCodeIde"
9+
import { ContinueCompletionProvider } from "../../continuedev/core/vscode-test-harness/src/autocomplete/completionProvider"
10+
11+
export class NewAutocompleteProvider {
1912
private completionProviderDisposable: vscode.Disposable | null = null
20-
private model: AutocompleteModel
13+
private model: NewAutocompleteModel
2114
private providerSettingsManager: ProviderSettingsManager
2215
private settings: GhostServiceSettings | null = null
2316

24-
private enabled: boolean = true
25-
private taskId: string | null = null
26-
private isProcessing: boolean = false
27-
private isRequestCancelled: boolean = false
28-
29-
// VSCode Providers
30-
public inlineCompletionProvider: any
31-
3217
constructor(
3318
private context: vscode.ExtensionContext,
3419
private cline: ClineProvider,
3520
) {
3621
// Register Internal Components
3722
this.providerSettingsManager = new ProviderSettingsManager(context)
38-
this.model = new AutocompleteModel()
23+
this.model = new NewAutocompleteModel()
3924

4025
void this.load()
4126
}
4227

43-
// Instance is created and managed by the registration function
44-
4528
// Settings Management
4629
private loadSettings() {
4730
const state = ContextProxy.instance.getValues()
@@ -74,7 +57,7 @@ export class AutocompleteProvider {
7457
// The model.reload() has already loaded the profile, so we can get the ILLM
7558
const llm = this.model.getILLM()
7659
if (!llm) {
77-
console.warn("[AutocompleteProvider] No valid autocomplete provider found")
60+
console.warn("[NewAutocompleteProvider] No valid autocomplete provider found")
7861
return
7962
}
8063

@@ -94,9 +77,9 @@ export class AutocompleteProvider {
9477
)
9578
this.context.subscriptions.push(this.completionProviderDisposable)
9679

97-
console.log("[AutocompleteProvider] Successfully registered autocomplete")
80+
console.log("[NewAutocompleteProvider] Successfully registered autocomplete")
9881
} catch (error) {
99-
console.error("[AutocompleteProvider] Error loading code completion:", error)
82+
console.error("[NewAutocompleteProvider] Error loading code completion:", error)
10083
}
10184
}
10285

@@ -146,7 +129,7 @@ export class AutocompleteProvider {
146129
}
147130

148131
/**
149-
* Dispose of all resources used by the AutocompleteProvider
132+
* Dispose of all resources used by the NewAutocompleteProvider
150133
*/
151134
public dispose(): void {
152135
if (this.completionProviderDisposable) {

src/services/autocomplete/__tests__/AutocompleteModel.spec.ts renamed to src/services/ghost/new-auto-complete/__tests__/NewAutocompleteModel.spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { describe, it, expect, beforeEach, vi } from "vitest"
2-
import { AutocompleteModel } from "../AutocompleteModel"
2+
import { NewAutocompleteModel } from "../NewAutocompleteModel"
33
import { ProviderSettings } from "@roo-code/types"
4-
import Mistral from "../../continuedev/core/llm/llms/Mistral"
5-
import { OpenAI } from "../../continuedev/core/llm/llms/OpenAI"
4+
import Mistral from "../../../continuedev/core/llm/llms/Mistral"
5+
import { OpenAI } from "../../../continuedev/core/llm/llms/OpenAI"
66

77
// Mock the LLM classes
8-
vi.mock("../../continuedev/core/llm/llms/Mistral")
9-
vi.mock("../../continuedev/core/llm/llms/OpenAI")
8+
vi.mock("../../../continuedev/core/llm/llms/Mistral")
9+
vi.mock("../../../continuedev/core/llm/llms/OpenAI")
1010

11-
describe("AutocompleteModel", () => {
12-
let model: AutocompleteModel
11+
describe("NewAutocompleteModel", () => {
12+
let model: NewAutocompleteModel
1313

1414
beforeEach(() => {
15-
model = new AutocompleteModel()
15+
model = new NewAutocompleteModel()
1616
vi.clearAllMocks()
1717
})
1818

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { NewAutocompleteProvider } from "./NewAutocompleteProvider"
2+
export { NewAutocompleteModel } from "./NewAutocompleteModel"

0 commit comments

Comments
 (0)