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
@@ -0,0 +1,303 @@
1
+ # file: autobyteus/autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py
2
+ """
3
+ ApiToolCallStreamingResponseHandler: Handler for API-provided tool calls.
4
+
5
+ This handler processes SDK-provided tool calls from providers like OpenAI,
6
+ Anthropic, and Gemini. It emits SegmentEvents and uses an internal
7
+ ToolInvocationAdapter to create ToolInvocations.
8
+ """
9
+ import json
10
+ import uuid
11
+ import logging
12
+ from dataclasses import dataclass
13
+ from typing import Optional, List, Dict, Callable
14
+
15
+ from .streaming_response_handler import StreamingResponseHandler
16
+ from ..segments.segment_events import SegmentEvent, SegmentType, SegmentEventType
17
+ from ..adapters.invocation_adapter import ToolInvocationAdapter
18
+ from ..api_tool_call.file_content_streamer import WriteFileContentStreamer, PatchFileContentStreamer
19
+ from autobyteus.agent.tool_invocation import ToolInvocation
20
+ from autobyteus.llm.utils.response_types import ChunkResponse
21
+
22
+ logger = logging.getLogger(__name__)
23
+
24
+
25
+ @dataclass
26
+ class ToolCallState:
27
+ """Tracks the state of an in-progress tool call."""
28
+ segment_id: str
29
+ name: str
30
+ accumulated_args: str = ""
31
+ segment_type: SegmentType = SegmentType.TOOL_CALL
32
+ streamer: Optional[object] = None
33
+ path: Optional[str] = None
34
+ segment_started: bool = False
35
+ pending_content: str = ""
36
+
37
+
38
+ class ApiToolCallStreamingResponseHandler(StreamingResponseHandler):
39
+ """
40
+ Handler for API-provided tool calls (OpenAI, Anthropic, Gemini native tool calling).
41
+
42
+ Responsibilities:
43
+ 1. Emit TEXT segments for text content
44
+ 2. Emit TOOL_CALL segments for SDK-provided tool calls
45
+ 3. Use internal ToolInvocationAdapter to create ToolInvocations
46
+
47
+ Key Design:
48
+ - Handler emits SegmentEvents
49
+ - Internal adapter processes events to create ToolInvocations
50
+ - get_all_invocations() returns adapter results (consistent interface)
51
+ """
52
+
53
+ def __init__(
54
+ self,
55
+ on_segment_event: Optional[Callable[[SegmentEvent], None]] = None,
56
+ on_tool_invocation: Optional[Callable[[ToolInvocation], None]] = None,
57
+ segment_id_prefix: str = "",
58
+ ):
59
+ self._on_segment_event = on_segment_event
60
+ self._on_tool_invocation = on_tool_invocation
61
+ self._segment_id_prefix = segment_id_prefix
62
+
63
+ # Internal adapter for creating invocations from events
64
+ self._adapter = ToolInvocationAdapter()
65
+
66
+ # State tracking
67
+ self._text_segment_id: Optional[str] = None
68
+ self._active_tools: Dict[int, ToolCallState] = {} # index -> state
69
+ self._all_events: List[SegmentEvent] = []
70
+ self._all_invocations: List[ToolInvocation] = []
71
+ self._is_finalized = False
72
+
73
+ def _generate_id(self) -> str:
74
+ return f"{self._segment_id_prefix}{uuid.uuid4().hex}"
75
+
76
+ @staticmethod
77
+ def _resolve_segment_type(tool_name: str):
78
+ if tool_name == "write_file":
79
+ return SegmentType.WRITE_FILE, WriteFileContentStreamer()
80
+ if tool_name == "patch_file":
81
+ return SegmentType.PATCH_FILE, PatchFileContentStreamer()
82
+ return SegmentType.TOOL_CALL, None
83
+
84
+ def _emit(self, event: SegmentEvent) -> None:
85
+ """Emit event and process through internal adapter."""
86
+ self._all_events.append(event)
87
+
88
+ # Notify callback
89
+ if self._on_segment_event:
90
+ try:
91
+ self._on_segment_event(event)
92
+ except Exception as e:
93
+ logger.error(f"Error in on_segment_event callback: {e}")
94
+
95
+ # Process through internal adapter
96
+ invocation = self._adapter.process_event(event)
97
+ if invocation:
98
+ self._all_invocations.append(invocation)
99
+ if self._on_tool_invocation:
100
+ try:
101
+ self._on_tool_invocation(invocation)
102
+ except Exception as e:
103
+ logger.error(f"Error in on_tool_invocation callback: {e}")
104
+
105
+ def feed(self, chunk: ChunkResponse) -> List[SegmentEvent]:
106
+ if self._is_finalized:
107
+ raise RuntimeError("Handler has been finalized.")
108
+
109
+ events = []
110
+
111
+ # 1. Handle text content → TEXT segment
112
+ if chunk.content:
113
+ if self._text_segment_id is None:
114
+ self._text_segment_id = self._generate_id()
115
+ start_event = SegmentEvent.start(
116
+ segment_id=self._text_segment_id,
117
+ segment_type=SegmentType.TEXT
118
+ )
119
+ self._emit(start_event)
120
+ events.append(start_event)
121
+
122
+ content_event = SegmentEvent.content(
123
+ segment_id=self._text_segment_id,
124
+ delta=chunk.content
125
+ )
126
+ self._emit(content_event)
127
+ events.append(content_event)
128
+
129
+ # 2. Handle tool calls from SDK
130
+ if chunk.tool_calls:
131
+ for delta in chunk.tool_calls:
132
+ if delta.index not in self._active_tools:
133
+ # New tool call - emit SEGMENT_START
134
+ seg_id = delta.call_id or self._generate_id()
135
+ tool_name = delta.name or ""
136
+ segment_type, streamer = self._resolve_segment_type(tool_name)
137
+ self._active_tools[delta.index] = ToolCallState(
138
+ segment_id=seg_id,
139
+ name=tool_name,
140
+ accumulated_args="",
141
+ segment_type=segment_type,
142
+ streamer=streamer,
143
+ )
144
+ if segment_type == SegmentType.TOOL_CALL:
145
+ start_event = SegmentEvent.start(
146
+ segment_id=seg_id,
147
+ segment_type=segment_type,
148
+ tool_name=tool_name,
149
+ )
150
+ self._active_tools[delta.index].segment_started = True
151
+ self._emit(start_event)
152
+ events.append(start_event)
153
+
154
+ # Accumulate arguments and emit content delta (for UI streaming)
155
+ if delta.arguments_delta:
156
+ state = self._active_tools[delta.index]
157
+ state.accumulated_args += delta.arguments_delta
158
+
159
+ if state.segment_type == SegmentType.TOOL_CALL:
160
+ if not state.segment_started:
161
+ start_event = SegmentEvent.start(
162
+ segment_id=state.segment_id,
163
+ segment_type=state.segment_type,
164
+ tool_name=state.name,
165
+ )
166
+ state.segment_started = True
167
+ self._emit(start_event)
168
+ events.append(start_event)
169
+ content_event = SegmentEvent.content(
170
+ segment_id=state.segment_id,
171
+ delta=delta.arguments_delta,
172
+ )
173
+ self._emit(content_event)
174
+ events.append(content_event)
175
+ else:
176
+ update = state.streamer.feed(delta.arguments_delta) if state.streamer else None
177
+ if update and update.path and not state.path:
178
+ state.path = update.path
179
+ if not state.segment_started and state.path:
180
+ start_event = SegmentEvent.start(
181
+ segment_id=state.segment_id,
182
+ segment_type=state.segment_type,
183
+ tool_name=state.name,
184
+ path=state.path,
185
+ )
186
+ state.segment_started = True
187
+ self._emit(start_event)
188
+ events.append(start_event)
189
+ if state.pending_content:
190
+ content_event = SegmentEvent.content(
191
+ segment_id=state.segment_id,
192
+ delta=state.pending_content,
193
+ )
194
+ self._emit(content_event)
195
+ events.append(content_event)
196
+ state.pending_content = ""
197
+ if update and update.content_delta:
198
+ if state.segment_started:
199
+ content_event = SegmentEvent.content(
200
+ segment_id=state.segment_id,
201
+ delta=update.content_delta,
202
+ )
203
+ self._emit(content_event)
204
+ events.append(content_event)
205
+ else:
206
+ state.pending_content += update.content_delta
207
+
208
+ # Update name if provided later
209
+ if delta.name and not self._active_tools[delta.index].name:
210
+ self._active_tools[delta.index].name = delta.name
211
+
212
+ return events
213
+
214
+ def finalize(self) -> List[SegmentEvent]:
215
+ if self._is_finalized:
216
+ return []
217
+
218
+ self._is_finalized = True
219
+ events = []
220
+
221
+ # Close text segment
222
+ if self._text_segment_id:
223
+ end_event = SegmentEvent.end(segment_id=self._text_segment_id)
224
+ self._emit(end_event)
225
+ events.append(end_event)
226
+
227
+ # Close tool segments with pre-parsed arguments in metadata
228
+ for state in self._active_tools.values():
229
+ if state.segment_type in {SegmentType.WRITE_FILE, SegmentType.PATCH_FILE}:
230
+ if not state.segment_started:
231
+ start_meta = {"tool_name": state.name}
232
+ if state.path:
233
+ start_meta["path"] = state.path
234
+ start_event = SegmentEvent.start(
235
+ segment_id=state.segment_id,
236
+ segment_type=state.segment_type,
237
+ **start_meta,
238
+ )
239
+ state.segment_started = True
240
+ self._emit(start_event)
241
+ events.append(start_event)
242
+ if state.pending_content:
243
+ content_event = SegmentEvent.content(
244
+ segment_id=state.segment_id,
245
+ delta=state.pending_content,
246
+ )
247
+ self._emit(content_event)
248
+ events.append(content_event)
249
+ state.pending_content = ""
250
+ if state.segment_type == SegmentType.TOOL_CALL:
251
+ # Parse accumulated JSON arguments
252
+ try:
253
+ parsed_args = json.loads(state.accumulated_args) if state.accumulated_args else {}
254
+ except json.JSONDecodeError as e:
255
+ logger.error(f"Failed to parse tool arguments for {state.name}: {e}")
256
+ parsed_args = {}
257
+
258
+ # Emit SEGMENT_END with arguments in metadata
259
+ # The internal adapter will use this to create ToolInvocation
260
+ end_event = SegmentEvent(
261
+ event_type=SegmentEventType.END,
262
+ segment_id=state.segment_id,
263
+ payload={
264
+ "metadata": {
265
+ "tool_name": state.name,
266
+ "arguments": parsed_args, # Pre-parsed for adapter
267
+ }
268
+ }
269
+ )
270
+ else:
271
+ metadata = {}
272
+ if state.path:
273
+ metadata["path"] = state.path
274
+ end_event = SegmentEvent(
275
+ event_type=SegmentEventType.END,
276
+ segment_id=state.segment_id,
277
+ payload={"metadata": metadata} if metadata else {},
278
+ )
279
+ self._emit(end_event)
280
+ events.append(end_event)
281
+
282
+ if self._all_invocations:
283
+ logger.info(
284
+ "ApiToolCallStreamingResponseHandler finalized %d tool invocations.",
285
+ len(self._all_invocations),
286
+ )
287
+
288
+ return events
289
+
290
+ def get_all_events(self) -> List[SegmentEvent]:
291
+ return self._all_events.copy()
292
+
293
+ def get_all_invocations(self) -> List[ToolInvocation]:
294
+ """Returns invocations created by the internal adapter."""
295
+ return self._all_invocations.copy()
296
+
297
+ def reset(self) -> None:
298
+ self._text_segment_id = None
299
+ self._active_tools.clear()
300
+ self._all_events.clear()
301
+ self._all_invocations.clear()
302
+ self._adapter = ToolInvocationAdapter()
303
+ self._is_finalized = False
@@ -0,0 +1,107 @@
1
+ """
2
+ ParsingStreamingResponseHandler: Concrete implementation of StreamingResponseHandler that uses a parser.
3
+ """
4
+ from typing import Optional, List, Callable, Any, Union
5
+ import logging
6
+
7
+ from .streaming_response_handler import StreamingResponseHandler
8
+ from ..parser.parser_factory import create_streaming_parser, resolve_parser_name
9
+ from ..segments.segment_events import SegmentEvent
10
+ from ..adapters.invocation_adapter import ToolInvocationAdapter
11
+ from ..parser.parser_context import ParserConfig
12
+ from autobyteus.agent.tool_invocation import ToolInvocation
13
+ from autobyteus.llm.utils.response_types import ChunkResponse
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class ParsingStreamingResponseHandler(StreamingResponseHandler):
19
+ """
20
+ Handler that uses a StreamingParser to process the LLM response.
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ on_segment_event: Optional[Callable[[SegmentEvent], None]] = None,
26
+ on_tool_invocation: Optional[Callable[[ToolInvocation], None]] = None,
27
+ config: Optional[ParserConfig] = None,
28
+ parser_name: Optional[str] = None,
29
+ ):
30
+ """
31
+ Initialize the parsing response handler.
32
+ """
33
+ self._parser_name = resolve_parser_name(parser_name)
34
+ self._parser_config = config
35
+ self._parser = create_streaming_parser(
36
+ config=config,
37
+ parser_name=self._parser_name,
38
+ )
39
+ self._adapter = ToolInvocationAdapter(
40
+ json_tool_parser=self._parser.config.json_tool_parser
41
+ )
42
+ self._on_segment_event = on_segment_event
43
+ self._on_tool_invocation = on_tool_invocation
44
+ self._is_finalized = False
45
+
46
+ # Accumulated data
47
+ self._all_events: List[SegmentEvent] = []
48
+ self._all_invocations: List[ToolInvocation] = []
49
+
50
+ def feed(self, chunk: ChunkResponse) -> List[SegmentEvent]:
51
+ if self._is_finalized:
52
+ raise RuntimeError("Handler has been finalized, cannot feed more chunks.")
53
+
54
+ # Extract text content from ChunkResponse (ignore tool_calls - not our concern)
55
+ text_content = chunk.content if isinstance(chunk, ChunkResponse) else chunk
56
+ if not text_content:
57
+ return []
58
+
59
+ events = self._parser.feed(text_content)
60
+ self._process_events(events)
61
+ return events
62
+
63
+ def finalize(self) -> List[SegmentEvent]:
64
+ if self._is_finalized:
65
+ return []
66
+
67
+ self._is_finalized = True
68
+ events = self._parser.finalize()
69
+ self._process_events(events)
70
+ return events
71
+
72
+ def _process_events(self, events: List[SegmentEvent]) -> None:
73
+ for event in events:
74
+ self._all_events.append(event)
75
+
76
+ if self._on_segment_event:
77
+ try:
78
+ self._on_segment_event(event)
79
+ except Exception as e:
80
+ logger.error(f"Error in on_segment_event callback: {e}")
81
+
82
+ invocation = self._adapter.process_event(event)
83
+ if invocation:
84
+ self._all_invocations.append(invocation)
85
+ if self._on_tool_invocation:
86
+ try:
87
+ self._on_tool_invocation(invocation)
88
+ except Exception as e:
89
+ logger.error(f"Error in on_tool_invocation callback: {e}")
90
+
91
+ def get_all_events(self) -> List[SegmentEvent]:
92
+ return self._all_events.copy()
93
+
94
+ def get_all_invocations(self) -> List[ToolInvocation]:
95
+ return self._all_invocations.copy()
96
+
97
+ def reset(self) -> None:
98
+ self._parser = create_streaming_parser(
99
+ config=self._parser_config,
100
+ parser_name=self._parser_name,
101
+ )
102
+ self._adapter = ToolInvocationAdapter(
103
+ json_tool_parser=self._parser.config.json_tool_parser
104
+ )
105
+ self._all_events.clear()
106
+ self._all_invocations.clear()
107
+ self._is_finalized = False
@@ -0,0 +1,107 @@
1
+ """
2
+ PassThroughStreamingResponseHandler: Implementation of StreamingResponseHandler that bypasses parsing.
3
+ """
4
+ import uuid
5
+ import logging
6
+ from typing import Optional, List, Callable
7
+
8
+ from .streaming_response_handler import StreamingResponseHandler
9
+ from ..segments.segment_events import SegmentEvent, SegmentType, SegmentEventType
10
+ from autobyteus.agent.tool_invocation import ToolInvocation
11
+ from autobyteus.llm.utils.response_types import ChunkResponse
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class PassThroughStreamingResponseHandler(StreamingResponseHandler):
17
+ """
18
+ Handler that passes raw text chunks directly as segment events without parsing.
19
+ Used when an agent has no tools configured.
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ on_segment_event: Optional[Callable[[SegmentEvent], None]] = None,
25
+ on_tool_invocation: Optional[Callable[[ToolInvocation], None]] = None,
26
+ segment_id_prefix: Optional[str] = None,
27
+ ):
28
+ """
29
+ Initialize the pass-through handler.
30
+
31
+ Args:
32
+ on_segment_event: Callback for UI streaming.
33
+ on_tool_invocation: Callback for tools (unused here, kept for compatibility).
34
+ segment_id_prefix: Prefix for the single text segment ID.
35
+ """
36
+ self._on_segment_event = on_segment_event
37
+ self._segment_id_prefix = segment_id_prefix or f"pt_{uuid.uuid4().hex}:"
38
+ self._segment_id = f"{self._segment_id_prefix}text_0"
39
+ self._is_active = False
40
+ self._is_finalized = False
41
+ self._all_events: List[SegmentEvent] = []
42
+
43
+ def feed(self, chunk: ChunkResponse) -> List[SegmentEvent]:
44
+ if self._is_finalized:
45
+ raise RuntimeError("Handler has been finalized, cannot feed more chunks.")
46
+
47
+ # Extract text content from ChunkResponse
48
+ text_content = chunk.content if isinstance(chunk, ChunkResponse) else chunk
49
+ if not text_content:
50
+ return []
51
+
52
+ events = []
53
+
54
+ # Start segment if not active
55
+ if not self._is_active:
56
+ self._is_active = True
57
+ start_event = SegmentEvent.start(
58
+ segment_id=self._segment_id,
59
+ segment_type=SegmentType.TEXT
60
+ )
61
+ events.append(start_event)
62
+
63
+ # Content event
64
+ content_event = SegmentEvent.content(
65
+ segment_id=self._segment_id,
66
+ delta=text_content
67
+ )
68
+ events.append(content_event)
69
+
70
+ self._process_events(events)
71
+ return events
72
+
73
+ def finalize(self) -> List[SegmentEvent]:
74
+ if self._is_finalized:
75
+ return []
76
+
77
+ self._is_finalized = True
78
+ events = []
79
+
80
+ if self._is_active:
81
+ end_event = SegmentEvent.end(segment_id=self._segment_id)
82
+ events.append(end_event)
83
+ self._is_active = False
84
+
85
+ self._process_events(events)
86
+ return events
87
+
88
+ def _process_events(self, events: List[SegmentEvent]) -> None:
89
+ for event in events:
90
+ self._all_events.append(event)
91
+ if self._on_segment_event:
92
+ try:
93
+ self._on_segment_event(event)
94
+ except Exception as e:
95
+ logger.error(f"Error in on_segment_event callback: {e}")
96
+
97
+ def get_all_events(self) -> List[SegmentEvent]:
98
+ return self._all_events.copy()
99
+
100
+ def get_all_invocations(self) -> List[ToolInvocation]:
101
+ return []
102
+
103
+ def reset(self) -> None:
104
+ self._segment_id = f"{self._segment_id_prefix}text_{uuid.uuid4().hex}"
105
+ self._is_active = False
106
+ self._is_finalized = False
107
+ self._all_events.clear()
@@ -0,0 +1,177 @@
1
+ # file: autobyteus/autobyteus/agent/streaming/handlers/streaming_handler_factory.py
2
+ """
3
+ Factory for selecting the appropriate StreamingResponseHandler implementation.
4
+
5
+ This factory encapsulates all configuration logic including:
6
+ - Format/mode resolution from environment
7
+ - ParserConfig construction for text parsing modes
8
+ - JSON profile selection for provider-aware parsing
9
+ - Tool schema building for API tool call mode
10
+ """
11
+ from __future__ import annotations
12
+
13
+ import logging
14
+ import uuid
15
+ from dataclasses import dataclass, field
16
+ from typing import Optional, Callable, List, Dict
17
+
18
+ from autobyteus.agent.tool_invocation import ToolInvocation
19
+ from autobyteus.llm.providers import LLMProvider
20
+ from autobyteus.utils.tool_call_format import resolve_tool_call_format
21
+
22
+ from .streaming_response_handler import StreamingResponseHandler
23
+ from .parsing_streaming_response_handler import ParsingStreamingResponseHandler
24
+ from .pass_through_streaming_response_handler import PassThroughStreamingResponseHandler
25
+ from .api_tool_call_streaming_response_handler import ApiToolCallStreamingResponseHandler
26
+ from ..parser.parser_context import ParserConfig
27
+ from ..parser.json_parsing_strategies.registry import get_json_tool_parsing_profile
28
+ from ..segments.segment_events import SegmentEvent
29
+
30
+ logger = logging.getLogger(__name__)
31
+
32
+
33
+ @dataclass
34
+ class StreamingHandlerResult:
35
+ """
36
+ Result of creating a streaming handler.
37
+
38
+ Attributes:
39
+ handler: The configured streaming response handler.
40
+ tool_schemas: Pre-built tool schemas for API mode (None for other modes).
41
+ """
42
+ handler: StreamingResponseHandler
43
+ tool_schemas: Optional[List[Dict]] = None
44
+
45
+
46
+ class StreamingResponseHandlerFactory:
47
+ """Factory for building streaming response handlers based on minimal inputs."""
48
+
49
+ @staticmethod
50
+ def create(
51
+ *,
52
+ tool_names: List[str],
53
+ provider: Optional[LLMProvider],
54
+ segment_id_prefix: Optional[str] = None,
55
+ on_segment_event: Optional[Callable[[SegmentEvent], None]] = None,
56
+ on_tool_invocation: Optional[Callable[[ToolInvocation], None]] = None,
57
+ agent_id: Optional[str] = None,
58
+ ) -> StreamingHandlerResult:
59
+ """
60
+ Create a streaming response handler with all necessary configuration.
61
+
62
+ Args:
63
+ tool_names: List of tool names the agent has access to.
64
+ provider: The LLM provider being used (for provider-specific parsing).
65
+ segment_id_prefix: Optional prefix for segment IDs.
66
+ on_segment_event: Callback for UI streaming events.
67
+ on_tool_invocation: Callback when a tool invocation is created.
68
+ agent_id: Agent identifier for logging.
69
+
70
+ Returns:
71
+ StreamingHandlerResult containing the handler and optional tool schemas.
72
+ """
73
+ # Resolve format from environment
74
+ format_override = resolve_tool_call_format()
75
+ parse_tool_calls = bool(tool_names)
76
+
77
+ # Generate segment ID prefix if not provided
78
+ if segment_id_prefix is None:
79
+ segment_id_prefix = f"turn_{uuid.uuid4().hex}:"
80
+
81
+ # No tools → PassThrough handler
82
+ if not parse_tool_calls:
83
+ logger.debug(
84
+ "Agent '%s': No tools enabled - using PassThroughStreamingResponseHandler",
85
+ agent_id or "unknown",
86
+ )
87
+ return StreamingHandlerResult(
88
+ handler=PassThroughStreamingResponseHandler(
89
+ on_segment_event=on_segment_event,
90
+ on_tool_invocation=on_tool_invocation,
91
+ segment_id_prefix=segment_id_prefix,
92
+ ),
93
+ tool_schemas=None,
94
+ )
95
+
96
+ # API tool call mode → ApiToolCall handler + build schemas
97
+ if format_override == "api_tool_call":
98
+ logger.debug(
99
+ "Agent '%s': Using ApiToolCallStreamingResponseHandler",
100
+ agent_id or "unknown",
101
+ )
102
+ # Build tool schemas for API mode
103
+ tool_schemas = StreamingResponseHandlerFactory._build_tool_schemas(
104
+ tool_names=tool_names,
105
+ provider=provider,
106
+ )
107
+ return StreamingHandlerResult(
108
+ handler=ApiToolCallStreamingResponseHandler(
109
+ on_segment_event=on_segment_event,
110
+ on_tool_invocation=on_tool_invocation,
111
+ segment_id_prefix=segment_id_prefix,
112
+ ),
113
+ tool_schemas=tool_schemas,
114
+ )
115
+
116
+ # Text parsing mode (XML/JSON/Sentinel) → Parsing handler
117
+ parser_name = StreamingResponseHandlerFactory._resolve_parser_name(
118
+ format_override=format_override,
119
+ provider=provider,
120
+ )
121
+
122
+ # Build ParserConfig with provider-aware JSON profile
123
+ json_profile = get_json_tool_parsing_profile(provider)
124
+ parser_config = ParserConfig(
125
+ parse_tool_calls=parse_tool_calls,
126
+ json_tool_patterns=json_profile.signature_patterns,
127
+ json_tool_parser=json_profile.parser,
128
+ segment_id_prefix=segment_id_prefix,
129
+ )
130
+
131
+ logger.debug(
132
+ "Agent '%s': Using ParsingStreamingResponseHandler with %s parser",
133
+ agent_id or "unknown",
134
+ parser_name,
135
+ )
136
+ return StreamingHandlerResult(
137
+ handler=ParsingStreamingResponseHandler(
138
+ on_segment_event=on_segment_event,
139
+ on_tool_invocation=on_tool_invocation,
140
+ config=parser_config,
141
+ parser_name=parser_name,
142
+ ),
143
+ tool_schemas=None,
144
+ )
145
+
146
+ @staticmethod
147
+ def _resolve_parser_name(
148
+ *,
149
+ format_override: Optional[str],
150
+ provider: Optional[LLMProvider],
151
+ ) -> str:
152
+ """Resolve which parser to use based on format and provider."""
153
+ if format_override in {"xml", "json", "sentinel"}:
154
+ return format_override
155
+ # Default: XML for Anthropic, JSON for others
156
+ return "xml" if provider == LLMProvider.ANTHROPIC else "json"
157
+
158
+ @staticmethod
159
+ def _build_tool_schemas(
160
+ tool_names: List[str],
161
+ provider: Optional[LLMProvider],
162
+ ) -> Optional[List[Dict]]:
163
+ """Build tool schemas for API tool call mode."""
164
+ if not tool_names:
165
+ return None
166
+
167
+ # Import here to avoid circular dependency
168
+ from autobyteus.tools.usage.tool_schema_provider import ToolSchemaProvider
169
+
170
+ schemas = ToolSchemaProvider().build_schema(tool_names, provider)
171
+ if schemas:
172
+ logger.debug(
173
+ "Built %d tool schemas for API tool calls (provider: %s)",
174
+ len(schemas),
175
+ provider,
176
+ )
177
+ return schemas if schemas else None