waldiez 0.5.3__py3-none-any.whl → 0.5.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of waldiez might be problematic. Click here for more details.

Files changed (76) hide show
  1. waldiez/_version.py +1 -1
  2. waldiez/cli.py +3 -27
  3. waldiez/exporter.py +0 -13
  4. waldiez/exporting/agent/exporter.py +38 -0
  5. waldiez/exporting/agent/extras/__init__.py +2 -0
  6. waldiez/exporting/agent/extras/doc_agent_extras.py +366 -0
  7. waldiez/exporting/agent/extras/group_member_extras.py +3 -2
  8. waldiez/exporting/agent/processor.py +113 -15
  9. waldiez/exporting/chats/processor.py +2 -21
  10. waldiez/exporting/chats/utils/common.py +66 -1
  11. waldiez/exporting/chats/utils/group.py +6 -3
  12. waldiez/exporting/chats/utils/nested.py +1 -1
  13. waldiez/exporting/chats/utils/sequential.py +25 -9
  14. waldiez/exporting/chats/utils/single.py +8 -6
  15. waldiez/exporting/core/context.py +0 -12
  16. waldiez/exporting/core/extras/agent_extras/standard_extras.py +3 -1
  17. waldiez/exporting/core/extras/base.py +20 -17
  18. waldiez/exporting/core/extras/path_resolver.py +39 -41
  19. waldiez/exporting/core/extras/serializer.py +16 -1
  20. waldiez/exporting/core/protocols.py +17 -0
  21. waldiez/exporting/core/types.py +6 -9
  22. waldiez/exporting/flow/execution_generator.py +56 -21
  23. waldiez/exporting/flow/exporter.py +1 -4
  24. waldiez/exporting/flow/factory.py +0 -9
  25. waldiez/exporting/flow/file_generator.py +6 -0
  26. waldiez/exporting/flow/orchestrator.py +27 -21
  27. waldiez/exporting/flow/utils/__init__.py +0 -2
  28. waldiez/exporting/flow/utils/common.py +15 -96
  29. waldiez/exporting/flow/utils/importing.py +4 -0
  30. waldiez/io/mqtt.py +33 -14
  31. waldiez/io/redis.py +18 -13
  32. waldiez/io/structured.py +9 -4
  33. waldiez/io/utils.py +32 -0
  34. waldiez/io/ws.py +8 -2
  35. waldiez/models/__init__.py +6 -0
  36. waldiez/models/agents/__init__.py +8 -0
  37. waldiez/models/agents/agent/agent.py +136 -38
  38. waldiez/models/agents/agent/agent_type.py +3 -2
  39. waldiez/models/agents/agents.py +10 -0
  40. waldiez/models/agents/doc_agent/__init__.py +13 -0
  41. waldiez/models/agents/doc_agent/doc_agent.py +126 -0
  42. waldiez/models/agents/doc_agent/doc_agent_data.py +149 -0
  43. waldiez/models/agents/doc_agent/rag_query_engine.py +127 -0
  44. waldiez/models/flow/flow.py +13 -2
  45. waldiez/models/model/__init__.py +2 -2
  46. waldiez/models/model/_aws.py +75 -0
  47. waldiez/models/model/_llm.py +516 -0
  48. waldiez/models/model/_price.py +30 -0
  49. waldiez/models/model/model.py +45 -2
  50. waldiez/models/model/model_data.py +2 -83
  51. waldiez/models/tool/predefined/_duckduckgo.py +123 -0
  52. waldiez/models/tool/predefined/_google.py +31 -9
  53. waldiez/models/tool/predefined/_perplexity.py +161 -0
  54. waldiez/models/tool/predefined/_searxng.py +152 -0
  55. waldiez/models/tool/predefined/_tavily.py +46 -9
  56. waldiez/models/tool/predefined/_wikipedia.py +26 -6
  57. waldiez/models/tool/predefined/_youtube.py +36 -8
  58. waldiez/models/tool/predefined/registry.py +6 -0
  59. waldiez/models/waldiez.py +12 -0
  60. waldiez/runner.py +177 -408
  61. waldiez/running/__init__.py +2 -4
  62. waldiez/running/base_runner.py +100 -112
  63. waldiez/running/environment.py +29 -4
  64. waldiez/running/post_run.py +0 -1
  65. waldiez/running/protocol.py +36 -48
  66. waldiez/running/run_results.py +5 -5
  67. waldiez/running/standard_runner.py +429 -0
  68. waldiez/running/timeline_processor.py +0 -82
  69. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/METADATA +59 -62
  70. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/RECORD +74 -64
  71. waldiez/running/import_runner.py +0 -437
  72. waldiez/running/subprocess_runner.py +0 -104
  73. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/WHEEL +0 -0
  74. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/entry_points.txt +0 -0
  75. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/licenses/LICENSE +0 -0
  76. {waldiez-0.5.3.dist-info → waldiez-0.5.5.dist-info}/licenses/NOTICE.md +0 -0
