Skip to content

Commit 0597708

Browse files
authored
Merge pull request #3279 from Kilo-Org/mark/inline-improve
Improve reuse of generated autocompletions
2 parents 2586e9b + 5655831 commit 0597708

File tree

3 files changed

+675
-37
lines changed

3 files changed

+675
-37
lines changed
Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,75 @@
11
import * as vscode from "vscode"
2-
import { GhostSuggestionsState } from "./GhostSuggestions"
2+
import { FillInAtCursorSuggestion, GhostSuggestionsState } from "./GhostSuggestions"
33
import { extractPrefixSuffix } from "./types"
44

5+
const MAX_SUGGESTIONS_HISTORY = 20
6+
7+
/**
8+
* Find a matching suggestion from the history based on current prefix and suffix
9+
* @param prefix - The text before the cursor position
10+
* @param suffix - The text after the cursor position
11+
* @param suggestionsHistory - Array of previous suggestions (most recent last)
12+
* @returns The matching suggestion text, or null if no match found
13+
*/
14+
export function findMatchingSuggestion(
15+
prefix: string,
16+
suffix: string,
17+
suggestionsHistory: FillInAtCursorSuggestion[],
18+
): string | null {
19+
// Search from most recent to least recent
20+
for (let i = suggestionsHistory.length - 1; i >= 0; i--) {
21+
const fillInAtCursor = suggestionsHistory[i]
22+
23+
// First, try exact prefix/suffix match
24+
if (prefix === fillInAtCursor.prefix && suffix === fillInAtCursor.suffix) {
25+
return fillInAtCursor.text
26+
}
27+
28+
// If no exact match, check for partial typing
29+
// The user may have started typing the suggested text
30+
if (prefix.startsWith(fillInAtCursor.prefix) && suffix === fillInAtCursor.suffix) {
31+
// Extract what the user has typed between the original prefix and current position
32+
const typedContent = prefix.substring(fillInAtCursor.prefix.length)
33+
34+
// Check if the typed content matches the beginning of the suggestion
35+
if (fillInAtCursor.text.startsWith(typedContent)) {
36+
// Return the remaining part of the suggestion (with already-typed portion removed)
37+
return fillInAtCursor.text.substring(typedContent.length)
38+
}
39+
}
40+
}
41+
42+
return null
43+
}
44+
545
export class GhostInlineCompletionProvider implements vscode.InlineCompletionItemProvider {
6-
private suggestions: GhostSuggestionsState | null = null
46+
private suggestionsHistory: FillInAtCursorSuggestion[] = []
747

8-
public updateSuggestions(suggestions: GhostSuggestionsState | null): void {
9-
this.suggestions = suggestions
48+
public updateSuggestions(suggestions: GhostSuggestionsState): void {
49+
const fillInAtCursor = suggestions.getFillInAtCursor()
50+
51+
if (!fillInAtCursor) {
52+
return
53+
}
54+
55+
const isDuplicate = this.suggestionsHistory.some(
56+
(existing) =>
57+
existing.text === fillInAtCursor.text &&
58+
existing.prefix === fillInAtCursor.prefix &&
59+
existing.suffix === fillInAtCursor.suffix,
60+
)
61+
62+
if (isDuplicate) {
63+
return
64+
}
65+
66+
// Add to the end of the array (most recent)
67+
this.suggestionsHistory.push(fillInAtCursor)
68+
69+
// Remove oldest if we exceed the limit
70+
if (this.suggestionsHistory.length > MAX_SUGGESTIONS_HISTORY) {
71+
this.suggestionsHistory.shift()
72+
}
1073
}
1174

1275
public provideInlineCompletionItems(
@@ -17,16 +80,16 @@ export class GhostInlineCompletionProvider implements vscode.InlineCompletionIte
1780
): vscode.ProviderResult<vscode.InlineCompletionItem[] | vscode.InlineCompletionList> {
1881
const { prefix, suffix } = extractPrefixSuffix(document, position)
1982

20-
const fillInAtCursor = this.suggestions?.getFillInAtCursor()
21-
if (!fillInAtCursor || prefix !== fillInAtCursor.prefix || suffix !== fillInAtCursor.suffix) {
22-
return []
23-
}
83+
const matchingText = findMatchingSuggestion(prefix, suffix, this.suggestionsHistory)
2484

25-
const item: vscode.InlineCompletionItem = {
26-
insertText: fillInAtCursor.text,
27-
range: new vscode.Range(position, position),
85+
if (matchingText !== null) {
86+
const item: vscode.InlineCompletionItem = {
87+
insertText: matchingText,
88+
range: new vscode.Range(position, position),
89+
}
90+
return [item]
2891
}
2992

30-
return [item]
93+
return []
3194
}
3295
}

src/services/ghost/GhostProvider.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,6 @@ export class GhostProvider {
434434
TelemetryService.instance.captureEvent(TelemetryEventName.INLINE_ASSIST_REJECT_SUGGESTION, {
435435
taskId: this.taskId,
436436
})
437-
this.inlineCompletionProvider.updateSuggestions(null)
438437
this.suggestions.clear()
439438

440439
this.clearAutoTriggerTimer()

0 commit comments

Comments
 (0)