autobyteus 1.2.1__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 (466) 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 +19 -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 +69 -59
  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/runtime/agent_runtime.py +29 -21
  39. autobyteus/agent/runtime/agent_worker.py +98 -19
  40. autobyteus/agent/shutdown_steps/__init__.py +2 -0
  41. autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
  42. autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
  43. autobyteus/agent/status/__init__.py +14 -0
  44. autobyteus/agent/status/manager.py +93 -0
  45. autobyteus/agent/status/status_deriver.py +96 -0
  46. autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
  47. autobyteus/agent/status/status_update_utils.py +73 -0
  48. autobyteus/agent/streaming/__init__.py +52 -5
  49. autobyteus/agent/streaming/adapters/__init__.py +18 -0
  50. autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
  51. autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
  52. autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
  53. autobyteus/agent/streaming/agent_event_stream.py +3 -183
  54. autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
  55. autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
  56. autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
  57. autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
  58. autobyteus/agent/streaming/events/__init__.py +6 -0
  59. autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
  60. autobyteus/agent/streaming/events/stream_events.py +141 -0
  61. autobyteus/agent/streaming/handlers/__init__.py +15 -0
  62. autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
  63. autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
  64. autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
  65. autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
  66. autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
  67. autobyteus/agent/streaming/parser/__init__.py +61 -0
  68. autobyteus/agent/streaming/parser/event_emitter.py +181 -0
  69. autobyteus/agent/streaming/parser/events.py +4 -0
  70. autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
  71. autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
  72. autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
  73. autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
  74. autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
  75. autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
  76. autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
  77. autobyteus/agent/streaming/parser/parser_context.py +227 -0
  78. autobyteus/agent/streaming/parser/parser_factory.py +132 -0
  79. autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
  80. autobyteus/agent/streaming/parser/state_factory.py +62 -0
  81. autobyteus/agent/streaming/parser/states/__init__.py +1 -0
  82. autobyteus/agent/streaming/parser/states/base_state.py +60 -0
  83. autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
  84. autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
  85. autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
  86. autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
  87. autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
  88. autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
  89. autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
  90. autobyteus/agent/streaming/parser/states/text_state.py +78 -0
  91. autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
  92. autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
  93. autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
  94. autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
  95. autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
  96. autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
  97. autobyteus/agent/streaming/parser/strategies/base.py +24 -0
  98. autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
  99. autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
  100. autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
  101. autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
  102. autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
  103. autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
  104. autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
  105. autobyteus/agent/streaming/parser/tool_constants.py +7 -0
  106. autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
  107. autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
  108. autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
  109. autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
  110. autobyteus/agent/streaming/queue_streamer.py +3 -57
  111. autobyteus/agent/streaming/segments/__init__.py +5 -0
  112. autobyteus/agent/streaming/segments/segment_events.py +81 -0
  113. autobyteus/agent/streaming/stream_event_payloads.py +2 -223
  114. autobyteus/agent/streaming/stream_events.py +3 -140
  115. autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
  116. autobyteus/agent/streaming/streaming_response_handler.py +4 -0
  117. autobyteus/agent/streaming/streams/__init__.py +5 -0
  118. autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
  119. autobyteus/agent/streaming/utils/__init__.py +5 -0
  120. autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
  121. autobyteus/agent/system_prompt_processor/__init__.py +2 -0
  122. autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
  123. autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
  124. autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
  125. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
  126. autobyteus/agent/token_budget.py +56 -0
  127. autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
  128. autobyteus/agent/tool_invocation.py +16 -40
  129. autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
  130. autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
  131. autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
  132. autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
  133. autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
  134. autobyteus/agent/utils/wait_for_idle.py +12 -14
  135. autobyteus/agent/workspace/base_workspace.py +6 -27
  136. autobyteus/agent_team/agent_team.py +3 -3
  137. autobyteus/agent_team/agent_team_builder.py +1 -41
  138. autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
  139. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
  140. autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
  141. autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
  142. autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
  143. autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +1 -2
  144. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +4 -4
  145. autobyteus/agent_team/context/agent_team_config.py +6 -3
  146. autobyteus/agent_team/context/agent_team_context.py +25 -3
  147. autobyteus/agent_team/context/agent_team_runtime_state.py +9 -6
  148. autobyteus/agent_team/events/__init__.py +11 -0
  149. autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
  150. autobyteus/agent_team/events/agent_team_events.py +16 -0
  151. autobyteus/agent_team/events/event_store.py +57 -0
  152. autobyteus/agent_team/factory/agent_team_factory.py +8 -0
  153. autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
  154. autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
  155. autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
  156. autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
  157. autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
  158. autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
  159. autobyteus/agent_team/status/__init__.py +14 -0
  160. autobyteus/agent_team/status/agent_team_status.py +18 -0
  161. autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
  162. autobyteus/agent_team/status/status_deriver.py +62 -0
  163. autobyteus/agent_team/status/status_update_utils.py +42 -0
  164. autobyteus/agent_team/streaming/__init__.py +2 -2
  165. autobyteus/agent_team/streaming/agent_team_event_notifier.py +6 -6
  166. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +4 -4
  167. autobyteus/agent_team/streaming/agent_team_stream_events.py +3 -3
  168. autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
  169. autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
  170. autobyteus/agent_team/task_notification/task_notification_mode.py +19 -0
  171. autobyteus/agent_team/utils/wait_for_idle.py +4 -4
  172. autobyteus/cli/agent_cli.py +18 -10
  173. autobyteus/cli/agent_team_tui/app.py +14 -11
  174. autobyteus/cli/agent_team_tui/state.py +13 -15
  175. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
  176. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +143 -36
  177. autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
  178. autobyteus/cli/agent_team_tui/widgets/shared.py +25 -25
  179. autobyteus/cli/cli_display.py +193 -44
  180. autobyteus/cli/workflow_tui/app.py +9 -10
  181. autobyteus/cli/workflow_tui/state.py +14 -16
  182. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
  183. autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
  184. autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
  185. autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
  186. autobyteus/clients/autobyteus_client.py +94 -1
  187. autobyteus/events/event_types.py +11 -18
  188. autobyteus/llm/api/autobyteus_llm.py +33 -29
  189. autobyteus/llm/api/claude_llm.py +142 -36
  190. autobyteus/llm/api/gemini_llm.py +163 -59
  191. autobyteus/llm/api/grok_llm.py +1 -1
  192. autobyteus/llm/api/minimax_llm.py +26 -0
  193. autobyteus/llm/api/mistral_llm.py +113 -87
  194. autobyteus/llm/api/ollama_llm.py +9 -42
  195. autobyteus/llm/api/openai_compatible_llm.py +127 -91
  196. autobyteus/llm/api/openai_llm.py +3 -3
  197. autobyteus/llm/api/openai_responses_llm.py +324 -0
  198. autobyteus/llm/api/zhipu_llm.py +21 -2
  199. autobyteus/llm/autobyteus_provider.py +70 -60
  200. autobyteus/llm/base_llm.py +85 -81
  201. autobyteus/llm/converters/__init__.py +14 -0
  202. autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
  203. autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
  204. autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
  205. autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
  206. autobyteus/llm/extensions/base_extension.py +6 -12
  207. autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
  208. autobyteus/llm/llm_factory.py +282 -204
  209. autobyteus/llm/lmstudio_provider.py +60 -49
  210. autobyteus/llm/models.py +35 -2
  211. autobyteus/llm/ollama_provider.py +60 -49
  212. autobyteus/llm/ollama_provider_resolver.py +0 -1
  213. autobyteus/llm/prompt_renderers/__init__.py +19 -0
  214. autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
  215. autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
  216. autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
  217. autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
  218. autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
  219. autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
  220. autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
  221. autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
  222. autobyteus/llm/providers.py +1 -3
  223. autobyteus/llm/token_counter/claude_token_counter.py +56 -25
  224. autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
  225. autobyteus/llm/token_counter/openai_token_counter.py +24 -5
  226. autobyteus/llm/token_counter/token_counter_factory.py +12 -5
  227. autobyteus/llm/utils/llm_config.py +6 -12
  228. autobyteus/llm/utils/media_payload_formatter.py +27 -20
  229. autobyteus/llm/utils/messages.py +55 -3
  230. autobyteus/llm/utils/response_types.py +3 -0
  231. autobyteus/llm/utils/tool_call_delta.py +31 -0
  232. autobyteus/memory/__init__.py +32 -0
  233. autobyteus/memory/active_transcript.py +69 -0
  234. autobyteus/memory/compaction/__init__.py +9 -0
  235. autobyteus/memory/compaction/compaction_result.py +8 -0
  236. autobyteus/memory/compaction/compactor.py +89 -0
  237. autobyteus/memory/compaction/summarizer.py +11 -0
  238. autobyteus/memory/compaction_snapshot_builder.py +84 -0
  239. autobyteus/memory/memory_manager.py +183 -0
  240. autobyteus/memory/models/__init__.py +14 -0
  241. autobyteus/memory/models/episodic_item.py +41 -0
  242. autobyteus/memory/models/memory_types.py +7 -0
  243. autobyteus/memory/models/raw_trace_item.py +79 -0
  244. autobyteus/memory/models/semantic_item.py +41 -0
  245. autobyteus/memory/models/tool_interaction.py +20 -0
  246. autobyteus/memory/policies/__init__.py +5 -0
  247. autobyteus/memory/policies/compaction_policy.py +16 -0
  248. autobyteus/memory/retrieval/__init__.py +7 -0
  249. autobyteus/memory/retrieval/memory_bundle.py +11 -0
  250. autobyteus/memory/retrieval/retriever.py +13 -0
  251. autobyteus/memory/store/__init__.py +7 -0
  252. autobyteus/memory/store/base_store.py +14 -0
  253. autobyteus/memory/store/file_store.py +98 -0
  254. autobyteus/memory/tool_interaction_builder.py +46 -0
  255. autobyteus/memory/turn_tracker.py +9 -0
  256. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
  257. autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
  258. autobyteus/multimedia/audio/audio_client_factory.py +47 -9
  259. autobyteus/multimedia/audio/audio_model.py +2 -1
  260. autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
  261. autobyteus/multimedia/image/api/gemini_image_client.py +38 -17
  262. autobyteus/multimedia/image/api/openai_image_client.py +125 -43
  263. autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
  264. autobyteus/multimedia/image/image_client_factory.py +47 -15
  265. autobyteus/multimedia/image/image_model.py +5 -2
  266. autobyteus/multimedia/providers.py +3 -2
  267. autobyteus/skills/loader.py +71 -0
  268. autobyteus/skills/model.py +11 -0
  269. autobyteus/skills/registry.py +70 -0
  270. autobyteus/task_management/tools/todo_tools/add_todo.py +2 -2
  271. autobyteus/task_management/tools/todo_tools/create_todo_list.py +2 -2
  272. autobyteus/task_management/tools/todo_tools/update_todo_status.py +2 -2
  273. autobyteus/tools/__init__.py +34 -47
  274. autobyteus/tools/base_tool.py +7 -0
  275. autobyteus/tools/file/__init__.py +2 -6
  276. autobyteus/tools/file/patch_file.py +149 -0
  277. autobyteus/tools/file/read_file.py +36 -5
  278. autobyteus/tools/file/write_file.py +4 -1
  279. autobyteus/tools/functional_tool.py +43 -6
  280. autobyteus/tools/mcp/__init__.py +2 -0
  281. autobyteus/tools/mcp/config_service.py +5 -1
  282. autobyteus/tools/mcp/server/__init__.py +2 -0
  283. autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
  284. autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
  285. autobyteus/tools/mcp/server_instance_manager.py +8 -1
  286. autobyteus/tools/mcp/types.py +61 -0
  287. autobyteus/tools/multimedia/audio_tools.py +70 -17
  288. autobyteus/tools/multimedia/download_media_tool.py +18 -4
  289. autobyteus/tools/multimedia/image_tools.py +246 -62
  290. autobyteus/tools/operation_executor/journal_manager.py +107 -0
  291. autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
  292. autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
  293. autobyteus/tools/operation_executor/operation_executor.py +58 -0
  294. autobyteus/tools/registry/tool_definition.py +43 -2
  295. autobyteus/tools/skill/load_skill.py +50 -0
  296. autobyteus/tools/terminal/__init__.py +45 -0
  297. autobyteus/tools/terminal/ansi_utils.py +32 -0
  298. autobyteus/tools/terminal/background_process_manager.py +233 -0
  299. autobyteus/tools/terminal/output_buffer.py +105 -0
  300. autobyteus/tools/terminal/prompt_detector.py +63 -0
  301. autobyteus/tools/terminal/pty_session.py +241 -0
  302. autobyteus/tools/terminal/session_factory.py +20 -0
  303. autobyteus/tools/terminal/terminal_session_manager.py +226 -0
  304. autobyteus/tools/terminal/tools/__init__.py +13 -0
  305. autobyteus/tools/terminal/tools/get_process_output.py +81 -0
  306. autobyteus/tools/terminal/tools/run_bash.py +109 -0
  307. autobyteus/tools/terminal/tools/start_background_process.py +104 -0
  308. autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
  309. autobyteus/tools/terminal/types.py +54 -0
  310. autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
  311. autobyteus/tools/terminal/wsl_utils.py +156 -0
  312. autobyteus/tools/transaction_management/backup_handler.py +48 -0
  313. autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
  314. autobyteus/tools/usage/__init__.py +1 -2
  315. autobyteus/tools/usage/formatters/__init__.py +17 -1
  316. autobyteus/tools/usage/formatters/base_formatter.py +8 -0
  317. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
  318. autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
  319. autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
  320. autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
  321. autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
  322. autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
  323. autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
  324. autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
  325. autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
  326. autobyteus/tools/usage/registries/__init__.py +1 -3
  327. autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
  328. autobyteus/tools/usage/tool_schema_provider.py +51 -0
  329. autobyteus/tools/web/__init__.py +4 -0
  330. autobyteus/tools/web/read_url_tool.py +80 -0
  331. autobyteus/utils/diff_utils.py +271 -0
  332. autobyteus/utils/download_utils.py +109 -0
  333. autobyteus/utils/file_utils.py +57 -2
  334. autobyteus/utils/gemini_helper.py +56 -0
  335. autobyteus/utils/gemini_model_mapping.py +71 -0
  336. autobyteus/utils/llm_output_formatter.py +75 -0
  337. autobyteus/utils/tool_call_format.py +36 -0
  338. autobyteus/workflow/agentic_workflow.py +3 -3
  339. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
  340. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
  341. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
  342. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +3 -9
  343. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
  344. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
  345. autobyteus/workflow/context/workflow_context.py +3 -3
  346. autobyteus/workflow/context/workflow_runtime_state.py +5 -5
  347. autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
  348. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
  349. autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
  350. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
  351. autobyteus/workflow/runtime/workflow_runtime.py +8 -8
  352. autobyteus/workflow/runtime/workflow_worker.py +3 -3
  353. autobyteus/workflow/status/__init__.py +11 -0
  354. autobyteus/workflow/status/workflow_status.py +19 -0
  355. autobyteus/workflow/status/workflow_status_manager.py +48 -0
  356. autobyteus/workflow/streaming/__init__.py +2 -2
  357. autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
  358. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
  359. autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
  360. autobyteus/workflow/utils/wait_for_idle.py +4 -4
  361. autobyteus-1.2.3.dist-info/METADATA +293 -0
  362. autobyteus-1.2.3.dist-info/RECORD +600 -0
  363. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
  364. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/top_level.txt +0 -1
  365. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
  366. autobyteus/agent/hooks/__init__.py +0 -16
  367. autobyteus/agent/hooks/base_phase_hook.py +0 -78
  368. autobyteus/agent/hooks/hook_definition.py +0 -36
  369. autobyteus/agent/hooks/hook_meta.py +0 -37
  370. autobyteus/agent/hooks/hook_registry.py +0 -106
  371. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
  372. autobyteus/agent/phases/__init__.py +0 -18
  373. autobyteus/agent/phases/discover.py +0 -53
  374. autobyteus/agent/phases/manager.py +0 -265
  375. autobyteus/agent/phases/transition_decorator.py +0 -40
  376. autobyteus/agent/phases/transition_info.py +0 -33
  377. autobyteus/agent/remote_agent.py +0 -244
  378. autobyteus/agent/workspace/workspace_definition.py +0 -36
  379. autobyteus/agent/workspace/workspace_meta.py +0 -37
  380. autobyteus/agent/workspace/workspace_registry.py +0 -72
  381. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
  382. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
  383. autobyteus/agent_team/phases/__init__.py +0 -11
  384. autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
  385. autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
  386. autobyteus/llm/api/bedrock_llm.py +0 -92
  387. autobyteus/llm/api/groq_llm.py +0 -94
  388. autobyteus/llm/api/nvidia_llm.py +0 -108
  389. autobyteus/llm/utils/token_pricing_config.py +0 -87
  390. autobyteus/rpc/__init__.py +0 -73
  391. autobyteus/rpc/client/__init__.py +0 -17
  392. autobyteus/rpc/client/abstract_client_connection.py +0 -124
  393. autobyteus/rpc/client/client_connection_manager.py +0 -153
  394. autobyteus/rpc/client/sse_client_connection.py +0 -306
  395. autobyteus/rpc/client/stdio_client_connection.py +0 -280
  396. autobyteus/rpc/config/__init__.py +0 -13
  397. autobyteus/rpc/config/agent_server_config.py +0 -153
  398. autobyteus/rpc/config/agent_server_registry.py +0 -152
  399. autobyteus/rpc/hosting.py +0 -244
  400. autobyteus/rpc/protocol.py +0 -244
  401. autobyteus/rpc/server/__init__.py +0 -20
  402. autobyteus/rpc/server/agent_server_endpoint.py +0 -181
  403. autobyteus/rpc/server/base_method_handler.py +0 -40
  404. autobyteus/rpc/server/method_handlers.py +0 -259
  405. autobyteus/rpc/server/sse_server_handler.py +0 -182
  406. autobyteus/rpc/server/stdio_server_handler.py +0 -151
  407. autobyteus/rpc/server_main.py +0 -198
  408. autobyteus/rpc/transport_type.py +0 -13
  409. autobyteus/tools/bash/__init__.py +0 -2
  410. autobyteus/tools/bash/bash_executor.py +0 -100
  411. autobyteus/tools/browser/__init__.py +0 -2
  412. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
  413. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
  414. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
  415. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
  416. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
  417. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
  418. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
  419. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
  420. autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
  421. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
  422. autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
  423. autobyteus/tools/browser/standalone/__init__.py +0 -6
  424. autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  425. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
  426. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
  427. autobyteus/tools/browser/standalone/navigate_to.py +0 -84
  428. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -101
  429. autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -169
  430. autobyteus/tools/browser/standalone/webpage_reader.py +0 -105
  431. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -105
  432. autobyteus/tools/file/edit_file.py +0 -200
  433. autobyteus/tools/file/list_directory.py +0 -168
  434. autobyteus/tools/file/search_files.py +0 -188
  435. autobyteus/tools/timer.py +0 -175
  436. autobyteus/tools/usage/parsers/__init__.py +0 -22
  437. autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
  438. autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
  439. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
  440. autobyteus/tools/usage/parsers/base_parser.py +0 -41
  441. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
  442. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
  443. autobyteus/tools/usage/parsers/exceptions.py +0 -13
  444. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
  445. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
  446. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
  447. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
  448. autobyteus/workflow/phases/__init__.py +0 -11
  449. autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
  450. autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
  451. autobyteus-1.2.1.dist-info/METADATA +0 -205
  452. autobyteus-1.2.1.dist-info/RECORD +0 -511
  453. examples/__init__.py +0 -1
  454. examples/agent_team/__init__.py +0 -1
  455. examples/discover_phase_transitions.py +0 -104
  456. examples/run_agentic_software_engineer.py +0 -239
  457. examples/run_browser_agent.py +0 -262
  458. examples/run_google_slides_agent.py +0 -287
  459. examples/run_mcp_browser_client.py +0 -174
  460. examples/run_mcp_google_slides_client.py +0 -270
  461. examples/run_mcp_list_tools.py +0 -189
  462. examples/run_poem_writer.py +0 -284
  463. examples/run_sqlite_agent.py +0 -295
  464. /autobyteus/{tools/browser/session_aware → skills}/__init__.py +0 -0
  465. /autobyteus/tools/{browser/session_aware/factory → skill}/__init__.py +0 -0
  466. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -1,182 +0,0 @@
