autobyteus 1.2.0__py3-none-any.whl → 1.2.3__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 (512) hide show
  1. autobyteus/agent/agent.py +15 -5
  2. autobyteus/agent/bootstrap_steps/__init__.py +1 -3
  3. autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +3 -59
  4. autobyteus/agent/bootstrap_steps/base_bootstrap_step.py +1 -4
  5. autobyteus/agent/bootstrap_steps/mcp_server_prewarming_step.py +1 -3
  6. autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +16 -13
  7. autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +2 -4
  8. autobyteus/agent/context/agent_config.py +43 -20
  9. autobyteus/agent/context/agent_context.py +23 -18
  10. autobyteus/agent/context/agent_runtime_state.py +23 -19
  11. autobyteus/agent/events/__init__.py +16 -1
  12. autobyteus/agent/events/agent_events.py +43 -3
  13. autobyteus/agent/events/agent_input_event_queue_manager.py +79 -26
  14. autobyteus/agent/events/event_store.py +57 -0
  15. autobyteus/agent/events/notifiers.py +74 -60
  16. autobyteus/agent/events/worker_event_dispatcher.py +21 -64
  17. autobyteus/agent/factory/agent_factory.py +52 -0
  18. autobyteus/agent/handlers/__init__.py +2 -0
  19. autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +51 -34
  20. autobyteus/agent/handlers/bootstrap_event_handler.py +155 -0
  21. autobyteus/agent/handlers/inter_agent_message_event_handler.py +10 -0
  22. autobyteus/agent/handlers/lifecycle_event_logger.py +19 -11
  23. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +10 -15
  24. autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +188 -48
  25. autobyteus/agent/handlers/tool_execution_approval_event_handler.py +0 -10
  26. autobyteus/agent/handlers/tool_invocation_request_event_handler.py +53 -48
  27. autobyteus/agent/handlers/tool_result_event_handler.py +7 -8
  28. autobyteus/agent/handlers/user_input_message_event_handler.py +10 -3
  29. autobyteus/agent/input_processor/memory_ingest_input_processor.py +40 -0
  30. autobyteus/agent/lifecycle/__init__.py +12 -0
  31. autobyteus/agent/lifecycle/base_processor.py +109 -0
  32. autobyteus/agent/lifecycle/events.py +35 -0
  33. autobyteus/agent/lifecycle/processor_definition.py +36 -0
  34. autobyteus/agent/lifecycle/processor_registry.py +106 -0
  35. autobyteus/agent/llm_request_assembler.py +98 -0
  36. autobyteus/agent/llm_response_processor/__init__.py +1 -8
  37. autobyteus/agent/message/context_file_type.py +1 -1
  38. autobyteus/agent/message/send_message_to.py +5 -4
  39. autobyteus/agent/runtime/agent_runtime.py +29 -21
  40. autobyteus/agent/runtime/agent_worker.py +98 -19
  41. autobyteus/agent/shutdown_steps/__init__.py +2 -0
  42. autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
  43. autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
  44. autobyteus/agent/status/__init__.py +14 -0
  45. autobyteus/agent/status/manager.py +93 -0
  46. autobyteus/agent/status/status_deriver.py +96 -0
  47. autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
  48. autobyteus/agent/status/status_update_utils.py +73 -0
  49. autobyteus/agent/streaming/__init__.py +52 -5
  50. autobyteus/agent/streaming/adapters/__init__.py +18 -0
  51. autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
  52. autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
  53. autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
  54. autobyteus/agent/streaming/agent_event_stream.py +3 -178
  55. autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
  56. autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
  57. autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
  58. autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
  59. autobyteus/agent/streaming/events/__init__.py +6 -0
  60. autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
  61. autobyteus/agent/streaming/events/stream_events.py +141 -0
  62. autobyteus/agent/streaming/handlers/__init__.py +15 -0
  63. autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
  64. autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
  65. autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
  66. autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
  67. autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
  68. autobyteus/agent/streaming/parser/__init__.py +61 -0
  69. autobyteus/agent/streaming/parser/event_emitter.py +181 -0
  70. autobyteus/agent/streaming/parser/events.py +4 -0
  71. autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
  72. autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
  73. autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
  74. autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
  75. autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
  76. autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
  77. autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
  78. autobyteus/agent/streaming/parser/parser_context.py +227 -0
  79. autobyteus/agent/streaming/parser/parser_factory.py +132 -0
  80. autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
  81. autobyteus/agent/streaming/parser/state_factory.py +62 -0
  82. autobyteus/agent/streaming/parser/states/__init__.py +1 -0
  83. autobyteus/agent/streaming/parser/states/base_state.py +60 -0
  84. autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
  85. autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
  86. autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
  87. autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
  88. autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
  89. autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
  90. autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
  91. autobyteus/agent/streaming/parser/states/text_state.py +78 -0
  92. autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
  93. autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
  94. autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
  95. autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
  96. autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
  97. autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
  98. autobyteus/agent/streaming/parser/strategies/base.py +24 -0
  99. autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
  100. autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
  101. autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
  102. autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
  103. autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
  104. autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
  105. autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
  106. autobyteus/agent/streaming/parser/tool_constants.py +7 -0
  107. autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
  108. autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
  109. autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
  110. autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
  111. autobyteus/agent/streaming/queue_streamer.py +3 -57
  112. autobyteus/agent/streaming/segments/__init__.py +5 -0
  113. autobyteus/agent/streaming/segments/segment_events.py +81 -0
  114. autobyteus/agent/streaming/stream_event_payloads.py +2 -198
  115. autobyteus/agent/streaming/stream_events.py +3 -128
  116. autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
  117. autobyteus/agent/streaming/streaming_response_handler.py +4 -0
  118. autobyteus/agent/streaming/streams/__init__.py +5 -0
  119. autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
  120. autobyteus/agent/streaming/utils/__init__.py +5 -0
  121. autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
  122. autobyteus/agent/system_prompt_processor/__init__.py +2 -0
  123. autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
  124. autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
  125. autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
  126. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
  127. autobyteus/agent/token_budget.py +56 -0
  128. autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
  129. autobyteus/agent/tool_invocation.py +16 -40
  130. autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
  131. autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
  132. autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
  133. autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
  134. autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
  135. autobyteus/agent/utils/wait_for_idle.py +12 -14
  136. autobyteus/agent/workspace/base_workspace.py +6 -27
  137. autobyteus/agent_team/agent_team.py +3 -3
  138. autobyteus/agent_team/agent_team_builder.py +1 -41
  139. autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
  140. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
  141. autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
  142. autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
  143. autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
  144. autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +5 -6
  145. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +15 -15
  146. autobyteus/agent_team/context/agent_team_config.py +6 -3
  147. autobyteus/agent_team/context/agent_team_context.py +25 -3
  148. autobyteus/agent_team/context/agent_team_runtime_state.py +11 -8
  149. autobyteus/agent_team/events/__init__.py +11 -0
  150. autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
  151. autobyteus/agent_team/events/agent_team_events.py +16 -0
  152. autobyteus/agent_team/events/event_store.py +57 -0
  153. autobyteus/agent_team/factory/agent_team_factory.py +8 -0
  154. autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
  155. autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
  156. autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
  157. autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
  158. autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
  159. autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
  160. autobyteus/agent_team/status/__init__.py +14 -0
  161. autobyteus/agent_team/status/agent_team_status.py +18 -0
  162. autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
  163. autobyteus/agent_team/status/status_deriver.py +62 -0
  164. autobyteus/agent_team/status/status_update_utils.py +42 -0
  165. autobyteus/agent_team/streaming/__init__.py +2 -2
  166. autobyteus/agent_team/streaming/agent_team_event_notifier.py +10 -10
  167. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +7 -7
  168. autobyteus/agent_team/streaming/agent_team_stream_events.py +11 -11
  169. autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
  170. autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
  171. autobyteus/agent_team/task_notification/activation_policy.py +1 -1
  172. autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +22 -22
  173. autobyteus/agent_team/task_notification/task_notification_mode.py +20 -1
  174. autobyteus/agent_team/utils/wait_for_idle.py +4 -4
  175. autobyteus/cli/agent_cli.py +18 -10
  176. autobyteus/cli/agent_team_tui/app.py +18 -15
  177. autobyteus/cli/agent_team_tui/state.py +21 -23
  178. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
  179. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +146 -39
  180. autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
  181. autobyteus/cli/agent_team_tui/widgets/shared.py +26 -26
  182. autobyteus/cli/agent_team_tui/widgets/{task_board_panel.py → task_plan_panel.py} +5 -5
  183. autobyteus/cli/cli_display.py +193 -44
  184. autobyteus/cli/workflow_tui/app.py +9 -10
  185. autobyteus/cli/workflow_tui/state.py +14 -16
  186. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
  187. autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
  188. autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
  189. autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
  190. autobyteus/clients/autobyteus_client.py +94 -1
  191. autobyteus/events/event_types.py +15 -21
  192. autobyteus/llm/api/autobyteus_llm.py +33 -29
  193. autobyteus/llm/api/claude_llm.py +142 -36
  194. autobyteus/llm/api/gemini_llm.py +163 -59
  195. autobyteus/llm/api/grok_llm.py +1 -1
  196. autobyteus/llm/api/minimax_llm.py +26 -0
  197. autobyteus/llm/api/mistral_llm.py +113 -87
  198. autobyteus/llm/api/ollama_llm.py +9 -42
  199. autobyteus/llm/api/openai_compatible_llm.py +127 -91
  200. autobyteus/llm/api/openai_llm.py +3 -3
  201. autobyteus/llm/api/openai_responses_llm.py +324 -0
  202. autobyteus/llm/api/zhipu_llm.py +21 -2
  203. autobyteus/llm/autobyteus_provider.py +70 -60
  204. autobyteus/llm/base_llm.py +85 -81
  205. autobyteus/llm/converters/__init__.py +14 -0
  206. autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
  207. autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
  208. autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
  209. autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
  210. autobyteus/llm/extensions/base_extension.py +6 -12
  211. autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
  212. autobyteus/llm/llm_factory.py +282 -204
  213. autobyteus/llm/lmstudio_provider.py +60 -49
  214. autobyteus/llm/models.py +35 -2
  215. autobyteus/llm/ollama_provider.py +60 -49
  216. autobyteus/llm/ollama_provider_resolver.py +0 -1
  217. autobyteus/llm/prompt_renderers/__init__.py +19 -0
  218. autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
  219. autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
  220. autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
  221. autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
  222. autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
  223. autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
  224. autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
  225. autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
  226. autobyteus/llm/providers.py +1 -3
  227. autobyteus/llm/token_counter/claude_token_counter.py +56 -25
  228. autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
  229. autobyteus/llm/token_counter/openai_token_counter.py +24 -5
  230. autobyteus/llm/token_counter/token_counter_factory.py +12 -5
  231. autobyteus/llm/utils/llm_config.py +6 -12
  232. autobyteus/llm/utils/media_payload_formatter.py +27 -20
  233. autobyteus/llm/utils/messages.py +55 -3
  234. autobyteus/llm/utils/response_types.py +3 -0
  235. autobyteus/llm/utils/tool_call_delta.py +31 -0
  236. autobyteus/memory/__init__.py +32 -0
  237. autobyteus/memory/active_transcript.py +69 -0
  238. autobyteus/memory/compaction/__init__.py +9 -0
  239. autobyteus/memory/compaction/compaction_result.py +8 -0
  240. autobyteus/memory/compaction/compactor.py +89 -0
  241. autobyteus/memory/compaction/summarizer.py +11 -0
  242. autobyteus/memory/compaction_snapshot_builder.py +84 -0
  243. autobyteus/memory/memory_manager.py +183 -0
  244. autobyteus/memory/models/__init__.py +14 -0
  245. autobyteus/memory/models/episodic_item.py +41 -0
  246. autobyteus/memory/models/memory_types.py +7 -0
  247. autobyteus/memory/models/raw_trace_item.py +79 -0
  248. autobyteus/memory/models/semantic_item.py +41 -0
  249. autobyteus/memory/models/tool_interaction.py +20 -0
  250. autobyteus/memory/policies/__init__.py +5 -0
  251. autobyteus/memory/policies/compaction_policy.py +16 -0
  252. autobyteus/memory/retrieval/__init__.py +7 -0
  253. autobyteus/memory/retrieval/memory_bundle.py +11 -0
  254. autobyteus/memory/retrieval/retriever.py +13 -0
  255. autobyteus/memory/store/__init__.py +7 -0
  256. autobyteus/memory/store/base_store.py +14 -0
  257. autobyteus/memory/store/file_store.py +98 -0
  258. autobyteus/memory/tool_interaction_builder.py +46 -0
  259. autobyteus/memory/turn_tracker.py +9 -0
  260. autobyteus/multimedia/audio/api/__init__.py +3 -2
  261. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
  262. autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
  263. autobyteus/multimedia/audio/api/openai_audio_client.py +112 -0
  264. autobyteus/multimedia/audio/audio_client_factory.py +84 -9
  265. autobyteus/multimedia/audio/audio_model.py +2 -1
  266. autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
  267. autobyteus/multimedia/image/api/gemini_image_client.py +38 -17
  268. autobyteus/multimedia/image/api/openai_image_client.py +125 -43
  269. autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
  270. autobyteus/multimedia/image/image_client_factory.py +47 -15
  271. autobyteus/multimedia/image/image_model.py +5 -2
  272. autobyteus/multimedia/providers.py +3 -2
  273. autobyteus/skills/loader.py +71 -0
  274. autobyteus/skills/model.py +11 -0
  275. autobyteus/skills/registry.py +70 -0
  276. autobyteus/task_management/__init__.py +43 -20
  277. autobyteus/task_management/{base_task_board.py → base_task_plan.py} +16 -13
  278. autobyteus/task_management/converters/__init__.py +2 -2
  279. autobyteus/task_management/converters/{task_board_converter.py → task_plan_converter.py} +13 -13
  280. autobyteus/task_management/events.py +7 -7
  281. autobyteus/task_management/{in_memory_task_board.py → in_memory_task_plan.py} +34 -22
  282. autobyteus/task_management/schemas/__init__.py +3 -0
  283. autobyteus/task_management/schemas/task_status_report.py +2 -2
  284. autobyteus/task_management/schemas/todo_definition.py +15 -0
  285. autobyteus/task_management/todo.py +29 -0
  286. autobyteus/task_management/todo_list.py +75 -0
  287. autobyteus/task_management/tools/__init__.py +24 -8
  288. autobyteus/task_management/tools/task_tools/__init__.py +19 -0
  289. autobyteus/task_management/tools/{assign_task_to.py → task_tools/assign_task_to.py} +18 -18
  290. autobyteus/task_management/tools/{publish_task.py → task_tools/create_task.py} +16 -18
  291. autobyteus/task_management/tools/{publish_tasks.py → task_tools/create_tasks.py} +19 -19
  292. autobyteus/task_management/tools/{get_my_tasks.py → task_tools/get_my_tasks.py} +15 -15
  293. autobyteus/task_management/tools/{get_task_board_status.py → task_tools/get_task_plan_status.py} +16 -16
  294. autobyteus/task_management/tools/{update_task_status.py → task_tools/update_task_status.py} +16 -16
  295. autobyteus/task_management/tools/todo_tools/__init__.py +18 -0
  296. autobyteus/task_management/tools/todo_tools/add_todo.py +78 -0
  297. autobyteus/task_management/tools/todo_tools/create_todo_list.py +79 -0
  298. autobyteus/task_management/tools/todo_tools/get_todo_list.py +55 -0
  299. autobyteus/task_management/tools/todo_tools/update_todo_status.py +85 -0
  300. autobyteus/tools/__init__.py +43 -52
  301. autobyteus/tools/base_tool.py +7 -0
  302. autobyteus/tools/file/__init__.py +9 -0
  303. autobyteus/tools/file/patch_file.py +149 -0
  304. autobyteus/tools/file/{file_reader.py → read_file.py} +38 -7
  305. autobyteus/tools/file/{file_writer.py → write_file.py} +7 -4
  306. autobyteus/tools/functional_tool.py +53 -14
  307. autobyteus/tools/mcp/__init__.py +2 -0
  308. autobyteus/tools/mcp/config_service.py +5 -1
  309. autobyteus/tools/mcp/server/__init__.py +2 -0
  310. autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
  311. autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
  312. autobyteus/tools/mcp/server_instance_manager.py +8 -1
  313. autobyteus/tools/mcp/tool.py +3 -3
  314. autobyteus/tools/mcp/tool_registrar.py +5 -2
  315. autobyteus/tools/mcp/types.py +61 -0
  316. autobyteus/tools/multimedia/__init__.py +2 -1
  317. autobyteus/tools/multimedia/audio_tools.py +72 -19
  318. autobyteus/tools/{download_media_tool.py → multimedia/download_media_tool.py} +21 -7
  319. autobyteus/tools/multimedia/image_tools.py +248 -64
  320. autobyteus/tools/multimedia/media_reader_tool.py +1 -1
  321. autobyteus/tools/operation_executor/journal_manager.py +107 -0
  322. autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
  323. autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
  324. autobyteus/tools/operation_executor/operation_executor.py +58 -0
  325. autobyteus/tools/registry/tool_definition.py +108 -14
  326. autobyteus/tools/registry/tool_registry.py +29 -0
  327. autobyteus/tools/search/__init__.py +17 -0
  328. autobyteus/tools/search/base_strategy.py +35 -0
  329. autobyteus/tools/search/client.py +24 -0
  330. autobyteus/tools/search/factory.py +81 -0
  331. autobyteus/tools/search/google_cse_strategy.py +68 -0
  332. autobyteus/tools/search/providers.py +10 -0
  333. autobyteus/tools/search/serpapi_strategy.py +65 -0
  334. autobyteus/tools/search/serper_strategy.py +87 -0
  335. autobyteus/tools/search_tool.py +83 -0
  336. autobyteus/tools/skill/load_skill.py +50 -0
  337. autobyteus/tools/terminal/__init__.py +45 -0
  338. autobyteus/tools/terminal/ansi_utils.py +32 -0
  339. autobyteus/tools/terminal/background_process_manager.py +233 -0
  340. autobyteus/tools/terminal/output_buffer.py +105 -0
  341. autobyteus/tools/terminal/prompt_detector.py +63 -0
  342. autobyteus/tools/terminal/pty_session.py +241 -0
  343. autobyteus/tools/terminal/session_factory.py +20 -0
  344. autobyteus/tools/terminal/terminal_session_manager.py +226 -0
  345. autobyteus/tools/terminal/tools/__init__.py +13 -0
  346. autobyteus/tools/terminal/tools/get_process_output.py +81 -0
  347. autobyteus/tools/terminal/tools/run_bash.py +109 -0
  348. autobyteus/tools/terminal/tools/start_background_process.py +104 -0
  349. autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
  350. autobyteus/tools/terminal/types.py +54 -0
  351. autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
  352. autobyteus/tools/terminal/wsl_utils.py +156 -0
  353. autobyteus/tools/tool_meta.py +4 -24
  354. autobyteus/tools/transaction_management/backup_handler.py +48 -0
  355. autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
  356. autobyteus/tools/usage/__init__.py +1 -2
  357. autobyteus/tools/usage/formatters/__init__.py +17 -1
  358. autobyteus/tools/usage/formatters/base_formatter.py +8 -0
  359. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
  360. autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
  361. autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
  362. autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
  363. autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
  364. autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
  365. autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
  366. autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
  367. autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
  368. autobyteus/tools/usage/registries/__init__.py +1 -3
  369. autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
  370. autobyteus/tools/usage/tool_schema_provider.py +51 -0
  371. autobyteus/tools/web/__init__.py +4 -0
  372. autobyteus/tools/web/read_url_tool.py +80 -0
  373. autobyteus/utils/diff_utils.py +271 -0
  374. autobyteus/utils/download_utils.py +109 -0
  375. autobyteus/utils/file_utils.py +57 -2
  376. autobyteus/utils/gemini_helper.py +56 -0
  377. autobyteus/utils/gemini_model_mapping.py +71 -0
  378. autobyteus/utils/llm_output_formatter.py +75 -0
  379. autobyteus/utils/tool_call_format.py +36 -0
  380. autobyteus/workflow/agentic_workflow.py +3 -3
  381. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
  382. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
  383. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
  384. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +4 -11
  385. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
  386. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
  387. autobyteus/workflow/context/workflow_context.py +3 -3
  388. autobyteus/workflow/context/workflow_runtime_state.py +5 -5
  389. autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
  390. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
  391. autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
  392. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
  393. autobyteus/workflow/runtime/workflow_runtime.py +8 -8
  394. autobyteus/workflow/runtime/workflow_worker.py +3 -3
  395. autobyteus/workflow/status/__init__.py +11 -0
  396. autobyteus/workflow/status/workflow_status.py +19 -0
  397. autobyteus/workflow/status/workflow_status_manager.py +48 -0
  398. autobyteus/workflow/streaming/__init__.py +2 -2
  399. autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
  400. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
  401. autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
  402. autobyteus/workflow/utils/wait_for_idle.py +4 -4
  403. autobyteus-1.2.3.dist-info/METADATA +293 -0
  404. autobyteus-1.2.3.dist-info/RECORD +600 -0
  405. {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
  406. {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/top_level.txt +0 -1
  407. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
  408. autobyteus/agent/hooks/__init__.py +0 -16
  409. autobyteus/agent/hooks/base_phase_hook.py +0 -78
  410. autobyteus/agent/hooks/hook_definition.py +0 -36
  411. autobyteus/agent/hooks/hook_meta.py +0 -37
  412. autobyteus/agent/hooks/hook_registry.py +0 -106
  413. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
  414. autobyteus/agent/phases/__init__.py +0 -18
  415. autobyteus/agent/phases/discover.py +0 -53
  416. autobyteus/agent/phases/manager.py +0 -265
  417. autobyteus/agent/phases/transition_decorator.py +0 -40
  418. autobyteus/agent/phases/transition_info.py +0 -33
  419. autobyteus/agent/remote_agent.py +0 -244
  420. autobyteus/agent/workspace/workspace_definition.py +0 -36
  421. autobyteus/agent/workspace/workspace_meta.py +0 -37
  422. autobyteus/agent/workspace/workspace_registry.py +0 -72
  423. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
  424. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
  425. autobyteus/agent_team/phases/__init__.py +0 -11
  426. autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
  427. autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
  428. autobyteus/llm/api/bedrock_llm.py +0 -92
  429. autobyteus/llm/api/groq_llm.py +0 -94
  430. autobyteus/llm/api/nvidia_llm.py +0 -108
  431. autobyteus/llm/utils/token_pricing_config.py +0 -87
  432. autobyteus/person/examples/sample_persons.py +0 -14
  433. autobyteus/person/examples/sample_roles.py +0 -14
  434. autobyteus/person/person.py +0 -29
  435. autobyteus/person/role.py +0 -14
  436. autobyteus/rpc/__init__.py +0 -73
  437. autobyteus/rpc/client/__init__.py +0 -17
  438. autobyteus/rpc/client/abstract_client_connection.py +0 -124
  439. autobyteus/rpc/client/client_connection_manager.py +0 -153
  440. autobyteus/rpc/client/sse_client_connection.py +0 -306
  441. autobyteus/rpc/client/stdio_client_connection.py +0 -280
  442. autobyteus/rpc/config/__init__.py +0 -13
  443. autobyteus/rpc/config/agent_server_config.py +0 -153
  444. autobyteus/rpc/config/agent_server_registry.py +0 -152
  445. autobyteus/rpc/hosting.py +0 -244
  446. autobyteus/rpc/protocol.py +0 -244
  447. autobyteus/rpc/server/__init__.py +0 -20
  448. autobyteus/rpc/server/agent_server_endpoint.py +0 -181
  449. autobyteus/rpc/server/base_method_handler.py +0 -40
  450. autobyteus/rpc/server/method_handlers.py +0 -259
  451. autobyteus/rpc/server/sse_server_handler.py +0 -182
  452. autobyteus/rpc/server/stdio_server_handler.py +0 -151
  453. autobyteus/rpc/server_main.py +0 -198
  454. autobyteus/rpc/transport_type.py +0 -13
  455. autobyteus/tools/bash/__init__.py +0 -2
  456. autobyteus/tools/bash/bash_executor.py +0 -100
  457. autobyteus/tools/browser/__init__.py +0 -2
  458. autobyteus/tools/browser/session_aware/__init__.py +0 -0
  459. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
  460. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
  461. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
  462. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
  463. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
  464. autobyteus/tools/browser/session_aware/factory/__init__.py +0 -0
  465. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
  466. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
  467. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
  468. autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
  469. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
  470. autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
  471. autobyteus/tools/browser/standalone/__init__.py +0 -6
  472. autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  473. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
  474. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
  475. autobyteus/tools/browser/standalone/navigate_to.py +0 -80
  476. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -97
  477. autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -165
  478. autobyteus/tools/browser/standalone/webpage_reader.py +0 -101
  479. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -101
  480. autobyteus/tools/file/file_editor.py +0 -200
  481. autobyteus/tools/google_search.py +0 -149
  482. autobyteus/tools/timer.py +0 -171
  483. autobyteus/tools/usage/parsers/__init__.py +0 -22
  484. autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
  485. autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
  486. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
  487. autobyteus/tools/usage/parsers/base_parser.py +0 -41
  488. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
  489. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
  490. autobyteus/tools/usage/parsers/exceptions.py +0 -13
  491. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
  492. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
  493. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
  494. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
  495. autobyteus/workflow/phases/__init__.py +0 -11
  496. autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
  497. autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
  498. autobyteus-1.2.0.dist-info/METADATA +0 -205
  499. autobyteus-1.2.0.dist-info/RECORD +0 -496
  500. examples/__init__.py +0 -1
  501. examples/agent_team/__init__.py +0 -1
  502. examples/discover_phase_transitions.py +0 -104
  503. examples/run_browser_agent.py +0 -262
  504. examples/run_google_slides_agent.py +0 -287
  505. examples/run_mcp_browser_client.py +0 -174
  506. examples/run_mcp_google_slides_client.py +0 -270
  507. examples/run_mcp_list_tools.py +0 -189
  508. examples/run_poem_writer.py +0 -284
  509. examples/run_sqlite_agent.py +0 -295
  510. /autobyteus/{person → skills}/__init__.py +0 -0
  511. /autobyteus/{person/examples → tools/skill}/__init__.py +0 -0
  512. {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,265 +0,0 @@
1
- # file: autobyteus/autobyteus/agent/phases/manager.py
2
- import asyncio
3
- import logging
4
- from typing import TYPE_CHECKING, Optional, Dict, Any
5
-
6
- from .phase_enum import AgentOperationalPhase
7
- from .transition_decorator import phase_transition
8
-
9
- if TYPE_CHECKING:
10
- from autobyteus.agent.context import AgentContext
11
- from autobyteus.agent.tool_invocation import ToolInvocation
12
- from autobyteus.agent.events.notifiers import AgentExternalEventNotifier
13
-
14
-
15
- logger = logging.getLogger(__name__)
16
-
17
- class AgentPhaseManager:
18
- """
19
- Manages the operational phase of an agent, uses an AgentExternalEventNotifier
20
- to signal phase changes externally, and executes phase transition hooks.
21
- """
22
- def __init__(self, context: 'AgentContext', notifier: 'AgentExternalEventNotifier'):
23
- self.context: 'AgentContext' = context
24
- self.notifier: 'AgentExternalEventNotifier' = notifier
25
-
26
- self.context.current_phase = AgentOperationalPhase.UNINITIALIZED
27
-
28
- logger.debug(f"AgentPhaseManager initialized for agent_id '{self.context.agent_id}'. "
29
- f"Initial phase: {self.context.current_phase.value}. Uses provided notifier.")
30
-
31
- async def _execute_hooks(self, old_phase: AgentOperationalPhase, new_phase: AgentOperationalPhase):
32
- """Asynchronously executes hooks that match the given phase transition."""
33
- hooks_to_run = [
34
- hook for hook in self.context.config.phase_hooks
35
- if hook.source_phase == old_phase and hook.target_phase == new_phase
36
- ]
37
-
38
- if not hooks_to_run:
39
- return
40
-
41
- hook_names = [hook.__class__.__name__ for hook in hooks_to_run]
42
- logger.info(f"Agent '{self.context.agent_id}': Executing {len(hooks_to_run)} hooks for transition "
43
- f"'{old_phase.value}' -> '{new_phase.value}': {hook_names}")
44
-
45
- for hook in hooks_to_run:
46
- try:
47
- await hook.execute(self.context)
48
- logger.debug(f"Agent '{self.context.agent_id}': Hook '{hook.__class__.__name__}' executed successfully.")
49
- except Exception as e:
50
- logger.error(f"Agent '{self.context.agent_id}': Error executing phase transition hook "
51
- f"'{hook.__class__.__name__}' for '{old_phase.value}' -> '{new_phase.value}': {e}",
52
- exc_info=True)
53
- # We log the error but do not halt the agent's phase transition.
54
-
55
- async def _transition_phase(self, new_phase: AgentOperationalPhase,
56
- notify_method_name: str,
57
- additional_data: Optional[Dict[str, Any]] = None):
58
- """
59
- Private async helper to change the agent's phase, execute hooks, and then
60
- call the appropriate notifier method. Hooks are now awaited.
61
- """
62
- if not isinstance(new_phase, AgentOperationalPhase):
63
- logger.error(f"AgentPhaseManager for '{self.context.agent_id}' received invalid type for new_phase: {type(new_phase)}. Must be AgentOperationalPhase.")
64
- return
65
-
66
- old_phase = self.context.current_phase
67
-
68
- if old_phase == new_phase:
69
- logger.debug(f"AgentPhaseManager for '{self.context.agent_id}': already in phase {new_phase.value}. No transition.")
70
- return
71
-
72
- logger.info(f"Agent '{self.context.agent_id}' phase transitioning from {old_phase.value} to {new_phase.value}.")
73
- self.context.current_phase = new_phase
74
-
75
- # Execute and wait for hooks to complete *before* notifying externally.
76
- await self._execute_hooks(old_phase, new_phase)
77
-
78
- notifier_method = getattr(self.notifier, notify_method_name, None)
79
- if notifier_method and callable(notifier_method):
80
- notify_args = {"old_phase": old_phase}
81
- if additional_data:
82
- notify_args.update(additional_data)
83
-
84
- notifier_method(**notify_args)
85
- else:
86
- logger.error(f"AgentPhaseManager for '{self.context.agent_id}': Notifier method '{notify_method_name}' not found or not callable on {type(self.notifier).__name__}.")
87
-
88
- @phase_transition(
89
- source_phases=[AgentOperationalPhase.SHUTDOWN_COMPLETE, AgentOperationalPhase.ERROR],
90
- target_phase=AgentOperationalPhase.UNINITIALIZED,
91
- description="Triggered when the agent runtime is started or restarted after being in a terminal state."
92
- )
93
- async def notify_runtime_starting_and_uninitialized(self) -> None:
94
- if self.context.current_phase == AgentOperationalPhase.UNINITIALIZED:
95
- await self._transition_phase(AgentOperationalPhase.UNINITIALIZED, "notify_phase_uninitialized_entered")
96
- elif self.context.current_phase.is_terminal():
97
- await self._transition_phase(AgentOperationalPhase.UNINITIALIZED, "notify_phase_uninitialized_entered")
98
- else:
99
- logger.warning(f"Agent '{self.context.agent_id}' notify_runtime_starting_and_uninitialized called in unexpected phase: {self.context.current_phase.value}")
100
-
101
- @phase_transition(
102
- source_phases=[AgentOperationalPhase.UNINITIALIZED],
103
- target_phase=AgentOperationalPhase.BOOTSTRAPPING,
104
- description="Occurs when the agent's internal bootstrapping process begins."
105
- )
106
- async def notify_bootstrapping_started(self) -> None:
107
- await self._transition_phase(AgentOperationalPhase.BOOTSTRAPPING, "notify_phase_bootstrapping_started")
108
-
109
- @phase_transition(
110
- source_phases=[AgentOperationalPhase.BOOTSTRAPPING],
111
- target_phase=AgentOperationalPhase.IDLE,
112
- description="Occurs when the agent successfully completes bootstrapping and is ready for input."
113
- )
114
- async def notify_initialization_complete(self) -> None:
115
- if self.context.current_phase.is_initializing() or self.context.current_phase == AgentOperationalPhase.UNINITIALIZED:
116
- # This will now be a BOOTSTRAPPING -> IDLE transition
117
- await self._transition_phase(AgentOperationalPhase.IDLE, "notify_phase_idle_entered")
118
- else:
119
- logger.warning(f"Agent '{self.context.agent_id}' notify_initialization_complete called in unexpected phase: {self.context.current_phase.value}")
120
-
121
- @phase_transition(
122
- source_phases=[
123
- AgentOperationalPhase.IDLE, AgentOperationalPhase.ANALYZING_LLM_RESPONSE,
124
- AgentOperationalPhase.PROCESSING_TOOL_RESULT, AgentOperationalPhase.EXECUTING_TOOL,
125
- AgentOperationalPhase.TOOL_DENIED
126
- ],
127
- target_phase=AgentOperationalPhase.PROCESSING_USER_INPUT,
128
- description="Fires when the agent begins processing a new user message or inter-agent message."
129
- )
130
- async def notify_processing_input_started(self, trigger_info: Optional[str] = None) -> None:
131
- if self.context.current_phase in [AgentOperationalPhase.IDLE, AgentOperationalPhase.ANALYZING_LLM_RESPONSE, AgentOperationalPhase.PROCESSING_TOOL_RESULT, AgentOperationalPhase.EXECUTING_TOOL, AgentOperationalPhase.TOOL_DENIED]:
132
- data = {"trigger_info": trigger_info} if trigger_info else {}
133
- await self._transition_phase(AgentOperationalPhase.PROCESSING_USER_INPUT, "notify_phase_processing_user_input_started", additional_data=data)
134
- elif self.context.current_phase == AgentOperationalPhase.PROCESSING_USER_INPUT:
135
- logger.debug(f"Agent '{self.context.agent_id}' already in PROCESSING_USER_INPUT phase.")
136
- else:
137
- logger.warning(f"Agent '{self.context.agent_id}' notify_processing_input_started called in unexpected phase: {self.context.current_phase.value}")
138
-
139
- @phase_transition(
140
- source_phases=[AgentOperationalPhase.PROCESSING_USER_INPUT, AgentOperationalPhase.PROCESSING_TOOL_RESULT],
141
- target_phase=AgentOperationalPhase.AWAITING_LLM_RESPONSE,
142
- description="Occurs just before the agent makes a call to the LLM."
143
- )
144
- async def notify_awaiting_llm_response(self) -> None:
145
- await self._transition_phase(AgentOperationalPhase.AWAITING_LLM_RESPONSE, "notify_phase_awaiting_llm_response_started")
146
-
147
- @phase_transition(
148
- source_phases=[AgentOperationalPhase.AWAITING_LLM_RESPONSE],
149
- target_phase=AgentOperationalPhase.ANALYZING_LLM_RESPONSE,
150
- description="Occurs after the agent has received a complete response from the LLM and begins to analyze it."
151
- )
152
- async def notify_analyzing_llm_response(self) -> None:
153
- await self._transition_phase(AgentOperationalPhase.ANALYZING_LLM_RESPONSE, "notify_phase_analyzing_llm_response_started")
154
-
155
- @phase_transition(
156
- source_phases=[AgentOperationalPhase.ANALYZING_LLM_RESPONSE],
157
- target_phase=AgentOperationalPhase.AWAITING_TOOL_APPROVAL,
158
- description="Occurs if the agent proposes a tool use that requires manual user approval."
159
- )
160
- async def notify_tool_execution_pending_approval(self, tool_invocation: 'ToolInvocation') -> None:
161
- await self._transition_phase(AgentOperationalPhase.AWAITING_TOOL_APPROVAL, "notify_phase_awaiting_tool_approval_started")
162
-
163
- @phase_transition(
164
- source_phases=[AgentOperationalPhase.AWAITING_TOOL_APPROVAL],
165
- target_phase=AgentOperationalPhase.EXECUTING_TOOL,
166
- description="Occurs after a pending tool use has been approved and is about to be executed."
167
- )
168
- async def notify_tool_execution_resumed_after_approval(self, approved: bool, tool_name: Optional[str]) -> None:
169
- if approved and tool_name:
170
- await self._transition_phase(AgentOperationalPhase.EXECUTING_TOOL, "notify_phase_executing_tool_started", additional_data={"tool_name": tool_name})
171
- else:
172
- logger.info(f"Agent '{self.context.agent_id}' tool execution denied for '{tool_name}'. Transitioning to allow LLM to process denial.")
173
- await self.notify_tool_denied(tool_name)
174
-
175
- @phase_transition(
176
- source_phases=[AgentOperationalPhase.AWAITING_TOOL_APPROVAL],
177
- target_phase=AgentOperationalPhase.TOOL_DENIED,
178
- description="Occurs after a pending tool use has been denied by the user."
179
- )
180
- async def notify_tool_denied(self, tool_name: Optional[str]) -> None:
181
- """Notifies that a tool execution has been denied."""
182
- await self._transition_phase(
183
- AgentOperationalPhase.TOOL_DENIED,
184
- "notify_phase_tool_denied_started",
185
- additional_data={"tool_name": tool_name, "denial_for_tool": tool_name}
186
- )
187
-
188
- @phase_transition(
189
- source_phases=[AgentOperationalPhase.ANALYZING_LLM_RESPONSE],
190
- target_phase=AgentOperationalPhase.EXECUTING_TOOL,
191
- description="Occurs when an agent with auto-approval executes a tool."
192
- )
193
- async def notify_tool_execution_started(self, tool_name: str) -> None:
194
- await self._transition_phase(AgentOperationalPhase.EXECUTING_TOOL, "notify_phase_executing_tool_started", additional_data={"tool_name": tool_name})
195
-
196
- @phase_transition(
197
- source_phases=[AgentOperationalPhase.EXECUTING_TOOL],
198
- target_phase=AgentOperationalPhase.PROCESSING_TOOL_RESULT,
199
- description="Fires after a tool has finished executing and the agent begins processing its result."
200
- )
201
- async def notify_processing_tool_result(self, tool_name: str) -> None:
202
- await self._transition_phase(AgentOperationalPhase.PROCESSING_TOOL_RESULT, "notify_phase_processing_tool_result_started", additional_data={"tool_name": tool_name})
203
-
204
- @phase_transition(
205
- source_phases=[
206
- AgentOperationalPhase.PROCESSING_USER_INPUT, AgentOperationalPhase.ANALYZING_LLM_RESPONSE,
207
- AgentOperationalPhase.PROCESSING_TOOL_RESULT
208
- ],
209
- target_phase=AgentOperationalPhase.IDLE,
210
- description="Occurs when an agent completes a processing cycle and is waiting for new input."
211
- )
212
- async def notify_processing_complete_and_idle(self) -> None:
213
- if not self.context.current_phase.is_terminal() and self.context.current_phase != AgentOperationalPhase.IDLE:
214
- await self._transition_phase(AgentOperationalPhase.IDLE, "notify_phase_idle_entered")
215
- elif self.context.current_phase == AgentOperationalPhase.IDLE:
216
- logger.debug(f"Agent '{self.context.agent_id}' processing complete, already IDLE.")
217
- else:
218
- logger.warning(f"Agent '{self.context.agent_id}' notify_processing_complete_and_idle called in unexpected phase: {self.context.current_phase.value}")
219
-
220
- @phase_transition(
221
- source_phases=[
222
- AgentOperationalPhase.UNINITIALIZED, AgentOperationalPhase.BOOTSTRAPPING, AgentOperationalPhase.IDLE,
223
- AgentOperationalPhase.PROCESSING_USER_INPUT, AgentOperationalPhase.AWAITING_LLM_RESPONSE,
224
- AgentOperationalPhase.ANALYZING_LLM_RESPONSE, AgentOperationalPhase.AWAITING_TOOL_APPROVAL,
225
- AgentOperationalPhase.TOOL_DENIED, AgentOperationalPhase.EXECUTING_TOOL,
226
- AgentOperationalPhase.PROCESSING_TOOL_RESULT, AgentOperationalPhase.SHUTTING_DOWN
227
- ],
228
- target_phase=AgentOperationalPhase.ERROR,
229
- description="A catch-all transition that can occur from any non-terminal state if an unrecoverable error happens."
230
- )
231
- async def notify_error_occurred(self, error_message: str, error_details: Optional[str] = None) -> None:
232
- if self.context.current_phase != AgentOperationalPhase.ERROR:
233
- data = {"error_message": error_message, "error_details": error_details}
234
- await self._transition_phase(AgentOperationalPhase.ERROR, "notify_phase_error_entered", additional_data=data)
235
- else:
236
- logger.debug(f"Agent '{self.context.agent_id}' already in ERROR phase when another error notified: {error_message}")
237
-
238
- @phase_transition(
239
- source_phases=[
240
- AgentOperationalPhase.UNINITIALIZED, AgentOperationalPhase.BOOTSTRAPPING, AgentOperationalPhase.IDLE,
241
- AgentOperationalPhase.PROCESSING_USER_INPUT, AgentOperationalPhase.AWAITING_LLM_RESPONSE,
242
- AgentOperationalPhase.ANALYZING_LLM_RESPONSE, AgentOperationalPhase.AWAITING_TOOL_APPROVAL,
243
- AgentOperationalPhase.TOOL_DENIED, AgentOperationalPhase.EXECUTING_TOOL,
244
- AgentOperationalPhase.PROCESSING_TOOL_RESULT
245
- ],
246
- target_phase=AgentOperationalPhase.SHUTTING_DOWN,
247
- description="Fires when the agent begins its graceful shutdown sequence."
248
- )
249
- async def notify_shutdown_initiated(self) -> None:
250
- if not self.context.current_phase.is_terminal():
251
- await self._transition_phase(AgentOperationalPhase.SHUTTING_DOWN, "notify_phase_shutting_down_started")
252
- else:
253
- logger.debug(f"Agent '{self.context.agent_id}' shutdown initiated but already in a terminal phase: {self.context.current_phase.value}")
254
-
255
- @phase_transition(
256
- source_phases=[AgentOperationalPhase.SHUTTING_DOWN],
257
- target_phase=AgentOperationalPhase.SHUTDOWN_COMPLETE,
258
- description="The final transition when the agent has successfully shut down and released its resources."
259
- )
260
- async def notify_final_shutdown_complete(self) -> None:
261
- final_phase = AgentOperationalPhase.ERROR if self.context.current_phase == AgentOperationalPhase.ERROR else AgentOperationalPhase.SHUTDOWN_COMPLETE
262
- if final_phase == AgentOperationalPhase.ERROR:
263
- await self._transition_phase(AgentOperationalPhase.ERROR, "notify_phase_error_entered", additional_data={"error_message": "Shutdown completed with agent in error state."})
264
- else:
265
- await self._transition_phase(AgentOperationalPhase.SHUTDOWN_COMPLETE, "notify_phase_shutdown_completed")
@@ -1,40 +0,0 @@
1
- # file: autobyteus/autobyteus/agent/phases/transition_decorator.py
2
- import functools
3
- from typing import List, Callable
4
-
5
- from .phase_enum import AgentOperationalPhase
6
- from .transition_info import PhaseTransitionInfo
7
-
8
- def phase_transition(
9
- source_phases: List[AgentOperationalPhase],
10
- target_phase: AgentOperationalPhase,
11
- description: str
12
- ) -> Callable:
13
- """
14
- A decorator to annotate methods in AgentPhaseManager that cause a phase transition.
15
-
16
- This decorator does not alter the method's execution. It attaches a
17
- PhaseTransitionInfo object to the method, making the transition discoverable
18
- via introspection.
19
-
20
- Args:
21
- source_phases: A list of valid source phases from which this transition can occur.
22
- target_phase: The phase the agent will be in after this transition.
23
- description: A human-readable description of what causes this transition.
24
- """
25
- def decorator(func: Callable) -> Callable:
26
- @functools.wraps(func)
27
- def wrapper(*args, **kwargs):
28
- return func(*args, **kwargs)
29
-
30
- # Attach the metadata to the function object itself.
31
- # We sort source phases for consistent representation.
32
- sorted_sources = tuple(sorted(source_phases, key=lambda p: p.value))
33
- setattr(wrapper, '_transition_info', PhaseTransitionInfo(
34
- source_phases=sorted_sources,
35
- target_phase=target_phase,
36
- description=description,
37
- triggering_method=func.__name__
38
- ))
39
- return wrapper
40
- return decorator
@@ -1,33 +0,0 @@
1
- # file: autobyteus/autobyteus/agent/phases/transition_info.py
2
- import logging
3
- from dataclasses import dataclass
4
- from typing import List, Tuple
5
-
6
- from .phase_enum import AgentOperationalPhase
7
-
8
- logger = logging.getLogger(__name__)
9
-
10
- @dataclass(frozen=True)
11
- class PhaseTransitionInfo:
12
- """
13
- A dataclass representing a valid, discoverable phase transition.
14
-
15
- This object provides the necessary metadata for users to understand what
16
- kinds of phase hooks they can create.
17
-
18
- Attributes:
19
- source_phases: A list of possible source phases for this transition.
20
- target_phase: The single target phase for this transition.
21
- description: A human-readable description of when this transition occurs.
22
- triggering_method: The name of the method in AgentPhaseManager that triggers this.
23
- """
24
- source_phases: Tuple[AgentOperationalPhase, ...]
25
- target_phase: AgentOperationalPhase
26
- description: str
27
- triggering_method: str
28
-
29
- def __repr__(self) -> str:
30
- sources = ", ".join(f"'{p.value}'" for p in self.source_phases)
31
- return (f"<PhaseTransitionInfo sources=[{sources}] -> "
32
- f"target='{self.target_phase.value}' "
33
- f"triggered_by='{self.triggering_method}'>")
@@ -1,244 +0,0 @@
1
- # file: autobyteus/autobyteus/agent/remote_agent.py
2
- import asyncio
3
- import logging
4
- import uuid # For generating default request IDs if ProtocolMessage doesn't
5
- from typing import Optional, Dict, Any, AsyncIterator
6
-
7
- from autobyteus.agent.agent import Agent
8
- from autobyteus.agent.phases import AgentOperationalPhase
9
- from autobyteus.agent.message.agent_input_user_message import AgentInputUserMessage
10
- from autobyteus.agent.message.inter_agent_message import InterAgentMessage
11
- from autobyteus.rpc.client import default_client_connection_manager, AbstractClientConnection
12
- from autobyteus.rpc.protocol import ProtocolMessage, MessageType, RequestType, ResponseType, ErrorCode
13
- from autobyteus.rpc.config import AgentServerConfig, default_agent_server_registry
14
- from autobyteus.rpc.transport_type import TransportType # For type checking config
15
-
16
-
17
- logger = logging.getLogger(__name__)
18
-
19
- class RemoteAgentProxy(Agent):
20
- """
21
- Provides an Agent-like interface for interacting with a remote Agent Server.
22
- It handles RPC communication and capability discovery.
23
- Can target a specific agent on a multi-agent gateway server if target_agent_id_on_server is provided.
24
- """
25
- def __init__(self,
26
- server_config_id: str,
27
- target_agent_id_on_server: Optional[str] = None, # Added for multi-agent servers
28
- loop: Optional[asyncio.AbstractEventLoop] = None):
29
- """
30
- Initializes the RemoteAgentProxy.
31
-
32
- Args:
33
- server_config_id: The ID of the AgentServerConfig in the AgentServerRegistry
34
- that specifies how to connect to the remote agent server/gateway.
35
- target_agent_id_on_server: Optional. If the server_config_id points to a multi-agent
36
- gateway, this specifies the ID of the target agent on that
37
- server. This ID is used for routing by the server.
38
- loop: The asyncio event loop. If None, the running loop is used.
39
- """
40
- self.server_config_id: str = server_config_id
41
- self.target_agent_id_on_server: Optional[str] = target_agent_id_on_server
42
-
43
- self._client_connection_manager = default_client_connection_manager
44
- self._connection: Optional[AbstractClientConnection] = None
45
- self._server_config: Optional[AgentServerConfig] = None # Will store the resolved config
46
- self._loop = loop or asyncio.get_running_loop()
47
-
48
- self._remote_agent_id_from_discovery: Optional[str] = None
49
- self._remote_capabilities: Dict[str, Any] = {}
50
- self._remote_status: AgentOperationalPhase = AgentOperationalPhase.UNINITIALIZED
51
-
52
- # For Agent compatibility:
53
- # If target_agent_id_on_server is known, use it for a more descriptive initial proxy agent_id.
54
- # This will be overwritten by the actual agent_id from discovery.
55
- default_proxy_id_suffix = target_agent_id_on_server or server_config_id
56
- self.agent_id: str = f"remote_proxy_for_{default_proxy_id_suffix}"
57
- self.context = None
58
-
59
- self._is_initialized: bool = False
60
- self._initialization_lock = asyncio.Lock()
61
-
62
- logger.info(f"RemoteAgentProxy for server_id '{server_config_id}' (Targeting: {target_agent_id_on_server or 'N/A'}) created. Not yet initialized.")
63
-
64
- async def _ensure_initialized(self):
65
- async with self._initialization_lock:
66
- if self._is_initialized:
67
- return
68
-
69
- if not self._connection or not self._connection.is_connected:
70
- logger.info(f"RemoteAgentProxy '{self.agent_id}': Attempting connection to server_config_id '{self.server_config_id}'.")
71
- # Resolve server_config here as it's needed for SSE event URL construction too
72
- self._server_config = default_agent_server_registry.get_config(self.server_config_id)
73
- if not self._server_config:
74
- raise ValueError(f"AgentServerConfig not found for ID '{self.server_config_id}'.")
75
- self._connection = await self._client_connection_manager.get_connection(self.server_config_id)
76
-
77
- await self._discover_capabilities() # This will use self.target_agent_id_on_server
78
- self._is_initialized = True
79
- logger.info(f"RemoteAgentProxy '{self.agent_id}' initialized. Discovered Remote Agent ID: '{self._remote_agent_id_from_discovery}'.")
80
-
81
-
82
- async def _discover_capabilities(self):
83
- if not self._connection:
84
- raise ConnectionError("Cannot discover capabilities: not connected.")
85
-
86
- params_for_discovery: Dict[str, Any] = {}
87
- if self.target_agent_id_on_server:
88
- params_for_discovery["target_agent_id"] = self.target_agent_id_on_server
89
-
90
- request_msg = ProtocolMessage.create_request(
91
- method=RequestType.DISCOVER_CAPABILITIES,
92
- params=params_for_discovery if params_for_discovery else None
93
- )
94
- logger.debug(f"RemoteAgentProxy '{self.agent_id}': Sending discover_capabilities request with params: {params_for_discovery}.")
95
-
96
- response_msg = await self._connection.send_request(request_msg)
97
-
98
- if response_msg.type == MessageType.RESPONSE and response_msg.result:
99
- self._remote_agent_id_from_discovery = response_msg.result.get("agent_id")
100
- # Update proxy's agent_id to the actual discovered ID for better logging/identification
101
- if self._remote_agent_id_from_discovery:
102
- self.agent_id = self._remote_agent_id_from_discovery
103
-
104
- self._remote_capabilities = response_msg.result.get("capabilities_details", {}) # Use detailed map
105
- initial_status_str = response_msg.result.get("status") # 'status' key for legacy, but should be 'phase'
106
- initial_phase_str = response_msg.result.get("phase", initial_status_str) # Prefer 'phase'
107
- if initial_phase_str:
108
- try: self._remote_status = AgentOperationalPhase(initial_phase_str)
109
- except ValueError: logger.warning(f"Invalid phase '{initial_phase_str}' from discovery."); self._remote_status = AgentOperationalPhase.UNINITIALIZED
110
- logger.info(f"RemoteAgentProxy (now ID: '{self.agent_id}'): Capabilities discovered. Remote Caps: {list(self._remote_capabilities.keys())}")
111
- elif response_msg.type == MessageType.ERROR and response_msg.error:
112
- err = response_msg.error
113
- logger.error(f"RemoteAgentProxy '{self.agent_id}': Error discovering capabilities: {err.code} - {err.message}")
114
- raise RuntimeError(f"Failed to discover remote agent capabilities: {err.message}")
115
- else:
116
- logger.error(f"RemoteAgentProxy '{self.agent_id}': Unexpected response during capability discovery: {response_msg.to_json_str()}")
117
- raise RuntimeError("Unexpected response from remote agent during capability discovery.")
118
-
119
- async def _invoke_remote_method(self, method_name: str, method_params: Optional[Dict[str, Any]] = None) -> Any:
120
- await self._ensure_initialized()
121
- if not self._connection:
122
- raise ConnectionError("Not connected to remote agent.")
123
-
124
- # Construct parameters for the INVOKE_METHOD RPC call itself
125
- rpc_params: Dict[str, Any] = {
126
- "method_name": method_name,
127
- "method_params": method_params or {}
128
- }
129
- if self.target_agent_id_on_server:
130
- rpc_params["target_agent_id"] = self.target_agent_id_on_server
131
-
132
- request_msg = ProtocolMessage.create_request(
133
- method=RequestType.INVOKE_METHOD,
134
- params=rpc_params
135
- )
136
- log_method_params = str(method_params)[:100] + "..." if method_params and len(str(method_params)) > 100 else method_params
137
- logger.debug(f"RemoteAgentProxy '{self.agent_id}': Invoking remote method '{method_name}' (Targeting: {self.target_agent_id_on_server or 'default'}) with params: {log_method_params}")
138
-
139
- response_msg = await self._connection.send_request(request_msg)
140
-
141
- if response_msg.type == MessageType.RESPONSE:
142
- logger.debug(f"RemoteAgentProxy '{self.agent_id}': Received successful response for '{method_name}'.")
143
- return response_msg.result
144
- elif response_msg.type == MessageType.ERROR and response_msg.error:
145
- err = response_msg.error
146
- logger.error(f"RemoteAgentProxy '{self.agent_id}': Error invoking remote method '{method_name}': {err.code} - {err.message}")
147
- raise RuntimeError(f"Error from remote agent on method '{method_name}': {err.message}")
148
- else:
149
- logger.error(f"RemoteAgentProxy '{self.agent_id}': Unexpected response invoking method '{method_name}': {response_msg.to_json_str()}")
150
- raise RuntimeError(f"Unexpected response from remote agent invoking '{method_name}'.")
151
-
152
- async def post_user_message(self, agent_input_user_message: AgentInputUserMessage) -> None:
153
- params = {"agent_input_user_message": agent_input_user_message.to_dict()}
154
- await self._invoke_remote_method("post_user_message", params)
155
- logger.debug(f"RemoteAgentProxy '{self.agent_id}': post_user_message request sent.")
156
-
157
- async def post_inter_agent_message(self, inter_agent_message: InterAgentMessage) -> None:
158
- params = { "inter_agent_message": {
159
- "recipient_role_name": inter_agent_message.recipient_role_name,
160
- "recipient_agent_id": inter_agent_message.recipient_agent_id,
161
- "content": inter_agent_message.content,
162
- "message_type": str(inter_agent_message.message_type.value),
163
- "sender_agent_id": inter_agent_message.sender_agent_id,
164
- }
165
- }
166
- await self._invoke_remote_method("post_inter_agent_message", params)
167
- logger.debug(f"RemoteAgentProxy '{self.agent_id}': post_inter_agent_message request sent.")
168
-
169
- async def post_tool_execution_approval(self,
170
- tool_invocation_id: str,
171
- is_approved: bool,
172
- reason: Optional[str] = None) -> None:
173
- params = { "tool_invocation_id": tool_invocation_id, "is_approved": is_approved, "reason": reason}
174
- await self._invoke_remote_method("post_tool_execution_approval", params)
175
- logger.debug(f"RemoteAgentProxy '{self.agent_id}': post_tool_execution_approval sent.")
176
-
177
- def get_current_phase(self) -> AgentOperationalPhase:
178
- if not self._is_initialized:
179
- logger.warning(f"RemoteAgentProxy '{self.agent_id}': get_current_phase called before initialization.")
180
- # Returns cached status updated by discovery or potentially by SSE events.
181
- return self._remote_status
182
-
183
- @property
184
- def is_running(self) -> bool:
185
- # A remote agent is "running" if it's not in a terminal state or uninitialized.
186
- if self._remote_status:
187
- return not self._remote_status.is_terminal() and self._remote_status != AgentOperationalPhase.UNINITIALIZED
188
- return False
189
-
190
- def start(self) -> None:
191
- # For RemoteAgentProxy, start() implies ensuring connection and readiness.
192
- # The actual remote agent lifecycle is independent.
193
- if not self._is_initialized:
194
- logger.info(f"RemoteAgentProxy '{self.agent_id}': start() called. Ensuring initialization (async).")
195
- if self._loop.is_running(): asyncio.create_task(self._ensure_initialized())
196
- else:
197
- try: self._loop.run_until_complete(self._ensure_initialized())
198
- except RuntimeError as e:
199
- if "cannot be nested" in str(e): logger.warning("RemoteAgentProxy.start() in sync context with running loop.")
200
- else: raise
201
-
202
- async def stop(self, timeout: float = 10.0) -> None:
203
- logger.info(f"RemoteAgentProxy '{self.agent_id}': stop() called. Closing connection to '{self.server_config_id}'.")
204
- if self._connection:
205
- await self._connection.close()
206
- self._connection = None
207
- self._is_initialized = False
208
- self._remote_status = AgentOperationalPhase.SHUTDOWN_COMPLETE
209
-
210
- def get_event_queues(self):
211
- logger.warning("RemoteAgentProxy does not provide direct access to remote event queues.")
212
- return None
213
-
214
- async def stream_events(self) -> AsyncIterator[ProtocolMessage]:
215
- """
216
- Streams server-pushed events if connected via SSE.
217
- """
218
- await self._ensure_initialized() # Ensures self._connection and self._server_config are set
219
- if not self._connection:
220
- raise ConnectionError("Not connected to remote agent.")
221
- if not self._server_config or self._server_config.transport_type != TransportType.SSE:
222
- logger.warning(f"Event streaming only supported for SSE transport. Current: {self._server_config.transport_type if self._server_config else 'Unknown'}")
223
- if False: yield # Make it an async generator
224
- return
225
-
226
- logger.info(f"RemoteAgentProxy '{self.agent_id}': Starting to stream events (Target: {self.target_agent_id_on_server or 'default'}).")
227
- async for event in self._connection.events():
228
- # Update remote status if a phase transition event is received
229
- if event.type == MessageType.EVENT and event.event_type == "agent_phase_transition" and event.payload:
230
- new_phase_str = event.payload.get("new_phase")
231
- if new_phase_str:
232
- try:
233
- self._remote_status = AgentOperationalPhase(new_phase_str)
234
- logger.debug(f"RemoteAgentProxy '{self.agent_id}': Remote phase updated to {self._remote_status.value}")
235
- except ValueError:
236
- logger.warning(f"Received invalid phase '{new_phase_str}' via SSE event.")
237
- yield event
238
-
239
-
240
- def __repr__(self) -> str:
241
- conn_status = self._connection.is_connected if self._connection else False
242
- return (f"<RemoteAgentProxy effective_id='{self.agent_id}' "
243
- f"(DiscoveredRemoteID: {self._remote_agent_id_from_discovery or 'N/A'}) "
244
- f"server_cfg='{self.server_config_id}' target_on_server='{self.target_agent_id_on_server or 'N/A'}' connected={conn_status}>")
@@ -1,36 +0,0 @@
1
- """
2
- This module defines the WorkspaceDefinition class, which encapsulates the metadata
3
- for a specific type of agent workspace.
4
- """
5
- import logging
6
- from typing import Type, Optional, TYPE_CHECKING
7
- from autobyteus.utils.parameter_schema import ParameterSchema
8
-
9
- if TYPE_CHECKING:
10
- from autobyteus.agent.workspace.base_workspace import BaseAgentWorkspace
11
-
12
- logger = logging.getLogger(__name__)
13
-
14
- class WorkspaceDefinition:
15
- """Represents the definition of a discoverable and creatable agent workspace type."""
16
- def __init__(self,
17
- workspace_type_name: str,
18
- description: str,
19
- workspace_class: Type['BaseAgentWorkspace'],
20
- config_schema: ParameterSchema):
21
- if not all([workspace_type_name, description, workspace_class, config_schema is not None]):
22
- raise ValueError("All parameters for WorkspaceDefinition are required.")
23
-
24
- self.workspace_type_name = workspace_type_name
25
- self.description = description
26
- self.workspace_class = workspace_class
27
- self.config_schema = config_schema
28
- logger.debug(f"WorkspaceDefinition created for type '{workspace_type_name}'.")
29
-
30
- def to_dict(self) -> dict:
31
- """Serializes the definition to a dictionary for API exposure."""
32
- return {
33
- "workspace_type_name": self.workspace_type_name,
34
- "description": self.description,
35
- "config_schema": self.config_schema.to_dict()
36
- }
@@ -1,37 +0,0 @@
1
- """
2
- This module contains the metaclass for BaseAgentWorkspace for automatic registration.
3
- """
4
- import logging
5
- from abc import ABCMeta
6
- from .workspace_registry import default_workspace_registry
7
- from .workspace_definition import WorkspaceDefinition
8
-
9
- logger = logging.getLogger(__name__)
10
-
11
- class WorkspaceMeta(ABCMeta):
12
- """Metaclass to automatically register concrete BaseAgentWorkspace subclasses."""
13
- def __init__(cls, name, bases, dct):
14
- super().__init__(name, bases, dct)
15
-
16
- if name == 'BaseAgentWorkspace' or getattr(cls, "__abstractmethods__", None):
17
- logger.debug(f"Skipping registration for abstract workspace class: {name}")
18
- return
19
-
20
- try:
21
- workspace_type_name = cls.get_workspace_type_name()
22
- description = cls.get_description()
23
- config_schema = cls.get_config_schema()
24
-
25
- definition = WorkspaceDefinition(
26
- workspace_type_name=workspace_type_name,
27
- description=description,
28
- workspace_class=cls,
29
- config_schema=config_schema
30
- )
31
- default_workspace_registry.register(definition)
32
- config_params_info = f"config_params: {len(config_schema) if config_schema else 0}"
33
- logger.info(f"Auto-registered workspace: '{workspace_type_name}' from class {name} ({config_params_info})")
34
- except AttributeError as e:
35
- logger.error(f"Workspace class {name} is missing a required static/class method ({e}). Skipping registration.")
36
- except Exception as e:
37
- logger.error(f"Failed to auto-register workspace class {name}: {e}", exc_info=True)