@@ -47,6 +47,29 @@ export class SessionDiscovery {
4747 }
4848 }
4949
50+ /**
51+ * Run async tasks with bounded concurrency to avoid saturating the extension host.
52+ */
53+ private async runWithConcurrency < T > (
54+ items : T [ ] ,
55+ fn : ( item : T , index : number ) => Promise < void > ,
56+ limit = 8
57+ ) : Promise < void > {
58+ if ( items . length === 0 ) { return ; }
59+ let index = 0 ;
60+ const workers = Array . from ( { length : Math . min ( limit , items . length ) } , async ( ) => {
61+ while ( index < items . length ) {
62+ const i = index ++ ;
63+ try {
64+ await fn ( items [ i ] , i ) ;
65+ } catch ( error ) {
66+ this . deps . warn ( `Failed to process session discovery item at index ${ i } : ${ error instanceof Error ? error . message : String ( error ) } ` ) ;
67+ }
68+ }
69+ } ) ;
70+ await Promise . all ( workers ) ;
71+ }
72+
5073 /**
5174 * Get all possible VS Code user data paths for all VS Code variants
5275 * Supports: Code (stable), Code - Insiders, VSCodium, remote servers, etc.
@@ -249,16 +272,16 @@ export class SessionDiscovery {
249272 }
250273
251274 try {
252- // Scan all found VS Code paths for session files — process all variants in parallel
253- await Promise . all ( foundPaths . map ( async ( codeUserPath ) => {
275+ // Scan all found VS Code paths for session files with bounded concurrency.
276+ await this . runWithConcurrency ( foundPaths , async ( codeUserPath ) => {
254277 const pathName = path . basename ( path . dirname ( codeUserPath ) ) ;
255278
256- // Workspace storage sessions — scan all workspace dirs in parallel
279+ // Workspace storage sessions — also bounded to avoid spawning hundreds of FS ops at once.
257280 const workspaceStoragePath = path . join ( codeUserPath , 'workspaceStorage' ) ;
258281 try {
259282 if ( await this . pathExists ( workspaceStoragePath ) ) {
260283 const workspaceDirs = await fs . promises . readdir ( workspaceStoragePath ) ;
261- await Promise . all ( workspaceDirs . map ( async ( workspaceDir ) => {
284+ await this . runWithConcurrency ( workspaceDirs , async ( workspaceDir ) => {
262285 const chatSessionsPath = path . join ( workspaceStoragePath , workspaceDir , 'chatSessions' ) ;
263286 try {
264287 if ( await this . pathExists ( chatSessionsPath ) ) {
@@ -273,7 +296,7 @@ export class SessionDiscovery {
273296 } catch {
274297 // Ignore individual workspace dir errors
275298 }
276- } ) ) ;
299+ } , 6 ) ;
277300 }
278301 } catch ( checkError ) {
279302 this . deps . warn ( `Could not check workspace storage path ${ workspaceStoragePath } : ${ checkError } ` ) ;
@@ -305,7 +328,7 @@ export class SessionDiscovery {
305328 } catch ( checkError ) {
306329 this . deps . warn ( `Could not check Copilot Chat global storage path ${ copilotChatGlobalPath } : ${ checkError } ` ) ;
307330 }
308- } ) ) ;
331+ } , 4 ) ;
309332
310333 // Check for Copilot CLI session-state directory (new location for agent mode sessions)
311334 const copilotCliSessionPath = path . join ( os . homedir ( ) , '.copilot' , 'session-state' ) ;
0 commit comments