1
- # file: autobyteus/autobyteus/rpc/server/sse_server_handler.py
2
- import asyncio
3
- import logging
4
- import json
5
- from typing import Dict, Optional, Union, Set, cast, AsyncIterator
6
- from weakref import WeakSet
7
-
8
- from aiohttp import web
9
- from aiohttp_sse import sse_response
10
-
11
- from autobyteus.agent.agent import Agent
12
- # MODIFIED: Import AgentEventStream (remains the same, but it's now the sole class)
13
- from autobyteus.agent.streaming import AgentEventStream
14
- from autobyteus.agent.streaming.stream_events import StreamEvent, StreamEventType
15
- from autobyteus.rpc.protocol import ProtocolMessage, MessageType, ErrorCode, RequestType, ResponseType, EventType as RPCEventType
16
- from autobyteus.rpc.server.base_method_handler import BaseMethodHandler
17
- from autobyteus.rpc.config import AgentServerConfig
18
-
19
- logger = logging.getLogger(__name__)
20
-
21
- DEFAULT_STREAM_CHUNK_SIZE = 8192
22
-
23
- class SseServerHandler:
24
- def __init__(self, agents: Dict[str, Agent], method_handlers: Dict[Union[RequestType, str], BaseMethodHandler]):
25
- self._agents: Dict[str, Agent] = agents
26
- self._method_handlers = method_handlers
27
- self._app = web.Application()
28
- self._runner: Optional[web.AppRunner] = None
29
- self._site: Optional[web.TCPSite] = None
30
- self._active_sse_forwarding_tasks: Dict[web.StreamResponse, asyncio.Task] = {}
31
- logger.info(f"SseServerHandler initialized to serve agents: {list(self._agents.keys())}.")
32
-
33
- def _setup_routes(self, config: AgentServerConfig):
34
- # ... (method body remains the same) ...
35
- rpc_request_path = config.sse_request_endpoint
36
- base_events_path = config.sse_events_endpoint.rstrip('/')
37
- full_events_path = f"{base_events_path}/{{agent_id_on_server}}"
38
- stream_download_prefix = config.sse_stream_download_path_prefix.rstrip('/')
39
- full_stream_download_path = f"{stream_download_prefix}/{{agent_id_on_server}}/{{stream_id}}"
40
- self._app.router.add_post(rpc_request_path, self.handle_rpc_request)
41
- self._app.router.add_get(full_events_path, self.handle_sse_events_subscription)
42
- self._app.router.add_get(full_stream_download_path, self.handle_http_stream_download)
43
- logger.info(f"SseServerHandler routes: POST {rpc_request_path} (RPC), GET {full_events_path} (SSE per agent), GET {full_stream_download_path} (HTTP Stream Download).")
44
-
45
- async def handle_rpc_request(self, http_request: web.Request) -> web.Response:
46
- # ... (method body remains the same) ...
47
- request_id: Optional[str] = None; raw_body_str: str = ""; target_agent_id: Optional[str] = None
48
- try:
49
- raw_body = await http_request.read(); raw_body_str = raw_body.decode()
50
- try: parsed_json_early = json.loads(raw_body_str); request_id = parsed_json_early.get("id")
51
- except json.JSONDecodeError: pass
52
- request_message = ProtocolMessage.from_json_str(raw_body_str); request_id = request_message.id
53
- if request_message.type != MessageType.REQUEST or not request_message.method:
54
- return self._create_json_error_response(request_id, ErrorCode.INVALID_REQUEST, "Must be REQUEST with method.", 400)
55
- if request_message.params and "target_agent_id" in request_message.params:
56
- target_agent_id = str(request_message.params["target_agent_id"])
57
- if not target_agent_id: return self._create_json_error_response(request_id, ErrorCode.INVALID_PARAMS, "'target_agent_id' missing in request params.", 400)
58
- target_agent = self._agents.get(target_agent_id)
59
- if not target_agent: return self._create_json_error_response(request_id, ErrorCode.METHOD_NOT_FOUND, f"Agent with id '{target_agent_id}' not found.", 404)
60
- actual_handler_params = request_message.params
61
- handler = self._method_handlers.get(request_message.method)
62
- if not handler: return self._create_json_error_response(request_id, ErrorCode.METHOD_NOT_FOUND, f"RPC Method '{request_message.method}' not found.", 404)
63
- logger.debug(f"SseServerHandler dispatching RPC '{request_message.method}' (ReqID: {request_id}) to '{handler.__class__.__name__}' for agent '{target_agent_id}'.")
64
- response_proto = await handler.handle(request_id, actual_handler_params, target_agent)
65
- if response_proto.response_type == ResponseType.STREAM_DOWNLOAD_READY and response_proto.result and "stream_id" in response_proto.result and target_agent_id:
66
- server_config: AgentServerConfig = http_request.app['agent_server_config']
67
- full_url_prefix = server_config.get_sse_full_stream_download_url_prefix_for_agent(target_agent_id)
68
- if full_url_prefix:
69
- stream_id = response_proto.result["stream_id"]; download_url = f"{full_url_prefix.rstrip('/')}/{stream_id}"
70
- response_proto.result["download_url"] = download_url; logger.info(f"Constructed download URL for stream_id '{stream_id}': {download_url}")
71
- else: logger.error(f"Could not construct download_url for stream_id '{response_proto.result['stream_id']}'.")
72
- http_status = 200
73
- if response_proto.type == MessageType.ERROR and response_proto.error:
74
- if response_proto.error.code == ErrorCode.METHOD_NOT_FOUND.value: http_status = 404
75
- elif response_proto.error.code in [ErrorCode.INVALID_REQUEST.value, ErrorCode.INVALID_PARAMS.value, ErrorCode.PARSE_ERROR.value]: http_status = 400
76
- else: http_status = 500
77
- return web.json_response(response_proto.model_dump(exclude_none=True), status=http_status)
78
- except json.JSONDecodeError as e: logger.error(f"Sse JSONDecodeError: {e}. Body: '{raw_body_str[:200]}'"); return self._create_json_error_response(request_id, ErrorCode.PARSE_ERROR, f"JSON parse error: {e}", 400)
79
- except ValueError as e: logger.error(f"Sse Protocol validation error: {e}. Body: '{raw_body_str[:200]}'"); return self._create_json_error_response(request_id, ErrorCode.INVALID_REQUEST, f"Invalid request: {e}", 400)
80
- except Exception as e: logger.error(f"Sse unexpected error: {e}", exc_info=True); return self._create_json_error_response(request_id, ErrorCode.INTERNAL_ERROR, f"Server error: {e}", 500)
81
-
82
- def _create_json_error_response(self, req_id: Optional[str], code: ErrorCode, msg: str, http_status: int) -> web.Response:
83
- # ... (method body remains the same) ...
84
- err_proto = ProtocolMessage.create_error_response(req_id, code, msg)
85
- return web.json_response(err_proto.model_dump(exclude_none=True), status=http_status)
86
-
87
- async def handle_sse_events_subscription(self, http_request: web.Request) -> web.StreamResponse:
88
- # ... (method body remains the same, it instantiates AgentEventStream and calls all_events()) ...
89
- agent_id_on_server = http_request.match_info.get("agent_id_on_server")
90
- if not agent_id_on_server: raise web.HTTPBadRequest(text="'agent_id_on_server' path param required.")
91
- target_agent = self._agents.get(agent_id_on_server)
92
- if not target_agent: raise web.HTTPNotFound(text=f"Agent '{agent_id_on_server}' not found.")
93
- client_addr = http_request.remote
94
- logger.info(f"SSE client {client_addr} subscribing to events for agent '{target_agent.agent_id}' (server key: '{agent_id_on_server}').")
95
- sse_resp = web.StreamResponse(status=200, reason='OK', headers={'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive'})
96
- await sse_resp.prepare(http_request)
97
- forwarding_task = asyncio.create_task(self._stream_agent_events_to_client(sse_resp, target_agent, agent_id_on_server), name=f"sse_fwd_{target_agent.agent_id}_{client_addr}")
98
- self._active_sse_forwarding_tasks[sse_resp] = forwarding_task
99
- try: await forwarding_task
100
- except asyncio.CancelledError: logger.info(f"SSE task for agent '{target_agent.agent_id}' to {client_addr} cancelled.")
101
- except Exception as e: logger.error(f"Error in SSE streaming for agent '{target_agent.agent_id}' to {client_addr}: {e}", exc_info=True)
102
- finally: logger.info(f"SSE client {client_addr} for agent '{target_agent.agent_id}' disconnected."); self._active_sse_forwarding_tasks.pop(sse_resp, None)
103
- return sse_resp
104
-
105
- async def _stream_agent_events_to_client(self, sse_client_resp: web.StreamResponse, agent: Agent, agent_id_on_server: str):
106
- # Instantiates AgentEventStream
107
- event_stream_provider = AgentEventStream(agent)
108
- logger.debug(f"SseServerHandler: Streaming events from agent '{agent.agent_id}' (key: {agent_id_on_server}) via AgentEventStream.all_events().")
109
- try:
110
- # Calls .all_events() method
111
- async for agent_event_obj in event_stream_provider.all_events():
112
- if sse_client_resp.closed: break
113
- rpc_event_type: RPCEventType
114
- if agent_event_obj.event_type == StreamEventType.ASSISTANT_CHUNK: rpc_event_type = RPCEventType.AGENT_OUTPUT_CHUNK
115
- elif agent_event_obj.event_type == StreamEventType.ASSISTANT_FINAL_MESSAGE: rpc_event_type = RPCEventType.AGENT_FINAL_MESSAGE
116
- elif agent_event_obj.event_type == StreamEventType.TOOL_INTERACTION_LOG_ENTRY: rpc_event_type = RPCEventType.TOOL_LOG_ENTRY
117
- elif agent_event_obj.event_type == StreamEventType.AGENT_STATUS_CHANGE: rpc_event_type = RPCEventType.AGENT_STATUS_UPDATE
118
- elif agent_event_obj.event_type == StreamEventType.ERROR_EVENT: rpc_event_type = RPCEventType.AGENT_STATUS_UPDATE; logger.error(f"Unified stream error for agent '{agent.agent_id}': {agent_event_obj.data}")
119
- else: rpc_event_type = RPCEventType.AGENT_STATUS_UPDATE; logger.warning(f"Unhandled StreamEventType '{agent_event_obj.event_type}' from agent '{agent.agent_id}'.")
120
- payload_data = {"agent_id_on_server": agent_id_on_server, **agent_event_obj.data}
121
- protocol_event_msg = ProtocolMessage.create_event(event_type=rpc_event_type, payload=payload_data)
122
- try:
123
- sse_event_str = f"event: {str(protocol_event_msg.event_type.value)}\ndata: {protocol_event_msg.to_json_str()}\n\n"
124
- await sse_client_resp.write(sse_event_str.encode('utf-8'))
125
- except ConnectionResetError: logger.info(f"SSE client reset for agent '{agent.agent_id}'."); break
126
- except Exception as send_e: logger.error(f"Error sending SSE event for agent '{agent.agent_id}': {send_e}"); break
127
- if not sse_client_resp.closed: await sse_client_resp.write_eof()
128
- except asyncio.CancelledError: logger.info(f"Event streaming for agent '{agent.agent_id}' (key: {agent_id_on_server}) cancelled.")
129
- except Exception as e: logger.error(f"Error in event streaming for agent '{agent.agent_id}' (key: {agent_id_on_server}): {e}", exc_info=True)
130
- finally: logger.debug(f"Finished event streaming from agent '{agent.agent_id}' (key: {agent_id_on_server}).")
131
-
132
- async def handle_http_stream_download(self, http_request: web.Request) -> web.StreamResponse:
133
- # ... (method body remains the same) ...
134
- agent_id_on_server = http_request.match_info.get("agent_id_on_server"); stream_id = http_request.match_info.get("stream_id")
135
- if not agent_id_on_server or not stream_id: raise web.HTTPBadRequest(text="'agent_id_on_server' and 'stream_id' path params required.")
136
- target_agent = self._agents.get(agent_id_on_server)
137
- if not target_agent: raise web.HTTPNotFound(text=f"Agent '{agent_id_on_server}' not found.")
138
- logger.info(f"HTTP stream download for agent '{target_agent.agent_id}' (key: '{agent_id_on_server}'), stream_id '{stream_id}'.")
139
- if not hasattr(target_agent, "get_stream_data") or not hasattr(target_agent, "cleanup_stream_resource"):
140
- raise web.HTTPNotImplemented(text=f"Agent '{target_agent.agent_id}' does not support stream retrieval.")
141
- try:
142
- get_stream_data_method = getattr(target_agent, "get_stream_data")
143
- data_iterator: AsyncIterator[bytes] = await get_stream_data_method(stream_id)
144
- response = web.StreamResponse(status=200, reason="OK", headers={"Content-Type": "application/octet-stream"})
145
- await response.prepare(http_request)
146
- async for chunk in data_iterator:
147
- if not isinstance(chunk, bytes): logger.error(f"Agent '{target_agent.agent_id}' stream '{stream_id}' yielded non-bytes: {type(chunk)}."); break
148
- await response.write(chunk); await asyncio.sleep(0)
149
- await response.write_eof(); logger.info(f"Streamed data for agent '{target_agent.agent_id}', stream_id '{stream_id}'."); return response
150
- except FileNotFoundError: logger.warning(f"Stream '{stream_id}' not found for agent '{target_agent.agent_id}'."); raise web.HTTPNotFound(text=f"Stream resource '{stream_id}' not found.")
151
- except asyncio.CancelledError: logger.info(f"HTTP stream download for '{stream_id}' (agent '{target_agent.agent_id}') cancelled."); raise
152
- except Exception as e: logger.error(f"Error during HTTP stream download for '{stream_id}' (agent '{target_agent.agent_id}'): {e}", exc_info=True); raise web.HTTPInternalServerError(text="Error serving stream data.")
153
- finally:
154
- try: cleanup_method = getattr(target_agent, "cleanup_stream_resource"); await cleanup_method(stream_id); logger.debug(f"Agent '{target_agent.agent_id}' cleaned up stream '{stream_id}'.")
155
- except Exception as cleanup_e: logger.error(f"Error cleaning up stream '{stream_id}': {cleanup_e}", exc_info=True)
156
-
157
- async def start_server(self, config: AgentServerConfig):
158
- # ... (method body remains the same) ...
159
- if not config.sse_base_url: raise ValueError("SSE base URL required.")
160
- self._app['agent_server_config'] = config; self._setup_routes(config)
161
- host = config.sse_base_url.host or "0.0.0.0"; port = config.sse_base_url.port or 80
162
- self._runner = web.AppRunner(self._app); await self._runner.setup()
163
- self._site = web.TCPSite(self._runner, host, port)
164
- try: await self._site.start(); logger.info(f"SseServerHandler started for agents {list(self._agents.keys())} on http://{host}:{port}")
165
- except OSError as e: logger.error(f"Failed to start SseServer on http://{host}:{port}: {e}", exc_info=True); await self.stop_server(); raise
166
- except Exception as e: logger.error(f"Unexpected error starting SseServer: {e}", exc_info=True); await self.stop_server(); raise
167
-
168
- async def stop_server(self):
169
- # ... (method body remains the same) ...
170
- logger.info(f"SseServerHandler for agents {list(self._agents.keys())} stopping...")
171
- for task in list(self._active_sse_forwarding_tasks.values()):
172
- if task and not task.done(): task.cancel()
173
- if self._active_sse_forwarding_tasks: await asyncio.gather(*self._active_sse_forwarding_tasks.values(), return_exceptions=True)
174
- self._active_sse_forwarding_tasks.clear()
175
- if self._site: try: await self._site.stop()
176
- except Exception as e: logger.error(f"Error stopping TCPSite: {e}", exc_info=True)
177
- self._site = None
178
- if self._runner: try: await self._runner.cleanup()
179
- except Exception as e: logger.error(f"Error cleaning AppRunner: {e}", exc_info=True)
180
- self._runner = None
181
- logger.info(f"SseServerHandler for agents {list(self._agents.keys())} stopped.")
182
-
@@ -1,151 +0,0 @@
1
- # file: autobyteus/autobyteus/rpc/server/stdio_server_handler.py
2
- import asyncio
3
- import sys
4
- import json
5
- import logging
6
- from typing import Dict, Optional, Union
7
-
8
- from autobyteus.rpc.protocol import ProtocolMessage, MessageType, ErrorCode, RequestType
9
- from autobyteus.rpc.server.base_method_handler import BaseMethodHandler
10
- from autobyteus.agent.agent import Agent # Changed from AgentRuntime
11
-
12
- logger = logging.getLogger(__name__)
13
-
14
- class StdioServerHandler:
15
- """
16
- Handles RPC communication over stdio for an Agent Server.
17
- Reads newline-delimited JSON ProtocolMessages from stdin, dispatches them
18
- to appropriate method handlers (which operate on an Agent instance),
19
- and writes responses to stdout.
20
- """
21
-
22
- def __init__(self, agent: Agent, method_handlers: Dict[Union[RequestType, str], BaseMethodHandler]): # Changed runtime to agent
23
- """
24
- Initializes the StdioServerHandler.
25
-
26
- Args:
27
- agent: The Agent instance this server handler is serving.
28
- method_handlers: A dictionary mapping method names (RequestType or str)
29
- to their handler instances.
30
- """
31
- self._agent = agent # Changed from _runtime to _agent
32
- self._method_handlers = method_handlers
33
- self._running = False
34
- logger.info(f"StdioServerHandler initialized for agent '{self._agent.agent_id}'.") # Use agent.agent_id
35
-
36
- async def listen_and_dispatch(self) -> None:
37
- """
38
- Starts listening on stdin for requests and dispatches them.
39
- This method runs indefinitely until stdin is closed or an error occurs.
40
- """
41
- self._running = True
42
- logger.info(f"StdioServerHandler for agent '{self._agent.agent_id}' now listening on stdin.")
43
-
44
- loop = asyncio.get_event_loop()
45
- reader = asyncio.StreamReader(loop=loop)
46
- protocol = asyncio.StreamReaderProtocol(reader, loop=loop)
47
- await loop.connect_read_pipe(lambda: protocol, sys.stdin)
48
-
49
- try:
50
- while self._running:
51
- line_bytes = await reader.readline()
52
- if not line_bytes:
53
- logger.info(f"StdioServerHandler for agent '{self._agent.agent_id}': stdin EOF reached. Shutting down.")
54
- self._running = False
55
- break
56
-
57
- line_str = line_bytes.decode().strip()
58
- if not line_str:
59
- continue
60
-
61
- request_id: Optional[str] = None
62
- try:
63
- try:
64
- parsed_json = json.loads(line_str)
65
- request_id = parsed_json.get("id")
66
- except json.JSONDecodeError:
67
- pass
68
-
69
- message = ProtocolMessage.from_json_str(line_str)
70
- request_id = message.id
71
-
72
- if message.type == MessageType.REQUEST:
73
- response_message = await self._process_request(message)
74
- else:
75
- logger.warning(f"StdioServerHandler received non-REQUEST message type: {message.type}. Ignoring.")
76
- response_message = ProtocolMessage.create_error_response(
77
- id=request_id,
78
- code=ErrorCode.INVALID_REQUEST,
79
- message="Server only accepts REQUEST messages via stdio."
80
- )
81
-
82
- await self._send_response(response_message)
83
-
84
- except json.JSONDecodeError as e:
85
- logger.error(f"StdioServerHandler: JSONDecodeError: {e}. Raw line: '{line_str[:200]}'")
86
- err_response = ProtocolMessage.create_error_response(
87
- id=request_id,
88
- code=ErrorCode.PARSE_ERROR,
89
- message=f"Failed to parse JSON request: {e}"
90
- )
91
- await self._send_response(err_response)
92
- except ValueError as e:
93
- logger.error(f"StdioServerHandler: ProtocolMessage validation error: {e}. Raw line: '{line_str[:200]}'")
94
- err_response = ProtocolMessage.create_error_response(
95
- id=request_id,
96
- code=ErrorCode.INVALID_REQUEST,
97
- message=f"Invalid request structure: {e}"
98
- )
99
- await self._send_response(err_response)
100
- except Exception as e:
101
- logger.error(f"StdioServerHandler: Unexpected error processing line: {e}. Raw line: '{line_str[:200]}'", exc_info=True)
102
- err_response = ProtocolMessage.create_error_response(
103
- id=request_id,
104
- code=ErrorCode.INTERNAL_ERROR,
105
- message=f"Internal server error: {e}"
106
- )
107
- await self._send_response(err_response)
108
-
109
- except asyncio.CancelledError:
110
- logger.info(f"StdioServerHandler for agent '{self._agent.agent_id}' listen_and_dispatch task cancelled.")
111
- except Exception as e:
112
- logger.error(f"StdioServerHandler for agent '{self._agent.agent_id}' fatal error in listen_and_dispatch: {e}", exc_info=True)
113
- finally:
114
- self._running = False
115
- logger.info(f"StdioServerHandler for agent '{self._agent.agent_id}' stopped listening.")
116
-
117
- async def _process_request(self, request_message: ProtocolMessage) -> ProtocolMessage:
118
- if not request_message.method:
119
- logger.warning(f"StdioServerHandler: Request message missing 'method'. ID: {request_message.id}")
120
- return ProtocolMessage.create_error_response(
121
- id=request_message.id,
122
- code=ErrorCode.INVALID_REQUEST,
123
- message="Request message must include a 'method'."
124
- )
125
-
126
- handler = self._method_handlers.get(request_message.method)
127
- if not handler:
128
- logger.warning(f"StdioServerHandler: No handler found for method '{request_message.method}'. ID: {request_message.id}")
129
- return ProtocolMessage.create_error_response(
130
- id=request_message.id,
131
- code=ErrorCode.METHOD_NOT_FOUND,
132
- message=f"Method '{request_message.method}' not found."
133
- )
134
-
135
- logger.debug(f"StdioServerHandler dispatching method '{request_message.method}' (ID: {request_message.id}) to {handler.__class__.__name__}.")
136
- return await handler.handle(request_message.id, request_message.params, self._agent) # Pass self._agent
137
-
138
- async def _send_response(self, response_message: ProtocolMessage) -> None:
139
- try:
140
- json_response = response_message.to_json_str()
141
- loop = asyncio.get_event_loop()
142
- await loop.run_in_executor(None, lambda: sys.stdout.write(json_response + '\n'))
143
- await loop.run_in_executor(None, sys.stdout.flush)
144
- logger.debug(f"StdioServerHandler sent response (ID: {response_message.id}, Type: {response_message.type}).")
145
- except Exception as e:
146
- logger.error(f"StdioServerHandler failed to send response: {e}", exc_info=True)
147
-
148
- def stop(self):
149
- logger.info(f"StdioServerHandler for agent '{self._agent.agent_id}' stop requested.")
150
- self._running = False
151
-
@@ -1,198 +0,0 @@
1
- # file: autobyteus/autobyteus/rpc/server_main.py
2
- import asyncio
3
- import logging
4
- import argparse
5
- import signal
6
- import sys
7
- from typing import Optional
8
-
9
- from autobyteus.agent.registry.agent_definition import AgentDefinition
10
- from autobyteus.agent.registry.agent_registry import default_definition_registry, default_agent_registry
11
- from autobyteus.agent.agent import Agent
12
- from autobyteus.llm.models import LLMModel
13
-
14
- from autobyteus.rpc.config import AgentServerConfig, default_agent_server_registry
15
- from autobyteus.rpc.server import AgentServerEndpoint
16
- from autobyteus.rpc.transport_type import TransportType
17
-
18
- try:
19
- from autobyteus.agent.input_processor import PassthroughInputProcessor
20
- except ImportError:
21
- print("WARNING: PassthroughInputProcessor not found, EchoAgentDefinition in server_main might fail if used.", file=sys.stderr)
22
-
23
-
24
- logging.basicConfig(
25
- level=logging.INFO,
26
- format='%(asctime)s - %(levelname)s - %(name)s - [%(process)d] - %(message)s',
27
- stream=sys.stderr
28
- )
29
- logger = logging.getLogger(__name__)
30
-
31
-
32
- ECHO_AGENT_DEF: Optional[AgentDefinition] = None
33
- try:
34
- if not default_definition_registry.get("EchoAgent", "echo_responder"):
35
- ECHO_AGENT_DEF = AgentDefinition(
36
- name="EchoAgent",
37
- role="echo_responder",
38
- description="A simple agent that echoes back user messages.",
39
- system_prompt="You are an echo agent. Repeat the user's message precisely.",
40
- tool_names=[],
41
- input_processor_names=["PassthroughInputProcessor"], # Assumes PassthroughInputProcessor is registered
42
- llm_response_processor_names=[]
43
- )
44
- logger.info(f"Example AgentDefinition '{ECHO_AGENT_DEF.name}' created and auto-registered for server_main.")
45
- else:
46
- ECHO_AGENT_DEF = default_definition_registry.get("EchoAgent", "echo_responder")
47
- logger.info(f"Example AgentDefinition 'EchoAgent' already registered. Using existing one for server_main.")
48
- except Exception as e:
49
- logger.error(f"Could not create/retrieve example EchoAgentDefinition: {e}. server_main might fail if it's requested.")
50
-
51
-
52
- shutdown_event = asyncio.Event()
53
- agent_global: Optional[Agent] = None
54
- server_endpoint_global: Optional[AgentServerEndpoint] = None
55
-
56
- async def main():
57
- global agent_global, server_endpoint_global
58
-
59
- parser = argparse.ArgumentParser(description="AutoByteUs Agent RPC Server")
60
- parser.add_argument("--agent-def-name", type=str, required=True, help="Name of the AgentDefinition.")
61
- parser.add_argument("--agent-def-role", type=str, required=True, help="Role of the AgentDefinition.")
62
- parser.add_argument("--llm-model-name", type=str, required=True, help="Name of the LLMModel (e.g., 'GPT_4o_API'). This is the string name for the model, not the enum member itself.")
63
- parser.add_argument("--server-config-id", type=str, required=True, help="ID of the AgentServerConfig.")
64
-
65
- args = parser.parse_args()
66
- logger.info(f"server_main starting with args: {args}")
67
-
68
- agent_definition = default_definition_registry.get(args.agent_def_name, args.agent_def_role)
69
- if not agent_definition:
70
- logger.error(f"AgentDefinition not found for name='{args.agent_def_name}', role='{args.agent_def_role}'.")
71
- sys.exit(1)
72
-
73
- # The llm_model_name from args is already a string, which is what create_agent now expects.
74
- # We still need to validate if it's a known model name for robustness,
75
- # though create_agent (via AgentFactory -> AgentConfig) will also do this.
76
- try:
77
- LLMModel[args.llm_model_name.upper()] # Validate if the name maps to a known LLMModel enum member
78
- except KeyError:
79
- logger.error(f"LLMModel name '{args.llm_model_name}' provided via --llm-model-name is not a recognized LLMModel. Available: {[m.name for m in LLMModel]}")
80
- sys.exit(1)
81
-
82
- server_config = default_agent_server_registry.get_config(args.server_config_id)
83
- if not server_config:
84
- logger.error(f"AgentServerConfig not found for server_config_id='{args.server_config_id}'.")
85
- sys.exit(1)
86
-
87
- try:
88
- # UPDATED: Pass llm_model_name directly as a string.
89
- # AgentRegistry.create_agent -> AgentFactory.create_agent_runtime -> AgentFactory.create_agent_context
90
- # -> AgentConfig now takes llm_model_name: str.
91
- agent = default_agent_registry.create_agent(
92
- definition=agent_definition,
93
- llm_model_name=args.llm_model_name # Pass the string name
94
- # custom_llm_config, custom_tool_config, etc., can be added here if needed
95
- )
96
- agent_global = agent
97
- except Exception as e:
98
- logger.error(f"Failed to create Agent instance: {e}", exc_info=True)
99
- sys.exit(1)
100
-
101
- logger.info(f"Agent instance created with agent_id '{agent.agent_id}'.")
102
-
103
- server_endpoint = AgentServerEndpoint(agent)
104
- server_endpoint_global = server_endpoint
105
- logger.info(f"AgentServerEndpoint instantiated for agent '{agent.agent_id}'.")
106
-
107
- try:
108
- logger.info(f"Starting Agent '{agent.agent_id}' (runtime execution loop)...")
109
- agent.start()
110
-
111
- logger.info(f"Starting AgentServerEndpoint for agent '{agent.agent_id}' with config '{server_config.server_id}' (Transport: {server_config.transport_type.value})...")
112
- await server_endpoint.start(server_config)
113
-
114
- logger.info(f"Agent '{agent.agent_id}' is now hosted and listening via RPC ({server_config.transport_type.value}).")
115
- await shutdown_event.wait()
116
-
117
- except Exception as e:
118
- logger.error(f"Error during server startup or main execution: {e}", exc_info=True)
119
- finally:
120
- logger.info("server_main performing final shutdown...")
121
- if server_endpoint_global and server_endpoint_global.is_running:
122
- logger.info("Stopping AgentServerEndpoint...")
123
- await server_endpoint_global.stop()
124
-
125
- if agent_global and agent_global.is_running:
126
- logger.info(f"Stopping Agent '{agent_global.agent_id}'...")
127
- await agent_global.stop()
128
-
129
- logger.info("server_main has shut down.")
130
-
131
- async def initiate_shutdown_from_signal():
132
- logger.debug("Initiating shutdown via signal...")
133
- shutdown_event.set()
134
-
135
- if __name__ == "__main__":
136
- # Ensure input processors are available if EchoAgentDefinition needs them
137
- # This try-except is more for robustness during development/examples.
138
- try:
139
- # This import ensures that processors like PassthroughInputProcessor are registered
140
- # if EchoAgentDefinition (or others used by server_main) depends on them.
141
- from autobyteus.agent import input_processor # type: ignore
142
- except ImportError as e_proc:
143
- logger.warning(f"Could not import autobyteus.agent.input_processor: {e_proc}. "
144
- "Make sure custom input processors are correctly installed and registered if used by agent definitions.")
145
-
146
-
147
- # Example STDIO server config (remains for testing server_main directly)
148
- stdio_cfg_id = "default_stdio_server_cfg"
149
- if not default_agent_server_registry.get_config(stdio_cfg_id):
150
- example_stdio_cfg = AgentServerConfig(
151
- server_id=stdio_cfg_id,
152
- transport_type=TransportType.STDIO,
153
- # stdio_command is usually for launching this script itself as a subprocess.
154
- # For direct execution of server_main.py, this specific command isn't directly used
155
- # but a valid config is needed if --server-config-id=default_stdio_server_cfg is passed.
156
- stdio_command=["python", "-m", "autobyteus.rpc.server_main",
157
- "--agent-def-name", "EchoAgent",
158
- "--agent-def-role", "echo_responder",
159
- "--llm-model-name", "GPT_4O_API", # Example model name
160
- "--server-config-id", stdio_cfg_id
161
- ]
162
- )
163
- default_agent_server_registry.register_config(example_stdio_cfg)
164
- logger.info(f"Registered example STDIOServerConfig '{stdio_cfg_id}'.")
165
-
166
- # Example SSE server config
167
- sse_cfg_id = "default_sse_server_cfg"
168
- if not default_agent_server_registry.get_config(sse_cfg_id):
169
- example_sse_cfg = AgentServerConfig(
170
- server_id=sse_cfg_id, # This ID is for the server config itself
171
- transport_type=TransportType.SSE,
172
- sse_base_url="http://localhost:8765",
173
- sse_request_endpoint="/invoke_rpc", # Changed from /rpc to avoid clash with potential future global /rpc
174
- sse_events_endpoint="/agent_events" # Changed from /events
175
- )
176
- default_agent_server_registry.register_config(example_sse_cfg)
177
- logger.info(f"Registered example SseServerConfig '{sse_cfg_id}'.")
178
-
179
- loop = asyncio.get_event_loop()
180
- for sig_name_str in ('SIGINT', 'SIGTERM'):
181
- sig_enum_member = getattr(signal, sig_name_str, None)
182
- if sig_enum_member:
183
- try:
184
- loop.add_signal_handler(sig_enum_member, lambda s=sig_name_str: asyncio.create_task(initiate_shutdown_from_signal()))
185
- except (ValueError, RuntimeError, NotImplementedError) as e: # Might fail on Windows for SIGTERM
186
- logger.warning(f"Could not set signal handler for {sig_name_str} on this platform: {e}.")
187
- try:
188
- loop.run_until_complete(main())
189
- except KeyboardInterrupt:
190
- logger.info("KeyboardInterrupt received in main. Shutting down.")
191
- if not shutdown_event.is_set():
192
- if loop.is_running():
193
- asyncio.ensure_future(initiate_shutdown_from_signal(), loop=loop)
194
- else: # Should not happen if loop was running
195
- loop.run_until_complete(initiate_shutdown_from_signal())
196
- finally:
197
- logger.info("Asyncio loop in server_main is finalizing.")
198
-
@@ -1,13 +0,0 @@
1
- # file: autobyteus/autobyteus/rpc/transport_type.py
2
- from enum import Enum
3
-
4
- class TransportType(str, Enum):
5
- """
6
- Defines the transport mechanisms supported for RPC communication.
7
- """
8
- STDIO = "stdio"
9
- SSE = "sse" # Server-Sent Events over HTTP
10
-
11
- def __str__(self) -> str:
12
- return self.value
13
-
@@ -1,2 +0,0 @@
1
- # This file makes 'bash' a package.
2
- # from .bash_executor import bash_executor # Optionally export
@@ -1,100 +0,0 @@
1
- import asyncio
2
- import subprocess
3
- import logging
4
- import shutil
5
- import tempfile
6
- from typing import TYPE_CHECKING, Optional
7
-
8
- from autobyteus.tools import tool
9
- from autobyteus.tools.tool_category import ToolCategory
10
-
11
- if TYPE_CHECKING:
12
- from autobyteus.agent.context import AgentContext
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
- @tool(name="execute_bash", category=ToolCategory.SYSTEM)
17
- async def bash_executor(context: Optional['AgentContext'], command: str) -> str:
18
- """
19
- Executes bash commands using the '/bin/bash' interpreter.
20
- On success, it returns a formatted string containing the command's standard output (stdout) and/or diagnostic logs.
21
- On failure, it raises an exception.
22
- - If a command has only stdout, its content is returned directly.
23
- - If a command has diagnostic output (from stderr), it will be included and labeled as 'LOGS' in the output.
24
- 'command' is the bash command string to be executed.
25
- The command is executed in the agent's workspace directory if available.
26
- """
27
- if not shutil.which("bash"):
28
- error_msg = "'bash' executable not found in system PATH. The execute_bash tool cannot be used."
29
- logger.error(error_msg)
30
- raise FileNotFoundError(error_msg)
31
-
32
- agent_id_str = context.agent_id if context else "Non-Agent"
33
-
34
- effective_cwd = None
35
- log_cwd_source = ""
36
-
37
- if context and hasattr(context, 'workspace') and context.workspace:
38
- try:
39
- base_path = context.workspace.get_base_path()
40
- if base_path and isinstance(base_path, str):
41
- effective_cwd = base_path
42
- log_cwd_source = f"agent workspace: {effective_cwd}"
43
- else:
44
- logger.warning(f"Agent '{agent_id_str}' has a workspace, but it provided an invalid base path ('{base_path}'). "
45
- f"Falling back to system temporary directory.")
46
- except Exception as e:
47
- logger.warning(f"Could not retrieve workspace for agent '{agent_id_str}': {e}. "
48
- f"Falling back to system temporary directory.")
49
-
50
- if not effective_cwd:
51
- effective_cwd = tempfile.gettempdir()
52
- log_cwd_source = f"system temporary directory: {effective_cwd}"
53
-
54
- logger.debug(f"Functional execute_bash tool executing for '{agent_id_str}': {command} in cwd from {log_cwd_source}")
55
-
56
- try:
57
- # Explicitly use 'bash -c' for reliable execution
58
- process = await asyncio.create_subprocess_exec(
59
- 'bash', '-c', command,
60
- stdout=asyncio.subprocess.PIPE,
61
- stderr=asyncio.subprocess.PIPE,
62
- cwd=effective_cwd
63
- )
64
- stdout, stderr = await process.communicate()
65
-
66
- stdout_output = stdout.decode().strip() if stdout else ""
67
- stderr_output = stderr.decode().strip() if stderr else ""
68
-
69
- if process.returncode != 0:
70
- error_message = stderr_output if stderr_output else "Unknown error"
71
- if not error_message and process.returncode != 0:
72
- error_message = f"Command failed with exit code {process.returncode} and no stderr output."
73
-
74
- logger.error(f"Command '{command}' failed with return code {process.returncode}: {error_message}")
75
- raise subprocess.CalledProcessError(
76
- returncode=process.returncode,
77
- cmd=command,
78
- output=stdout_output,
79
- stderr=error_message
80
- )
81
-
82
- # Adaptive return for successful commands to provide maximum context to the agent.
83
- if stdout_output and stderr_output:
84
- return f"STDOUT:\n{stdout_output}\n\nLOGS:\n{stderr_output}"
85
- elif stdout_output:
86
- return stdout_output # Keep it simple for commands with only stdout
87
- elif stderr_output:
88
- return f"LOGS:\n{stderr_output}"
89
- else:
90
- return "Command executed successfully with no output."
91
-
92
- except subprocess.CalledProcessError:
93
- raise
94
- except FileNotFoundError:
95
- # This can be raised by create_subprocess_exec if 'bash' is not found, despite the initial check.
96
- logger.error("'bash' executable not found when attempting to execute command. Please ensure it is installed and in the PATH.")
97
- raise
98
- except Exception as e:
99
- logger.exception(f"An error occurred while preparing or executing command '{command}': {str(e)}")
100
- raise RuntimeError(f"Failed to execute command '{command}': {str(e)}")
@@ -1,2 +0,0 @@
1
- # This file makes 'browser' a package.
2
- # It can be empty or import submodules/subpackages.