@@ -73,20 +73,58 @@ class AgentProcessor:
73
73
  resolved_args = self.arguments_resolver(self.agent)
74
74
  if resolved_args: # pragma: no branch
75
75
  extra_args += ",\n".join(resolved_args)
76
+ if not extra_args.startswith("\n"):
77
+ extra_args = "\n" + extra_args
78
+ if not extra_args.endswith("\n"):
79
+ extra_args += "\n"
76
80
  # Build the agent definition
77
- agent_str = f"""{agent_name} = {ag2_class}(
78
- {self.get_name_arg()}
79
- {self.get_description_arg()},{self.extras.get_system_message_arg()}
80
- {self.get_human_input_mode_arg()},
81
- {self.get_max_consecutive_auto_reply_arg()},
82
- {self.get_auto_reply_arg()},
83
- {self.extras.get_code_execution_arg()}
84
- {self.extras.get_termination_arg()}
85
- {extra_args}
86
- )"""
81
+ agent_str = self.get_agent_string(
82
+ agent_name=agent_name, ag2_class=ag2_class, extra_args=extra_args
83
+ )
87
84
 
88
85
  return AgentProcessingResult(content=agent_str)
89
86
 
87
+ def get_agent_string(
88
+ self, agent_name: str, ag2_class: str, extra_args: str
89
+ ) -> str:
90
+ """Get the agent definition string.
91
+
92
+ Parameters
93
+ ----------
94
+ agent_name : str
95
+ The name of the agent.
96
+ ag2_class : str
97
+ The class of the agent.
98
+ extra_args : str
99
+ Additional arguments for the agent.
100
+
101
+ Returns
102
+ -------
103
+ str
104
+ The agent definition string.
105
+ """
106
+ agent_str: str = f"{agent_name} = {ag2_class}(\n"
107
+ if "name" not in self.agent.args_to_skip:
108
+ agent_str += self.get_name_arg()
109
+ if "description" not in self.agent.args_to_skip:
110
+ agent_str += self.get_description_arg()
111
+ if "system_message" not in self.agent.args_to_skip:
112
+ agent_str += self.get_system_message_arg()
113
+ if "human_input_mode" not in self.agent.args_to_skip:
114
+ agent_str += self.get_human_input_mode_arg()
115
+ if "max_consecutive_auto_reply" not in self.agent.args_to_skip:
116
+ agent_str += self.get_max_consecutive_auto_reply_arg()
117
+ if "default_auto_reply" not in self.agent.args_to_skip:
118
+ agent_str += self.get_auto_reply_arg()
119
+ if "code_execution_config" not in self.agent.args_to_skip:
120
+ agent_str += self.get_code_execution_arg()
121
+ if "is_termination_msg" not in self.agent.args_to_skip:
122
+ agent_str += self.get_termination_arg()
123
+ if extra_args: # pragma: no branch
124
+ agent_str = self.add_extra_args(agent_str, extra_args)
125
+ agent_str += ")"
126
+ return agent_str
127
+
90
128
  def get_name_arg(self) -> str:
