1717 Sequence ,
1818 Union ,
1919)
20- import aiofiles
21- import yaml
2220from loguru import logger
2321from autogen_agentchat .base import ChatAgent , TaskResult , Team
2422from autogen_agentchat .messages import AgentEvent , ChatMessage , TextMessage
2523from autogen_core import EVENT_LOGGER_NAME , CancellationToken , ComponentModel
2624from autogen_core .logging import LLMCallEvent
2725from ...task_team import get_task_team
28- from ...teams import GroupChat
2926from ...types import RunPaths
3027from ...magentic_ui_config import MagenticUIConfig , ModelClientConfigs
3128from ...input_func import InputFuncType
@@ -73,17 +70,9 @@ def __init__(
7370 @staticmethod
7471 async def load_from_file (path : Union [str , Path ]) -> Dict [str , Any ]:
7572 """Load team configuration from JSON/YAML file"""
76- path = Path (path )
77- if not path .exists ():
78- raise FileNotFoundError (f"Config file not found: { path } " )
79-
80- async with aiofiles .open (path ) as f : # type: ignore
81- content = await f .read ()
82- if path .suffix == ".json" :
83- return json .loads (content )
84- elif path .suffix in (".yml" , ".yaml" ):
85- return yaml .safe_load (content )
86- raise ValueError (f"Unsupported file format: { path .suffix } " )
73+ raise NotImplementedError (
74+ "This method should be implemented in a subclass or replaced with actual loading logic."
75+ )
8776
8877 def prepare_run_paths (
8978 self ,
@@ -178,19 +167,9 @@ def add_uploaded_files(self, file_names: set[str]) -> None:
178167 @staticmethod
179168 async def load_from_directory (directory : Union [str , Path ]) -> List [Dict [str , Any ]]:
180169 """Load all team configurations from a directory"""
181- directory = Path (directory )
182- configs : List [Dict [str , Any ]] = []
183- valid_extensions = {".json" , ".yaml" , ".yml" }
184-
185- for path in directory .iterdir ():
186- if path .is_file () and path .suffix .lower () in valid_extensions :
187- try :
188- config = await TeamManager .load_from_file (path )
189- configs .append (config )
190- except Exception as e :
191- logger .error (f"Failed to load { path } : { e } " )
192-
193- return configs
170+ raise NotImplementedError (
171+ "This method should be implemented in a subclass or replaced with actual loading logic."
172+ )
194173
195174 async def _create_team (
196175 self ,
@@ -212,123 +191,86 @@ async def _create_team(
212191 playwright_port = - 1
213192
214193 try :
215- if not self .load_from_config :
216- # The settings_config dictionary provides the Model configs in a key `model_configs`
217- # But MagenticUIConfig expects `model_client_configs` so we need to update that here
218- settings_model_configs : Dict [str , Any ] = {}
219- if "model_configs" in settings_config :
220- try :
221- settings_model_configs = yaml .safe_load (
222- settings_config ["model_configs" ]
223- )
224- except Exception as e :
225- logger .warning (
226- f"Error loading model configs from UI. Using defaults. Inner exception: { e } "
227- )
194+ # Logic here: we first see if the config file passed to magentic-ui has valid configs for all clients
195+ # If Yes: this takes precedent over the UI LLM config and is passed to magentic-ui team
196+ # If No: we disregard it and use the UI LLM config
197+ model_client_from_config_file = ModelClientConfigs (
198+ orchestrator = self .config .get ("orchestrator_client" , None ),
199+ web_surfer = self .config .get ("web_surfer_client" , None ),
200+ coder = self .config .get ("coder_client" , None ),
201+ file_surfer = self .config .get ("file_surfer_client" , None ),
202+ action_guard = self .config .get ("action_guard_client" , None ),
203+ )
204+ is_complete_config_from_file = all (
205+ [
206+ model_client_from_config_file .orchestrator ,
207+ model_client_from_config_file .web_surfer ,
208+ model_client_from_config_file .coder ,
209+ model_client_from_config_file .file_surfer ,
210+ model_client_from_config_file .action_guard ,
211+ ]
212+ )
228213
229- # Use settings_config values if available, otherwise fall back to instance defaults (self.config)
230- model_client_configs = ModelClientConfigs (
231- orchestrator = settings_model_configs .get (
232- "orchestrator_client" ,
233- self .config .get ("orchestrator_client" , None ),
234- ),
235- web_surfer = settings_model_configs .get (
236- "web_surfer_client" ,
237- self .config .get ("web_surfer_client" , None ),
238- ),
239- coder = settings_model_configs .get (
240- "coder_client" , self .config .get ("coder_client" , None )
241- ),
242- file_surfer = settings_model_configs .get (
243- "file_surfer_client" ,
244- self .config .get ("file_surfer_client" , None ),
245- ),
246- action_guard = settings_model_configs .get (
247- "action_guard_client" ,
248- self .config .get ("action_guard_client" , None ),
249- ),
214+ # Common configuration parameters
215+ config_params = {
216+ ** settings_config , # type: ignore,
217+ # These must always be set to the values computed above
218+ "playwright_port" : playwright_port ,
219+ "novnc_port" : novnc_port ,
220+ # Defer to self for inside_docker
221+ "inside_docker" : self .inside_docker ,
222+ }
223+
224+ # Override client configs if complete config from file is available
225+ if is_complete_config_from_file :
226+ config_params ["model_client_configs" ] = model_client_from_config_file
227+ else :
228+ logger .warning (
229+ "Using LLM client configurations from UI settings (default is OpenAI) since no config file passed or config file incomplete."
250230 )
251-
252- config_params = {
253- # Lowest priority defaults
254- ** self .config , # type: ignore
255- # Provided settings override defaults
256- ** settings_config , # type: ignore,
257- "model_client_configs" : model_client_configs ,
258- # These must always be set to the values computed above
259- "playwright_port" : playwright_port ,
260- "novnc_port" : novnc_port ,
261- # Defer to self for inside_docker
262- "inside_docker" : self .inside_docker ,
263- }
264- if self .run_without_docker :
265- config_params ["run_without_docker" ] = True
266- # Allow browser_headless to be set by settings_config
231+ if self .run_without_docker :
232+ config_params ["run_without_docker" ] = True
233+ # Allow browser_headless to be set by settings_config
234+ else :
235+ if settings_config .get ("run_without_docker" , False ):
236+ # Allow settings_config to set browser_headless
237+ pass
267238 else :
268- if settings_config .get ("run_without_docker" , False ):
269- # Allow settings_config to set browser_headless
239+ config_params ["browser_headless" ] = False
240+ magentic_ui_config = MagenticUIConfig (** config_params ) # type: ignore
241+ self .team = cast (
242+ Team ,
243+ await get_task_team (
244+ magentic_ui_config = magentic_ui_config ,
245+ input_func = input_func ,
246+ paths = paths ,
247+ ),
248+ )
249+ if hasattr (self .team , "_participants" ):
250+ for agent in cast (list [ChatAgent ], self .team ._participants ): # type: ignore
251+ if isinstance (agent , WebSurfer ):
252+ novnc_port = agent .novnc_port
253+ playwright_port = agent .playwright_port
254+
255+ if state :
256+ if isinstance (state , str ):
257+ # Check if the string is empty or whitespace only
258+ if not state .strip ():
259+ # Skip loading if state is empty
270260 pass
271261 else :
272- config_params ["browser_headless" ] = False
273- magentic_ui_config = MagenticUIConfig (** config_params ) # type: ignore
274-
275- self .team = cast (
276- Team ,
277- await get_task_team (
278- magentic_ui_config = magentic_ui_config ,
279- input_func = input_func ,
280- paths = paths ,
281- ),
282- )
283- if hasattr (self .team , "_participants" ):
284- for agent in cast (list [ChatAgent ], self .team ._participants ): # type: ignore
285- if isinstance (agent , WebSurfer ):
286- novnc_port = agent .novnc_port
287- playwright_port = agent .playwright_port
288-
289- if state :
290- if isinstance (state , str ):
291- # Check if the string is empty or whitespace only
292- if not state .strip ():
293- # Skip loading if state is empty
294- pass
295- else :
296- try :
297- state_dict = json .loads (state )
298- await self .team .load_state (state_dict )
299- except json .JSONDecodeError as json_error :
300- # Log error and skip loading invalid JSON state
301- logger .warning (
302- f"Warning: Failed to load state - invalid JSON: { json_error } "
303- )
304-
305- else :
306- await self .team .load_state (state )
307-
308- return self .team , novnc_port , playwright_port
309-
310- if isinstance (team_config , (str , Path )):
311- config = await self .load_from_file (team_config )
312- elif isinstance (team_config , dict ):
313- config = team_config
314- else :
315- config = team_config .model_dump ()
316-
317- # Load env vars into environment if provided
318- if env_vars :
319- logger .info ("Loading environment variables" )
320- for var in env_vars :
321- os .environ [var .name ] = var .value
262+ try :
263+ state_dict = json .loads (state )
264+ await self .team .load_state (state_dict )
265+ except json .JSONDecodeError as json_error :
266+ # Log error and skip loading invalid JSON state
267+ logger .warning (
268+ f"Warning: Failed to load state - invalid JSON: { json_error } "
269+ )
322270
323- self .team = cast (Team , GroupChat .load_component (config ))
271+ else :
272+ await self .team .load_state (state )
324273
325- if hasattr (self .team , "_participants" ):
326- for agent in cast (list [ChatAgent ], self .team ._participants ): # type: ignore
327- if hasattr (agent , "input_func" ):
328- agent .input_func = input_func # type: ignore
329- if isinstance (agent , WebSurfer ):
330- novnc_port = agent .novnc_port or - 1
331- playwright_port = agent .playwright_port or - 1
332274 return self .team , novnc_port , playwright_port
333275 except Exception as e :
334276 logger .error (f"Error creating team: { e } " )
0 commit comments