55
66import * as vscode from 'vscode'
77import { getLogger } from '../../shared/logger/logger'
8- import { DiagnosticsMonitor , DiagnosticSnapshot } from './diagnostics/diagnosticsMonitor'
9- import { ProblemDetector , Problem , CategorizedProblems } from './diagnostics/problemDetector'
108import { ErrorContextFormatter , ErrorContext } from './diagnostics/errorContext'
119import { AutoDebugLspClient } from './lsp/autoDebugLspClient'
1210import { randomUUID } from '../../shared/crypto'
1311import { mapDiagnosticSeverity } from './shared/diagnosticUtils'
1412
1513export interface AutoDebugConfig {
1614 readonly enabled : boolean
17- readonly autoReportThreshold : number
18- readonly includedSources : string [ ]
1915 readonly excludedSources : string [ ]
2016 readonly severityFilter : ( 'error' | 'warning' | 'info' | 'hint' ) [ ]
21- readonly debounceMs : number
2217}
2318
24- export interface AutoDebugSession {
25- readonly id : string
26- readonly startTime : number
27- readonly baseline : DiagnosticSnapshot
28- readonly problems : Problem [ ]
29- readonly isActive : boolean
19+ export interface Problem {
20+ readonly uri : vscode . Uri
21+ readonly diagnostic : vscode . Diagnostic
22+ readonly severity : 'error' | 'warning' | 'info' | 'hint'
23+ readonly source : string
24+ readonly isNew : boolean
3025}
3126
3227/**
33- * Main controller for the Amazon Q Auto Debug system.
34- * Orchestrates diagnostic monitoring, problem detection, and AI-powered debugging assistance .
28+ * Simplified controller for Amazon Q Auto Debug system.
29+ * Focuses on context menu and quick fix functionality without workspace-wide monitoring .
3530 */
3631export class AutoDebugController implements vscode . Disposable {
3732 private readonly logger = getLogger ( 'amazonqLsp' )
38- private readonly diagnosticsMonitor : DiagnosticsMonitor
39- private readonly problemDetector : ProblemDetector
4033 private readonly errorFormatter : ErrorContextFormatter
4134 private readonly lspClient : AutoDebugLspClient
4235 private readonly disposables : vscode . Disposable [ ] = [ ]
4336
44- private currentSession : AutoDebugSession | undefined
4537 private config : AutoDebugConfig
4638
47- public readonly onProblemsDetected = new vscode . EventEmitter < Problem [ ] > ( )
48- public readonly onSessionStarted = new vscode . EventEmitter < AutoDebugSession > ( )
49- public readonly onSessionEnded = new vscode . EventEmitter < string > ( )
50-
5139 constructor ( config ?: Partial < AutoDebugConfig > , client ?: any , encryptionKey ?: Buffer ) {
5240 this . config = {
5341 enabled : true ,
54- autoReportThreshold : 1 , // Report when 1 or more errors detected
55- includedSources : [ ] , // Empty means include all
5642 excludedSources : [ 'spell-checker' ] , // Common sources to exclude
5743 severityFilter : [ 'error' ] , // Only auto-fix errors, not warnings
58- debounceMs : 500 , // Wait 0.5 seconds before auto-sending to avoid spam
5944 ...config ,
6045 }
6146
62- this . diagnosticsMonitor = new DiagnosticsMonitor ( )
63- this . problemDetector = new ProblemDetector ( )
6447 this . errorFormatter = new ErrorContextFormatter ( )
6548 this . lspClient = new AutoDebugLspClient ( client , encryptionKey )
66-
67- this . disposables . push (
68- this . diagnosticsMonitor ,
69- this . onProblemsDetected ,
70- this . onSessionStarted ,
71- this . onSessionEnded
72- )
73- }
74-
75- /**
76- * Starts a new auto debug session
77- */
78- public async startSession ( ) : Promise < AutoDebugSession > {
79- if ( this . currentSession ?. isActive ) {
80- await this . endSession ( )
81- }
82-
83- const baseline = await this . diagnosticsMonitor . captureBaseline ( )
84- const session : AutoDebugSession = {
85- id : this . generateSessionId ( ) ,
86- startTime : Date . now ( ) ,
87- baseline,
88- problems : [ ] ,
89- isActive : true ,
90- }
91-
92- this . currentSession = session
93- this . onSessionStarted . fire ( session )
94- return session
95- }
96-
97- /**
98- * Ends the current auto debug session
99- */
100- public async endSession ( ) : Promise < void > {
101- if ( ! this . currentSession ) {
102- return
103- }
104- const sessionId = this . currentSession . id
105- this . currentSession = undefined
106- this . onSessionEnded . fire ( sessionId )
107- }
108-
109- /**
110- * Gets the current active session
111- */
112- public getCurrentSession ( ) : AutoDebugSession | undefined {
113- return this . currentSession
114- }
115-
116- /**
117- * Manually triggers problem detection
118- */
119- public async detectProblems ( ) : Promise < Problem [ ] > {
120- if ( ! this . config . enabled ) {
121- return [ ]
122- }
123-
124- if ( ! this . currentSession ) {
125- await this . startSession ( )
126- }
127-
128- const currentDiagnostics = await this . diagnosticsMonitor . getCurrentDiagnostics ( false )
129- const currentSnapshot : DiagnosticSnapshot = {
130- diagnostics : currentDiagnostics ,
131- captureTime : Date . now ( ) ,
132- id : this . generateSnapshotId ( ) ,
133- }
134-
135- const newProblems = this . problemDetector . detectNewProblems ( this . currentSession ! . baseline , currentSnapshot )
136-
137- const filteredProblems = this . filterProblems ( newProblems )
138-
139- if ( filteredProblems . length > 0 ) {
140- this . onProblemsDetected . fire ( filteredProblems )
141- }
142-
143- return filteredProblems
14449 }
14550
14651 /**
@@ -168,17 +73,6 @@ export class AutoDebugController implements vscode.Disposable {
16873 return this . errorFormatter . formatProblemsString ( problems , cwd )
16974 }
17075
171- /**
172- * Gets categorized problems from the current session
173- */
174- public getCategorizedProblems ( ) : CategorizedProblems | undefined {
175- if ( ! this . currentSession ) {
176- return undefined
177- }
178-
179- return this . problemDetector . categorizeBySeverity ( this . currentSession . problems )
180- }
181-
18276 /**
18377 * Gets the current configuration
18478 */
@@ -207,13 +101,6 @@ export class AutoDebugController implements vscode.Disposable {
207101 await this . sendMessageToChat ( message )
208102 }
209103
210- /**
211- * Marks that Amazon Q has responded (called when response is received)
212- */
213- public markAmazonQResponse ( ) : void {
214- this . logger . debug ( 'AutoDebugController: Amazon Q response received' )
215- }
216-
217104 /**
218105 * Fix with Amazon Q - sends up to 15 error messages one time when user clicks the button
219106 */
@@ -228,16 +115,20 @@ export class AutoDebugController implements vscode.Disposable {
228115 const fileName = editor . document . fileName
229116
230117 try {
231- // Start session if not active
232- if ( ! this . currentSession ) {
233- await this . startSession ( )
234- }
235-
236118 // Get all diagnostics for the current file
237119 const allDiagnostics = vscode . languages . getDiagnostics ( editor . document . uri )
238120
239- // Filter to only errors (not warnings/info)
240- const errorDiagnostics = allDiagnostics . filter ( ( d ) => d . severity === vscode . DiagnosticSeverity . Error )
121+ // Filter to only errors (not warnings/info) and apply source filtering
122+ const errorDiagnostics = allDiagnostics . filter ( ( d ) => {
123+ if ( d . severity !== vscode . DiagnosticSeverity . Error ) {
124+ return false
125+ }
126+ // Apply source filtering
127+ if ( this . config . excludedSources . length > 0 && d . source ) {
128+ return ! this . config . excludedSources . includes ( d . source )
129+ }
130+ return true
131+ } )
241132
242133 if ( errorDiagnostics . length === 0 ) {
243134 void vscode . window . showInformationMessage ( `✅ No errors found in ${ fileName } ` )
@@ -246,8 +137,7 @@ export class AutoDebugController implements vscode.Disposable {
246137
247138 // Take up to maxProblems errors (15 by default)
248139 const diagnosticsToFix = errorDiagnostics . slice ( 0 , maxProblems )
249- const totalErrors = errorDiagnostics . length
250- const errorsBeingSent = diagnosticsToFix . length
140+
251141 // Convert diagnostics to problems
252142 const problems = diagnosticsToFix . map ( ( diagnostic ) => ( {
253143 uri : editor . document . uri ,
@@ -257,34 +147,15 @@ export class AutoDebugController implements vscode.Disposable {
257147 isNew : false ,
258148 } ) )
259149
260- // Get the code range that covers all the errors
261- const problemRange = this . getProblemsRange ( problems )
262- const codeWithErrors = editor . document . getText ( problemRange )
263- const languageId = editor . document . languageId
264-
265150 // Create fix message
266- const fixMessage = this . createFixMessage (
267- codeWithErrors ,
268- filePath ,
269- languageId ,
270- problems ,
271- totalErrors ,
272- errorsBeingSent
273- )
151+ const fixMessage = this . createFixMessage ( filePath , problems )
274152 await this . sendChatMessage ( fixMessage , 'singleFix' )
275153 } catch ( error ) {
276154 this . logger . error ( 'AutoDebugController: Error in fix process: %s' , error )
277155 }
278156 }
279157
280- private createFixMessage (
281- selectedText : string ,
282- filePath : string ,
283- languageId : string ,
284- problems : any [ ] ,
285- totalErrors : number ,
286- errorsBeingSent : number
287- ) : string {
158+ private createFixMessage ( filePath : string , problems : Problem [ ] ) : string {
288159 const parts = [ `Please help me fix the following errors in ${ filePath } ` ]
289160
290161 for ( const problem of problems ) {
@@ -327,105 +198,8 @@ export class AutoDebugController implements vscode.Disposable {
327198 }
328199 }
329200
330- /**
331- * Automatically fixes problems using the language server
332- */
333- public async autoFixProblems ( problems : Problem [ ] , filePath : string , autoApply : boolean = false ) : Promise < boolean > {
334- try {
335- // Get file content
336- const document = await vscode . workspace . openTextDocument ( vscode . Uri . file ( filePath ) )
337- const fileContent = document . getText ( )
338-
339- // Create error contexts
340- const errorContexts = await this . createErrorContexts ( problems )
341-
342- // Request fixes from language server
343- const fixResult = await this . lspClient . requestAutoFix ( {
344- problems,
345- errorContexts,
346- filePath,
347- fileContent,
348- autoApply,
349- } )
350-
351- if ( ! fixResult . success ) {
352- this . logger . error ( 'AutoDebugController: Auto-fix failed: %s' , fixResult . error )
353- return false
354- }
355-
356- if ( fixResult . fixes . length === 0 ) {
357- this . logger . debug ( 'AutoDebugController: No fixes generated' )
358- return false
359- }
360-
361- this . logger . debug ( 'AutoDebugController: Generated %d fixes' , fixResult . fixes . length )
362- return false
363- } catch ( error ) {
364- this . logger . error ( 'AutoDebugController: Error during auto-fix: %s' , error )
365- return false
366- }
367- }
368-
369- /**
370- * Gets the range that encompasses all problems
371- */
372- private getProblemsRange ( problems : Problem [ ] ) : vscode . Range {
373- if ( problems . length === 0 ) {
374- return new vscode . Range ( 0 , 0 , 0 , 0 )
375- }
376-
377- let startLine = problems [ 0 ] . diagnostic . range . start . line
378- let endLine = problems [ 0 ] . diagnostic . range . end . line
379-
380- for ( const problem of problems ) {
381- startLine = Math . min ( startLine , problem . diagnostic . range . start . line )
382- endLine = Math . max ( endLine , problem . diagnostic . range . end . line )
383- }
384-
385- // Add some context lines around the errors
386- const contextLines = 3
387- startLine = Math . max ( 0 , startLine - contextLines )
388- endLine = endLine + contextLines
389-
390- return new vscode . Range ( startLine , 0 , endLine , 0 )
391- }
392-
393- private filterProblems ( problems : Problem [ ] ) : Problem [ ] {
394- let filtered = problems
395-
396- // Filter by severity
397- filtered = filtered . filter ( ( problem ) => this . config . severityFilter . includes ( problem . severity ) )
398-
399- // Filter by included sources
400- if ( this . config . includedSources . length > 0 ) {
401- filtered = filtered . filter ( ( problem ) => this . config . includedSources . includes ( problem . source ) )
402- }
403-
404- // Filter out excluded sources
405- if ( this . config . excludedSources . length > 0 ) {
406- filtered = filtered . filter ( ( problem ) => ! this . config . excludedSources . includes ( problem . source ) )
407- }
408-
409- return filtered
410- }
411-
412- private generateSessionId ( ) : string {
413- return `session_${ Date . now ( ) } _${ Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) } `
414- }
415-
416- private generateSnapshotId ( ) : string {
417- return `snapshot_${ Date . now ( ) } _${ Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) } `
418- }
419-
420201 public dispose ( ) : void {
421202 this . logger . debug ( 'AutoDebugController: Disposing auto debug controller' )
422-
423- if ( this . currentSession ) {
424- this . endSession ( ) . catch ( ( error ) => {
425- this . logger . error ( 'AutoDebugController: Error ending session during disposal: %s' , error )
426- } )
427- }
428-
429203 vscode . Disposable . from ( ...this . disposables ) . dispose ( )
430204 }
431205}
0 commit comments