91
129
  """Get the agent name argument.
92
130
 
@@ -95,7 +133,46 @@ class AgentProcessor:
95
133
  str
96
134
  The agent name argument.
97
135
  """
98
- return f' name="{self.agent_names[self.agent.id]}",'
136
+ return f' name="{self.agent_names[self.agent.id]}",\n'
137
+
138
+ def get_system_message_arg(self) -> str:
139
+ """Get the system message argument.
140
+
141
+ Returns
142
+ -------
143
+ str
144
+ The system message argument.
145
+ """
146
+ arg = str(self.extras.get_system_message_arg())
147
+ if arg:
148
+ return f"{arg},\n"
149
+ return ""
150
+
151
+ def get_code_execution_arg(self) -> str:
152
+ """Get the code execution argument.
153
+
154
+ Returns
155
+ -------
156
+ str
157
+ The code execution argument.
158
+ """
159
+ arg = str(self.extras.get_code_execution_arg())
160
+ if arg:
161
+ return f"{arg},\n"
162
+ return ""
163
+
164
+ def get_termination_arg(self) -> str:
165
+ """Get the termination argument.
166
+
167
+ Returns
168
+ -------
169
+ str
170
+ The termination argument.
171
+ """
172
+ arg = str(self.extras.get_termination_arg())
173
+ if arg:
174
+ return f"{arg}\n"
175
+ return ""
99
176
 
100
177
  def get_human_input_mode_arg(self) -> str:
101
178
  """Get the human input mode argument.
@@ -105,7 +182,7 @@ class AgentProcessor:
105
182
  str
106
183
  The human input mode argument.
107
184
  """
108
- return f' human_input_mode="{self.agent.data.human_input_mode}"'
185
+ return f' human_input_mode="{self.agent.data.human_input_mode}",\n'
109
186
 
110
187
  def get_max_consecutive_auto_reply_arg(self) -> str:
111
188
  """Get the maximum consecutive auto reply argument.
@@ -116,7 +193,7 @@ class AgentProcessor:
116
193
  The maximum consecutive auto reply argument.
117
194
  """
118
195
  value = self.agent.data.max_consecutive_auto_reply
119
- return f" max_consecutive_auto_reply={value}"
196
+ return f" max_consecutive_auto_reply={value},\n"
120
197
 
121
198
  def get_description_arg(self) -> str:
122
199
  """Get the agent description.
@@ -131,7 +208,7 @@ class AgentProcessor:
131
208
  if self.agent.description
132
209
  else '""'
133
210
  )
134
- return f" description={description}"
211
+ return f" description={description},\n"
135
212
 
136
213
  def get_auto_reply_arg(self) -> str:
137
214
  """Get the default auto reply argument.
@@ -147,4 +224,25 @@ class AgentProcessor:
147
224
  default_auto_reply = json.dumps(
148
225
  self.agent.data.agent_default_auto_reply
149
226
  )
