@@ -17,22 +17,31 @@ import { featureName } from '../../models/constants'
17
17
import { AuthUtil } from '../../../codewhisperer/util/authUtil'
18
18
import {
19
19
compileProject ,
20
+ finishHumanInTheLoop ,
20
21
getValidCandidateProjects ,
22
+ openHilPomFile ,
21
23
processTransformFormInput ,
22
24
startTransformByQ ,
23
25
stopTransformByQ ,
24
26
validateCanCompileProject ,
25
27
} from '../../../codewhisperer/commands/startTransformByQ'
26
28
import { JDKVersion , TransformationCandidateProject , transformByQState } from '../../../codewhisperer/models/model'
29
+ import {
30
+ AlternateDependencyVersionsNotFoundError ,
31
+ JavaHomeNotSetError ,
32
+ ModuleUploadError ,
33
+ NoJavaProjectsFoundError ,
34
+ NoMavenJavaProjectsFoundError ,
35
+ } from '../../errors'
27
36
import * as CodeWhispererConstants from '../../../codewhisperer/models/constants'
28
- import { JavaHomeNotSetError , NoJavaProjectsFoundError , NoMavenJavaProjectsFoundError } from '../../errors'
29
37
import MessengerUtils , { ButtonActions , GumbyCommands } from './messenger/messengerUtils'
30
38
import { CancelActionPositions } from '../../telemetry/codeTransformTelemetry'
31
39
import { openUrl } from '../../../shared/utilities/vsCodeUtils'
32
40
import { telemetry } from '../../../shared/telemetry/telemetry'
33
41
import { MetadataResult } from '../../../shared/telemetry/telemetryClient'
34
42
import { CodeTransformTelemetryState } from '../../telemetry/codeTransformTelemetryState'
35
43
import { getAuthType } from '../../../codewhisperer/service/transformByQ/transformApiHandler'
44
+ import DependencyVersions from '../../models/dependencies'
36
45
37
46
// These events can be interactions within the chat,
38
47
// or elsewhere in the IDE
@@ -46,6 +55,10 @@ export interface ChatControllerEventEmitters {
46
55
readonly transformationFinished : vscode . EventEmitter < any >
47
56
readonly processHumanChatMessage : vscode . EventEmitter < any >
48
57
readonly linkClicked : vscode . EventEmitter < any >
58
+ readonly humanInTheLoopStartIntervention : vscode . EventEmitter < any >
59
+ readonly humanInTheLoopPromptUserForDependency : vscode . EventEmitter < any >
60
+ readonly humanInTheLoopSelectionUploaded : vscode . EventEmitter < any >
61
+ readonly errorThrown : vscode . EventEmitter < any >
49
62
}
50
63
51
64
export class GumbyController {
@@ -97,6 +110,22 @@ export class GumbyController {
97
110
this . chatControllerMessageListeners . linkClicked . event ( data => {
98
111
this . openLink ( data )
99
112
} )
113
+
114
+ this . chatControllerMessageListeners . humanInTheLoopStartIntervention . event ( data => {
115
+ return this . startHILIntervention ( data )
116
+ } )
117
+
118
+ this . chatControllerMessageListeners . humanInTheLoopPromptUserForDependency . event ( data => {
119
+ return this . HILPromptForDependency ( data )
120
+ } )
121
+
122
+ this . chatControllerMessageListeners . humanInTheLoopSelectionUploaded . event ( data => {
123
+ return this . HILDependencySelectionUploaded ( data )
124
+ } )
125
+
126
+ this . chatControllerMessageListeners . errorThrown . event ( data => {
127
+ return this . handleError ( data )
128
+ } )
100
129
}
101
130
102
131
private async tabOpened ( message : any ) {
@@ -143,7 +172,7 @@ export class GumbyController {
143
172
// check that a project is open
144
173
const workspaceFolders = vscode . workspace . workspaceFolders
145
174
if ( workspaceFolders === undefined || workspaceFolders . length === 0 ) {
146
- this . messenger . sendRetryableErrorResponse ( 'no-project-found' , message . tabID )
175
+ this . messenger . sendUnrecoverableErrorResponse ( 'no-project-found' , message . tabID )
147
176
return
148
177
}
149
178
@@ -197,11 +226,11 @@ export class GumbyController {
197
226
return await getValidCandidateProjects ( )
198
227
} catch ( err : any ) {
199
228
if ( err instanceof NoJavaProjectsFoundError ) {
200
- this . messenger . sendRetryableErrorResponse ( 'no-java-project-found' , message . tabID )
229
+ this . messenger . sendUnrecoverableErrorResponse ( 'no-java-project-found' , message . tabID )
201
230
} else if ( err instanceof NoMavenJavaProjectsFoundError ) {
202
- this . messenger . sendRetryableErrorResponse ( 'no-maven-java-project-found' , message . tabID )
231
+ this . messenger . sendUnrecoverableErrorResponse ( 'no-maven-java-project-found' , message . tabID )
203
232
} else {
204
- this . messenger . sendRetryableErrorResponse ( 'no-project-found' , message . tabID )
233
+ this . messenger . sendUnrecoverableErrorResponse ( 'no-project-found' , message . tabID )
205
234
}
206
235
}
207
236
return [ ]
@@ -227,6 +256,16 @@ export class GumbyController {
227
256
this . messenger . sendCommandMessage ( { ...message , command : GumbyCommands . CLEAR_CHAT } )
228
257
await this . transformInitiated ( message )
229
258
break
259
+ case ButtonActions . CONFIRM_DEPENDENCY_FORM :
260
+ await this . continueJobWithSelectedDependency ( { ...message , tabID : message . tabId } )
261
+ break
262
+ case ButtonActions . CANCEL_DEPENDENCY_FORM :
263
+ this . messenger . sendUserPrompt ( 'Cancel' , message . tabId )
264
+ await this . continueTransformationWithoutHIL ( { tabID : message . tabId } )
265
+ break
266
+ case ButtonActions . OPEN_FILE :
267
+ await openHilPomFile ( )
268
+ break
230
269
}
231
270
}
232
271
@@ -246,7 +285,7 @@ export class GumbyController {
246
285
this . messenger . sendProjectSelectionMessage ( projectName , fromJDKVersion , toJDKVersion , message . tabID )
247
286
248
287
if ( fromJDKVersion === JDKVersion . UNSUPPORTED ) {
249
- this . messenger . sendRetryableErrorResponse ( 'unsupported-source-jdk-version' , message . tabID )
288
+ this . messenger . sendUnrecoverableErrorResponse ( 'unsupported-source-jdk-version' , message . tabID )
250
289
return
251
290
}
252
291
@@ -267,7 +306,7 @@ export class GumbyController {
267
306
this . messenger . sendCompilationInProgress ( message . tabID )
268
307
await compileProject ( )
269
308
} catch ( err : any ) {
270
- this . messenger . sendRetryableErrorResponse ( 'could-not-compile-project' , message . tabID )
309
+ this . messenger . sendUnrecoverableErrorResponse ( 'could-not-compile-project' , message . tabID )
271
310
// reset state to allow "Start a new transformation" button to work
272
311
this . sessionStorage . getSession ( ) . conversationState = ConversationState . IDLE
273
312
throw err
@@ -310,12 +349,26 @@ export class GumbyController {
310
349
await this . prepareProjectForSubmission ( message )
311
350
}
312
351
313
- private async transformationFinished ( data : { message : string ; tabID : string } ) {
352
+ private async transformationFinished ( data : { message ? : string ; tabID : string } ) {
314
353
this . sessionStorage . getSession ( ) . conversationState = ConversationState . IDLE
315
354
// at this point job is either completed, partially_completed, cancelled, or failed
316
355
this . messenger . sendJobFinishedMessage ( data . tabID , data . message )
317
356
}
318
357
358
+ private startHILIntervention ( data : { tabID : string ; codeSnippet : string } ) {
359
+ this . sessionStorage . getSession ( ) . conversationState = ConversationState . WAITING_FOR_INPUT
360
+ this . messenger . sendHumanInTheLoopInitialMessage ( data . tabID , data . codeSnippet )
361
+ }
362
+
363
+ private HILPromptForDependency ( data : { tabID : string ; dependencies : DependencyVersions } ) {
364
+ this . messenger . sendDependencyVersionsFoundMessage ( data . dependencies , data . tabID )
365
+ }
366
+
367
+ private HILDependencySelectionUploaded ( data : { tabID : string } ) {
368
+ this . sessionStorage . getSession ( ) . conversationState = ConversationState . JOB_SUBMITTED
369
+ this . messenger . sendHILResumeMessage ( data . tabID )
370
+ }
371
+
319
372
private async processHumanChatMessage ( data : { message : string ; tabID : string } ) {
320
373
this . messenger . sendUserPrompt ( data . message , data . tabID )
321
374
this . messenger . sendChatInputEnabled ( data . tabID , false )
@@ -332,15 +385,47 @@ export class GumbyController {
332
385
tabID : data . tabID ,
333
386
} )
334
387
} else {
335
- this . messenger . sendRetryableErrorResponse ( 'invalid-java-home' , data . tabID )
388
+ this . messenger . sendUnrecoverableErrorResponse ( 'invalid-java-home' , data . tabID )
336
389
}
337
390
}
338
391
}
339
392
}
340
393
394
+ private async continueJobWithSelectedDependency ( message : { tabID : string ; formSelectedValues : any } ) {
395
+ const selectedDependency = message . formSelectedValues [ 'GumbyTransformDependencyForm' ]
396
+ this . messenger . sendHILContinueMessage ( message . tabID , selectedDependency )
397
+ await finishHumanInTheLoop ( selectedDependency )
398
+ }
399
+
341
400
private openLink ( message : { link : string } ) {
342
401
void openUrl ( vscode . Uri . parse ( message . link ) )
343
402
}
403
+
404
+ private async handleError ( message : { error : Error ; tabID : string } ) {
405
+ if ( message . error instanceof AlternateDependencyVersionsNotFoundError ) {
406
+ this . messenger . sendKnownErrorResponse ( 'no-alternate-dependencies-found' , message . tabID )
407
+ await this . continueTransformationWithoutHIL ( message )
408
+ } else if ( message . error instanceof ModuleUploadError ) {
409
+ this . messenger . sendKnownErrorResponse ( 'upload-to-s3-failed' , message . tabID )
410
+ await this . transformationFinished ( message )
411
+ } else {
412
+ this . messenger . sendErrorMessage ( message . error . message , message . tabID )
413
+ }
414
+ }
415
+
416
+ private async continueTransformationWithoutHIL ( message : { tabID : string } ) {
417
+ this . sessionStorage . getSession ( ) . conversationState = ConversationState . JOB_SUBMITTED
418
+ CodeTransformTelemetryState . instance . setCodeTransformMetaDataField ( {
419
+ canceledFromChat : true ,
420
+ } )
421
+ try {
422
+ await finishHumanInTheLoop ( )
423
+ } catch ( err : any ) {
424
+ await this . transformationFinished ( { tabID : message . tabID } )
425
+ }
426
+
427
+ this . messenger . sendStaticTextResponse ( 'end-HIL-early' , message . tabID )
428
+ }
344
429
}
345
430
346
431
/**
0 commit comments