Coverage for session_buddy / core / features.py: 100.00%

80 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-04 00:43 -0800

1"""Feature detection and availability checking. 

2 

3This module provides the FeatureDetector class for detecting available 

4features and dependencies in the runtime environment. 

5""" 

6 

7from __future__ import annotations 

8 

9import importlib.util 

10import logging 

11 

12logger = logging.getLogger(__name__) 

13 

14 

15class FeatureDetector: 

16 """Centralized feature detection for MCP server capabilities.""" 

17 

18 def __init__(self) -> None: 

19 """Initialize feature detector with all availability checks.""" 

20 self.SESSION_MANAGEMENT_AVAILABLE = self._check_session_management() 

21 self.REFLECTION_TOOLS_AVAILABLE = self._check_reflection_tools() 

22 self.ENHANCED_SEARCH_AVAILABLE = self._check_enhanced_search() 

23 self.UTILITY_FUNCTIONS_AVAILABLE = self._check_utility_functions() 

24 self.MULTI_PROJECT_AVAILABLE = self._check_multi_project() 

25 self.ADVANCED_SEARCH_AVAILABLE = self._check_advanced_search() 

26 self.CONFIG_AVAILABLE = self._check_config() 

27 self.AUTO_CONTEXT_AVAILABLE = self._check_auto_context() 

28 self.MEMORY_OPTIMIZER_AVAILABLE = self._check_memory_optimizer() 

29 self.APP_MONITOR_AVAILABLE = self._check_app_monitor() 

30 self.LLM_PROVIDERS_AVAILABLE = self._check_llm_providers() 

31 self.SERVERLESS_MODE_AVAILABLE = self._check_serverless_mode() 

32 self.CRACKERJACK_INTEGRATION_AVAILABLE = self._check_crackerjack() 

33 

34 @staticmethod 

35 def _check_session_management() -> bool: 

36 """Check if session management is available.""" 

37 try: 

38 import session_buddy.core 

39 

40 _ = ( 

41 session_buddy.core.session_manager 

42 ) # Reference to avoid unused import warning during static analysis 

43 return True 

44 except ImportError: 

45 return False 

46 

47 @staticmethod 

48 def _check_reflection_tools() -> bool: 

49 """Check if reflection tools are available.""" 

50 try: 

51 import session_buddy.reflection_tools 

52 

53 _ = ( 

54 session_buddy.reflection_tools 

55 ) # Use the import to avoid unused import warning 

56 return True 

57 except ImportError: 

58 return False 

59 

60 @staticmethod 

61 def _check_enhanced_search() -> bool: 

62 """Check if enhanced search is available.""" 

63 try: 

64 return importlib.util.find_spec("session_buddy.search_enhanced") is not None 

65 except ImportError: 

66 return False 

67 

68 @staticmethod 

69 def _check_utility_functions() -> bool: 

70 """Check if utility functions are available.""" 

71 try: 

72 # Check for the general module availability without importing unused functions 

73 return ( 

74 importlib.util.find_spec("session_buddy.tools.search_tools") is not None 

75 ) 

76 except ImportError: 

77 return False 

78 

79 @staticmethod 

80 def _check_multi_project() -> bool: 

81 """Check if multi-project coordination is available.""" 

82 try: 

83 return ( 

84 importlib.util.find_spec("session_buddy.multi_project_coordinator") 

85 is not None 

86 ) 

87 except ImportError: 

88 return False 

89 

90 @staticmethod 

91 def _check_advanced_search() -> bool: 

92 """Check if advanced search engine is available.""" 

93 try: 

94 return importlib.util.find_spec("session_buddy.advanced_search") is not None 

95 except ImportError: 

96 return False 

97 

98 @staticmethod 

99 def _check_config() -> bool: 

100 """Check if configuration management is available.""" 

101 try: 

102 return importlib.util.find_spec("session_buddy.settings") is not None 

103 except ImportError: 

104 return False 

105 

106 @staticmethod 

107 def _check_auto_context() -> bool: 

108 """Check if auto-context loading is available.""" 

109 try: 

110 return importlib.util.find_spec("session_buddy.context_manager") is not None 

111 except ImportError: 

112 return False 

113 

114 @staticmethod 

115 def _check_memory_optimizer() -> bool: 

116 """Check if memory optimizer is available.""" 

117 try: 

118 return ( 

119 importlib.util.find_spec("session_buddy.memory_optimizer") is not None 

120 ) 

121 except ImportError: 

122 return False 

123 

124 @staticmethod 

125 def _check_app_monitor() -> bool: 

126 """Check if application monitoring is available.""" 

127 try: 

128 return importlib.util.find_spec("session_buddy.app_monitor") is not None 

129 except ImportError: 

130 return False 

131 

132 @staticmethod 

133 def _check_llm_providers() -> bool: 

134 """Check if LLM providers are available.""" 

135 try: 

136 return importlib.util.find_spec("session_buddy.llm_providers") is not None 

137 except ImportError: 

138 return False 

139 

140 @staticmethod 

141 def _check_serverless_mode() -> bool: 

142 """Check if serverless mode is available.""" 

143 try: 

144 return importlib.util.find_spec("session_buddy.serverless_mode") is not None 

145 except ImportError: 

146 return False 

147 

148 @staticmethod 

149 def _check_crackerjack() -> bool: 

150 """Check if crackerjack integration is available.""" 

151 try: 

152 return ( 

153 importlib.util.find_spec("session_buddy.crackerjack_integration") 

154 is not None 

155 ) 

156 except ImportError: 

157 return False 

158 

159 def get_feature_flags(self) -> dict[str, bool]: 

160 """Get all feature flags as a dictionary.""" 

161 return { 

162 "SESSION_MANAGEMENT_AVAILABLE": self.SESSION_MANAGEMENT_AVAILABLE, 

163 "REFLECTION_TOOLS_AVAILABLE": self.REFLECTION_TOOLS_AVAILABLE, 

164 "ENHANCED_SEARCH_AVAILABLE": self.ENHANCED_SEARCH_AVAILABLE, 

165 "UTILITY_FUNCTIONS_AVAILABLE": self.UTILITY_FUNCTIONS_AVAILABLE, 

166 "MULTI_PROJECT_AVAILABLE": self.MULTI_PROJECT_AVAILABLE, 

167 "ADVANCED_SEARCH_AVAILABLE": self.ADVANCED_SEARCH_AVAILABLE, 

168 "CONFIG_AVAILABLE": self.CONFIG_AVAILABLE, 

169 "AUTO_CONTEXT_AVAILABLE": self.AUTO_CONTEXT_AVAILABLE, 

170 "MEMORY_OPTIMIZER_AVAILABLE": self.MEMORY_OPTIMIZER_AVAILABLE, 

171 "APP_MONITOR_AVAILABLE": self.APP_MONITOR_AVAILABLE, 

172 "LLM_PROVIDERS_AVAILABLE": self.LLM_PROVIDERS_AVAILABLE, 

173 "SERVERLESS_MODE_AVAILABLE": self.SERVERLESS_MODE_AVAILABLE, 

174 "CRACKERJACK_INTEGRATION_AVAILABLE": self.CRACKERJACK_INTEGRATION_AVAILABLE, 

175 } 

176 

177 

178# Create global feature detector instance 

179_feature_detector = FeatureDetector() 

180 

181 

182def get_feature_flags() -> dict[str, bool]: 

183 """Get feature availability flags for the MCP server. 

184 

185 Returns: 

186 Dictionary mapping feature names to availability status. 

187 

188 """ 

189 return _feature_detector.get_feature_flags()