Skip to content

Commit 65df621

Browse files
committed
feat(amazonq): discard edit suggestions if it's displayed less than 1 sec when a completion arrives
1 parent 1c2686f commit 65df621

File tree

3 files changed

+57
-14
lines changed

3 files changed

+57
-14
lines changed

packages/amazonq/src/app/inline/EditRendering/displayImage.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export class EditDecorationManager {
2424
private currentImageDecoration: vscode.DecorationOptions | undefined
2525
private currentRemovedCodeDecorations: vscode.DecorationOptions[] = []
2626
private acceptHandler: (() => void) | undefined
27-
private rejectHandler: (() => void) | undefined
27+
private rejectHandler: ((isDiscard: boolean) => void) | undefined
2828

2929
constructor() {
3030
this.registerCommandHandlers()
@@ -131,7 +131,7 @@ export class EditDecorationManager {
131131
svgImage: vscode.Uri,
132132
startLine: number,
133133
onAccept: () => Promise<void>,
134-
onReject: () => Promise<void>,
134+
onReject: (isDiscard: boolean) => Promise<void>,
135135
originalCode: string,
136136
newCode: string,
137137
originalCodeHighlightRanges: Array<{ line: number; start: number; end: number }>
@@ -185,9 +185,9 @@ export class EditDecorationManager {
185185
})
186186

187187
// Register Esc key handler for rejecting suggestion
188-
vscode.commands.registerCommand('aws.amazonq.inline.rejectEdit', () => {
188+
vscode.commands.registerCommand('aws.amazonq.inline.rejectEdit', (isDiscard: boolean = false) => {
189189
if (this.rejectHandler) {
190-
this.rejectHandler()
190+
this.rejectHandler(isDiscard)
191191
}
192192
})
193193
}
@@ -416,20 +416,31 @@ export async function displaySvgDecoration(
416416
// )
417417
// }
418418
},
419-
async () => {
419+
async (isDiscard: boolean) => {
420420
// Handle reject
421-
getLogger().info('Edit suggestion rejected')
421+
if (isDiscard) {
422+
getLogger().info('Edit suggestion discarded')
423+
} else {
424+
getLogger().info('Edit suggestion rejected')
425+
}
422426
await decorationManager.clearDecorations(editor)
423427
documentChangeListener.dispose()
424428
cursorChangeListener.dispose()
429+
const suggestionState = isDiscard
430+
? {
431+
seen: false,
432+
accepted: false,
433+
discarded: true,
434+
}
435+
: {
436+
seen: true,
437+
accepted: false,
438+
discarded: false,
439+
}
425440
const params: LogInlineCompletionSessionResultsParams = {
426441
sessionId: session.sessionId,
427442
completionSessionResult: {
428-
[item.itemId]: {
429-
seen: true,
430-
accepted: false,
431-
discarded: false,
432-
},
443+
[item.itemId]: suggestionState,
433444
},
434445
totalSessionDisplayTime: Date.now() - session.requestStartTime,
435446
firstCompletionDisplayLatency: session.firstCompletionDisplayLatency,

packages/amazonq/src/app/inline/editSuggestionState.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@
88
*/
99
export class EditSuggestionState {
1010
private static isEditSuggestionCurrentlyActive = false
11+
private static displayStartTime = performance.now()
1112

1213
static setEditSuggestionActive(active: boolean): void {
1314
this.isEditSuggestionCurrentlyActive = active
15+
this.displayStartTime = performance.now()
1416
}
1517

1618
static isEditSuggestionActive(): boolean {
1719
return this.isEditSuggestionCurrentlyActive
1820
}
21+
22+
static isEditSuggestionDisplayingOverOneSecond(): boolean {
23+
return this.isEditSuggestionActive() && performance.now() - this.displayStartTime > 1000
24+
}
1925
}

packages/amazonq/src/app/inline/recommendationService.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import {
88
inlineCompletionWithReferencesRequestType,
99
TextDocumentContentChangeEvent,
1010
editCompletionRequestType,
11+
LogInlineCompletionSessionResultsParams,
1112
} from '@aws/language-server-runtimes/protocol'
12-
import { CancellationToken, InlineCompletionContext, Position, TextDocument } from 'vscode'
13+
import { CancellationToken, InlineCompletionContext, Position, TextDocument, commands } from 'vscode'
1314
import { LanguageClient } from 'vscode-languageclient'
1415
import { SessionManager } from './sessionManager'
1516
import {
@@ -24,8 +25,8 @@ import { getLogger } from 'aws-core-vscode/shared'
2425
import { DocumentEventListener } from './documentEventListener'
2526
import { getOpenFilesInWindow } from 'aws-core-vscode/utils'
2627
import { asyncCallWithTimeout } from '../../util/timeoutUtil'
27-
import { EditSuggestionState } from './editSuggestionState'
2828
import { extractFileContextInNotebooks } from './notebookUtil'
29+
import { EditSuggestionState } from './editSuggestionState'
2930

3031
export interface GetAllRecommendationsOptions {
3132
emitTelemetry?: boolean
@@ -137,7 +138,7 @@ export class RecommendationService {
137138
* Completions use PartialResultToken with single 1 call of [getAllRecommendations].
138139
* Edits leverage partialResultToken to achieve EditStreak such that clients can pull all continuous suggestions generated by the model within 1 EOS block.
139140
*/
140-
if (!isTriggerByDeletion && !request.partialResultToken && !EditSuggestionState.isEditSuggestionActive()) {
141+
if (!isTriggerByDeletion && !request.partialResultToken) {
141142
const completionPromise: Promise<InlineCompletionListWithReferences> = languageClient.sendRequest(
142143
inlineCompletionWithReferencesRequestType.method,
143144
request,
@@ -187,6 +188,31 @@ export class RecommendationService {
187188
})),
188189
})
189190

191+
// Completion will not be rendered if an edit suggestion has been active for longer than 1 second
192+
if (EditSuggestionState.isEditSuggestionDisplayingOverOneSecond()) {
193+
const session = this.sessionManager.getActiveSession()
194+
if (!session) {
195+
return []
196+
}
197+
const itemId = this.sessionManager.getActiveRecommendation()?.[0]?.itemId
198+
const params: LogInlineCompletionSessionResultsParams = {
199+
sessionId: session.sessionId,
200+
completionSessionResult: {
201+
[itemId]: {
202+
seen: false,
203+
accepted: false,
204+
discarded: true,
205+
},
206+
},
207+
}
208+
languageClient.sendNotification('aws/logInlineCompletionSessionResults', params)
209+
this.sessionManager.clear()
210+
return []
211+
} else if (EditSuggestionState.isEditSuggestionActive()) {
212+
// discard the current edit suggestion if its display time is less than 1 sec
213+
await commands.executeCommand('aws.amazonq.inline.rejectEdit', true)
214+
}
215+
190216
TelemetryHelper.instance.setSdkApiCallEndTime()
191217
TelemetryHelper.instance.setSessionId(result.sessionId)
192218
if (result.items.length > 0 && result.items[0].itemId !== undefined) {

0 commit comments

Comments
 (0)