@@ -431,46 +431,53 @@ class CopilotTokenTracker implements vscode.Disposable {
431431 } ) ;
432432 }
433433 } else if ( scanMode === 'oneLevel' ) {
434- // Find the first '*' segment to determine base directory
435- // Treat oneLevel as: enumerate a single directory and glob-match within it.
434+ // Split at the first '*' wildcard to find base directory and remaining path
435+ // e.g., ".github/skills/*/SKILL.md" -> base: ".github/skills/", remaining: "/SKILL.md"
436436 const normalizedPattern = relativePattern . replace ( / \\ / g, '/' ) ;
437- const segments = normalizedPattern . split ( '/' ) . filter ( s => s . length > 0 ) ;
438- if ( segments . length === 0 ) { continue ; }
437+ const starIndex = normalizedPattern . indexOf ( '*' ) ;
438+ if ( starIndex === - 1 ) { continue ; } // No wildcard, skip
439439
440- // The last segment is the filename glob (e.g., "*.md"); preceding segments form the base directory.
441- const filePattern = segments [ segments . length - 1 ] ;
442- const baseDirSegments = segments . slice ( 0 , segments . length - 1 ) ;
443- const baseDir = path . join ( workspaceFolderPath , ...baseDirSegments ) ;
440+ // Split the pattern at the '*'
441+ const beforeStar = normalizedPattern . substring ( 0 , starIndex ) ;
442+ const afterStar = normalizedPattern . substring ( starIndex + 1 ) ;
443+
444+ // The base directory is everything before the '*' (trim trailing slash)
445+ const baseDirPath = beforeStar . replace ( / \/ $ / , '' ) ;
446+ const baseDir = baseDirPath ? path . join ( workspaceFolderPath , baseDirPath ) : workspaceFolderPath ;
444447
445448 if ( ! fs . existsSync ( baseDir ) ) { continue ; }
446449 const baseStat = fs . statSync ( baseDir ) ;
447450 if ( ! baseStat . isDirectory ( ) ) { continue ; }
448451
449- // Convert simple glob pattern to a RegExp for matching file names.
450- const escaped = filePattern . replace ( / [ . + ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' ) ;
451- const regexSource = '^' + escaped . replace ( / \* / g, '.*' ) . replace ( / \? / g, '.' ) + '$' ;
452- const globRegex = new RegExp ( regexSource ) ;
453-
452+ // Enumerate directories in the base directory
454453 const entries = fs . readdirSync ( baseDir , { withFileTypes : true } ) ;
455454 for ( const entry of entries ) {
456- // Only consider files for oneLevel patterns.
457- if ( ! entry . isFile ( ) ) { continue ; }
458- // Directory exclusions are irrelevant for files but keep the check harmlessly.
459- if ( entry . isDirectory ( ) && excludeDirs . includes ( entry . name ) ) { continue ; }
460- if ( ! globRegex . test ( entry . name ) ) { continue ; }
461-
462- const absCandidate = path . join ( baseDir , entry . name ) ;
463- const stat = fs . statSync ( absCandidate ) ;
464- results . push ( {
465- path : absCandidate ,
466- relativePath : path . relative ( workspaceFolderPath , absCandidate ) . replace ( / \\ / g, '/' ) ,
467- type : pattern . type || 'unknown' ,
468- icon : pattern . icon || '' ,
469- label : pattern . label || path . basename ( absCandidate ) ,
470- name : path . basename ( absCandidate ) ,
471- lastModified : stat . mtime . toISOString ( ) ,
472- isStale : ( Date . now ( ) - stat . mtime . getTime ( ) ) > stalenessDays * 24 * 60 * 60 * 1000
473- } ) ;
455+ // Only consider directories at this level (unless afterStar is just a filename)
456+ if ( excludeDirs . includes ( entry . name ) ) { continue ; }
457+
458+ // Construct the full path with this entry replacing the '*'
459+ const fullPattern = afterStar . startsWith ( '/' ) ? afterStar . substring ( 1 ) : afterStar ;
460+ const candidatePath = path . join ( baseDir , entry . name , fullPattern ) ;
461+
462+ // Check if this path exists
463+ if ( fs . existsSync ( candidatePath ) ) {
464+ const stat = fs . statSync ( candidatePath ) ;
465+ if ( stat . isFile ( ) ) {
466+ // For skills, use the directory name (parent of SKILL.md) as the display name
467+ const displayName = pattern . type === 'skill' ? entry . name : path . basename ( candidatePath ) ;
468+
469+ results . push ( {
470+ path : candidatePath ,
471+ relativePath : path . relative ( workspaceFolderPath , candidatePath ) . replace ( / \\ / g, '/' ) ,
472+ type : pattern . type || 'unknown' ,
473+ icon : pattern . icon || '' ,
474+ label : pattern . label || displayName ,
475+ name : displayName ,
476+ lastModified : stat . mtime . toISOString ( ) ,
477+ isStale : ( Date . now ( ) - stat . mtime . getTime ( ) ) > stalenessDays * 24 * 60 * 60 * 1000
478+ } ) ;
479+ }
480+ }
474481 }
475482 } else if ( scanMode === 'recursive' ) {
476483 const maxDepth = typeof pattern . maxDepth === 'number' ? pattern . maxDepth : 6 ;
0 commit comments