@@ -220,6 +220,25 @@ def __init__(self, personal_dir: str, rag_manager=None):
220220 self ._load_excluded ()
221221 self .refresh_index ()
222222
223+ def get_rag_manager (self ):
224+ """Return the live RAG manager and adopt lazy startup recovery.
225+
226+ The application may start while Chroma is unavailable. Personal routes
227+ already retry the singleton later, but the long-lived manager retained
228+ the startup ``None`` and chat/agent retrieval stayed keyword-only. Keep
229+ the recovered singleton on this shared manager so every caller sees the
230+ same live provider.
231+ """
232+ if self .rag_manager is not None :
233+ return self .rag_manager
234+
235+ from src .rag_singleton import get_rag_manager
236+
237+ recovered = get_rag_manager ()
238+ if recovered is not None :
239+ self .rag_manager = recovered
240+ return recovered
241+
223242 def load_directories (self ):
224243 """Load the list of indexed directories from persistent storage."""
225244 try :
@@ -297,9 +316,10 @@ def add_directory(self, directory: str, *, index: bool = True, owner: str = None
297316 # If RAG manager is available, index the directory immediately.
298317 # Callers that already indexed with owner metadata can pass
299318 # index=False so we do not create a second ownerless copy.
300- if index and self .rag_manager :
319+ rag_manager = self .get_rag_manager () if index else None
320+ if rag_manager :
301321 try :
302- result = self . rag_manager .index_personal_documents (directory , owner = owner )
322+ result = rag_manager .index_personal_documents (directory , owner = owner )
303323 logger .info (f"Indexed { result .get ('indexed_count' , 0 )} chunks from { directory } " )
304324 except Exception as e :
305325 logger .error (f"Failed to index directory { directory } : { e } " )
@@ -328,9 +348,10 @@ def remove_directory(self, directory: str):
328348 # re-indexed only the remaining tracked dirs — ownerless and never
329349 # personal_dir — a catastrophic wipe (#1660). remove_directory now
330350 # removes exactly this directory's chunks and leaves the rest intact.
331- if self .rag_manager :
351+ rag_manager = self .get_rag_manager ()
352+ if rag_manager :
332353 try :
333- self . rag_manager .remove_directory (directory )
354+ rag_manager .remove_directory (directory )
334355 except Exception as e :
335356 logger .error (f"Failed to remove directory from RAG index: { e } " )
336357 else :
@@ -417,7 +438,7 @@ def refresh_index(self):
417438
418439 def retrieve (self , query : str , k : int = 5 ) -> List [str ]:
419440 """Retrieve relevant documents for a query."""
420- return retrieve_personal (self .index , query , k , self .rag_manager )
441+ return retrieve_personal (self .index , query , k , self .get_rag_manager () )
421442
422443 def get_file_list (self ) -> List [Dict [str , Any ]]:
423444 """Get list of indexed files with metadata."""
@@ -447,7 +468,8 @@ def get_stats(self) -> Dict[str, Any]:
447468
448469 def index_all_directories (self ):
449470 """Re-index all tracked directories in the RAG system."""
450- if not self .rag_manager :
471+ rag_manager = self .get_rag_manager ()
472+ if not rag_manager :
451473 logger .warning ("No RAG manager available for indexing" )
452474 return
453475
@@ -456,7 +478,7 @@ def index_all_directories(self):
456478
457479 # Index the base personal directory
458480 try :
459- result = self . rag_manager .index_personal_documents (self .personal_dir )
481+ result = rag_manager .index_personal_documents (self .personal_dir )
460482 if result .get ('success' ):
461483 success_count += 1
462484 logger .info (f"Indexed base directory: { self .personal_dir } " )
@@ -472,7 +494,7 @@ def index_all_directories(self):
472494 continue
473495
474496 try :
475- result = self . rag_manager .index_personal_documents (directory )
497+ result = rag_manager .index_personal_documents (directory )
476498 if result .get ('success' ):
477499 success_count += 1
478500 logger .info (f"Indexed directory: { directory } " )
0 commit comments