autobyteus 1.1.3__py3-none-any.whl → 1.1.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.
Files changed (284) hide show
  1. autobyteus/agent/agent.py +1 -1
  2. autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +4 -2
  3. autobyteus/agent/context/__init__.py +4 -2
  4. autobyteus/agent/context/agent_config.py +35 -8
  5. autobyteus/agent/context/agent_context_registry.py +73 -0
  6. autobyteus/agent/events/notifiers.py +4 -0
  7. autobyteus/agent/events/worker_event_dispatcher.py +1 -2
  8. autobyteus/agent/handlers/inter_agent_message_event_handler.py +8 -3
  9. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +19 -19
  10. autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +2 -2
  11. autobyteus/agent/handlers/tool_result_event_handler.py +48 -20
  12. autobyteus/agent/handlers/user_input_message_event_handler.py +16 -1
  13. autobyteus/agent/input_processor/__init__.py +1 -7
  14. autobyteus/agent/message/context_file_type.py +6 -0
  15. autobyteus/agent/message/send_message_to.py +74 -99
  16. autobyteus/agent/phases/discover.py +2 -1
  17. autobyteus/agent/runtime/agent_runtime.py +10 -2
  18. autobyteus/agent/runtime/agent_worker.py +1 -0
  19. autobyteus/agent/sender_type.py +15 -0
  20. autobyteus/agent/streaming/agent_event_stream.py +6 -0
  21. autobyteus/agent/streaming/stream_event_payloads.py +12 -0
  22. autobyteus/agent/streaming/stream_events.py +3 -0
  23. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +7 -4
  24. autobyteus/agent/tool_execution_result_processor/__init__.py +9 -0
  25. autobyteus/agent/tool_execution_result_processor/base_processor.py +46 -0
  26. autobyteus/agent/tool_execution_result_processor/processor_definition.py +36 -0
  27. autobyteus/agent/tool_execution_result_processor/processor_meta.py +36 -0
  28. autobyteus/agent/tool_execution_result_processor/processor_registry.py +70 -0
  29. autobyteus/agent/workspace/base_workspace.py +17 -2
  30. autobyteus/agent_team/__init__.py +1 -0
  31. autobyteus/agent_team/agent_team.py +93 -0
  32. autobyteus/agent_team/agent_team_builder.py +184 -0
  33. autobyteus/agent_team/base_agent_team.py +86 -0
  34. autobyteus/agent_team/bootstrap_steps/__init__.py +24 -0
  35. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +73 -0
  36. autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +54 -0
  37. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +25 -0
  38. autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +23 -0
  39. autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +41 -0
  40. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +85 -0
  41. autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +51 -0
  42. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +45 -0
  43. autobyteus/agent_team/context/__init__.py +17 -0
  44. autobyteus/agent_team/context/agent_team_config.py +33 -0
  45. autobyteus/agent_team/context/agent_team_context.py +61 -0
  46. autobyteus/agent_team/context/agent_team_runtime_state.py +56 -0
  47. autobyteus/agent_team/context/team_manager.py +147 -0
  48. autobyteus/agent_team/context/team_node_config.py +76 -0
  49. autobyteus/agent_team/events/__init__.py +29 -0
  50. autobyteus/agent_team/events/agent_team_event_dispatcher.py +39 -0
  51. autobyteus/agent_team/events/agent_team_events.py +53 -0
  52. autobyteus/agent_team/events/agent_team_input_event_queue_manager.py +21 -0
  53. autobyteus/agent_team/exceptions.py +8 -0
  54. autobyteus/agent_team/factory/__init__.py +9 -0
  55. autobyteus/agent_team/factory/agent_team_factory.py +99 -0
  56. autobyteus/agent_team/handlers/__init__.py +19 -0
  57. autobyteus/agent_team/handlers/agent_team_event_handler_registry.py +23 -0
  58. autobyteus/agent_team/handlers/base_agent_team_event_handler.py +16 -0
  59. autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +61 -0
  60. autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +27 -0
  61. autobyteus/agent_team/handlers/process_user_message_event_handler.py +46 -0
  62. autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +48 -0
  63. autobyteus/agent_team/phases/__init__.py +11 -0
  64. autobyteus/agent_team/phases/agent_team_operational_phase.py +19 -0
  65. autobyteus/agent_team/phases/agent_team_phase_manager.py +48 -0
  66. autobyteus/agent_team/runtime/__init__.py +13 -0
  67. autobyteus/agent_team/runtime/agent_team_runtime.py +82 -0
  68. autobyteus/agent_team/runtime/agent_team_worker.py +117 -0
  69. autobyteus/agent_team/shutdown_steps/__init__.py +17 -0
  70. autobyteus/agent_team/shutdown_steps/agent_team_shutdown_orchestrator.py +35 -0
  71. autobyteus/agent_team/shutdown_steps/agent_team_shutdown_step.py +42 -0
  72. autobyteus/agent_team/shutdown_steps/base_agent_team_shutdown_step.py +16 -0
  73. autobyteus/agent_team/shutdown_steps/bridge_cleanup_step.py +28 -0
  74. autobyteus/agent_team/shutdown_steps/sub_team_shutdown_step.py +41 -0
  75. autobyteus/agent_team/streaming/__init__.py +26 -0
  76. autobyteus/agent_team/streaming/agent_event_bridge.py +48 -0
  77. autobyteus/agent_team/streaming/agent_event_multiplexer.py +70 -0
  78. autobyteus/agent_team/streaming/agent_team_event_notifier.py +64 -0
  79. autobyteus/agent_team/streaming/agent_team_event_stream.py +33 -0
  80. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +32 -0
  81. autobyteus/agent_team/streaming/agent_team_stream_events.py +56 -0
  82. autobyteus/agent_team/streaming/team_event_bridge.py +50 -0
  83. autobyteus/agent_team/task_notification/__init__.py +11 -0
  84. autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +164 -0
  85. autobyteus/agent_team/task_notification/task_notification_mode.py +24 -0
  86. autobyteus/agent_team/utils/__init__.py +9 -0
  87. autobyteus/agent_team/utils/wait_for_idle.py +46 -0
  88. autobyteus/cli/__init__.py +1 -1
  89. autobyteus/cli/agent_team_tui/__init__.py +4 -0
  90. autobyteus/cli/agent_team_tui/app.py +210 -0
  91. autobyteus/cli/agent_team_tui/state.py +180 -0
  92. autobyteus/cli/agent_team_tui/widgets/__init__.py +6 -0
  93. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +149 -0
  94. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +320 -0
  95. autobyteus/cli/agent_team_tui/widgets/logo.py +20 -0
  96. autobyteus/cli/agent_team_tui/widgets/renderables.py +77 -0
  97. autobyteus/cli/agent_team_tui/widgets/shared.py +60 -0
  98. autobyteus/cli/agent_team_tui/widgets/status_bar.py +14 -0
  99. autobyteus/cli/agent_team_tui/widgets/task_board_panel.py +82 -0
  100. autobyteus/cli/cli_display.py +1 -1
  101. autobyteus/cli/workflow_tui/__init__.py +4 -0
  102. autobyteus/cli/workflow_tui/app.py +210 -0
  103. autobyteus/cli/workflow_tui/state.py +189 -0
  104. autobyteus/cli/workflow_tui/widgets/__init__.py +6 -0
  105. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +149 -0
  106. autobyteus/cli/workflow_tui/widgets/focus_pane.py +335 -0
  107. autobyteus/cli/workflow_tui/widgets/logo.py +27 -0
  108. autobyteus/cli/workflow_tui/widgets/renderables.py +70 -0
  109. autobyteus/cli/workflow_tui/widgets/shared.py +51 -0
  110. autobyteus/cli/workflow_tui/widgets/status_bar.py +14 -0
  111. autobyteus/events/event_types.py +8 -0
  112. autobyteus/llm/api/autobyteus_llm.py +11 -12
  113. autobyteus/llm/api/lmstudio_llm.py +34 -0
  114. autobyteus/llm/api/ollama_llm.py +8 -13
  115. autobyteus/llm/api/openai_compatible_llm.py +20 -3
  116. autobyteus/llm/autobyteus_provider.py +73 -46
  117. autobyteus/llm/llm_factory.py +103 -139
  118. autobyteus/llm/lmstudio_provider.py +104 -0
  119. autobyteus/llm/models.py +83 -53
  120. autobyteus/llm/ollama_provider.py +69 -61
  121. autobyteus/llm/ollama_provider_resolver.py +1 -0
  122. autobyteus/llm/providers.py +13 -12
  123. autobyteus/llm/runtimes.py +11 -0
  124. autobyteus/llm/token_counter/token_counter_factory.py +2 -0
  125. autobyteus/task_management/__init__.py +43 -0
  126. autobyteus/task_management/base_task_board.py +68 -0
  127. autobyteus/task_management/converters/__init__.py +11 -0
  128. autobyteus/task_management/converters/task_board_converter.py +64 -0
  129. autobyteus/task_management/converters/task_plan_converter.py +48 -0
  130. autobyteus/task_management/deliverable.py +16 -0
  131. autobyteus/task_management/deliverables/__init__.py +8 -0
  132. autobyteus/task_management/deliverables/file_deliverable.py +15 -0
  133. autobyteus/task_management/events.py +27 -0
  134. autobyteus/task_management/in_memory_task_board.py +126 -0
  135. autobyteus/task_management/schemas/__init__.py +15 -0
  136. autobyteus/task_management/schemas/deliverable_schema.py +13 -0
  137. autobyteus/task_management/schemas/plan_definition.py +35 -0
  138. autobyteus/task_management/schemas/task_status_report.py +27 -0
  139. autobyteus/task_management/task_plan.py +110 -0
  140. autobyteus/task_management/tools/__init__.py +14 -0
  141. autobyteus/task_management/tools/get_task_board_status.py +68 -0
  142. autobyteus/task_management/tools/publish_task_plan.py +113 -0
  143. autobyteus/task_management/tools/update_task_status.py +135 -0
  144. autobyteus/tools/__init__.py +2 -0
  145. autobyteus/tools/ask_user_input.py +2 -1
  146. autobyteus/tools/bash/bash_executor.py +61 -15
  147. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +2 -0
  148. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +3 -0
  149. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +3 -0
  150. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +3 -0
  151. autobyteus/tools/browser/standalone/google_search_ui.py +2 -0
  152. autobyteus/tools/browser/standalone/navigate_to.py +2 -0
  153. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +3 -0
  154. autobyteus/tools/browser/standalone/webpage_image_downloader.py +3 -0
  155. autobyteus/tools/browser/standalone/webpage_reader.py +2 -0
  156. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +3 -0
  157. autobyteus/tools/file/file_reader.py +36 -9
  158. autobyteus/tools/file/file_writer.py +37 -9
  159. autobyteus/tools/functional_tool.py +5 -4
  160. autobyteus/tools/image_downloader.py +2 -0
  161. autobyteus/tools/mcp/config_service.py +63 -58
  162. autobyteus/tools/mcp/server/http_managed_mcp_server.py +14 -2
  163. autobyteus/tools/mcp/server/stdio_managed_mcp_server.py +14 -2
  164. autobyteus/tools/mcp/server_instance_manager.py +30 -4
  165. autobyteus/tools/mcp/tool_registrar.py +106 -51
  166. autobyteus/tools/parameter_schema.py +17 -11
  167. autobyteus/tools/pdf_downloader.py +2 -1
  168. autobyteus/tools/registry/tool_definition.py +36 -37
  169. autobyteus/tools/registry/tool_registry.py +50 -2
  170. autobyteus/tools/timer.py +2 -0
  171. autobyteus/tools/tool_category.py +15 -4
  172. autobyteus/tools/tool_meta.py +6 -1
  173. autobyteus/tools/tool_origin.py +10 -0
  174. autobyteus/tools/usage/formatters/default_json_example_formatter.py +78 -3
  175. autobyteus/tools/usage/formatters/default_xml_example_formatter.py +23 -3
  176. autobyteus/tools/usage/formatters/gemini_json_example_formatter.py +6 -0
  177. autobyteus/tools/usage/formatters/google_json_example_formatter.py +7 -0
  178. autobyteus/tools/usage/formatters/openai_json_example_formatter.py +6 -4
  179. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +23 -7
  180. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +14 -25
  181. autobyteus/tools/usage/providers/__init__.py +2 -12
  182. autobyteus/tools/usage/providers/tool_manifest_provider.py +36 -29
  183. autobyteus/tools/usage/registries/__init__.py +7 -12
  184. autobyteus/tools/usage/registries/tool_formatter_pair.py +15 -0
  185. autobyteus/tools/usage/registries/tool_formatting_registry.py +58 -0
  186. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +55 -0
  187. autobyteus/workflow/agentic_workflow.py +93 -0
  188. autobyteus/{agent/workflow → workflow}/base_agentic_workflow.py +19 -27
  189. autobyteus/workflow/bootstrap_steps/__init__.py +20 -0
  190. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +34 -0
  191. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +23 -0
  192. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +41 -0
  193. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +108 -0
  194. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +50 -0
  195. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +25 -0
  196. autobyteus/workflow/context/__init__.py +17 -0
  197. autobyteus/workflow/context/team_manager.py +147 -0
  198. autobyteus/workflow/context/workflow_config.py +30 -0
  199. autobyteus/workflow/context/workflow_context.py +61 -0
  200. autobyteus/workflow/context/workflow_node_config.py +76 -0
  201. autobyteus/workflow/context/workflow_runtime_state.py +53 -0
  202. autobyteus/workflow/events/__init__.py +29 -0
  203. autobyteus/workflow/events/workflow_event_dispatcher.py +39 -0
  204. autobyteus/workflow/events/workflow_events.py +53 -0
  205. autobyteus/workflow/events/workflow_input_event_queue_manager.py +21 -0
  206. autobyteus/workflow/exceptions.py +8 -0
  207. autobyteus/workflow/factory/__init__.py +9 -0
  208. autobyteus/workflow/factory/workflow_factory.py +99 -0
  209. autobyteus/workflow/handlers/__init__.py +19 -0
  210. autobyteus/workflow/handlers/base_workflow_event_handler.py +16 -0
  211. autobyteus/workflow/handlers/inter_agent_message_request_event_handler.py +61 -0
  212. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +27 -0
  213. autobyteus/workflow/handlers/process_user_message_event_handler.py +46 -0
  214. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +39 -0
  215. autobyteus/workflow/handlers/workflow_event_handler_registry.py +23 -0
  216. autobyteus/workflow/phases/__init__.py +11 -0
  217. autobyteus/workflow/phases/workflow_operational_phase.py +19 -0
  218. autobyteus/workflow/phases/workflow_phase_manager.py +48 -0
  219. autobyteus/workflow/runtime/__init__.py +13 -0
  220. autobyteus/workflow/runtime/workflow_runtime.py +82 -0
  221. autobyteus/workflow/runtime/workflow_worker.py +117 -0
  222. autobyteus/workflow/shutdown_steps/__init__.py +17 -0
  223. autobyteus/workflow/shutdown_steps/agent_team_shutdown_step.py +42 -0
  224. autobyteus/workflow/shutdown_steps/base_workflow_shutdown_step.py +16 -0
  225. autobyteus/workflow/shutdown_steps/bridge_cleanup_step.py +28 -0
  226. autobyteus/workflow/shutdown_steps/sub_workflow_shutdown_step.py +41 -0
  227. autobyteus/workflow/shutdown_steps/workflow_shutdown_orchestrator.py +35 -0
  228. autobyteus/workflow/streaming/__init__.py +26 -0
  229. autobyteus/workflow/streaming/agent_event_bridge.py +48 -0
  230. autobyteus/workflow/streaming/agent_event_multiplexer.py +70 -0
  231. autobyteus/workflow/streaming/workflow_event_bridge.py +50 -0
  232. autobyteus/workflow/streaming/workflow_event_notifier.py +83 -0
  233. autobyteus/workflow/streaming/workflow_event_stream.py +33 -0
  234. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +28 -0
  235. autobyteus/workflow/streaming/workflow_stream_events.py +45 -0
  236. autobyteus/workflow/utils/__init__.py +9 -0
  237. autobyteus/workflow/utils/wait_for_idle.py +46 -0
  238. autobyteus/workflow/workflow_builder.py +151 -0
  239. {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/METADATA +16 -14
  240. autobyteus-1.1.5.dist-info/RECORD +455 -0
  241. {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/top_level.txt +1 -0
  242. examples/__init__.py +1 -0
  243. examples/agent_team/__init__.py +1 -0
  244. examples/discover_phase_transitions.py +104 -0
  245. examples/run_browser_agent.py +262 -0
  246. examples/run_google_slides_agent.py +287 -0
  247. examples/run_mcp_browser_client.py +174 -0
  248. examples/run_mcp_google_slides_client.py +270 -0
  249. examples/run_mcp_list_tools.py +189 -0
  250. examples/run_poem_writer.py +284 -0
  251. examples/run_sqlite_agent.py +295 -0
  252. autobyteus/agent/context/agent_phase_manager.py +0 -264
  253. autobyteus/agent/context/phases.py +0 -49
  254. autobyteus/agent/group/__init__.py +0 -0
  255. autobyteus/agent/group/agent_group.py +0 -164
  256. autobyteus/agent/group/agent_group_context.py +0 -81
  257. autobyteus/agent/input_processor/content_prefixing_input_processor.py +0 -41
  258. autobyteus/agent/input_processor/metadata_appending_input_processor.py +0 -34
  259. autobyteus/agent/input_processor/passthrough_input_processor.py +0 -33
  260. autobyteus/agent/workflow/__init__.py +0 -11
  261. autobyteus/agent/workflow/agentic_workflow.py +0 -89
  262. autobyteus/tools/mcp/call_handlers/__init__.py +0 -16
  263. autobyteus/tools/mcp/call_handlers/base_handler.py +0 -40
  264. autobyteus/tools/mcp/call_handlers/stdio_handler.py +0 -76
  265. autobyteus/tools/mcp/call_handlers/streamable_http_handler.py +0 -55
  266. autobyteus/tools/mcp/registrar.py +0 -202
  267. autobyteus/tools/usage/providers/json_example_provider.py +0 -32
  268. autobyteus/tools/usage/providers/json_schema_provider.py +0 -35
  269. autobyteus/tools/usage/providers/json_tool_usage_parser_provider.py +0 -28
  270. autobyteus/tools/usage/providers/xml_example_provider.py +0 -28
  271. autobyteus/tools/usage/providers/xml_schema_provider.py +0 -29
  272. autobyteus/tools/usage/providers/xml_tool_usage_parser_provider.py +0 -26
  273. autobyteus/tools/usage/registries/json_example_formatter_registry.py +0 -51
  274. autobyteus/tools/usage/registries/json_schema_formatter_registry.py +0 -51
  275. autobyteus/tools/usage/registries/json_tool_usage_parser_registry.py +0 -42
  276. autobyteus/tools/usage/registries/xml_example_formatter_registry.py +0 -30
  277. autobyteus/tools/usage/registries/xml_schema_formatter_registry.py +0 -33
  278. autobyteus/tools/usage/registries/xml_tool_usage_parser_registry.py +0 -30
  279. autobyteus/workflow/simple_task.py +0 -98
  280. autobyteus/workflow/task.py +0 -147
  281. autobyteus/workflow/workflow.py +0 -49
  282. autobyteus-1.1.3.dist-info/RECORD +0 -312
  283. {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/WHEEL +0 -0
  284. {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/licenses/LICENSE +0 -0
@@ -1,150 +1,125 @@
1
- # file: autobyteus/autobyteus/agent/message/send_message_to.py
1
+ # file: autobyteus/agent/message/send_message_to.py
2
2
  import logging
3
3
  from typing import TYPE_CHECKING, Any, Optional
4
4
 
5
- from autobyteus.agent.message.inter_agent_message import InterAgentMessage
6
5
  from autobyteus.tools.base_tool import BaseTool
7
- from autobyteus.agent.group.agent_group_context import AgentGroupContext
8
- # Updated imports for schema
6
+ from autobyteus.tools.tool_category import ToolCategory
9
7
  from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
10
-
8
+ from autobyteus.tools.tool_config import ToolConfig
9
+ # This import is for type hinting only and avoids circular dependencies at runtime
11
10
  if TYPE_CHECKING:
12
11
  from autobyteus.agent.context import AgentContext
13
- from autobyteus.agent.agent import Agent
12
+ from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
13
+ from autobyteus.agent_team.context.team_manager import TeamManager
14
+ from autobyteus.agent_team.events.agent_team_events import InterAgentMessageRequestEvent
14
15
 
15
16
  logger = logging.getLogger(__name__)
16
17
 
17
18
  class SendMessageTo(BaseTool):
18
19
  """
19
- A tool for sending messages to other agents within the same AgentGroup.
20
- It utilizes AgentGroupContext injected into the calling agent's AgentContext
21
- to resolve recipient agents.
20
+ A tool for sending messages to other agents within the same agent team.
21
+ This tool dynamically retrieves the team communication channel from the
22
+ agent's context at runtime.
22
23
  """
23
- TOOL_NAME = "SendMessageTo" # Class attribute for the name
24
+ TOOL_NAME = "SendMessageTo"
25
+ CATEGORY = ToolCategory.AGENT_COMMUNICATION
26
+
27
+ def __init__(self, config: Optional[ToolConfig] = None):
28
+ """
29
+ Initializes the stateless SendMessageTo tool.
30
+ """
31
+ super().__init__(config=config)
32
+ # The TeamManager is no longer stored as an instance variable.
33
+ logger.debug("SendMessageTo tool initialized (stateless).")
24
34
 
25
- def __init__(self):
26
- super().__init__()
27
- logger.debug(f"{self.get_name()} tool initialized.") # Use get_name()
35
+ # The set_team_manager method has been removed.
28
36
 
29
37
  @classmethod
30
- def get_name(cls) -> str: # Implemented as per BaseTool requirement
38
+ def get_name(cls) -> str:
31
39
  return cls.TOOL_NAME
32
40
 
33
41
  @classmethod
34
42
  def get_description(cls) -> str:
35
- return ("Sends a message to another agent within the same group. "
36
- "Can target by role or specific agent ID.")
43
+ return ("Sends a message to another agent within the same team, starting them if necessary. "
44
+ "You must specify the recipient by their unique name as provided in your team manifest.")
37
45
 
38
46
  @classmethod
39
47
  def get_argument_schema(cls) -> Optional[ParameterSchema]:
40
48
  schema = ParameterSchema()
41
49
  schema.add_parameter(ParameterDefinition(
42
- name="recipient_role_name",
50
+ name="recipient_name",
43
51
  param_type=ParameterType.STRING,
44
- description="The general role name of the recipient agent (e.g., 'worker', 'reviewer').",
52
+ description='The unique name of the recipient agent (e.g., "Researcher", "Writer_1"). This MUST match a name from your team manifest.',
45
53
  required=True
46
54
  ))
47
55
  schema.add_parameter(ParameterDefinition(
48
56
  name="content",
49
57
  param_type=ParameterType.STRING,
50
- description="The actual message text.",
58
+ description="The actual message content or task instruction.",
51
59
  required=True
52
60
  ))
53
61
  schema.add_parameter(ParameterDefinition(
54
62
  name="message_type",
55
- param_type=ParameterType.STRING, # Or ENUM if InterAgentMessageType values are known and fixed for schema
63
+ param_type=ParameterType.STRING,
56
64
  description="Type of the message (e.g., TASK_ASSIGNMENT, CLARIFICATION). Custom types allowed.",
57
65
  required=True
58
66
  ))
59
- schema.add_parameter(ParameterDefinition(
60
- name="recipient_agent_id",
61
- param_type=ParameterType.STRING,
62
- description='Optional. Specific ID of the recipient agent. If "unknown" or omitted, resolves by role.',
63
- required=False,
64
- default_value=None # Explicitly no default, truly optional
65
- ))
66
67
  return schema
67
68
 
68
- # tool_usage_xml() and tool_usage_json() are inherited from BaseTool
69
- # get_config_schema() for instantiation defaults to None
70
-
71
69
  async def _execute(self,
72
70
  context: 'AgentContext',
73
- recipient_role_name: str,
71
+ recipient_name: str,
74
72
  content: str,
75
- message_type: str,
76
- recipient_agent_id: Optional[str] = None) -> str: # Named parameters
73
+ message_type: str) -> str:
77
74
  """
78
- Sends a message to another agent in the group.
79
- Arguments are validated by BaseTool.execute().
75
+ Creates and dispatches an InterAgentMessageRequestEvent to the parent agent team
76
+ by retrieving the TeamManager from the agent's context.
80
77
  """
81
- sender_agent_id = context.agent_id
82
- logger.info(f"Tool '{self.get_name()}': Sender '{sender_agent_id}' attempting to send message. "
83
- f"Recipient Role: '{recipient_role_name}', Recipient ID: '{recipient_agent_id}', Type: '{message_type}'.")
84
-
85
- group_context_any = context.custom_data.get('agent_group_context')
86
-
87
- if not isinstance(group_context_any, AgentGroupContext):
88
- error_msg = f"Tool '{self.get_name()}' critical error: AgentGroupContext not found or invalid in AgentContext.custom_data for agent '{sender_agent_id}'. Cannot send message."
89
- logger.error(error_msg)
78
+ # Local import to break circular dependency at module load time.
79
+ from autobyteus.agent_team.events.agent_team_events import InterAgentMessageRequestEvent
80
+
81
+ # --- NEW: Retrieve TeamManager dynamically from context ---
82
+ team_context: Optional['AgentTeamContext'] = context.custom_data.get("team_context")
83
+ if not team_context:
84
+ error_msg = "Critical error: SendMessageTo tool is not configured for team communication. It can only be used within a managed AgentTeam."
85
+ logger.error(f"Agent '{context.agent_id}': {error_msg}")
90
86
  return f"Error: {error_msg}"
91
87
 
92
- group_context: AgentGroupContext = group_context_any # Type cast after check
93
-
94
- target_agent: Optional['Agent'] = None
95
-
96
- # Use recipient_agent_id if provided and not explicitly "unknown" (case-insensitive)
97
- if recipient_agent_id and recipient_agent_id.lower() != "unknown":
98
- target_agent = group_context.get_agent(recipient_agent_id)
99
- if not target_agent:
100
- logger.warning(f"Tool '{self.get_name()}': Agent with ID '{recipient_agent_id}' not found in group '{group_context.group_id}'. "
101
- f"Attempting to find by role '{recipient_role_name}'.")
102
-
103
- if not target_agent:
104
- agents_with_role = group_context.get_agents_by_role(recipient_role_name)
105
- if not agents_with_role:
106
- error_msg = f"No agent found with role '{recipient_role_name}' (and specific ID '{recipient_agent_id}' if provided was not found) in group '{group_context.group_id}'."
107
- logger.error(f"Tool '{self.get_name()}': {error_msg}")
108
- return f"Error: {error_msg}"
109
-
110
- if len(agents_with_role) > 1:
111
- logger.warning(f"Tool '{self.get_name()}': Multiple agents ({len(agents_with_role)}) found for role '{recipient_role_name}'. "
112
- f"Sending to the first one: {agents_with_role[0].agent_id}. "
113
- "Consider using specific recipient_agent_id for clarity.")
114
- target_agent = agents_with_role[0]
115
- # Update recipient_agent_id to the one resolved by role if it was initially None or "unknown"
116
- recipient_agent_id = target_agent.agent_id
117
-
118
-
119
- if not target_agent:
120
- error_msg = f"Could not resolve recipient agent with role '{recipient_role_name}' or ID '{recipient_agent_id}'." # recipient_agent_id would be updated here
121
- logger.error(f"Tool '{self.get_name()}': {error_msg}")
88
+ team_manager: Optional['TeamManager'] = team_context.team_manager
89
+ if not team_manager:
90
+ # This is an internal framework error and should not happen in a correctly configured team.
91
+ error_msg = "Internal Error: TeamManager not found in the provided team_context."
92
+ logger.error(f"Agent '{context.agent_id}': {error_msg}")
122
93
  return f"Error: {error_msg}"
123
94
 
124
- try:
125
- message_to_send = InterAgentMessage.create_with_dynamic_message_type(
126
- recipient_role_name=target_agent.context.config.role,
127
- recipient_agent_id=target_agent.agent_id, # Use the definitively resolved agent ID
128
- content=content,
129
- message_type=message_type,
130
- sender_agent_id=sender_agent_id
131
- )
95
+ # --- Input Validation ---
96
+ if not isinstance(recipient_name, str) or not recipient_name.strip():
97
+ error_msg = "Error: `recipient_name` must be a non-empty string."
98
+ logger.error(f"Tool '{self.get_name()}' validation failed: {error_msg}")
99
+ return error_msg
100
+ if not isinstance(content, str) or not content.strip():
101
+ error_msg = "Error: `content` must be a non-empty string."
102
+ logger.error(f"Tool '{self.get_name()}' validation failed: {error_msg}")
103
+ return error_msg
104
+ if not isinstance(message_type, str) or not message_type.strip():
105
+ error_msg = "Error: `message_type` must be a non-empty string."
106
+ logger.error(f"Tool '{self.get_name()}' validation failed: {error_msg}")
107
+ return error_msg
132
108
 
133
- await target_agent.post_inter_agent_message(message_to_send)
134
- success_msg = (f"Message successfully sent from '{sender_agent_id}' to agent "
135
- f"'{target_agent.agent_id}' (Role: '{target_agent.context.config.role}').")
136
- logger.info(f"Tool '{self.get_name()}': {success_msg}")
137
- return success_msg
138
- except ValueError as ve:
139
- error_msg = f"Error creating message: {str(ve)}"
140
- logger.error(f"Tool '{self.get_name()}': {error_msg}", exc_info=True)
141
- return f"Error: {error_msg}"
142
- except Exception as e:
143
- error_msg = f"An unexpected error occurred while sending message: {str(e)}"
144
- logger.error(f"Tool '{self.get_name()}': {error_msg}", exc_info=True)
145
- return f"Error: {error_msg}"
109
+ sender_agent_id = context.agent_id
110
+ logger.info(f"Tool '{self.get_name()}': Agent '{sender_agent_id}' requesting to send message to '{recipient_name}'.")
111
+
112
+ # Create the event for the agent team to handle
113
+ event = InterAgentMessageRequestEvent(
114
+ sender_agent_id=sender_agent_id,
115
+ recipient_name=recipient_name,
116
+ content=content,
117
+ message_type=message_type
118
+ )
119
+
120
+ # Dispatch the event "up" to the team's event loop via the dynamically retrieved team manager
121
+ await team_manager.dispatch_inter_agent_message_request(event)
146
122
 
147
- # tool_usage_xml was defined directly here, this is now inherited from BaseTool
148
- # BaseTool.tool_usage_xml() will use get_argument_schema() to generate it.
149
- # If a custom XML format was desired that differs from the auto-generated one,
150
- # then this method could be overridden. For now, assume auto-generated is fine.
123
+ success_msg = f"Message dispatch for recipient '{recipient_name}' has been successfully requested."
124
+ logger.info(f"Tool '{self.get_name()}': {success_msg}")
125
+ return success_msg
@@ -3,7 +3,8 @@ import inspect
3
3
  import logging
4
4
  from typing import List, Optional
5
5
 
6
- from autobyteus.agent.context.agent_phase_manager import AgentPhaseManager
6
+ from autobyteus.agent.phases.manager import AgentPhaseManager
7
+
7
8
  from .transition_info import PhaseTransitionInfo
8
9
 
9
10
  logger = logging.getLogger(__name__)
@@ -5,7 +5,7 @@ import traceback
5
5
  import concurrent.futures
6
6
  from typing import Optional, Any, Callable, Awaitable, TYPE_CHECKING
7
7
 
8
- from autobyteus.agent.context import AgentContext
8
+ from autobyteus.agent.context import AgentContext, AgentContextRegistry
9
9
  from autobyteus.agent.phases import AgentOperationalPhase, AgentPhaseManager
10
10
  from autobyteus.agent.events.notifiers import AgentExternalEventNotifier
11
11
  from autobyteus.agent.events import BaseEvent
@@ -39,8 +39,12 @@ class AgentRuntime:
39
39
  event_handler_registry=self.event_handler_registry,
40
40
  )
41
41
  self._worker.add_done_callback(self._handle_worker_completion)
42
+
43
+ # Register the context with the global registry
44
+ self._context_registry = AgentContextRegistry()
45
+ self._context_registry.register_context(self.context)
42
46
 
43
- logger.info(f"AgentRuntime initialized for agent_id '{self.context.agent_id}'.")
47
+ logger.info(f"AgentRuntime initialized for agent_id '{self.context.agent_id}'. Context registered.")
44
48
 
45
49
  def get_worker_loop(self) -> Optional[asyncio.AbstractEventLoop]:
46
50
  return self._worker.get_worker_loop()
@@ -122,6 +126,10 @@ class AgentRuntime:
122
126
 
123
127
  # LLM instance cleanup is now handled by the AgentWorker before its loop closes.
124
128
 
129
+ # Unregister the context from the global registry
130
+ self._context_registry.unregister_context(agent_id)
131
+ logger.info(f"AgentRuntime for '{agent_id}': Context unregistered.")
132
+
125
133
  await self.phase_manager.notify_final_shutdown_complete()
126
134
  logger.info(f"AgentRuntime for '{agent_id}' stop() method completed.")
127
135
 
@@ -221,6 +221,7 @@ class AgentWorker:
221
221
  # Wait for the main thread future to complete.
222
222
  if self._thread_future:
223
223
  try:
224
+ # FIX: Use asyncio.wait_for() to handle the timeout correctly.
224
225
  await asyncio.wait_for(asyncio.wrap_future(self._thread_future), timeout=timeout)
225
226
  logger.info(f"AgentWorker '{agent_id}': Worker thread has terminated.")
226
227
  except asyncio.TimeoutError:
@@ -0,0 +1,15 @@
1
+ # file: autobyteus/autobyteus/agent/sender_type.py
2
+ from enum import Enum
3
+ from typing import Set
4
+
5
+ class SenderType(str, Enum):
6
+ """
7
+ Categorizes the origin of a message or event within the system.
8
+ """
9
+ USER = "user" # A message originating from an external human user.
10
+ AGENT = "agent" # A message from another agent within the same team or a different team.
11
+ SYSTEM = "system" # An automated message from an internal system component.
12
+
13
+
14
+ # --- System Sender Identification ---
15
+ TASK_NOTIFIER_SENDER_ID = "system.task_notifier"
@@ -16,6 +16,7 @@ from autobyteus.agent.streaming.stream_event_payloads import (
16
16
  create_error_event_data,
17
17
  create_tool_invocation_approval_requested_data,
18
18
  create_tool_invocation_auto_executing_data,
19
+ create_system_task_notification_data, # NEW
19
20
  AssistantChunkData,
20
21
  AssistantCompleteResponseData,
21
22
  ToolInteractionLogEntryData,
@@ -23,6 +24,7 @@ from autobyteus.agent.streaming.stream_event_payloads import (
23
24
  ToolInvocationApprovalRequestedData,
24
25
  ToolInvocationAutoExecutingData,
25
26
  ErrorEventData,
27
+ SystemTaskNotificationData, # NEW
26
28
  EmptyData,
27
29
  StreamDataPayload,
28
30
  )
@@ -101,6 +103,10 @@ class AgentEventStream(EventEmitter):
101
103
  elif event_type == EventType.AGENT_ERROR_OUTPUT_GENERATION:
102
104
  typed_payload_for_stream_event = create_error_event_data(payload)
103
105
  stream_event_type_for_generic_stream = StreamEventType.ERROR_EVENT
106
+ # NEW MAPPING
107
+ elif event_type == EventType.AGENT_DATA_SYSTEM_TASK_NOTIFICATION_RECEIVED:
108
+ typed_payload_for_stream_event = create_system_task_notification_data(payload)
109
+ stream_event_type_for_generic_stream = StreamEventType.SYSTEM_TASK_NOTIFICATION
104
110
 
105
111
  elif event_type in [EventType.AGENT_DATA_ASSISTANT_CHUNK_STREAM_END, EventType.AGENT_DATA_TOOL_LOG_STREAM_END]:
106
112
  pass
@@ -55,6 +55,11 @@ class ToolInvocationAutoExecutingData(BaseStreamPayload):
55
55
  tool_name: str
56
56
  arguments: Dict[str, Any]
57
57
 
58
+ # NEW PAYLOAD
59
+ class SystemTaskNotificationData(BaseStreamPayload):
60
+ sender_id: str
61
+ content: str
62
+
58
63
  class EmptyData(BaseStreamPayload):
59
64
  pass
60
65
 
@@ -67,6 +72,7 @@ StreamDataPayload = Union[
67
72
  ErrorEventData,
68
73
  ToolInvocationApprovalRequestedData,
69
74
  ToolInvocationAutoExecutingData,
75
+ SystemTaskNotificationData, # NEW
70
76
  EmptyData
71
77
  ]
72
78
 
@@ -165,3 +171,9 @@ def create_tool_invocation_auto_executing_data(auto_exec_data_dict: Any) -> Tool
165
171
  if isinstance(auto_exec_data_dict, dict):
166
172
  return ToolInvocationAutoExecutingData(**auto_exec_data_dict)
167
173
  raise ValueError(f"Cannot create ToolInvocationAutoExecutingData from {type(auto_exec_data_dict)}")
174
+
175
+ # NEW FACTORY FUNCTION
176
+ def create_system_task_notification_data(notification_data_dict: Any) -> SystemTaskNotificationData:
177
+ if isinstance(notification_data_dict, dict):
178
+ return SystemTaskNotificationData(**notification_data_dict)
179
+ raise ValueError(f"Cannot create SystemTaskNotificationData from {type(notification_data_dict)}")
@@ -16,6 +16,7 @@ from .stream_event_payloads import (
16
16
  ErrorEventData,
17
17
  ToolInvocationApprovalRequestedData,
18
18
  ToolInvocationAutoExecutingData,
19
+ SystemTaskNotificationData, # NEW
19
20
  EmptyData
20
21
  )
21
22
 
@@ -33,6 +34,7 @@ class StreamEventType(str, Enum):
33
34
  ERROR_EVENT = "error_event"
34
35
  TOOL_INVOCATION_APPROVAL_REQUESTED = "tool_invocation_approval_requested"
35
36
  TOOL_INVOCATION_AUTO_EXECUTING = "tool_invocation_auto_executing"
37
+ SYSTEM_TASK_NOTIFICATION = "system_task_notification" # NEW
36
38
  AGENT_IDLE = "agent_idle"
37
39
 
38
40
 
@@ -44,6 +46,7 @@ _STREAM_EVENT_TYPE_TO_PAYLOAD_CLASS: Dict[StreamEventType, Type[BaseModel]] = {
44
46
  StreamEventType.ERROR_EVENT: ErrorEventData,
45
47
  StreamEventType.TOOL_INVOCATION_APPROVAL_REQUESTED: ToolInvocationApprovalRequestedData,
46
48
  StreamEventType.TOOL_INVOCATION_AUTO_EXECUTING: ToolInvocationAutoExecutingData,
49
+ StreamEventType.SYSTEM_TASK_NOTIFICATION: SystemTaskNotificationData, # NEW
47
50
  StreamEventType.AGENT_IDLE: AgentOperationalPhaseTransitionData,
48
51
  }
49
52
 
@@ -6,6 +6,7 @@ from .base_processor import BaseSystemPromptProcessor
6
6
  from autobyteus.tools.registry import default_tool_registry, ToolDefinition
7
7
  from autobyteus.tools.usage.providers import ToolManifestProvider
8
8
  from autobyteus.prompt.prompt_template import PromptTemplate
9
+ from autobyteus.llm.providers import LLMProvider
9
10
 
10
11
  if TYPE_CHECKING:
11
12
  from autobyteus.tools.base_tool import BaseTool
@@ -18,6 +19,7 @@ class ToolManifestInjectorProcessor(BaseSystemPromptProcessor):
18
19
  Injects a tool manifest into the system prompt using Jinja2-style placeholders.
19
20
  It primarily targets the '{{tools}}' variable. It uses PromptTemplate for
20
21
  rendering and delegates manifest generation to a ToolManifestProvider.
22
+ It automatically determines whether to use XML or JSON based on the LLM provider.
21
23
  """
22
24
  # The '{{tools}}' placeholder is now handled by Jinja2 via PromptTemplate.
23
25
  DEFAULT_PREFIX_FOR_TOOLS_ONLY_PROMPT = "You have access to a set of tools. Use them by outputting the appropriate tool call format. The user can only see the output of the tool, not the call itself. The available tools are:\n\n"
@@ -42,6 +44,10 @@ class ToolManifestInjectorProcessor(BaseSystemPromptProcessor):
42
44
  if "tools" not in prompt_template.required_vars:
43
45
  return system_prompt
44
46
 
47
+ llm_provider = None
48
+ if context.llm_instance and context.llm_instance.model:
49
+ llm_provider = context.llm_instance.model.provider
50
+
45
51
  # Generate the manifest string for the 'tools' variable.
46
52
  tools_manifest: str
47
53
  if not tool_instances:
@@ -52,13 +58,10 @@ class ToolManifestInjectorProcessor(BaseSystemPromptProcessor):
52
58
  td for name in tool_instances if (td := default_tool_registry.get_tool_definition(name))
53
59
  ]
54
60
 
55
- llm_provider = context.llm_instance.model.provider if context.llm_instance and context.llm_instance.model else None
56
-
57
61
  try:
58
- # Delegate manifest generation to the provider
62
+ # Delegate manifest generation to the provider, which now handles all format logic.
59
63
  tools_manifest = self._manifest_provider.provide(
60
64
  tool_definitions=tool_definitions,
61
- use_xml=context.config.use_xml_tool_format,
62
65
  provider=llm_provider
63
66
  )
64
67
  except Exception as e:
@@ -0,0 +1,9 @@
1
+ # file: autobyteus/autobyteus/agent/tool_execution_result_processor/__init__.py
2
+ """
3
+ Components for processing tool execution results before they are sent to the LLM.
4
+ """
5
+ from .base_processor import BaseToolExecutionResultProcessor
6
+
7
+ __all__ = [
8
+ "BaseToolExecutionResultProcessor",
9
+ ]
@@ -0,0 +1,46 @@
1
+ # file: autobyteus/autobyteus/agent/tool_execution_result_processor/base_processor.py
2
+ import logging
3
+ from abc import ABC, abstractmethod
4
+ from typing import TYPE_CHECKING
5
+
6
+ from .processor_meta import ToolExecutionResultProcessorMeta
7
+
8
+ if TYPE_CHECKING:
9
+ from autobyteus.agent.context import AgentContext
10
+ from autobyteus.agent.events import ToolResultEvent
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ class BaseToolExecutionResultProcessor(ABC, metaclass=ToolExecutionResultProcessorMeta):
15
+ """
16
+ Abstract base class for processors that can modify a tool's execution result.
17
+ These processors are applied after a tool runs but before its result is formatted
18
+ for the LLM.
19
+ """
20
+
21
+ @classmethod
22
+ def get_name(cls) -> str:
23
+ """
24
+ Returns the unique registration name for this processor.
25
+ Defaults to the class name.
26
+ """
27
+ return cls.__name__
28
+
29
+ @abstractmethod
30
+ async def process(self,
31
+ event: 'ToolResultEvent',
32
+ context: 'AgentContext') -> 'ToolResultEvent':
33
+ """
34
+ Processes the given ToolResultEvent.
35
+
36
+ Args:
37
+ event: The ToolResultEvent containing the tool's output or error.
38
+ context: The agent's context, providing access to config and state.
39
+
40
+ Returns:
41
+ The processed (potentially modified) ToolResultEvent.
42
+ """
43
+ raise NotImplementedError("Subclasses must implement the 'process' method.")
44
+
45
+ def __repr__(self) -> str:
46
+ return f"<{self.__class__.__name__}>"
@@ -0,0 +1,36 @@
1
+ # file: autobyteus/autobyteus/agent/tool_execution_result_processor/processor_definition.py
2
+ import logging
3
+ from typing import Type, TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from .base_processor import BaseToolExecutionResultProcessor
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ class ToolExecutionResultProcessorDefinition:
11
+ """
12
+ Represents the definition of a tool execution result processor.
13
+ Contains its registered name and the class itself.
14
+ """
15
+ def __init__(self, name: str, processor_class: Type['BaseToolExecutionResultProcessor']):
16
+ """
17
+ Initializes the ToolExecutionResultProcessorDefinition.
18
+
19
+ Args:
20
+ name: The unique registered name of the processor.
21
+ processor_class: The class of the tool execution result processor.
22
+
23
+ Raises:
24
+ ValueError: If name is empty or processor_class is not a type.
25
+ """
26
+ if not name or not isinstance(name, str):
27
+ raise ValueError("Tool Execution Result Processor name must be a non-empty string.")
28
+ if not isinstance(processor_class, type):
29
+ raise ValueError("processor_class must be a class type.")
30
+
31
+ self.name: str = name
32
+ self.processor_class: Type['BaseToolExecutionResultProcessor'] = processor_class
33
+ logger.debug(f"ToolExecutionResultProcessorDefinition created: name='{name}', class='{processor_class.__name__}'.")
34
+
35
+ def __repr__(self) -> str:
36
+ return f"<ToolExecutionResultProcessorDefinition name='{self.name}', class='{self.processor_class.__name__}'>"
@@ -0,0 +1,36 @@
1
+ # file: autobyteus/autobyteus/agent/tool_execution_result_processor/processor_meta.py
2
+ import logging
3
+ from abc import ABCMeta
4
+
5
+ from .processor_registry import default_tool_execution_result_processor_registry
6
+ from .processor_definition import ToolExecutionResultProcessorDefinition
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ class ToolExecutionResultProcessorMeta(ABCMeta):
11
+ """
12
+ Metaclass for BaseToolExecutionResultProcessor that automatically registers
13
+ concrete processor subclasses with the default registry.
14
+ """
15
+ def __init__(cls, name, bases, dct):
16
+ super().__init__(name, bases, dct)
17
+
18
+ if name == 'BaseToolExecutionResultProcessor' or getattr(cls, "__abstractmethods__", None):
19
+ logger.debug(f"Skipping registration for abstract tool execution result processor class: {name}")
20
+ return
21
+
22
+ try:
23
+ processor_name = cls.get_name()
24
+
25
+ if not processor_name or not isinstance(processor_name, str):
26
+ logger.error(f"Tool execution result processor class {name} must return a valid string from get_name(). Skipping.")
27
+ return
28
+
29
+ definition = ToolExecutionResultProcessorDefinition(name=processor_name, processor_class=cls)
30
+ default_tool_execution_result_processor_registry.register_processor(definition)
31
+ logger.info(f"Auto-registered tool execution result processor: '{processor_name}' from class {name}.")
32
+
33
+ except AttributeError as e:
34
+ logger.error(f"Tool execution result processor class {name} is missing 'get_name' method ({e}). Skipping registration.")
35
+ except Exception as e:
36
+ logger.error(f"Failed to auto-register tool execution result processor class {name}: {e}", exc_info=True)
@@ -0,0 +1,70 @@
1
+ # file: autobyteus/autobyteus/agent/tool_execution_result_processor/processor_registry.py
2
+ import logging
3
+ from typing import TYPE_CHECKING, Dict, List, Optional
4
+
5
+ from autobyteus.utils.singleton import SingletonMeta
6
+ from .processor_definition import ToolExecutionResultProcessorDefinition
7
+
8
+ if TYPE_CHECKING:
9
+ from .base_processor import BaseToolExecutionResultProcessor
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ class ToolExecutionResultProcessorRegistry(metaclass=SingletonMeta):
14
+ """
15
+ A singleton registry for ToolExecutionResultProcessorDefinition objects.
16
+ Processors are typically auto-registered via ToolExecutionResultProcessorMeta.
17
+ """
18
+
19
+ def __init__(self):
20
+ """Initializes the registry with an empty store."""
21
+ self._definitions: Dict[str, ToolExecutionResultProcessorDefinition] = {}
22
+ logger.info("ToolExecutionResultProcessorRegistry initialized.")
23
+
24
+ def register_processor(self, definition: ToolExecutionResultProcessorDefinition) -> None:
25
+ """
26
+ Registers a tool execution result processor definition.
27
+ """
28
+ if not isinstance(definition, ToolExecutionResultProcessorDefinition):
29
+ raise TypeError(f"Expected ToolExecutionResultProcessorDefinition instance, got {type(definition).__name__}.")
30
+
31
+ processor_name = definition.name
32
+ if processor_name in self._definitions:
33
+ logger.warning(f"Overwriting existing tool execution result processor definition for name: '{processor_name}'.")
34
+
35
+ self._definitions[processor_name] = definition
36
+ logger.info(f"Tool execution result processor definition '{processor_name}' registered successfully.")
37
+
38
+ def get_processor_definition(self, name: str) -> Optional[ToolExecutionResultProcessorDefinition]:
39
+ """
40
+ Retrieves a processor definition by its name.
41
+ """
42
+ return self._definitions.get(name)
43
+
44
+ def get_processor(self, name: str) -> Optional['BaseToolExecutionResultProcessor']:
45
+ """
46
+ Retrieves an instance of a processor by its name.
47
+ """
48
+ definition = self.get_processor_definition(name)
49
+ if definition:
50
+ try:
51
+ return definition.processor_class()
52
+ except Exception as e:
53
+ logger.error(f"Failed to instantiate tool execution result processor '{name}': {e}", exc_info=True)
54
+ return None
55
+ return None
56
+
57
+ def list_processor_names(self) -> List[str]:
58
+ """
59
+ Returns a list of names of all registered processor definitions.
60
+ """
61
+ return list(self._definitions.keys())
62
+
63
+ def get_all_definitions(self) -> Dict[str, ToolExecutionResultProcessorDefinition]:
64
+ """
65
+ Returns a dictionary of all registered processor definitions.
66
+ """
67
+ return dict(self._definitions)
68
+
69
+ # Default instance of the registry
70
+ default_tool_execution_result_processor_registry = ToolExecutionResultProcessorRegistry()