150
- return f" default_auto_reply={default_auto_reply}"
227
+ return f" default_auto_reply={default_auto_reply},\n"
228
+
229
+ def add_extra_args(self, agent_str: str, extra_args: str) -> str:
230
+ """Add extra agent args.
231
+
232
+ Parameters
233
+ ----------
234
+ agent_str : str
235
+ The current agent string
236
+ extra_args : str
237
+ The extra args to add
238
+
239
+ Returns
240
+ -------
241
+ str
242
+ The new agent string
243
+ """
244
+ agent_string = str(agent_str)
245
+ if agent_string.endswith("\n"):
246
+ agent_string = agent_string[: -len("\n")]
247
+ agent_string += extra_args
248
+ return agent_string
@@ -197,30 +197,11 @@ class ChatsProcessor:
197
197
  """
198
198
  if self.is_group_patterned():
199
199
  if self._is_async:
200
- import_string = (
201
- "from autogen.agentchat import a_initiate_group_chat"
202
- )
200
+ import_string = "from autogen.agentchat import a_run_group_chat"
203
201
  else:
204
- import_string = (
205
- "from autogen.agentchat import initiate_group_chat"
206
- )
202
+ import_string = "from autogen.agentchat import run_group_chat"
207
203
  self._extras.add_import(
208
204
  ImportStatement(
209
205
  statement=import_string, position=ImportPosition.THIRD_PARTY
210
206
  )
211
207
  )
212
- return
213
- if len(self._chats.main) == 1:
214
- # no additional imports, it is `sender.initiate_chat(....)`
215
- return
216
- if self._is_async:
217
- import_string = (
218
- "from autogen.agentchat.chat import a_initiate_chats"
219
- )
220
- else:
221
- import_string = "from autogen.agentchat.chat import initiate_chats"
222
- self._extras.add_import(
223
- ImportStatement(
224
- statement=import_string, position=ImportPosition.THIRD_PARTY
225
- )
226
- )
@@ -2,6 +2,7 @@
2
2
  # Copyright (c) 2024 - 2025 Waldiez and contributors.
3
3
  """Common utilities for exporting chats."""
4
4
 
5
+ import json
5
6
  from typing import Optional
6
7
 
7
8
  from waldiez.models import WaldiezAgent, WaldiezChat
@@ -36,7 +37,9 @@ def get_chat_message_string(
36
37
  if chat.message.content is None: # pragma: no cover
37
38
  # should be coverred previousliy on pydantic validation
38
39
  return "None", None
39
- return chat.message.content, None
40
+ if not chat.message.content:
41
+ return "", None
42
+ return json.dumps(chat.message.content, ensure_ascii=False), None
40
43
 
41
44
  is_rag_with_carryover = sender.is_rag_user and chat.message.use_carryover
42
45
  chat_name = chat_names[chat.id]
@@ -45,3 +48,65 @@ def get_chat_message_string(
45
48
  is_rag=is_rag_with_carryover,
46
49
  )
47
50
  return function_name, function_content
51
+
52
+
53
+ def get_event_handler_string(
54
+ tab: str,
55
+ is_async: bool,
56
+ ) -> str:
57
+ """Get the event handler string.
58
+
59
+ Parameters
60
+ ----------
61
+ tab : str
62
+ The tab string.
63
+ is_async : bool
64
+ Whether the handler is asynchronous.
65
+
66
+ Returns
67
+ -------
68
+ str
69
+ The event handler string.
70
+ """
71
+ content = (
72
+ f"{tab}if on_event:\n"
73
+ f"{tab} if not isinstance(results, list):\n"
74
+ f"{tab} results = [results]\n"
75
+ f"{tab} for index, result in enumerate(results):\n"
76
+ )
77
+ if is_async:
78
+ content += (
79
+ f"{tab} async for event in result.events:\n"
80
+ f"{tab} try:\n"
81
+ f"{tab} should_continue = await on_event(event)\n"
82
+ f"{tab} except Exception as e:\n"
83
+ f"{tab} raise RuntimeError(\n"
84
+ f"{tab} 'Error in event handler: ' + str(e)\n"
85
+ f"{tab} ) from e\n"
86
+ )
87
+ else:
88
+ content += (
89
+ f"{tab} for event in result.events:\n"
90
+ f"{tab} try:\n"
91
+ f"{tab} should_continue = on_event(event)\n"
92
+ f"{tab} except Exception as e:\n"
93
+ f"{tab} raise RuntimeError(\n"
94
+ f"{tab} 'Error in event handler: ' + str(e)\n"
95
+ f"{tab} ) from e\n"
96
+ )
97
+ content += (
98
+ f"{tab} if event.type == 'run_completion':\n"
99
+ f"{tab} should_continue = False\n"
100
+ f"{tab} if not should_continue:\n"
101
+ f"{tab} break\n"
102
+ f"{tab}else:\n"
103
+ f"{tab} if not isinstance(results, list):\n"
104
+ f"{tab} results = [results]\n"
105
+ f"{tab} for result in results:\n"
106
+ )
107
+ if is_async:
108
+ content += f"{tab} await result.process()\n"
109
+ else:
110
+ content += f"{tab} result.process()\n"
111
+
112
+ return content
@@ -10,6 +10,8 @@ import json
10
10
 
11
11
  from waldiez.models import WaldiezGroupManager
12
12
 
13
+ from .common import get_event_handler_string
14
+
13
15
 
14
16
  def export_group_chats(
15
17
  agent_names: dict[str, str],
@@ -39,12 +41,12 @@ def export_group_chats(
39
41
  The group chat string and the import string.
40
42
  """
