@@ -15,6 +15,7 @@ import { logger } from "../../utils/logging"
1515import { GlobalFileNames } from "../../shared/globalFileNames"
1616import { ensureSettingsDirectoryExists } from "../../utils/globalContext"
1717import { t } from "../../i18n"
18+ import { ModeFamiliesManager } from "./ModeFamiliesManager"
1819
1920const ROOMODES_FILENAME = ".roomodes"
2021
@@ -55,6 +56,7 @@ export class CustomModesManager {
5556 constructor (
5657 private readonly context : vscode . ExtensionContext ,
5758 private readonly onUpdate : ( ) => Promise < void > ,
59+ private readonly modeFamiliesManager ?: ModeFamiliesManager ,
5860 ) {
5961 this . watchCustomModesFiles ( ) . catch ( ( error ) => {
6062 console . error ( "[CustomModesManager] Failed to setup file watchers:" , error )
@@ -356,6 +358,10 @@ export class CustomModesManager {
356358 // Check if we have a valid cached result.
357359 const now = Date . now ( )
358360
361+ // Include active family ID in cache key for proper invalidation
362+ const activeFamilyId = this . modeFamiliesManager ? await this . modeFamiliesManager . getActiveFamily ( ) . then ( f => f ?. id || null ) : null
363+ const cacheKey = `customModes:${ activeFamilyId } `
364+
359365 if ( this . cachedModes && now - this . cachedAt < CustomModesManager . cacheTTL ) {
360366 return this . cachedModes
361367 }
@@ -394,10 +400,22 @@ export class CustomModesManager {
394400
395401 await this . context . globalState . update ( "customModes" , mergedModes )
396402
397- this . cachedModes = mergedModes
403+ // Apply family filtering if ModeFamiliesManager is available
404+ let filteredModes = mergedModes
405+ if ( this . modeFamiliesManager ) {
406+ try {
407+ filteredModes = await this . modeFamiliesManager . getFilteredModes ( mergedModes )
408+ } catch ( error ) {
409+ console . error ( "[CustomModesManager] Error filtering modes by family:" , error )
410+ // Fall back to returning all modes if filtering fails
411+ filteredModes = mergedModes
412+ }
413+ }
414+
415+ this . cachedModes = filteredModes
398416 this . cachedAt = now
399417
400- return mergedModes
418+ return filteredModes
401419 }
402420
403421 public async updateCustomMode ( slug : string , config : ModeConfig ) : Promise < void > {
@@ -1002,6 +1020,95 @@ export class CustomModesManager {
10021020 this . cachedAt = 0
10031021 }
10041022
1023+ /**
1024+ * Clear cache when family changes occur
1025+ * This ensures that mode filtering updates when families are modified
1026+ */
1027+ public clearCacheForFamilyChange ( ) : void {
1028+ this . clearCache ( )
1029+ }
1030+
1031+ /**
1032+ * Get all modes without family filtering (bypasses family restrictions)
1033+ * This is useful for administrative operations or when all modes are needed
1034+ */
1035+ public async getAllModes ( ) : Promise < ModeConfig [ ] > {
1036+ // Check if we have a valid cached result for all modes.
1037+ const now = Date . now ( )
1038+ const cacheKey = "allModes"
1039+
1040+ if ( this . cachedModes && now - this . cachedAt < CustomModesManager . cacheTTL ) {
1041+ return this . cachedModes
1042+ }
1043+
1044+ // Get modes from settings file.
1045+ const settingsPath = await this . getCustomModesFilePath ( )
1046+ const settingsModes = await this . loadModesFromFile ( settingsPath )
1047+
1048+ // Get modes from .roomodes if it exists.
1049+ const roomodesPath = await this . getWorkspaceRoomodes ( )
1050+ const roomodesModes = roomodesPath ? await this . loadModesFromFile ( roomodesPath ) : [ ]
1051+
1052+ // Create maps to store modes by source.
1053+ const projectModes = new Map < string , ModeConfig > ( )
1054+ const globalModes = new Map < string , ModeConfig > ( )
1055+
1056+ // Add project modes (they take precedence).
1057+ for ( const mode of roomodesModes ) {
1058+ projectModes . set ( mode . slug , { ...mode , source : "project" as const } )
1059+ }
1060+
1061+ // Add global modes.
1062+ for ( const mode of settingsModes ) {
1063+ if ( ! projectModes . has ( mode . slug ) ) {
1064+ globalModes . set ( mode . slug , { ...mode , source : "global" as const } )
1065+ }
1066+ }
1067+
1068+ // Combine modes in the correct order: project modes first, then global modes.
1069+ const mergedModes = [
1070+ ...roomodesModes . map ( ( mode ) => ( { ...mode , source : "project" as const } ) ) ,
1071+ ...settingsModes
1072+ . filter ( ( mode ) => ! projectModes . has ( mode . slug ) )
1073+ . map ( ( mode ) => ( { ...mode , source : "global" as const } ) ) ,
1074+ ]
1075+
1076+ await this . context . globalState . update ( "customModes" , mergedModes )
1077+
1078+ this . cachedModes = mergedModes
1079+ this . cachedAt = now
1080+
1081+ return mergedModes
1082+ }
1083+
1084+ /**
1085+ * Check if family filtering is currently active
1086+ */
1087+ public isFamilyFilteringActive ( ) : boolean {
1088+ return this . modeFamiliesManager !== undefined
1089+ }
1090+
1091+ /**
1092+ * Get the current active family information if family filtering is enabled
1093+ */
1094+ public async getActiveFamilyInfo ( ) : Promise < { isActive : boolean ; familyName ?: string ; familyId ?: string } > {
1095+ if ( ! this . modeFamiliesManager ) {
1096+ return { isActive : false }
1097+ }
1098+
1099+ try {
1100+ const activeFamily = await this . modeFamiliesManager . getActiveFamily ( )
1101+ return {
1102+ isActive : ! ! activeFamily ,
1103+ familyName : activeFamily ?. name ,
1104+ familyId : activeFamily ?. id ,
1105+ }
1106+ } catch ( error ) {
1107+ console . error ( "[CustomModesManager] Error getting active family info:" , error )
1108+ return { isActive : false }
1109+ }
1110+ }
1111+
10051112 dispose ( ) : void {
10061113 for ( const disposable of this . disposables ) {
10071114 disposable . dispose ( )
0 commit comments