@@ -28,16 +28,27 @@ def __init__(self, args=None):
2828 self .console = Console ()
2929 self .config : Dict [str , Any ] = {}
3030 self .args = args or argparse .Namespace ()
31- self .config_yml_path = Path ("../../config.yml" ) # Repo root config.yml
32- self .config_yml_data = None
3331
3432 # Check if we're in the right directory
3533 if not Path ("pyproject.toml" ).exists () or not Path ("src" ).exists ():
3634 self .console .print ("[red][ERROR][/red] Please run this script from the backends/advanced directory" )
3735 sys .exit (1 )
3836
39- # Load config.yml if it exists
40- self .load_config_yml ()
37+ # Initialize ConfigManager
38+ repo_root = Path .cwd ().parent .parent # backends/advanced -> repo root
39+ if str (repo_root ) not in sys .path :
40+ sys .path .insert (0 , str (repo_root ))
41+
42+ from config_manager import ConfigManager
43+
44+ self .config_manager = ConfigManager (service_path = "backends/advanced" )
45+ self .console .print (f"[blue][INFO][/blue] Using config.yml at: { self .config_manager .config_yml_path } " )
46+
47+ # Load existing config or create default structure
48+ self .config_yml_data = self .config_manager .get_full_config ()
49+ if not self .config_yml_data :
50+ self .console .print ("[yellow][WARNING][/yellow] config.yml not found, will create default structure" )
51+ self .config_yml_data = self ._get_default_config_structure ()
4152
4253 def print_header (self , title : str ):
4354 """Print a colorful header"""
@@ -126,21 +137,6 @@ def mask_api_key(self, key: str, show_chars: int = 5) -> str:
126137
127138 return f"{ key_clean [:show_chars ]} { '*' * min (15 , len (key_clean ) - show_chars * 2 )} { key_clean [- show_chars :]} "
128139
129- def load_config_yml (self ):
130- """Load config.yml from repository root"""
131- if not self .config_yml_path .exists ():
132- self .console .print (f"[yellow][WARNING][/yellow] config.yml not found at { self .config_yml_path } " )
133- self .console .print ("[yellow]Will create a new config.yml during setup[/yellow]" )
134- self .config_yml_data = self ._get_default_config_structure ()
135- return
136-
137- try :
138- with open (self .config_yml_path , 'r' ) as f :
139- self .config_yml_data = yaml .safe_load (f )
140- self .console .print (f"[blue][INFO][/blue] Loaded existing config.yml" )
141- except Exception as e :
142- self .console .print (f"[red][ERROR][/red] Failed to load config.yml: { e } " )
143- self .config_yml_data = self ._get_default_config_structure ()
144140
145141 def _get_default_config_structure (self ) -> Dict [str , Any ]:
146142 """Return default config.yml structure if file doesn't exist"""
@@ -163,36 +159,6 @@ def _get_default_config_structure(self) -> Dict[str, Any]:
163159 }
164160 }
165161
166- def save_config_yml (self ):
167- """Save config.yml back to repository root"""
168- try :
169- # Backup existing config.yml if it exists
170- if self .config_yml_path .exists ():
171- timestamp = datetime .now ().strftime ("%Y%m%d_%H%M%S" )
172- backup_path = self .config_yml_path .parent / f"config.yml.backup.{ timestamp } "
173- shutil .copy2 (self .config_yml_path , backup_path )
174- self .console .print (f"[blue][INFO][/blue] Backed up config.yml to { backup_path .name } " )
175-
176- # Write updated config
177- with open (self .config_yml_path , 'w' ) as f :
178- yaml .dump (self .config_yml_data , f , default_flow_style = False , sort_keys = False )
179-
180- self .console .print ("[green][SUCCESS][/green] config.yml updated successfully" )
181- except Exception as e :
182- self .console .print (f"[red][ERROR][/red] Failed to save config.yml: { e } " )
183- raise
184-
185- def update_config_default (self , key : str , value : str ):
186- """Update a default value in config.yml"""
187- if "defaults" not in self .config_yml_data :
188- self .config_yml_data ["defaults" ] = {}
189- self .config_yml_data ["defaults" ][key ] = value
190-
191- def update_memory_config (self , updates : Dict [str , Any ]):
192- """Update memory configuration in config.yml"""
193- if "memory" not in self .config_yml_data :
194- self .config_yml_data ["memory" ] = {}
195- self .config_yml_data ["memory" ].update (updates )
196162
197163 def setup_authentication (self ):
198164 """Configure authentication settings"""
@@ -306,8 +272,8 @@ def setup_llm(self):
306272 if api_key :
307273 self .config ["OPENAI_API_KEY" ] = api_key
308274 # Update config.yml to use OpenAI models
309- self .update_config_default ( "llm" , "openai-llm" )
310- self .update_config_default ( "embedding" , "openai-embed" )
275+ self .config_manager . update_config_defaults ({ "llm" : "openai-llm" , "embedding" : "openai-embed" } )
276+ self .config_yml_data = self . config_manager . get_full_config () # Reload to stay in sync
311277 self .console .print ("[green][SUCCESS][/green] OpenAI configured in config.yml" )
312278 self .console .print ("[blue][INFO][/blue] Set defaults.llm: openai-llm" )
313279 self .console .print ("[blue][INFO][/blue] Set defaults.embedding: openai-embed" )
@@ -317,8 +283,8 @@ def setup_llm(self):
317283 elif choice == "2" :
318284 self .console .print ("[blue][INFO][/blue] Ollama selected" )
319285 # Update config.yml to use Ollama models
320- self .update_config_default ( "llm" , "local-llm" )
321- self .update_config_default ( "embedding" , "local-embed" )
286+ self .config_manager . update_config_defaults ({ "llm" : "local-llm" , "embedding" : "local-embed" } )
287+ self .config_yml_data = self . config_manager . get_full_config () # Reload to stay in sync
322288 self .console .print ("[green][SUCCESS][/green] Ollama configured in config.yml" )
323289 self .console .print ("[blue][INFO][/blue] Set defaults.llm: local-llm" )
324290 self .console .print ("[blue][INFO][/blue] Set defaults.embedding: local-embed" )
@@ -327,7 +293,8 @@ def setup_llm(self):
327293 elif choice == "3" :
328294 self .console .print ("[blue][INFO][/blue] Skipping LLM setup - memory extraction disabled" )
329295 # Disable memory extraction in config.yml
330- self .update_memory_config ({"extraction" : {"enabled" : False }})
296+ self .config_manager .update_memory_config ({"extraction" : {"enabled" : False }})
297+ self .config_yml_data = self .config_manager .get_full_config () # Reload to stay in sync
331298
332299 def setup_memory (self ):
333300 """Configure memory provider - updates config.yml"""
@@ -347,9 +314,10 @@ def setup_memory(self):
347314 qdrant_url = self .prompt_value ("Qdrant URL" , "qdrant" )
348315 self .config ["QDRANT_BASE_URL" ] = qdrant_url
349316
350- # Update config.yml
351- self .update_memory_config ({"provider" : "chronicle" })
352- self .console .print ("[green][SUCCESS][/green] Chronicle memory provider configured in config.yml" )
317+ # Update config.yml (also updates .env automatically)
318+ self .config_manager .update_memory_config ({"provider" : "chronicle" })
319+ self .config_yml_data = self .config_manager .get_full_config () # Reload to stay in sync
320+ self .console .print ("[green][SUCCESS][/green] Chronicle memory provider configured in config.yml and .env" )
353321
354322 elif choice == "2" :
355323 self .console .print ("[blue][INFO][/blue] OpenMemory MCP selected" )
@@ -359,8 +327,8 @@ def setup_memory(self):
359327 user_id = self .prompt_value ("OpenMemory user ID" , "openmemory" )
360328 timeout = self .prompt_value ("OpenMemory timeout (seconds)" , "30" )
361329
362- # Update config.yml with OpenMemory MCP settings
363- self .update_memory_config ({
330+ # Update config.yml with OpenMemory MCP settings (also updates .env automatically)
331+ self .config_manager . update_memory_config ({
364332 "provider" : "openmemory_mcp" ,
365333 "openmemory_mcp" : {
366334 "server_url" : mcp_url ,
@@ -369,7 +337,8 @@ def setup_memory(self):
369337 "timeout" : int (timeout )
370338 }
371339 })
372- self .console .print ("[green][SUCCESS][/green] OpenMemory MCP configured in config.yml" )
340+ self .config_yml_data = self .config_manager .get_full_config () # Reload to stay in sync
341+ self .console .print ("[green][SUCCESS][/green] OpenMemory MCP configured in config.yml and .env" )
373342 self .console .print ("[yellow][WARNING][/yellow] Remember to start OpenMemory: cd ../../extras/openmemory-mcp && docker compose up -d" )
374343
375344 elif choice == "3" :
@@ -378,15 +347,16 @@ def setup_memory(self):
378347 mycelia_url = self .prompt_value ("Mycelia API URL" , "http://localhost:5173" )
379348 timeout = self .prompt_value ("Mycelia timeout (seconds)" , "30" )
380349
381- # Update config.yml with Mycelia settings
382- self .update_memory_config ({
350+ # Update config.yml with Mycelia settings (also updates .env automatically)
351+ self .config_manager . update_memory_config ({
383352 "provider" : "mycelia" ,
384353 "mycelia" : {
385354 "api_url" : mycelia_url ,
386355 "timeout" : int (timeout )
387356 }
388357 })
389- self .console .print ("[green][SUCCESS][/green] Mycelia memory provider configured in config.yml" )
358+ self .config_yml_data = self .config_manager .get_full_config () # Reload to stay in sync
359+ self .console .print ("[green][SUCCESS][/green] Mycelia memory provider configured in config.yml and .env" )
390360 self .console .print ("[yellow][WARNING][/yellow] Make sure Mycelia is running at the configured URL" )
391361
392362 def setup_optional_services (self ):
@@ -559,10 +529,8 @@ def generate_env_file(self):
559529
560530 self .console .print ("[green][SUCCESS][/green] .env file configured successfully with secure permissions" )
561531
562- # Save config.yml with all updates
563- self .console .print ()
564- self .console .print ("[blue][INFO][/blue] Saving configuration to config.yml..." )
565- self .save_config_yml ()
532+ # Note: config.yml is automatically saved by ConfigManager when updates are made
533+ self .console .print ("[blue][INFO][/blue] Configuration saved to config.yml and .env (via ConfigManager)" )
566534
567535 def copy_config_templates (self ):
568536 """Copy other configuration files"""
0 commit comments