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,73 +0,0 @@
1
- # file: autobyteus/autobyteus/rpc/__init__.py
2
- """
3
- AutoByteUs Remote Procedure Call (RPC) Framework.
4
-
5
- This package provides components for enabling communication between AutoByteUs agents
6
- running in separate processes or on different machines. It includes:
7
- - Protocol definitions for structured messaging.
8
- - Configuration management for RPC servers.
9
- - Client-side components for connecting to and interacting with remote agents.
10
- - Server-side components for exposing an agent's capabilities remotely.
11
- - High-level hosting utilities for easily serving agents.
12
- """
13
-
14
- from .protocol import ProtocolMessage, MessageType, RequestType, ResponseType, ErrorCode, ErrorDetails, EventType
15
- from .transport_type import TransportType
16
- from .config import AgentServerConfig, AgentServerRegistry, default_agent_server_registry
17
- from .client import (
18
- AbstractClientConnection,
19
- StdioClientConnection,
20
- SseClientConnection,
21
- ClientConnectionManager,
22
- default_client_connection_manager
23
- )
24
- from .server import (
25
- AgentServerEndpoint,
26
- StdioServerHandler,
27
- SseServerHandler,
28
- BaseMethodHandler,
29
- DiscoverCapabilitiesHandler,
30
- InvokeMethodHandler,
31
- InitiateStreamDownloadHandler # Added InitiateStreamDownloadHandler
32
- )
33
- from .hosting import serve_agent_stdio, serve_agent_http_sse, serve_single_agent_http_sse, serve_multiple_agents_http_sse # Added all hosting functions
34
-
35
- # RemoteAgentProxy is part of the agent package, but closely related
36
- # from ..agent.remote_agent import RemoteAgentProxy
37
-
38
- __all__ = [
39
- # Protocol
40
- "ProtocolMessage",
41
- "MessageType",
42
- "RequestType",
43
- "ResponseType",
44
- "ErrorCode",
45
- "ErrorDetails",
46
- "EventType",
47
- # Transport
48
- "TransportType",
49
- # Config
50
- "AgentServerConfig",
51
- "AgentServerRegistry",
52
- "default_agent_server_registry",
53
- # Client
54
- "AbstractClientConnection",
55
- "StdioClientConnection",
56
- "SseClientConnection",
57
- "ClientConnectionManager",
58
- "default_client_connection_manager",
59
- # Server
60
- "AgentServerEndpoint",
61
- "StdioServerHandler",
62
- "SseServerHandler",
63
- "BaseMethodHandler",
64
- "DiscoverCapabilitiesHandler",
65
- "InvokeMethodHandler",
66
- "InitiateStreamDownloadHandler", # Added
67
- # Hosting
68
- "serve_agent_stdio",
69
- "serve_agent_http_sse", # Main alias
70
- "serve_single_agent_http_sse", # Specific for one agent
71
- "serve_multiple_agents_http_sse", # Specific for multiple agents
72
- ]
73
-
@@ -1,17 +0,0 @@
1
- # file: autobyteus/autobyteus/rpc/client/__init__.py
2
- """
3
- Client-side components for the AutoByteUs RPC framework.
4
- These components are used to connect to and interact with remote Agent Servers.
5
- """
6
- from .abstract_client_connection import AbstractClientConnection
7
- from .stdio_client_connection import StdioClientConnection
8
- from .sse_client_connection import SseClientConnection # Added SseClientConnection
9
- from .client_connection_manager import ClientConnectionManager, default_client_connection_manager
10
-
11
- __all__ = [
12
- "AbstractClientConnection",
13
- "StdioClientConnection",
14
- "SseClientConnection", # Added SseClientConnection to exports
15
- "ClientConnectionManager",
16
- "default_client_connection_manager",
17
- ]
@@ -1,124 +0,0 @@
1
- # file: autobyteus/autobyteus/rpc/client/abstract_client_connection.py
2
- import asyncio
3
- import logging
4
- from abc import ABC, abstractmethod
5
- from typing import AsyncIterator, Optional, Dict, Any # Added Dict, Any
6
-
7
- from autobyteus.rpc.protocol import ProtocolMessage
8
-
9
- logger = logging.getLogger(__name__)
10
-
11
- class AbstractClientConnection(ABC):
12
- """
13
- Abstract base class for client-side connections to an Agent Server.
14
- Defines the common interface for sending requests and handling responses/events.
15
- """
16
-
17
- def __init__(self, server_id: str):
18
- self.server_id = server_id
19
- self._is_connected: bool = False
20
- self._connection_lock = asyncio.Lock()
21
-
22
- @property
23
- def is_connected(self) -> bool:
24
- """Indicates if the connection is currently active."""
25
- return self._is_connected
26
-
27
- @abstractmethod
28
- async def connect(self) -> None:
29
- """
30
- Establishes the connection to the remote server.
31
- Sets _is_connected to True on success.
32
- Raises:
33
- ConnectionError: If connection fails.
34
- """
35
- raise NotImplementedError
36
-
37
- @abstractmethod
38
- async def close(self) -> None:
39
- """
40
- Closes the connection to the remote server.
41
- Sets _is_connected to False.
42
- """
43
- raise NotImplementedError
44
-
45
- @abstractmethod
46
- async def send_request(self, request_message: ProtocolMessage) -> ProtocolMessage:
47
- """
48
- Sends a request ProtocolMessage to the server and awaits a corresponding
49
- response ProtocolMessage (either a result or an error).
50
-
51
- Args:
52
- request_message: The ProtocolMessage to send (must be of type REQUEST).
53
-
54
- Returns:
55
- The response ProtocolMessage from the server.
56
-
57
- Raises:
58
- ConnectionError: If not connected or if communication fails.
59
- TimeoutError: If the server does not respond within a reasonable time.
60
- ValueError: If request_message is not a valid request.
61
- """
62
- raise NotImplementedError
63
-
64
- async def events(self) -> AsyncIterator[ProtocolMessage]: # pragma: no cover
65
- """
66
- (Optional for some connection types like stdio, primary for SSE)
67
- Provides an asynchronous iterator for server-pushed events.
68
-
69
- Yields:
70
- ProtocolMessage objects of type EVENT from the server.
71
-
72
- Raises:
73
- ConnectionError: If not connected or if the event stream fails.
74
- """
75
- # Default implementation for connection types that don't support server-pushed events.
76
- if False: # This makes the method an async generator while doing nothing
77
- yield
78
- logger.warning(f"Connection type {self.__class__.__name__} does not support server-pushed events via events().")
79
- return
80
-
81
-
82
- @abstractmethod
83
- async def request_and_download_stream(
84
- self,
85
- stream_request_params: Dict[str, Any],
86
- target_agent_id: str
87
- ) -> AsyncIterator[bytes]: # pragma: no cover
88
- """
89
- Requests a stream download from the server and then streams the data.
90
- This typically involves a two-step process:
91
- 1. An RPC call to initiate the stream download and get a download URL.
92
- 2. An HTTP GET request to the download URL to fetch the stream.
93
-
94
- Args:
95
- stream_request_params: Parameters for the REQUEST_STREAM_DOWNLOAD RPC call,
96
- e.g., `{"resource_id": "some_file"}`.
97
- target_agent_id: The ID of the target agent on the server that owns/provides the stream.
98
- This is used to construct the `target_agent_id` field in the RPC request params.
99
-
100
- Yields:
101
- bytes: Chunks of the downloaded data.
102
-
103
- Raises:
104
- ConnectionError: If not connected or if communication fails.
105
- ValueError: If the server response for stream initiation is invalid.
106
- NotImplementedError: If the connection type does not support this.
107
- """
108
- # Default implementation for connection types that don't support this.
109
- if False: # Makes it an async generator
110
- yield b''
111
- logger.warning(f"Connection type {self.__class__.__name__} does not support request_and_download_stream().")
112
- raise NotImplementedError(f"{self.__class__.__name__} does not support stream downloads.")
113
-
114
-
115
- async def __aenter__(self):
116
- await self.connect()
117
- return self
118
-
119
- async def __aexit__(self, exc_type, exc_val, exc_tb):
120
- await self.close()
121
-
122
- def __repr__(self) -> str:
123
- return f"<{self.__class__.__name__} server_id='{self.server_id}', connected={self.is_connected}>"
124
-
@@ -1,153 +0,0 @@
1
- # file: autobyteus/autobyteus/rpc/client/client_connection_manager.py
2
- import logging
3
- from typing import Dict, Optional
4
-
5
- from autobyteus.utils.singleton import SingletonMeta
6
- from autobyteus.rpc.config import AgentServerConfig, AgentServerRegistry, default_agent_server_registry
7
- from autobyteus.rpc.transport_type import TransportType
8
- from .abstract_client_connection import AbstractClientConnection
9
- from .stdio_client_connection import StdioClientConnection
10
- from .sse_client_connection import SseClientConnection # Import SseClientConnection
11
-
12
- logger = logging.getLogger(__name__)
13
-
14
- class ClientConnectionManager(metaclass=SingletonMeta):
15
- """
16
- Manages the creation and caching of AbstractClientConnection instances.
17
- Uses AgentServerRegistry to find server configurations.
18
- """
19
-
20
- def __init__(self, agent_server_registry: AgentServerRegistry = default_agent_server_registry):
21
- self._agent_server_registry: AgentServerRegistry = agent_server_registry
22
- self._active_connections: Dict[str, AbstractClientConnection] = {} # Cache connections by server_id
23
- logger.info("ClientConnectionManager initialized.")
24
-
25
- async def get_connection(self, server_config_id: str) -> AbstractClientConnection:
26
- """
27
- Gets or creates a client connection for the given server configuration ID.
28
- If a connection for this ID already exists and is connected, it's returned.
29
- Otherwise, a new connection is established.
30
-
31
- Args:
32
- server_config_id: The ID of the AgentServerConfig to connect to.
33
-
34
- Returns:
35
- An AbstractClientConnection instance.
36
-
37
- Raises:
38
- ValueError: If server_config_id is not found or config is invalid.
39
- ConnectionError: If establishing a new connection fails.
40
- """
41
- if server_config_id in self._active_connections:
42
- conn = self._active_connections[server_config_id]
43
- if conn.is_connected:
44
- logger.debug(f"Returning cached and connected connection for '{server_config_id}'.")
45
- return conn
46
- else:
47
- logger.info(f"Cached connection for '{server_config_id}' found but not connected. Attempting to recreate.")
48
- await self.close_connection(server_config_id)
49
-
50
-
51
- server_config: Optional[AgentServerConfig] = self._agent_server_registry.get_config(server_config_id)
52
- if not server_config:
53
- raise ValueError(f"AgentServerConfig not found in registry for server_id: '{server_config_id}'.")
54
-
55
- connection: AbstractClientConnection
56
- if server_config.transport_type == TransportType.STDIO:
57
- connection = StdioClientConnection(server_config)
58
- elif server_config.transport_type == TransportType.SSE:
59
- connection = SseClientConnection(server_config) # Added SSE case
60
- else:
61
- raise NotImplementedError(f"Unsupported transport type '{server_config.transport_type}' for server_id '{server_config_id}'.")
62
-
63
- try:
64
- await connection.connect()
65
- self._active_connections[server_config_id] = connection
66
- logger.info(f"Successfully established new connection for server_id '{server_config_id}' type '{server_config.transport_type}'.")
67
- return connection
68
- except Exception as e:
69
- logger.error(f"Failed to establish connection for server_id '{server_config_id}': {e}", exc_info=True)
70
- await connection.close() # Ensure cleanup on failed connect
71
- if server_config_id in self._active_connections:
72
- del self._active_connections[server_config_id]
73
- raise ConnectionError(f"Failed to connect to server '{server_config_id}': {e}") from e
74
-
75
-
76
- async def close_connection(self, server_config_id: str) -> None:
77
- """
78
- Closes and removes a specific connection from the manager.
79
-
80
- Args:
81
- server_config_id: The ID of the server connection to close.
82
- """
83
- connection = self._active_connections.pop(server_config_id, None)
84
- if connection:
85
- logger.info(f"Closing connection for server_id '{server_config_id}'.")
86
- try:
87
- await connection.close()
88
- except Exception as e:
89
- logger.error(f"Error closing connection for server_id '{server_config_id}': {e}", exc_info=True)
90
- else:
91
- logger.debug(f"No active connection found for server_id '{server_config_id}' to close.")
92
-
93
- async def close_all_connections(self) -> None:
94
- """Closes all active connections managed by this instance."""
95
- logger.info(f"Closing all {len(self._active_connections)} active connections.")
96
- for server_id in list(self._active_connections.keys()):
97
- await self.close_connection(server_id)
98
- logger.info("All active connections have been requested to close.")
99
-
100
- default_client_connection_manager = ClientConnectionManager()
101
-
102
- if __name__ == "__main__": # pragma: no cover
103
- logging.basicConfig(level=logging.DEBUG)
104
-
105
- # Mock server configs
106
- mock_stdio_id = "mock_stdio_ccm"
107
- mock_stdio_cfg = AgentServerConfig(
108
- server_id=mock_stdio_id,
109
- transport_type=TransportType.STDIO,
110
- stdio_command=["python", "-c", "import sys, time, json; print(json.dumps({'type':'response', 'id':'1', 'result':{'status':'ok'}}), flush=True); time.sleep(0.1); sys.exit(0)"]
111
- )
112
- default_agent_server_registry.register_config(mock_stdio_cfg)
113
-
114
- mock_sse_id = "mock_sse_ccm"
115
- mock_sse_cfg = AgentServerConfig(
116
- server_id=mock_sse_id,
117
- transport_type=TransportType.SSE,
118
- sse_base_url="http://localhost:12345", # Dummy URL, server won't actually run here
119
- sse_request_endpoint="/rpc",
120
- sse_events_endpoint="/stream"
121
- )
122
- default_agent_server_registry.register_config(mock_sse_cfg)
123
-
124
-
125
- manager = default_client_connection_manager
126
-
127
- async def main_ccm_test():
128
- stdio_conn = None
129
- sse_conn = None
130
- try:
131
- logger.info(f"Testing CCM with Stdio: {mock_stdio_id}")
132
- stdio_conn = await manager.get_connection(mock_stdio_id)
133
- logger.info(f"Stdio connection: {stdio_conn}")
134
- if stdio_conn.is_connected:
135
- # Test send_request on stdio_conn
136
- req = ProtocolMessage.create_request(method="test", id="1")
137
- resp = await stdio_conn.send_request(req)
138
- logger.info(f"Stdio test response: {resp}")
139
-
140
-
141
- logger.info(f"Testing CCM with SSE: {mock_sse_id}")
142
- sse_conn = await manager.get_connection(mock_sse_id) # This will create SseClientConnection and its session
143
- logger.info(f"SSE connection: {sse_conn}")
144
- # Actual SSE requests would fail here as no server is running at localhost:12345
145
-
146
- except Exception as e:
147
- logger.error(f"Error in CCM main_ccm_test: {e}", exc_info=True)
148
- finally:
149
- logger.info("Closing all connections via CCM.")
150
- await manager.close_all_connections()
151
- default_agent_server_registry.clear() # Clean up registry for other tests if any
152
-
153
- asyncio.run(main_ccm_test())
@@ -1,306 +0,0 @@
1
- # file: autobyteus/autobyteus/rpc/client/sse_client_connection.py
2
- import asyncio
3
- import logging
4
- import json
5
- from typing import Optional, AsyncIterator, Dict, Any # Added Dict, Any
6
-
7
- import aiohttp
8
- from aiohttp_sse_client.client import EventSource # type: ignore
9
-
10
- from autobyteus.rpc.protocol import ProtocolMessage, MessageType, ErrorCode, EventType, RequestType, ResponseType # Added RequestType, ResponseType
11
- from .abstract_client_connection import AbstractClientConnection
12
- from autobyteus.rpc.config import AgentServerConfig, TransportType # Added TransportType from config
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
- DEFAULT_SSE_TIMEOUT = 30.0 # seconds for an HTTP request response
17
- DEFAULT_SSE_RECONNECTION_TIME = 5 # seconds
18
- DEFAULT_STREAM_DOWNLOAD_TIMEOUT = 300.0 # 5 minutes for stream download requests
19
-
20
- class SseClientConnection(AbstractClientConnection):
21
- """
22
- Client connection implementation for SSE-based Agent Servers.
23
- Uses aiohttp for HTTP requests and aiohttp-sse-client for consuming SSE event streams.
24
- Also supports direct HTTP stream downloads.
25
- """
26
-
27
- def __init__(self, server_config: AgentServerConfig):
28
- """
29
- Initializes the SseClientConnection.
30
-
31
- Args:
32
- server_config: The configuration for the SSE server.
33
-
34
- Raises:
35
- ValueError: If server_config is not for SSE or base URL is missing.
36
- """
37
- if server_config.transport_type != TransportType.SSE: # Use Enum member
38
- raise ValueError("SseClientConnection requires an AgentServerConfig with transport_type 'sse'.")
39
- if not server_config.sse_base_url:
40
- raise ValueError("AgentServerConfig for sse transport must have an sse_base_url.")
41
-
42
- super().__init__(server_id=server_config.server_id)
43
- self.server_config: AgentServerConfig = server_config
44
- self._session: Optional[aiohttp.ClientSession] = None
45
- self._event_source: Optional[EventSource] = None
46
-
47
- async def connect(self) -> None:
48
- """
49
- Establishes the aiohttp ClientSession. For SSE, actual connection
50
- to event stream happens when events() is iterated.
51
- """
52
- async with self._connection_lock:
53
- if self._is_connected and self._session and not self._session.closed:
54
- logger.debug(f"SseClientConnection to '{self.server_id}' session already active.")
55
- return
56
-
57
- try:
58
- # Create a new session if it doesn't exist or is closed
59
- if not self._session or self._session.closed:
60
- self._session = aiohttp.ClientSession()
61
- logger.info(f"SseClientConnection to '{self.server_id}': new aiohttp.ClientSession created.")
62
-
63
- self._is_connected = True # Mark as connected once session is ready
64
- logger.info(f"SseClientConnection to '{self.server_id}' connected (session ready).")
65
- except Exception as e:
66
- logger.error(f"Failed to create/ensure aiohttp.ClientSession for '{self.server_id}': {e}", exc_info=True)
67
- self._is_connected = False
68
- if self._session and not self._session.closed:
69
- await self._session.close()
70
- self._session = None
71
- raise ConnectionError(f"Failed to initialize HTTP session for SSE server '{self.server_id}': {e}") from e
72
-
73
- async def close(self) -> None:
74
- """Closes the aiohttp ClientSession and any active EventSource."""
75
- async with self._connection_lock:
76
- if not self._is_connected and not self._session: # Check both state and session object
77
- logger.debug(f"SseClientConnection to '{self.server_id}' already closed or never connected.")
78
- return
79
-
80
- self._is_connected = False
81
-
82
- if self._event_source:
83
- try:
84
- await self._event_source.close()
85
- logger.debug(f"EventSource for '{self.server_id}' closed.")
86
- except Exception as e:
87
- logger.error(f"Error closing EventSource for '{self.server_id}': {e}", exc_info=True)
88
- self._event_source = None
89
-
90
- if self._session and not self._session.closed:
91
- try:
92
- await self._session.close()
93
- logger.debug(f"aiohttp.ClientSession for '{self.server_id}' closed.")
94
- except Exception as e:
95
- logger.error(f"Error closing aiohttp.ClientSession for '{self.server_id}': {e}", exc_info=True)
96
- self._session = None # Ensure session object is cleared
97
-
98
- logger.info(f"SseClientConnection to '{self.server_id}' closed.")
99
-
100
- async def send_request(self, request_message: ProtocolMessage) -> ProtocolMessage:
101
- """Sends a request via HTTP POST and awaits a JSON response."""
102
- if not self._is_connected or not self._session or self._session.closed:
103
- logger.info(f"SseClientConnection '{self.server_id}' not connected or session closed/missing. Attempting to connect before send_request.")
104
- await self.connect()
105
- if not self._is_connected or not self._session or self._session.closed: # Check again after connect attempt
106
- raise ConnectionError(f"Failed to connect to SSE server '{self.server_id}' for send_request (connection attempt failed).")
107
-
108
- if request_message.type != MessageType.REQUEST:
109
- raise ValueError("ProtocolMessage must be of type REQUEST to be sent via send_request.")
110
- if not request_message.id:
111
- raise ValueError("Request ProtocolMessage must have an ID.")
112
-
113
- request_url = self.server_config.get_sse_full_request_url()
114
- if not request_url:
115
- raise ValueError("SSE request URL is not configured.")
116
-
117
- logger.debug(f"SseClient '{self.server_id}' sending request to {request_url}: {request_message.to_json_str()}")
118
-
119
- try:
120
- async with self._session.post(
121
- request_url,
122
- json=request_message.model_dump(exclude_none=True),
123
- timeout=DEFAULT_SSE_TIMEOUT
124
- ) as response:
125
- response_text = await response.text()
126
- if response.status >= 200 and response.status < 300:
127
- try:
128
- return ProtocolMessage.from_json_str(response_text)
129
- except (json.JSONDecodeError, ValueError) as e:
130
- logger.error(f"Error decoding JSON response from '{request_url}': {e}. Response text: {response_text[:200]}")
131
- return ProtocolMessage.create_error_response(
132
- id=request_message.id,
133
- code=ErrorCode.PARSE_ERROR,
134
- message=f"Failed to parse JSON response from server: {e}"
135
- )
136
- else:
137
- logger.error(f"HTTP error from '{request_url}': {response.status} {response.reason}. Response: {response_text[:200]}")
138
- return ProtocolMessage.create_error_response(
139
- id=request_message.id,
140
- code=ErrorCode.INTERNAL_ERROR,
141
- message=f"Server returned HTTP error {response.status}: {response.reason}. Body: {response_text[:200]}"
142
- )
143
- except aiohttp.ClientConnectorError as e:
144
- logger.error(f"Connection error for '{request_url}': {e}", exc_info=True)
145
- await self.close() # Connection is likely broken, perform full close
146
- raise ConnectionError(f"Could not connect to SSE server at '{request_url}': {e}") from e
147
- except asyncio.TimeoutError:
148
- logger.warning(f"Timeout sending request to '{request_url}' for ID '{request_message.id}'.")
149
- # Don't necessarily close connection on timeout, server might be slow.
150
- return ProtocolMessage.create_error_response(
151
- id=request_message.id,
152
- code=ErrorCode.SERVER_ERROR_TIMEOUT,
153
- message=f"Timeout waiting for response from SSE server for request ID '{request_message.id}'."
154
- )
155
- except Exception as e:
156
- logger.error(f"Unexpected error sending request to '{request_url}': {e}", exc_info=True)
157
- if isinstance(e, (aiohttp.ClientError)):
158
- await self.close() # If it's a client lib error, connection might be compromised
159
- return ProtocolMessage.create_error_response(
160
- id=request_message.id,
161
- code=ErrorCode.INTERNAL_ERROR,
162
- message=f"Client-side error sending request: {e}"
163
- )
164
-
165
- async def events(self) -> AsyncIterator[ProtocolMessage]:
166
- """Connects to the SSE event stream and yields ProtocolMessages."""
167
- if not self._is_connected or not self._session or self._session.closed:
168
- logger.info(f"SseClientConnection '{self.server_id}' session not found or closed, attempting to connect before streaming events.")
169
- await self.connect()
170
- if not self._is_connected or not self._session or self._session.closed: # Check again
171
- raise ConnectionError(f"Not connected to SSE server '{self.server_id}' for event streaming (connection attempt failed).")
172
-
173
- # Construct event URL. Note: SseServerHandler expects /events/{agent_id_on_server}
174
- # The client config's server_id typically maps to an agent_id_on_server or is the agent_id_on_server.
175
- # For multi-agent servers, the client needs to know which agent_id_on_server to subscribe to.
176
- # This implies server_config.server_id is the agent_id_on_server for SSE event subscriptions.
177
- base_events_url = self.server_config.get_sse_full_events_url()
178
- if not base_events_url: # This is base path like /events
179
- raise ValueError("SSE events base URL path is not configured.")
180
-
181
- # Assuming self.server_id (from config) is the key for the agent on the server.
182
- events_url = f"{base_events_url.rstrip('/')}/{self.server_id}"
183
- logger.info(f"SseClient '{self.server_id}' connecting to event stream at {events_url}")
184
-
185
- if self._event_source: # Close existing if any
186
- await self._event_source.close()
187
- self._event_source = None
188
-
189
- try:
190
- self._event_source = EventSource(
191
- events_url,
192
- session=self._session, # Use existing session
193
- reconnection_time=DEFAULT_SSE_RECONNECTION_TIME,
194
- )
195
- await self._event_source.connect()
196
-
197
- async for sse_event in self._event_source:
198
- try:
199
- logger.debug(f"SseClient '{self.server_id}' received SSE event data: {sse_event.data[:200]}")
200
- msg = ProtocolMessage.from_json_str(sse_event.data)
201
- if msg.type == MessageType.EVENT:
202
- yield msg
203
- else:
204
- logger.warning(f"Received non-EVENT ProtocolMessage via SSE stream: {msg.type}. Ignoring.")
205
- except json.JSONDecodeError as e:
206
- logger.error(f"Error decoding JSON from SSE event data: {e}. Data: {sse_event.data[:200]}")
207
- except ValueError as e:
208
- logger.error(f"Error validating ProtocolMessage from SSE event data: {e}. Data: {sse_event.data[:200]}")
209
- except Exception as e:
210
- logger.error(f"Error processing SSE event: {e}", exc_info=True)
211
-
212
- except ConnectionRefusedError as e:
213
- logger.error(f"SSE EventStream for '{self.server_id}' connection refused at {events_url}: {e}")
214
- await self.close()
215
- raise ConnectionError(f"SSE EventStream connection refused: {e}") from e
216
- except aiohttp.ClientError as e:
217
- logger.error(f"SSE EventStream client error for '{self.server_id}' at {events_url}: {e}", exc_info=True)
218
- await self.close()
219
- raise ConnectionError(f"SSE EventStream client error: {e}") from e
220
- except asyncio.CancelledError:
221
- logger.info(f"SSE event stream for '{self.server_id}' cancelled.")
222
- if self._event_source: await self._event_source.close()
223
- raise
224
- except Exception as e:
225
- logger.error(f"Unexpected error in SSE event stream for '{self.server_id}': {e}", exc_info=True)
226
- if self._event_source: await self._event_source.close()
227
- await self.close()
228
- raise ConnectionError(f"Unexpected error in SSE event stream: {e}") from e
229
- finally:
230
- logger.info(f"SseClient '{self.server_id}' event stream iteration finished.")
231
- if self._event_source:
232
- await self._event_source.close()
233
- self._event_source = None
234
-
235
-
236
- async def request_and_download_stream(
237
- self,
238
- stream_request_params: Dict[str, Any],
239
- target_agent_id: str # This is the agent_id_on_server key
240
- ) -> AsyncIterator[bytes]:
241
- """
242
- Requests a stream download via RPC and then downloads the stream via HTTP GET.
243
- """
244
- if not self._is_connected or not self._session or self._session.closed:
245
- logger.info(f"SseClientConnection '{self.server_id}' not connected or session closed/missing. Attempting to connect before stream download.")
246
- await self.connect()
247
- if not self._is_connected or not self._session or self._session.closed:
248
- raise ConnectionError(f"Failed to connect to SSE server '{self.server_id}' for stream download (connection attempt failed).")
249
-
250
- # Step 1: RPC call to initiate stream download
251
- # The target_agent_id for the stream must be included in the params for the RPC call.
252
- rpc_params = {**stream_request_params, "target_agent_id": target_agent_id}
253
- initiate_request_msg = ProtocolMessage.create_request(
254
- method=RequestType.REQUEST_STREAM_DOWNLOAD,
255
- params=rpc_params
256
- )
257
-
258
- logger.debug(f"SseClient '{self.server_id}' sending stream download initiation request for target_agent_id '{target_agent_id}': {initiate_request_msg.to_json_str()}")
259
-
260
- initiate_response_msg = await self.send_request(initiate_request_msg)
261
-
262
- if initiate_response_msg.type == MessageType.ERROR or not initiate_response_msg.result:
263
- err_details = initiate_response_msg.error.message if initiate_response_msg.error else "Unknown error"
264
- logger.error(f"Failed to initiate stream download for target_agent_id '{target_agent_id}'. Server error: {err_details}")
265
- raise ValueError(f"Server error initiating stream download: {err_details}")
266
-
267
- if initiate_response_msg.response_type != ResponseType.STREAM_DOWNLOAD_READY:
268
- logger.error(f"Unexpected response type from stream download initiation: {initiate_response_msg.response_type}")
269
- raise ValueError(f"Unexpected response type: {initiate_response_msg.response_type}")
270
-
271
- download_url = initiate_response_msg.result.get("download_url")
272
- if not download_url:
273
- logger.error(f"No 'download_url' in STREAM_DOWNLOAD_READY response. Result: {initiate_response_msg.result}")
274
- raise ValueError("Server response did not include a download_url for the stream.")
275
-
276
- stream_metadata = initiate_response_msg.result.get("metadata", {})
277
- logger.info(f"SseClient '{self.server_id}' received download URL: {download_url}. Metadata: {stream_metadata}")
278
-
279
- # Step 2: HTTP GET request to the download_url
280
- try:
281
- logger.debug(f"SseClient '{self.server_id}' starting GET request to stream from {download_url}")
282
- async with self._session.get(download_url, timeout=DEFAULT_STREAM_DOWNLOAD_TIMEOUT) as response:
283
- response.raise_for_status() # Raise an exception for HTTP error codes (4xx or 5xx)
284
-
285
- # Stream the content
286
- async for chunk in response.content.iter_any(): # iter_any() or iter_chunked(chunk_size)
287
- yield chunk
288
- logger.info(f"SseClient '{self.server_id}' finished streaming from {download_url}")
289
-
290
- except aiohttp.ClientResponseError as e:
291
- logger.error(f"HTTP error during stream download from '{download_url}': {e.status} {e.message}", exc_info=True)
292
- # Connection might still be usable for other RPCs, don't necessarily close.
293
- raise ConnectionError(f"HTTP error downloading stream: {e.status} {e.message}") from e
294
- except aiohttp.ClientConnectorError as e:
295
- logger.error(f"Connection error during stream download from '{download_url}': {e}", exc_info=True)
296
- await self.close() # Connection likely broken
297
- raise ConnectionError(f"Could not connect to download stream at '{download_url}': {e}") from e
298
- except asyncio.TimeoutError:
299
- logger.warning(f"Timeout downloading stream from '{download_url}'.")
300
- # Don't close connection, server might be slow or stream very long with no data.
301
- raise TimeoutError(f"Timeout downloading stream from '{download_url}'.")
302
- except Exception as e:
303
- logger.error(f"Unexpected error downloading stream from '{download_url}': {e}", exc_info=True)
304
- if isinstance(e, (aiohttp.ClientError)):
305
- await self.close() # If it's a client lib error, connection might be compromised
306
- raise ConnectionError(f"Client-side error downloading stream: {e}") from e