@@ -139,6 +139,8 @@ export class InlineCompletionManager implements Disposable {
139139 await ImportAdderProvider . instance . onAcceptRecommendation ( editor , item , startLine )
140140 }
141141 this . sessionManager . incrementSuggestionCount ( )
142+ // clear session manager states once accepted
143+ this . sessionManager . clear ( )
142144 }
143145 commands . registerCommand ( 'aws.amazonq.acceptInline' , onInlineAcceptance )
144146
@@ -166,6 +168,8 @@ export class InlineCompletionManager implements Disposable {
166168 } ,
167169 }
168170 this . languageClient . sendNotification ( this . logSessionResultMessageName , params )
171+ // clear session manager states once rejected
172+ this . sessionManager . clear ( )
169173 }
170174 commands . registerCommand ( 'aws.amazonq.rejectCodeSuggestion' , onInlineRejection )
171175 }
@@ -179,6 +183,7 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
179183 private readonly inlineTutorialAnnotation : InlineTutorialAnnotation
180184 ) { }
181185
186+ private readonly logSessionResultMessageName = 'aws/logInlineCompletionSessionResults'
182187 provideInlineCompletionItems = debounce (
183188 this . _provideInlineCompletionItems . bind ( this ) ,
184189 inlineCompletionsDebounceDelay ,
@@ -191,6 +196,11 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
191196 context : InlineCompletionContext ,
192197 token : CancellationToken
193198 ) : Promise < InlineCompletionItem [ ] > {
199+ console . log ( `_provideInlineCompletionItems` )
200+ // prevent concurrent API calls and write to shared state variables
201+ if ( vsCodeState . isRecommendationsActive ) {
202+ return [ ]
203+ }
194204 try {
195205 vsCodeState . isRecommendationsActive = true
196206 const isAutoTrigger = context . triggerKind === InlineCompletionTriggerKind . Automatic
@@ -199,6 +209,24 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
199209 return [ ]
200210 }
201211
212+ // report suggestion state for previous suggestions if they exist
213+ const sessionId = this . sessionManager . getActiveSession ( ) ?. sessionId
214+ const itemId = this . sessionManager . getActiveRecommendation ( ) ?. [ 0 ] ?. itemId
215+ if ( sessionId && itemId ) {
216+ const params : LogInlineCompletionSessionResultsParams = {
217+ sessionId : sessionId ,
218+ completionSessionResult : {
219+ [ itemId ] : {
220+ seen : true ,
221+ accepted : false ,
222+ discarded : false ,
223+ } ,
224+ } ,
225+ }
226+ this . languageClient . sendNotification ( this . logSessionResultMessageName , params )
227+ this . sessionManager . clear ( )
228+ }
229+
202230 // tell the tutorial that completions has been triggered
203231 await this . inlineTutorialAnnotation . triggered ( context . triggerKind )
204232 TelemetryHelper . instance . setInvokeSuggestionStartTime ( )
@@ -229,24 +257,72 @@ export class AmazonQInlineCompletionItemProvider implements InlineCompletionItem
229257 }
230258
231259 const cursorPosition = document . validatePosition ( position )
232- for ( const item of items ) {
233- item . command = {
234- command : 'aws.amazonq.acceptInline' ,
235- title : 'On acceptance' ,
236- arguments : [
237- session . sessionId ,
238- item ,
239- editor ,
240- session . requestStartTime ,
241- cursorPosition . line ,
242- session . firstCompletionDisplayLatency ,
243- ] ,
260+
261+ if ( position . isAfter ( editor . selection . active ) ) {
262+ getLogger ( ) . debug ( `Cursor moved behind trigger position. Discarding suggestion` )
263+ const params : LogInlineCompletionSessionResultsParams = {
264+ sessionId : session . sessionId ,
265+ completionSessionResult : {
266+ [ itemId ] : {
267+ seen : false ,
268+ accepted : false ,
269+ discarded : true ,
270+ } ,
271+ } ,
244272 }
245- item . range = new Range ( cursorPosition , cursorPosition )
273+ this . languageClient . sendNotification ( this . logSessionResultMessageName , params )
274+ this . sessionManager . clear ( )
275+ return [ ]
276+ }
277+
278+ // the user typed characters from invoking suggestion cursor position to receiving suggestion position
279+ const typeahead = document . getText ( new Range ( position , editor . selection . active ) )
280+
281+ const itemsMatchingTypeahead = [ ]
282+
283+ for ( const item of items ) {
246284 item . insertText = typeof item . insertText === 'string' ? item . insertText : item . insertText . value
247- ImportAdderProvider . instance . onShowRecommendation ( document , cursorPosition . line , item )
285+ if ( item . insertText . startsWith ( typeahead ) ) {
286+ item . command = {
287+ command : 'aws.amazonq.acceptInline' ,
288+ title : 'On acceptance' ,
289+ arguments : [
290+ session . sessionId ,
291+ item ,
292+ editor ,
293+ session . requestStartTime ,
294+ cursorPosition . line ,
295+ session . firstCompletionDisplayLatency ,
296+ ] ,
297+ }
298+ item . range = new Range ( cursorPosition , cursorPosition )
299+ itemsMatchingTypeahead . push ( item )
300+ ImportAdderProvider . instance . onShowRecommendation ( document , cursorPosition . line , item )
301+ }
248302 }
249- return items as InlineCompletionItem [ ]
303+
304+ // report discard if none of suggestions match typeahead
305+ if ( itemsMatchingTypeahead . length === 0 ) {
306+ getLogger ( ) . debug (
307+ `Suggestion does not match user typed new characters during generation. Discarding suggestion`
308+ )
309+ const params : LogInlineCompletionSessionResultsParams = {
310+ sessionId : session . sessionId ,
311+ completionSessionResult : {
312+ [ itemId ] : {
313+ seen : false ,
314+ accepted : false ,
315+ discarded : true ,
316+ } ,
317+ } ,
318+ }
319+ this . languageClient . sendNotification ( this . logSessionResultMessageName , params )
320+ this . sessionManager . clear ( )
321+ return [ ]
322+ }
323+
324+ // suggestions returned here will be displayed on screen
325+ return itemsMatchingTypeahead as InlineCompletionItem [ ]
250326 } catch ( e ) {
251327 getLogger ( 'amazonqLsp' ) . error ( 'Failed to provide completion items: %O' , e )
252328 return [ ]
0 commit comments