@@ -36,8 +36,21 @@ def __init__(self, args=None):
3636 self .console .print ("[red][ERROR][/red] Please run this script from the backends/advanced directory" )
3737 sys .exit (1 )
3838
39- # Load config.yml if it exists
40- self .load_config_yml ()
39+ # Initialize ConfigManager
40+ repo_root = Path .cwd ().parent .parent # backends/advanced -> repo root
41+ if str (repo_root ) not in sys .path :
42+ sys .path .insert (0 , str (repo_root ))
43+
44+ from config_manager import ConfigManager
45+
46+ self .config_manager = ConfigManager (service_path = "backends/advanced" )
47+ self .console .print (f"[blue][INFO][/blue] Using config.yml at: { self .config_manager .config_yml_path } " )
48+
49+ # Load existing config or create default structure
50+ self .config_yml_data = self .config_manager .get_full_config ()
51+ if not self .config_yml_data :
52+ self .console .print ("[yellow][WARNING][/yellow] config.yml not found, will create default structure" )
53+ self .config_yml_data = self ._get_default_config_structure ()
4154
4255 def print_header (self , title : str ):
4356 """Print a colorful header"""
@@ -126,21 +139,6 @@ def mask_api_key(self, key: str, show_chars: int = 5) -> str:
126139
127140 return f"{ key_clean [:show_chars ]} { '*' * min (15 , len (key_clean ) - show_chars * 2 )} { key_clean [- show_chars :]} "
128141
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 ()
144142
145143 def _get_default_config_structure (self ) -> Dict [str , Any ]:
146144 """Return default config.yml structure if file doesn't exist"""
@@ -163,36 +161,6 @@ def _get_default_config_structure(self) -> Dict[str, Any]:
163161 }
164162 }
165163
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 )
196164
197165 def setup_authentication (self ):
198166 """Configure authentication settings"""
@@ -306,8 +274,8 @@ def setup_llm(self):
306274 if api_key :
307275 self .config ["OPENAI_API_KEY" ] = api_key
308276 # Update config.yml to use OpenAI models
309- self .update_config_default ( "llm" , "openai-llm" )
310- self .update_config_default ( "embedding" , "openai-embed" )
277+ self .config_manager . update_config_defaults ({ "llm" : "openai-llm" , "embedding" : "openai-embed" } )
278+ self .config_yml_data = self . config_manager . get_full_config () # Reload to stay in sync
311279 self .console .print ("[green][SUCCESS][/green] OpenAI configured in config.yml" )
312280 self .console .print ("[blue][INFO][/blue] Set defaults.llm: openai-llm" )
313281 self .console .print ("[blue][INFO][/blue] Set defaults.embedding: openai-embed" )
@@ -317,8 +285,8 @@ def setup_llm(self):
317285 elif choice == "2" :
318286 self .console .print ("[blue][INFO][/blue] Ollama selected" )
319287 # Update config.yml to use Ollama models
320- self .update_config_default ( "llm" , "local-llm" )
321- self .update_config_default ( "embedding" , "local-embed" )
288+ self .config_manager . update_config_defaults ({ "llm" : "local-llm" , "embedding" : "local-embed" } )
289+ self .config_yml_data = self . config_manager . get_full_config () # Reload to stay in sync
322290 self .console .print ("[green][SUCCESS][/green] Ollama configured in config.yml" )
323291 self .console .print ("[blue][INFO][/blue] Set defaults.llm: local-llm" )
324292 self .console .print ("[blue][INFO][/blue] Set defaults.embedding: local-embed" )
@@ -327,7 +295,8 @@ def setup_llm(self):
327295 elif choice == "3" :
328296 self .console .print ("[blue][INFO][/blue] Skipping LLM setup - memory extraction disabled" )
329297 # Disable memory extraction in config.yml
330- self .update_memory_config ({"extraction" : {"enabled" : False }})
298+ self .config_manager .update_memory_config ({"extraction" : {"enabled" : False }})
299+ self .config_yml_data = self .config_manager .get_full_config () # Reload to stay in sync
331300
332301 def setup_memory (self ):
333302 """Configure memory provider - updates config.yml"""
@@ -347,9 +316,10 @@ def setup_memory(self):
347316 qdrant_url = self .prompt_value ("Qdrant URL" , "qdrant" )
348317 self .config ["QDRANT_BASE_URL" ] = qdrant_url
349318
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" )
319+ # Update config.yml (also updates .env automatically)
320+ self .config_manager .update_memory_config ({"provider" : "chronicle" })
321+ self .config_yml_data = self .config_manager .get_full_config () # Reload to stay in sync
322+ self .console .print ("[green][SUCCESS][/green] Chronicle memory provider configured in config.yml and .env" )
353323
354324 elif choice == "2" :
355325 self .console .print ("[blue][INFO][/blue] OpenMemory MCP selected" )
@@ -359,8 +329,8 @@ def setup_memory(self):
359329 user_id = self .prompt_value ("OpenMemory user ID" , "openmemory" )
360330 timeout = self .prompt_value ("OpenMemory timeout (seconds)" , "30" )
361331
362- # Update config.yml with OpenMemory MCP settings
363- self .update_memory_config ({
332+ # Update config.yml with OpenMemory MCP settings (also updates .env automatically)
333+ self .config_manager . update_memory_config ({
364334 "provider" : "openmemory_mcp" ,
365335 "openmemory_mcp" : {
366336 "server_url" : mcp_url ,
@@ -369,7 +339,8 @@ def setup_memory(self):
369339 "timeout" : int (timeout )
370340 }
371341 })
372- self .console .print ("[green][SUCCESS][/green] OpenMemory MCP configured in config.yml" )
342+ self .config_yml_data = self .config_manager .get_full_config () # Reload to stay in sync
343+ self .console .print ("[green][SUCCESS][/green] OpenMemory MCP configured in config.yml and .env" )
373344 self .console .print ("[yellow][WARNING][/yellow] Remember to start OpenMemory: cd ../../extras/openmemory-mcp && docker compose up -d" )
374345
375346 elif choice == "3" :
@@ -378,15 +349,16 @@ def setup_memory(self):
378349 mycelia_url = self .prompt_value ("Mycelia API URL" , "http://localhost:5173" )
379350 timeout = self .prompt_value ("Mycelia timeout (seconds)" , "30" )
380351
381- # Update config.yml with Mycelia settings
382- self .update_memory_config ({
352+ # Update config.yml with Mycelia settings (also updates .env automatically)
353+ self .config_manager . update_memory_config ({
383354 "provider" : "mycelia" ,
384355 "mycelia" : {
385356 "api_url" : mycelia_url ,
386357 "timeout" : int (timeout )
387358 }
388359 })
389- self .console .print ("[green][SUCCESS][/green] Mycelia memory provider configured in config.yml" )
360+ self .config_yml_data = self .config_manager .get_full_config () # Reload to stay in sync
361+ self .console .print ("[green][SUCCESS][/green] Mycelia memory provider configured in config.yml and .env" )
390362 self .console .print ("[yellow][WARNING][/yellow] Make sure Mycelia is running at the configured URL" )
391363
392364 def setup_optional_services (self ):
@@ -604,10 +576,8 @@ def generate_env_file(self):
604576
605577 self .console .print ("[green][SUCCESS][/green] .env file configured successfully with secure permissions" )
606578
607- # Save config.yml with all updates
608- self .console .print ()
609- self .console .print ("[blue][INFO][/blue] Saving configuration to config.yml..." )
610- self .save_config_yml ()
579+ # Note: config.yml is automatically saved by ConfigManager when updates are made
580+ self .console .print ("[blue][INFO][/blue] Configuration saved to config.yml and .env (via ConfigManager)" )
611581
612582 def copy_config_templates (self ):
613583 """Copy other configuration files"""
0 commit comments