@@ -22,7 +22,7 @@ import { CodeWhispererSession, SessionManager } from '../session/sessionManager'
2222import { CursorTracker } from '../tracker/cursorTracker'
2323import { CodewhispererLanguage , getSupportedLanguageId } from '../../../shared/languageDetection'
2424import { WorkspaceFolderManager } from '../../workspaceContext/workspaceFolderManager'
25- import { shouldTriggerEdits } from '../utils/triggerUtils'
25+ import { inferTriggerChar } from '../utils/triggerUtils'
2626import {
2727 emitEmptyUserTriggerDecisionTelemetry ,
2828 emitServiceInvocationFailure ,
@@ -36,9 +36,10 @@ import { RejectedEditTracker } from '../tracker/rejectedEditTracker'
3636import { getErrorMessage , hasConnectionExpired } from '../../../shared/utils'
3737import { AmazonQError , AmazonQServiceConnectionExpiredError } from '../../../shared/amazonQServiceManager/errors'
3838import { DocumentChangedListener } from '../documentChangedListener'
39- import { EMPTY_RESULT , EDIT_DEBOUNCE_INTERVAL_MS } from '../contants/constants'
39+ import { EMPTY_RESULT } from '../contants/constants'
4040import { StreakTracker } from '../tracker/streakTracker'
4141import { processEditSuggestion } from '../utils/diffUtils'
42+ import { EditClassifier } from '../auto-trigger/editPredictionAutoTrigger'
4243
4344export class EditCompletionHandler {
4445 private readonly editsEnabled : boolean
@@ -79,14 +80,15 @@ export class EditCompletionHandler {
7980 * Also as a followup, ideally it should be a message/event publish/subscribe pattern instead of manual invocation like this
8081 */
8182 documentChanged ( ) {
82- if ( this . debounceTimeout ) {
83- if ( this . isWaiting ) {
84- this . hasDocumentChangedSinceInvocation = true
85- } else {
86- this . logging . info ( `refresh and debounce edits suggestion for another ${ EDIT_DEBOUNCE_INTERVAL_MS } ` )
87- this . debounceTimeout . refresh ( )
88- }
89- }
83+ // TODO: Remove this entirely once we are sure we dont need debounce
84+ // if (this.debounceTimeout) {
85+ // if (this.isWaiting) {
86+ // this.hasDocumentChangedSinceInvocation = true
87+ // } else {
88+ // this.logging.info(`refresh and debounce edits suggestion for another ${EDIT_DEBOUNCE_INTERVAL_MS}`)
89+ // this.debounceTimeout.refresh()
90+ // }
91+ // }
9092 }
9193
9294 async onEditCompletion (
@@ -171,40 +173,18 @@ export class EditCompletionHandler {
171173 }
172174 }
173175
174- return new Promise < InlineCompletionListWithReferences > ( async resolve => {
175- this . debounceTimeout = setTimeout ( async ( ) => {
176- try {
177- this . isWaiting = true
178- const result = await this . _invoke (
179- params ,
180- startPreprocessTimestamp ,
181- token ,
182- textDocument ,
183- inferredLanguageId ,
184- currentSession
185- ) . finally ( ( ) => {
186- this . isWaiting = false
187- } )
188- if ( this . hasDocumentChangedSinceInvocation ) {
189- this . logging . info (
190- 'EditCompletionHandler - Document changed during execution, resolving empty result'
191- )
192- resolve ( {
193- sessionId : SessionManager . getInstance ( 'EDITS' ) . getActiveSession ( ) ?. id ?? '' ,
194- items : [ ] ,
195- } )
196- } else {
197- this . logging . info ( 'EditCompletionHandler - No document changes, resolving result' )
198- resolve ( result )
199- }
200- } finally {
201- this . debounceTimeout = undefined
202- this . hasDocumentChangedSinceInvocation = false
203- }
204- } , EDIT_DEBOUNCE_INTERVAL_MS )
205- } ) . finally ( ( ) => {
176+ try {
177+ return await this . _invoke (
178+ params ,
179+ startPreprocessTimestamp ,
180+ token ,
181+ textDocument ,
182+ inferredLanguageId ,
183+ currentSession
184+ )
185+ } finally {
206186 this . isInProgress = false
207- } )
187+ }
208188 }
209189
210190 async _invoke (
@@ -218,53 +198,57 @@ export class EditCompletionHandler {
218198 // Build request context
219199 const isAutomaticLspTriggerKind = params . context . triggerKind == InlineCompletionTriggerKind . Automatic
220200 const maxResults = isAutomaticLspTriggerKind ? 1 : 5
221- const fileContext = getFileContext ( {
201+ const fileContextClss = getFileContext ( {
222202 textDocument,
223203 inferredLanguageId,
224204 position : params . position ,
225205 workspaceFolder : this . workspace . getWorkspaceFolder ( textDocument . uri ) ,
226206 } )
227207
208+ // TODO: Parametrize these to a util function, duplicate code as inineCompletionHandler
209+ const triggerCharacters = inferTriggerChar ( fileContextClss , params . documentChangeParams )
210+
228211 const workspaceState = WorkspaceFolderManager . getInstance ( ) ?. getWorkspaceState ( )
229212 const workspaceId = workspaceState ?. webSocketClient ?. isConnected ( ) ? workspaceState . workspaceId : undefined
230213
231- const qEditsTrigger = shouldTriggerEdits (
232- this . codeWhispererService ,
233- fileContext ,
234- params ,
235- this . cursorTracker ,
236- this . recentEditsTracker ,
237- this . sessionManager ,
238- true
214+ const recentEdits = await this . recentEditsTracker . generateEditBasedContext ( textDocument )
215+ const classifier = new EditClassifier (
216+ {
217+ fileContext : fileContextClss ,
218+ triggerChar : triggerCharacters ,
219+ recentEdits : recentEdits ,
220+ recentDecisions : this . sessionManager . userDecisionLog . map ( it => it . decision ) ,
221+ } ,
222+ this . logging
239223 )
240224
241- if ( ! qEditsTrigger ) {
225+ const qEditsTrigger = classifier . shouldTriggerNep ( )
226+
227+ if ( ! qEditsTrigger . shouldTrigger ) {
242228 return EMPTY_RESULT
243229 }
244230
245231 const generateCompletionReq : GenerateSuggestionsRequest = {
246- fileContext : fileContext ,
232+ fileContext : fileContextClss . toServiceModel ( ) ,
247233 maxResults : maxResults ,
248234 predictionTypes : [ 'EDITS' ] ,
249235 workspaceId : workspaceId ,
250236 }
251237
252- if ( qEditsTrigger ) {
253- generateCompletionReq . editorState = {
254- document : {
255- relativeFilePath : textDocument . uri ,
256- programmingLanguage : {
257- languageName : generateCompletionReq . fileContext ?. programmingLanguage ?. languageName ,
258- } ,
259- text : textDocument . getText ( ) ,
238+ generateCompletionReq . editorState = {
239+ document : {
240+ relativeFilePath : textDocument . uri ,
241+ programmingLanguage : {
242+ languageName : generateCompletionReq . fileContext ?. programmingLanguage ?. languageName ,
260243 } ,
261- cursorState : {
262- position : {
263- line : params . position . line ,
264- character : params . position . character ,
265- } ,
244+ text : textDocument . getText ( ) ,
245+ } ,
246+ cursorState : {
247+ position : {
248+ line : params . position . line ,
249+ character : params . position . character ,
266250 } ,
267- }
251+ } ,
268252 }
269253
270254 const supplementalContext = await this . codeWhispererService . constructSupplementalContext (
@@ -306,7 +290,7 @@ export class EditCompletionHandler {
306290 startPreprocessTimestamp : startPreprocessTimestamp ,
307291 startPosition : params . position ,
308292 triggerType : isAutomaticLspTriggerKind ? 'AutoTrigger' : 'OnDemand' ,
309- language : fileContext . programmingLanguage . languageName ,
293+ language : fileContextClss . programmingLanguage . languageName ,
310294 requestContext : generateCompletionReq ,
311295 autoTriggerType : undefined ,
312296 triggerCharacter : '' ,
0 commit comments