@@ -43,7 +43,7 @@ import {
43
43
} from '../../../shared/utilities/workspaceUtils'
44
44
import { getPathsFromZipFilePath , SvgFileExtension } from '../../../amazonq/util/files'
45
45
import { FollowUpTypes } from '../../../amazonq/commons/types'
46
- import { DocGenerationTask } from '../docGenerationTask'
46
+ import { DocGenerationTask , DocGenerationTasks } from '../docGenerationTask'
47
47
import { DevPhase } from '../../types'
48
48
49
49
export interface ChatControllerEventEmitters {
@@ -67,9 +67,7 @@ export class DocController {
67
67
private readonly messenger : DocMessenger
68
68
private readonly sessionStorage : BaseChatSessionStorage < Session >
69
69
private authController : AuthController
70
- private folderPath = ''
71
- private mode : Mode = Mode . NONE
72
- public docGenerationTask : DocGenerationTask
70
+ private docGenerationTasks : DocGenerationTasks
73
71
74
72
public constructor (
75
73
private readonly chatControllerMessageListeners : ChatControllerEventEmitters ,
@@ -80,7 +78,7 @@ export class DocController {
80
78
this . messenger = messenger
81
79
this . sessionStorage = sessionStorage
82
80
this . authController = new AuthController ( )
83
- this . docGenerationTask = new DocGenerationTask ( )
81
+ this . docGenerationTasks = new DocGenerationTasks ( )
84
82
85
83
this . chatControllerMessageListeners . processHumanChatMessage . event ( ( data ) => {
86
84
this . processUserChatMessage ( data ) . catch ( ( e ) => {
@@ -157,23 +155,23 @@ export class DocController {
157
155
} else {
158
156
let displayPath = ''
159
157
const relativePath = getWorkspaceRelativePath ( uri . fsPath )
160
-
158
+ const docGenerationTask = this . docGenerationTasks . getTask ( data . tabID )
161
159
if ( relativePath ) {
162
160
// Display path should always include workspace folder name
163
161
displayPath = path . join ( relativePath . workspaceFolder . name , relativePath . relativePath )
164
162
// Only include workspace folder name in API call if multi-root workspace
165
- this . folderPath = isMultiRootWorkspace ( ) ? displayPath : relativePath . relativePath
163
+ docGenerationTask . folderPath = isMultiRootWorkspace ( ) ? displayPath : relativePath . relativePath
166
164
167
165
if ( ! relativePath . relativePath ) {
168
- this . docGenerationTask . folderLevel = 'ENTIRE_WORKSPACE'
166
+ docGenerationTask . folderLevel = 'ENTIRE_WORKSPACE'
169
167
} else {
170
- this . docGenerationTask . folderLevel = 'SUB_FOLDER'
168
+ docGenerationTask . folderLevel = 'SUB_FOLDER'
171
169
}
172
170
}
173
171
174
172
this . messenger . sendFolderConfirmationMessage (
175
173
data . tabID ,
176
- this . mode === Mode . CREATE
174
+ docGenerationTask . mode === Mode . CREATE
177
175
? i18n ( 'AWS.amazonq.doc.answer.createReadme' )
178
176
: i18n ( 'AWS.amazonq.doc.answer.updateReadme' ) ,
179
177
displayPath ,
@@ -218,6 +216,7 @@ export class DocController {
218
216
private initializeFollowUps ( ) : void {
219
217
this . chatControllerMessageListeners . followUpClicked . event ( async ( data ) => {
220
218
const session : Session = await this . sessionStorage . getSession ( data . tabID )
219
+ const docGenerationTask = this . docGenerationTasks . getTask ( data . tabID )
221
220
222
221
const workspaceFolders = vscode . workspace . workspaceFolders
223
222
if ( workspaceFolders === undefined || workspaceFolders . length === 0 ) {
@@ -245,7 +244,7 @@ export class DocController {
245
244
246
245
switch ( data . followUp . type ) {
247
246
case FollowUpTypes . Retry :
248
- if ( this . mode === Mode . EDIT ) {
247
+ if ( docGenerationTask . mode === Mode . EDIT ) {
249
248
this . enableUserInput ( data ?. tabID )
250
249
} else {
251
250
await this . tabOpened ( data )
@@ -262,19 +261,19 @@ export class DocController {
262
261
case FollowUpTypes . CloseSession :
263
262
return this . closeSession ( data )
264
263
case FollowUpTypes . CreateDocumentation :
265
- this . docGenerationTask . interactionType = 'GENERATE_README'
266
- this . mode = Mode . CREATE
264
+ docGenerationTask . interactionType = 'GENERATE_README'
265
+ docGenerationTask . mode = Mode . CREATE
267
266
sendFolderConfirmationMessage ( i18n ( 'AWS.amazonq.doc.answer.createReadme' ) )
268
267
break
269
268
case FollowUpTypes . ChooseFolder :
270
269
await this . folderSelector ( data )
271
270
break
272
271
case FollowUpTypes . SynchronizeDocumentation :
273
- this . mode = Mode . SYNC
272
+ docGenerationTask . mode = Mode . SYNC
274
273
sendFolderConfirmationMessage ( i18n ( 'AWS.amazonq.doc.answer.updateReadme' ) )
275
274
break
276
275
case FollowUpTypes . UpdateDocumentation :
277
- this . docGenerationTask . interactionType = 'UPDATE_README'
276
+ docGenerationTask . interactionType = 'UPDATE_README'
278
277
this . messenger . sendAnswer ( {
279
278
type : 'answer' ,
280
279
tabID : data ?. tabID ,
@@ -283,21 +282,21 @@ export class DocController {
283
282
} )
284
283
break
285
284
case FollowUpTypes . EditDocumentation :
286
- this . docGenerationTask . interactionType = 'EDIT_README'
287
- this . mode = Mode . EDIT
285
+ docGenerationTask . interactionType = 'EDIT_README'
286
+ docGenerationTask . mode = Mode . EDIT
288
287
sendFolderConfirmationMessage ( i18n ( 'AWS.amazonq.doc.answer.updateReadme' ) )
289
288
break
290
289
case FollowUpTypes . MakeChanges :
291
- this . mode = Mode . EDIT
290
+ docGenerationTask . mode = Mode . EDIT
292
291
this . enableUserInput ( data . tabID )
293
292
break
294
293
case FollowUpTypes . AcceptChanges :
295
- this . docGenerationTask . userDecision = 'ACCEPT'
294
+ docGenerationTask . userDecision = 'ACCEPT'
296
295
await this . sendDocAcceptanceEvent ( data )
297
296
await this . insertCode ( data )
298
297
return
299
298
case FollowUpTypes . RejectChanges :
300
- this . docGenerationTask . userDecision = 'REJECT'
299
+ docGenerationTask . userDecision = 'REJECT'
301
300
await this . sendDocAcceptanceEvent ( data )
302
301
this . messenger . sendAnswer ( {
303
302
type : 'answer' ,
@@ -309,26 +308,27 @@ export class DocController {
309
308
break
310
309
case FollowUpTypes . ProceedFolderSelection :
311
310
// If a user did not change the folder in a multi-root workspace, default to the first workspace folder
312
- if ( this . folderPath === '' && isMultiRootWorkspace ( ) ) {
313
- this . folderPath = workspaceFolderName
311
+ if ( docGenerationTask . folderPath === '' && isMultiRootWorkspace ( ) ) {
312
+ docGenerationTask . folderPath = workspaceFolderName
314
313
}
315
- if ( this . mode === Mode . EDIT ) {
314
+ if ( docGenerationTask . mode === Mode . EDIT ) {
316
315
this . enableUserInput ( data . tabID )
317
316
} else {
318
- await this . generateDocumentation ( {
319
- message : {
317
+ await this . generateDocumentation (
318
+ {
320
319
...data ,
321
320
message :
322
- this . mode === Mode . CREATE
321
+ docGenerationTask . mode === Mode . CREATE
323
322
? 'Create documentation for a specific folder'
324
323
: 'Sync documentation' ,
325
324
} ,
326
325
session ,
327
- } )
326
+ docGenerationTask
327
+ )
328
328
}
329
329
break
330
330
case FollowUpTypes . CancelFolderSelection :
331
- this . docGenerationTask . folderLevel = 'ENTIRE_WORKSPACE'
331
+ docGenerationTask . reset ( )
332
332
return this . tabOpened ( data )
333
333
}
334
334
} )
@@ -383,7 +383,8 @@ export class DocController {
383
383
384
384
private async newTask ( message : any ) {
385
385
// Old session for the tab is ending, delete it so we can create a new one for the message id
386
- this . docGenerationTask = new DocGenerationTask ( )
386
+
387
+ this . docGenerationTasks . deleteTask ( message . tabID )
387
388
this . sessionStorage . deleteSession ( message . tabID )
388
389
389
390
// Re-run the opening flow, where we check auth + create a session
@@ -399,18 +400,22 @@ export class DocController {
399
400
} )
400
401
this . messenger . sendUpdatePlaceholder ( message . tabID , i18n ( 'AWS.amazonq.featureDev.placeholder.sessionClosed' ) )
401
402
this . messenger . sendChatInputEnabled ( message . tabID , false )
402
-
403
- this . docGenerationTask . reset ( )
403
+ this . docGenerationTasks . deleteTask ( message . tabID )
404
404
}
405
405
406
- private processErrorChatMessage = ( err : any , message : any , session : Session | undefined ) => {
406
+ private processErrorChatMessage = (
407
+ err : any ,
408
+ message : any ,
409
+ session : Session | undefined ,
410
+ docGenerationTask : DocGenerationTask
411
+ ) => {
407
412
const errorMessage = createUserFacingErrorMessage ( `${ err . cause ?. message ?? err . message } ` )
408
413
// eslint-disable-next-line unicorn/no-null
409
414
this . messenger . sendUpdatePromptProgress ( message . tabID , null )
410
415
if ( err . constructor . name === MonthlyConversationLimitError . name ) {
411
416
this . messenger . sendMonthlyLimitError ( message . tabID )
412
417
} else {
413
- const enableUserInput = this . mode === Mode . EDIT && err . remainingIterations > 0
418
+ const enableUserInput = docGenerationTask . mode === Mode . EDIT && err . remainingIterations > 0
414
419
415
420
this . messenger . sendErrorMessage (
416
421
errorMessage ,
@@ -423,11 +428,11 @@ export class DocController {
423
428
}
424
429
}
425
430
426
- private async generateDocumentation ( { message, session } : { message : any ; session : any } ) {
431
+ private async generateDocumentation ( message : any , session : any , docGenerationTask : DocGenerationTask ) {
427
432
try {
428
- await this . onDocsGeneration ( session , message . message , message . tabID )
433
+ await this . onDocsGeneration ( session , message . message , message . tabID , docGenerationTask )
429
434
} catch ( err : any ) {
430
- this . processErrorChatMessage ( err , message , session )
435
+ this . processErrorChatMessage ( err , message , session , docGenerationTask )
431
436
}
432
437
}
433
438
@@ -448,6 +453,7 @@ export class DocController {
448
453
}
449
454
450
455
const session : Session = await this . sessionStorage . getSession ( message . tabID )
456
+ const docGenerationTask = this . docGenerationTasks . getTask ( message . tabID )
451
457
452
458
try {
453
459
getLogger ( ) . debug ( `${ featureName } : Processing message: ${ message . message } ` )
@@ -459,9 +465,9 @@ export class DocController {
459
465
return
460
466
}
461
467
462
- await this . generateDocumentation ( { message, session } )
468
+ await this . generateDocumentation ( message , session , docGenerationTask )
463
469
} catch ( err : any ) {
464
- this . processErrorChatMessage ( err , message , session )
470
+ this . processErrorChatMessage ( err , message , session , docGenerationTask )
465
471
}
466
472
}
467
473
@@ -483,17 +489,18 @@ export class DocController {
483
489
let session : Session | undefined
484
490
try {
485
491
session = await this . sessionStorage . getSession ( message . tabID )
492
+ const docGenerationTask = this . docGenerationTasks . getTask ( message . tabID )
486
493
getLogger ( ) . debug ( `${ featureName } : Session created with id: ${ session . tabID } ` )
487
- this . folderPath = ''
488
- this . mode = Mode . NONE
494
+ docGenerationTask . folderPath = ''
495
+ docGenerationTask . mode = Mode . NONE
489
496
490
497
const authState = await AuthUtil . instance . getChatAuthState ( )
491
498
if ( authState . amazonQ !== 'connected' ) {
492
499
void this . messenger . sendAuthNeededExceptionMessage ( authState , message . tabID )
493
500
session . isAuthenticating = true
494
501
return
495
502
}
496
- this . docGenerationTask . numberOfNavigations += 1
503
+ docGenerationTask . numberOfNavigations += 1
497
504
this . messenger . sendAnswer ( {
498
505
type : 'answer' ,
499
506
tabID : message . tabID ,
@@ -536,13 +543,18 @@ export class DocController {
536
543
await vscode . commands . executeCommand ( 'markdown.showPreview' )
537
544
}
538
545
539
- private async onDocsGeneration ( session : Session , message : string , tabID : string ) {
540
- this . messenger . sendDocProgress ( tabID , DocGenerationStep . UPLOAD_TO_S3 , 0 , this . mode )
546
+ private async onDocsGeneration (
547
+ session : Session ,
548
+ message : string ,
549
+ tabID : string ,
550
+ docGenerationTask : DocGenerationTask
551
+ ) {
552
+ this . messenger . sendDocProgress ( tabID , DocGenerationStep . UPLOAD_TO_S3 , 0 , docGenerationTask . mode )
541
553
542
554
await session . preloader ( message )
543
555
544
556
try {
545
- await session . send ( message , this . mode , this . folderPath )
557
+ await session . send ( message , docGenerationTask . mode , docGenerationTask . folderPath )
546
558
const filePaths = session . state . filePaths ?? [ ]
547
559
const deletedFiles = session . state . deletedFiles ?? [ ]
548
560
@@ -585,7 +597,7 @@ export class DocController {
585
597
this . messenger . sendAnswer ( {
586
598
type : 'answer' ,
587
599
tabID : tabID ,
588
- message : `${ this . mode === Mode . CREATE ? i18n ( 'AWS.amazonq.doc.answer.readmeCreated' ) : i18n ( 'AWS.amazonq.doc.answer.readmeUpdated' ) } ${ remainingIterations > 0 ? i18n ( 'AWS.amazonq.doc.answer.codeResult' ) : i18n ( 'AWS.amazonq.doc.answer.acceptOrReject' ) } ` ,
600
+ message : `${ docGenerationTask . mode === Mode . CREATE ? i18n ( 'AWS.amazonq.doc.answer.readmeCreated' ) : i18n ( 'AWS.amazonq.doc.answer.readmeUpdated' ) } ${ remainingIterations > 0 ? i18n ( 'AWS.amazonq.doc.answer.codeResult' ) : i18n ( 'AWS.amazonq.doc.answer.acceptOrReject' ) } ` ,
589
601
disableChatInput : true ,
590
602
} )
591
603
@@ -601,13 +613,14 @@ export class DocController {
601
613
} )
602
614
}
603
615
if ( session ?. state . phase === DevPhase . CODEGEN ) {
616
+ const docGenerationTask = this . docGenerationTasks . getTask ( tabID )
604
617
const { totalGeneratedChars, totalGeneratedLines, totalGeneratedFiles } =
605
- await session . countGeneratedContent ( this . docGenerationTask . interactionType )
606
- this . docGenerationTask . conversationId = session . conversationId
607
- this . docGenerationTask . numberOfGeneratedChars = totalGeneratedChars
608
- this . docGenerationTask . numberOfGeneratedLines = totalGeneratedLines
609
- this . docGenerationTask . numberOfGeneratedFiles = totalGeneratedFiles
610
- const docGenerationEvent = this . docGenerationTask . docGenerationEventBase ( )
618
+ await session . countGeneratedContent ( docGenerationTask . interactionType )
619
+ docGenerationTask . conversationId = session . conversationId
620
+ docGenerationTask . numberOfGeneratedChars = totalGeneratedChars
621
+ docGenerationTask . numberOfGeneratedLines = totalGeneratedLines
622
+ docGenerationTask . numberOfGeneratedFiles = totalGeneratedFiles
623
+ const docGenerationEvent = docGenerationTask . docGenerationEventBase ( )
611
624
612
625
await session . sendDocTelemetryEvent ( docGenerationEvent , 'generation' )
613
626
}
@@ -635,6 +648,7 @@ export class DocController {
635
648
636
649
private tabClosed ( message : any ) {
637
650
this . sessionStorage . deleteSession ( message . tabID )
651
+ this . docGenerationTasks . deleteTask ( message . tabID )
638
652
}
639
653
640
654
private async insertCode ( message : any ) {
@@ -670,14 +684,15 @@ export class DocController {
670
684
}
671
685
private async sendDocAcceptanceEvent ( message : any ) {
672
686
const session = await this . sessionStorage . getSession ( message . tabID )
673
- this . docGenerationTask . conversationId = session . conversationId
687
+ const docGenerationTask = this . docGenerationTasks . getTask ( message . tabID )
688
+ docGenerationTask . conversationId = session . conversationId
674
689
const { totalAddedChars, totalAddedLines, totalAddedFiles } = await session . countAddedContent (
675
- this . docGenerationTask . interactionType
690
+ docGenerationTask . interactionType
676
691
)
677
- this . docGenerationTask . numberOfAddedChars = totalAddedChars
678
- this . docGenerationTask . numberOfAddedLines = totalAddedLines
679
- this . docGenerationTask . numberOfAddedFiles = totalAddedFiles
680
- const docAcceptanceEvent = this . docGenerationTask . docAcceptanceEventBase ( )
692
+ docGenerationTask . numberOfAddedChars = totalAddedChars
693
+ docGenerationTask . numberOfAddedLines = totalAddedLines
694
+ docGenerationTask . numberOfAddedFiles = totalAddedFiles
695
+ const docAcceptanceEvent = docGenerationTask . docAcceptanceEventBase ( )
681
696
682
697
await session . sendDocTelemetryEvent ( docAcceptanceEvent , 'acceptance' )
683
698
}
0 commit comments