41
43
  tab = " " * tabs
42
- initiate_group_chat = "initiate_group_chat"
44
+ run_group_chat = "run_group_chat"
43
45
  if is_async:
44
- initiate_group_chat = "a_initiate_group_chat"
46
+ run_group_chat = "a_run_group_chat"
45
47
  manager_name = agent_names[manager.id]
46
48
  pattern_name = f"{manager_name}_pattern"
47
- content = f"{tab}results, _, __ = {initiate_group_chat}(" + "\n"
49
+ content = f"{tab}results = {run_group_chat}(" + "\n"
48
50
  content += f"{tab} pattern={pattern_name}," + "\n"
49
51
  if initial_chat:
50
52
  content += f"{tab} messages={json.dumps(initial_chat)}," + "\n"
@@ -52,4 +54,5 @@ def export_group_chats(
52
54
  content += f'{tab} messages="",\n'
53
55
  content += f"{tab} max_rounds={manager.data.max_round},\n"
54
56
  content += f"{tab})\n"
57
+ content += get_event_handler_string(tab=tab, is_async=is_async)
55
58
  return content
@@ -270,7 +270,7 @@ def get_chat_nested_string(
270
270
  return message.content, None
271
271
  chat_name = chat_names[chat.id]
272
272
  if is_reply:
273
- function_content, function_name = chat.get_nested_chat_message_function(
273
+ function_content, function_name = chat.get_nested_chat_reply_function(
274
274
  name_suffix=chat_name
275
275
  )
276
276
  else:
@@ -10,7 +10,7 @@ from waldiez.models import (
10
10
  WaldiezRagUserProxy,
11
11
  )
12
12
 
13
- from .common import get_chat_message_string
13
+ from .common import get_chat_message_string, get_event_handler_string
14
14
 
15
15
 
16
16
  def export_sequential_chat(
@@ -115,9 +115,15 @@ def export_sequential_chat(
115
115
  tab = " " * tabs if tabs > 0 else ""
116
116
  content = "\n"
117
117
  additional_methods_string = ""
118
- content += _get_initiate_chats_line(tab, is_async)
119
- for connection in main_chats:
118
+ sender = main_chats[0]["source"]
119
+ content += _get_initiate_chats_line(
120
+ tab=tab,
121
+ is_async=is_async,
122
+ sender=agent_names[sender.id],
123
+ )
124
+ for idx, connection in enumerate(main_chats):
120
125
  chat_string, additional_methods = _get_chat_dict_string(
126
+ is_first=idx == 0,
121
127
  chat_names=chat_names,
122
128
  connection=connection,
123
129
  agent_names=agent_names,
@@ -128,11 +134,13 @@ def export_sequential_chat(
128
134
  additional_methods_string += additional_methods
129
135
  content += "\n" + f"{tab} {chat_string}"
130
136
  content += "\n" + " " * tabs + "])\n"
137
+ content += get_event_handler_string(tab=tab, is_async=is_async)
131
138
  return content, additional_methods_string
132
139
 
133
140
 
134
141
  def _get_chat_dict_string(
135
142
  connection: WaldiezAgentConnection,
143
+ is_first: bool,
136
144
  chat_names: dict[str, str],
137
145
  agent_names: dict[str, str],
138
146
  serializer: Callable[..., str],
@@ -147,6 +155,8 @@ def _get_chat_dict_string(
147
155
 
148
156
  Parameters
149
157
  ----------
158
+ is_first : bool
159
+ Whether this is the first chat in the sequence.
150
160
  connection : WaldiezAgentConnection
151
161
  The connection object containing the chat and agents.
152
162
  chat_names : dict[str, str]
@@ -168,8 +178,9 @@ def _get_chat_dict_string(
168
178
  tab = " " * tabs
169
179
  chat = connection["chat"]
170
180
  sender = connection["source"]
171
- chat_string = _get_chat_strig_start(
181
+ chat_string = _get_chat_string_start(
172
182
  connection=connection,
183
+ is_first=is_first,
173
184
  agent_names=agent_names,
174
185
  serializer=serializer,
175
186
  tabs=tabs,
@@ -196,13 +207,14 @@ def _get_chat_dict_string(
196
207
  additional_methods_string += "\n" + method_content
197
208
  chat_string += "\n" + f'{tab} "message": {message},'
198
209
  elif chat.data.message.type == "string" and chat.data.message.content:
199
- chat_string += "\n" + f'{tab} "message": "{message}",'
210
+ chat_string += "\n" + f'{tab} "message": {message},'
200
211
  chat_string += "\n" + tab + "},"
201
212
  return chat_string, additional_methods_string
202
213
 
203
214
 
204
- def _get_chat_strig_start(
215
+ def _get_chat_string_start(
205
216
  connection: WaldiezAgentConnection,
217
+ is_first: bool,
206
218
  agent_names: dict[str, str],
207
219
  serializer: Callable[..., str],
208
220
  tabs: int,
@@ -215,7 +227,8 @@ def _get_chat_strig_start(
215
227
  chat_args = chat.get_chat_args(for_queue=True, sender=sender)
216
228
  # chat_args = update_summary_chat_args(chat_args)
217
229
  chat_string = "{"
218
- chat_string += "\n" + f'{tab} "sender": {agent_names[sender.id]},'
230
+ if not is_first:
231
+ chat_string += "\n" + f'{tab} "sender": {agent_names[sender.id]},'
219
232
  chat_string += "\n" + f'{tab} "recipient": {agent_names[recipient.id]},'
220
233
  if skip_cache is False:
221
234
  chat_string += "\n" + f'{tab} "cache": cache,'
@@ -233,6 +246,7 @@ def _get_chat_strig_start(
233
246
  def _get_initiate_chats_line(
234
247
  tab: str,
235
248
  is_async: bool,
249
+ sender: str,
236
250
  ) -> str:
237
251
  """Get the initiate chats line.
238
252
 
@@ -242,6 +256,8 @@ def _get_initiate_chats_line(
242
256
  The tab string.
243
257
  is_async : bool
244
258
  Whether the chat is asynchronous.
259
+ sender : str
260
+ The sender that starts the chat.
245
261
 
246
262
  Returns
247
263
  -------
@@ -249,8 +265,8 @@ def _get_initiate_chats_line(
249
265
  The initiate chats line.
250
266
  """
251
267
  results_is = f"{tab}results = "
252
- initiate = "initiate_chats"
268
+ initiate = f"{sender}.sequential_run"
253
269
  if is_async:
254
270
  results_is += "await "
255
- initiate = "a_initiate_chats"
271
+ initiate = f"{sender}.a_sequential_run"
256
272
  return results_is + initiate + "(["
@@ -13,7 +13,7 @@ from waldiez.models import (
13
13
  WaldiezRagUserProxy,
14
14
  )
15
15
 
16
- from .common import get_chat_message_string
16
+ from .common import get_chat_message_string, get_event_handler_string
17
17
 
18
18
 
19
19
  def export_single_chat(
@@ -166,17 +166,17 @@ def get_simple_chat_string(
166
166
  """
167
167
  tab = " " * tabs
168
168
  sender_name = agent_names[sender.id]
169
- initiate = "initiate_chat"
169
+ initiate = "run"
170
170
  if is_async:
171
171
  sender_name = f"await {sender_name}"
172
- initiate = "a_initiate_chat"
172
+ initiate = "a_run"
173
173
  recipient_name = agent_names[recipient.id]
174
174
  chat_string = "\n" + f"{tab}results = {sender_name}.{initiate}(" + "\n"
175
175
  chat_string += f"{tab} {recipient_name},"
176
176
  if not skip_cache:
177
177
  chat_string += "\n" + f"{tab} cache=cache,"
178
178
  for key, value in chat_args.items():
179
- if isinstance(value, str):
179
+ if isinstance(value, str) and key != "message":
180
180
  chat_string += "\n" + f'{tab} {key}="{value}",'
181
181
  elif isinstance(value, dict):
182
182
  chat_string += (
@@ -193,6 +193,7 @@ def get_simple_chat_string(
193
193
  )
194
194
  chat_string += message_arg
195
195
  chat_string += "\n" + f"{tab})" + "\n"
196
+ chat_string += get_event_handler_string(tab=tab, is_async=is_async)
196
197
  return chat_string, additional_methods_string
197
198
 
198
199
 
@@ -233,7 +234,7 @@ def get_empty_simple_chat_string(
233
234
  if is_async:
234
235
  sender_name = f"await {sender_name}"
235
236
  recipient_name = agent_names[recipient.id]
236
- initiate = "a_initiate_chat" if is_async else "initiate_chat"
237
+ initiate = "a_run" if is_async else "run"
237
238
  content = "\n" + f"{tab}results = {sender_name}.{initiate}(" + "\n"
238
239
  content += f"{tab} {recipient_name}," + "\n"
239
240
  if not skip_cache:
@@ -247,6 +248,7 @@ def get_empty_simple_chat_string(
247
248
  )
248
249
  content += message_arg
249
250
  content += f"{tab})" + "\n"
251
+ content += get_event_handler_string(tab=tab, is_async=is_async)
250
252
  return content, ""
251
253
 
252
254
 
@@ -303,7 +305,7 @@ def get_chat_message(
303
305
  )
304
306
  if chat.message.type == "string" and chat.data.message.content:
305
307
  return (
306
- "\n" + f'{tab} message="{message}",',
308
+ "\n" + f"{tab} message={message},",
307
309
  additional_methods_string,
308
310
  )
309
311
  if chat.message.type == "rag_message_generator":
@@ -54,8 +54,6 @@ class ExporterContext:
54
54
  is_async: bool = False,
55
55
  output_directory: Optional[str] = None,
56
56
  cache_seed: Optional[int] = None,
57
- structured_io: bool = False,
58
- skip_patch_io: bool = True,
59
57
  ) -> ExportConfig:
60
58
  """Get export config or return default.
61
59
 
@@ -77,10 +75,6 @@ class ExporterContext:
77
75
  The directory where the output will be saved, by default None
78
76
  cache_seed : Optional[int], optional
79
77
  The seed for caching, by default None
80
- structured_io : bool, optional
81
- Whether to use structured I/O, by default False
82
- skip_patch_io : bool, optional
83
- Whether to skip patching I/O, by default True
84
78
 
85
79
  Returns
86
80
  -------
@@ -91,12 +85,6 @@ class ExporterContext:
91
85
  "requirements": requirements or [],
92
86
  "tags": tags or [],
93
87
  "is_async": self.config.is_async if self.config else is_async,
94
- "structured_io": (
95
- self.config.structured_io if self.config else structured_io
96
- ),
97
- "skip_patch_io": (
98
- self.config.skip_patch_io if self.config else skip_patch_io
99
- ),
100
88
  }
101
89
  if output_extension is not None:
102
90
  kwargs["output_extension"] = output_extension
@@ -139,6 +139,7 @@ class StandardExtras(BaseExtras):
139
139
  instance_id=self.instance_id,
140
140
  name="code_execution_config",
141
141
  value=argunent,
142
+ skip_trailing_comma=True,
142
143
  tabs=1,
143
144
  )
144
145
 
@@ -185,7 +186,8 @@ class StandardExtras(BaseExtras):
185
186
  name="system_message",
186
187
  value=argument,
187
188
  skip_if_empty_string=True,
188
- with_new_line_before=True,
189
+ with_new_line_before=False,
190
+ skip_trailing_comma=True,
189
191
  tabs=1,
190
192
  )
191
193
 
@@ -101,11 +101,12 @@ class BaseExtras(ExportContributor):
101
101
  content : str
102
102
  The content to prepend.
103
103
  """
104
- if content and content.strip():
104
+ stripped = content.rstrip()
105
+ if stripped and stripped not in self.before_agent:
105
106
  if self.before_agent:
106
- self.before_agent = content.rstrip() + "\n" + self.before_agent
107
+ self.before_agent = stripped + "\n" + self.before_agent
107
108
  else:
108
- self.before_agent = content.rstrip()
109
+ self.before_agent = stripped
109
110
 
110
111
  def append_before_agent(self, content: str) -> None:
111
112
  """Append content to the before_agent section.
@@ -115,11 +116,12 @@ class BaseExtras(ExportContributor):
115
116
  content : str
116
117
  The content to append.
117
118
  """
118
- if content and content.strip():
119
+ stripped = content.rstrip()
120
+ if stripped and stripped not in self.before_agent:
119
121
  if self.before_agent:
120
- self.before_agent += "\n" + content.rstrip()
122
+ self.before_agent += "\n" + stripped
121
123
  else:
122
- self.before_agent = content.rstrip()
124
+ self.before_agent = stripped
123
125
 
124
126
  def append_after_agent(self, content: str) -> None:
125
127
  """Append content to the after_agent section.
@@ -129,11 +131,12 @@ class BaseExtras(ExportContributor):
129
131
  content : str
130
132
  The content to append.
131
133
  """
132
- if content and content.strip():
134
+ stripped = content.rstrip()
135
+ if stripped and stripped not in self.after_agent:
133
136
  if self.after_agent:
134
- self.after_agent += "\n" + content.rstrip()
137
+ self.after_agent += "\n" + stripped
135
138
  else:
136
- self.after_agent = content.rstrip()
139
+ self.after_agent = stripped
137
140
 
138
141
  def append_after_all_agents(self, content: str) -> None:
139
142
  """Append content to the after_all_agents section.
@@ -143,11 +146,12 @@ class BaseExtras(ExportContributor):
143
146
  content : str
144
147
  The content to append.
145
148
  """
146
- if content and content.strip():
149
+ stripped = content.rstrip()
150
+ if stripped and stripped not in self.after_all_agents:
147
151
  if self.after_all_agents:
148
- self.after_all_agents += "\n" + content.rstrip()
152
+ self.after_all_agents += "\n" + stripped
149
153
  else:
150
- self.after_all_agents = content.rstrip()
154
+ self.after_all_agents = stripped
151
155
 
152
156
  def prepend_after_all_agents(self, content: str) -> None:
153
157
  """Prepend content to the after_all_agents section.
@@ -157,13 +161,12 @@ class BaseExtras(ExportContributor):
157
161
  content : str
158
162
  The content to prepend.
159
163
  """
160
- if content and content.strip():
164
+ stripped = content.rstrip()
165
+ if stripped and stripped not in self.after_all_agents:
161
166
  if self.after_all_agents:
162
- self.after_all_agents = (
163
- content.rstrip() + "\n" + self.after_all_agents
164
- )
167
+ self.after_all_agents = stripped + "\n" + self.after_all_agents
165
168
  else:
166
- self.after_all_agents = content.rstrip()
169
+ self.after_all_agents = stripped
167
170
 
168
171
  def contribute_to_export(self, result: ExportResult) -> None:
169
172
  """Contribute this extras' content to the export result.