@@ -612,16 +612,41 @@ class CopilotTokenTracker implements vscode.Disposable {
612612 }
613613
614614 try {
615+ // Fast check: Get file stats first to avoid processing old files
615616 const fileStats = fs . statSync ( sessionFile ) ;
617+
618+ // Skip files modified before the current month (quick filter)
619+ // This is the main performance optimization - filters out old sessions without reading file content
620+ if ( fileStats . mtime < monthStart ) {
621+ skippedFiles ++ ;
622+ continue ;
623+ }
624+
625+ // For files within current month, check if data is cached to avoid redundant reads
626+ const mtime = fileStats . mtime . getTime ( ) ;
627+ const wasCached = this . isCacheValid ( sessionFile , mtime ) ;
628+
629+ // Get interactions count (uses cache if available)
630+ const interactions = await this . countInteractionsInSessionCached ( sessionFile , mtime ) ;
631+
632+ // Skip empty sessions (no interactions = just opened chat panel, no messages sent)
633+ if ( interactions === 0 ) {
634+ skippedFiles ++ ;
635+ continue ;
636+ }
637+
638+ // Get remaining data (all use cache if available)
639+ const tokens = await this . estimateTokensFromSessionCached ( sessionFile , mtime ) ;
640+ const modelUsage = await this . getModelUsageFromSessionCached ( sessionFile , mtime ) ;
641+ const editorType = this . getEditorTypeFromPath ( sessionFile ) ;
642+
643+ // For date filtering, get lastInteraction from session details
644+ const details = await this . getSessionFileDetails ( sessionFile ) ;
645+ const lastActivity = details . lastInteraction
646+ ? new Date ( details . lastInteraction )
647+ : new Date ( details . modified ) ;
616648
617- if ( fileStats . mtime >= monthStart ) {
618- // Check if data is cached before making calls
619- const wasCached = this . isCacheValid ( sessionFile , fileStats . mtime . getTime ( ) ) ;
620-
621- const tokens = await this . estimateTokensFromSessionCached ( sessionFile , fileStats . mtime . getTime ( ) ) ;
622- const interactions = await this . countInteractionsInSessionCached ( sessionFile , fileStats . mtime . getTime ( ) ) ;
623- const modelUsage = await this . getModelUsageFromSessionCached ( sessionFile , fileStats . mtime . getTime ( ) ) ;
624- const editorType = this . getEditorTypeFromPath ( sessionFile ) ;
649+ if ( lastActivity >= monthStart ) {
625650
626651 // Update cache statistics
627652 if ( wasCached ) {
@@ -650,7 +675,7 @@ class CopilotTokenTracker implements vscode.Disposable {
650675 monthStats . modelUsage [ model ] . outputTokens += usage . outputTokens ;
651676 }
652677
653- if ( fileStats . mtime >= todayStart ) {
678+ if ( lastActivity >= todayStart ) {
654679 todayStats . tokens += tokens ;
655680 todayStats . sessions += 1 ;
656681 todayStats . interactions += interactions ;
@@ -673,7 +698,7 @@ class CopilotTokenTracker implements vscode.Disposable {
673698 }
674699 }
675700 else {
676- // File is too old, skip it
701+ // Session is too old (no activity in current month) , skip it
677702 skippedFiles ++ ;
678703 }
679704 } catch ( fileError ) {
@@ -683,7 +708,7 @@ class CopilotTokenTracker implements vscode.Disposable {
683708
684709 this . log ( `✅ Analysis complete: Today ${ todayStats . sessions } sessions, Month ${ monthStats . sessions } sessions` ) ;
685710 if ( skippedFiles > 0 ) {
686- this . log ( `⏭️ Skipped ${ skippedFiles } session file(s) (too old, not in current month)` ) ;
711+ this . log ( `⏭️ Skipped ${ skippedFiles } session file(s) (empty or no activity in current month)` ) ;
687712 }
688713 const totalCacheAccesses = cacheHits + cacheMisses ;
689714 this . log ( `💾 Cache performance: ${ cacheHits } hits, ${ cacheMisses } misses (${ totalCacheAccesses > 0 ? ( ( cacheHits / totalCacheAccesses ) * 100 ) . toFixed ( 1 ) : 0 } % hit rate)` ) ;
@@ -3206,7 +3231,25 @@ class CopilotTokenTracker implements vscode.Disposable {
32063231 fourteenDaysAgo . setDate ( fourteenDaysAgo . getDate ( ) - 14 ) ;
32073232 const detailedSessionFiles : SessionFileDetails [ ] = [ ] ;
32083233
3209- for ( const file of sessionFiles . slice ( 0 , 500 ) ) {
3234+ // Sort files by modification time (most recent first) before taking first 500
3235+ // This ensures we prioritize recent sessions regardless of their folder location
3236+ const fileStats = await Promise . all (
3237+ sessionFiles . map ( async ( file ) => {
3238+ try {
3239+ const stat = await fs . promises . stat ( file ) ;
3240+ return { file, mtime : stat . mtime . getTime ( ) } ;
3241+ } catch {
3242+ return { file, mtime : 0 } ;
3243+ }
3244+ } )
3245+ ) ;
3246+
3247+ const sortedFiles = fileStats
3248+ . sort ( ( a , b ) => b . mtime - a . mtime )
3249+ . map ( item => item . file ) ;
3250+
3251+ // Process up to 500 most recent session files
3252+ for ( const file of sortedFiles . slice ( 0 , 500 ) ) {
32103253 // Check if panel was disposed
32113254 if ( ! panel . visible && panel . viewColumn === undefined ) {
32123255 this . log ( 'Diagnostic panel closed, stopping background load' ) ;
@@ -3215,11 +3258,7 @@ class CopilotTokenTracker implements vscode.Disposable {
32153258
32163259 try {
32173260 const details = await this . getSessionFileDetails ( file ) ;
3218- // Filter: skip empty sessions (no interactions = just opened chat panel, no messages sent)
3219- if ( details . interactions === 0 ) {
3220- continue ;
3221- }
3222- // Filter: only include sessions with activity in the last 14 days
3261+ // Only include sessions with activity (lastInteraction or file modified time) within the last 14 days
32233262 const lastActivity = details . lastInteraction
32243263 ? new Date ( details . lastInteraction )
32253264 : new Date ( details . modified ) ;
0 commit comments