@@ -121,12 +121,12 @@ def __init__(self, topic="Movie Story writing about AI", agent_file="test.yaml",
121121 mode = instructor .Mode .JSON ,
122122 )
123123
124- def generate (self ):
124+ def generate (self , merge = False ):
125125 """
126126 Generates a team structure for the specified topic.
127127
128128 Args:
129- None
129+ merge (bool): Whether to merge with existing agents.yaml file instead of overwriting.
130130
131131 Returns:
132132 str: The full path of the YAML file containing the generated team structure.
@@ -149,45 +149,118 @@ def generate(self):
149149 ]
150150 )
151151 json_data = json .loads (response .model_dump_json ())
152- self .convert_and_save (json_data )
152+ self .convert_and_save (json_data , merge = merge )
153153 full_path = os .path .abspath (self .agent_file )
154154 return full_path
155155
156- def convert_and_save (self , json_data ):
156+ def convert_and_save (self , json_data , merge = False ):
157157 """Converts the provided JSON data into the desired YAML format and saves it to a file.
158158
159159 Args:
160160 json_data (dict): The JSON data representing the team structure.
161- topic (str, optional): The topic to be inserted into the YAML. Defaults to "Artificial Intelligence".
162- agent_file (str, optional): The name of the YAML file to save. Defaults to "test.yaml".
161+ merge (bool): Whether to merge with existing agents.yaml file instead of overwriting.
163162 """
164163
165- yaml_data = {
166- "framework" : self .framework ,
167- "topic" : self .topic ,
168- "roles" : {},
169- "dependencies" : []
170- }
164+ # Handle merge functionality
165+ if merge and os .path .exists (self .agent_file ):
166+ yaml_data = self .merge_with_existing_agents (json_data )
167+ else :
168+ # Original behavior: create new yaml_data structure
169+ yaml_data = {
170+ "framework" : self .framework ,
171+ "topic" : self .topic ,
172+ "roles" : {},
173+ "dependencies" : []
174+ }
175+
176+ for role_id , role_details in json_data ['roles' ].items ():
177+ yaml_data ['roles' ][role_id ] = {
178+ "backstory" : "" + role_details ['backstory' ],
179+ "goal" : role_details ['goal' ],
180+ "role" : role_details ['role' ],
181+ "tasks" : {},
182+ # "tools": role_details.get('tools', []),
183+ "tools" : ['' ]
184+ }
185+
186+ for task_id , task_details in role_details ['tasks' ].items ():
187+ yaml_data ['roles' ][role_id ]['tasks' ][task_id ] = {
188+ "description" : "" + task_details ['description' ],
189+ "expected_output" : "" + task_details ['expected_output' ]
190+ }
191+
192+ # Save to YAML file, maintaining the order
193+ with open (self .agent_file , 'w' ) as f :
194+ yaml .dump (yaml_data , f , allow_unicode = True , sort_keys = False )
171195
172- for role_id , role_details in json_data ['roles' ].items ():
173- yaml_data ['roles' ][role_id ] = {
196+ def merge_with_existing_agents (self , new_json_data ):
197+ """
198+ Merge existing agents.yaml with new auto-generated agents.
199+
200+ Args:
201+ new_json_data (dict): The JSON data representing the new team structure.
202+
203+ Returns:
204+ dict: The merged YAML data structure.
205+ """
206+ try :
207+ # Load existing agents.yaml
208+ with open (self .agent_file , 'r' ) as f :
209+ existing_data = yaml .safe_load (f )
210+
211+ if not existing_data :
212+ # If existing file is empty, treat as new file
213+ existing_data = {"roles" : {}, "dependencies" : []}
214+ except (yaml .YAMLError , FileNotFoundError ) as e :
215+ logging .warning (f"Could not load existing agents file { self .agent_file } : { e } " )
216+ logging .warning ("Creating new file instead of merging" )
217+ existing_data = {"roles" : {}, "dependencies" : []}
218+
219+ # Start with existing data structure
220+ merged_data = existing_data .copy ()
221+
222+ # Ensure required fields exist
223+ if 'roles' not in merged_data :
224+ merged_data ['roles' ] = {}
225+ if 'dependencies' not in merged_data :
226+ merged_data ['dependencies' ] = []
227+ if 'framework' not in merged_data :
228+ merged_data ['framework' ] = self .framework
229+
230+ # Handle topic merging
231+ existing_topic = merged_data .get ('topic' , '' )
232+ new_topic = self .topic
233+ if existing_topic and existing_topic != new_topic :
234+ merged_data ['topic' ] = f"{ existing_topic } + { new_topic } "
235+ else :
236+ merged_data ['topic' ] = new_topic
237+
238+ # Merge new roles with existing ones
239+ for role_id , role_details in new_json_data ['roles' ].items ():
240+ # Check for conflicts and rename if necessary
241+ final_role_id = role_id
242+ counter = 1
243+ while final_role_id in merged_data ['roles' ]:
244+ final_role_id = f"{ role_id } _auto_{ counter } "
245+ counter += 1
246+
247+ # Add the new role
248+ merged_data ['roles' ][final_role_id ] = {
174249 "backstory" : "" + role_details ['backstory' ],
175250 "goal" : role_details ['goal' ],
176251 "role" : role_details ['role' ],
177252 "tasks" : {},
178- # "tools": role_details.get('tools', []),
179253 "tools" : ['' ]
180254 }
181-
255+
256+ # Add tasks for this role
182257 for task_id , task_details in role_details ['tasks' ].items ():
183- yaml_data ['roles' ][role_id ]['tasks' ][task_id ] = {
258+ merged_data ['roles' ][final_role_id ]['tasks' ][task_id ] = {
184259 "description" : "" + task_details ['description' ],
185260 "expected_output" : "" + task_details ['expected_output' ]
186261 }
187-
188- # Save to YAML file, maintaining the order
189- with open (self .agent_file , 'w' ) as f :
190- yaml .dump (yaml_data , f , allow_unicode = True , sort_keys = False )
262+
263+ return merged_data
191264
192265 def get_user_content (self ):
193266 """
0 commit comments