autobyteus 1.2.1__py3-none-any.whl → 1.3.0__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 (472) hide show
  1. autobyteus/agent/agent.py +15 -5
  2. autobyteus/agent/bootstrap_steps/__init__.py +3 -3
  3. autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +5 -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/working_context_snapshot_restore_step.py +38 -0
  8. autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +2 -4
  9. autobyteus/agent/context/agent_config.py +47 -20
  10. autobyteus/agent/context/agent_context.py +23 -18
  11. autobyteus/agent/context/agent_runtime_state.py +21 -19
  12. autobyteus/agent/events/__init__.py +16 -1
  13. autobyteus/agent/events/agent_events.py +43 -3
  14. autobyteus/agent/events/agent_input_event_queue_manager.py +79 -26
  15. autobyteus/agent/events/event_store.py +57 -0
  16. autobyteus/agent/events/notifiers.py +69 -59
  17. autobyteus/agent/events/worker_event_dispatcher.py +21 -64
  18. autobyteus/agent/factory/agent_factory.py +83 -6
  19. autobyteus/agent/handlers/__init__.py +2 -0
  20. autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +51 -34
  21. autobyteus/agent/handlers/bootstrap_event_handler.py +155 -0
  22. autobyteus/agent/handlers/inter_agent_message_event_handler.py +10 -0
  23. autobyteus/agent/handlers/lifecycle_event_logger.py +19 -11
  24. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +10 -15
  25. autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +188 -48
  26. autobyteus/agent/handlers/tool_execution_approval_event_handler.py +0 -10
  27. autobyteus/agent/handlers/tool_invocation_request_event_handler.py +53 -48
  28. autobyteus/agent/handlers/tool_result_event_handler.py +7 -8
  29. autobyteus/agent/handlers/user_input_message_event_handler.py +10 -3
  30. autobyteus/agent/input_processor/memory_ingest_input_processor.py +44 -0
  31. autobyteus/agent/lifecycle/__init__.py +12 -0
  32. autobyteus/agent/lifecycle/base_processor.py +109 -0
  33. autobyteus/agent/lifecycle/events.py +35 -0
  34. autobyteus/agent/lifecycle/processor_definition.py +36 -0
  35. autobyteus/agent/lifecycle/processor_registry.py +106 -0
  36. autobyteus/agent/llm_request_assembler.py +98 -0
  37. autobyteus/agent/llm_response_processor/__init__.py +1 -8
  38. autobyteus/agent/message/context_file_type.py +1 -1
  39. autobyteus/agent/runtime/agent_runtime.py +29 -21
  40. autobyteus/agent/runtime/agent_worker.py +98 -19
  41. autobyteus/agent/shutdown_steps/__init__.py +2 -0
  42. autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
  43. autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
  44. autobyteus/agent/status/__init__.py +14 -0
  45. autobyteus/agent/status/manager.py +93 -0
  46. autobyteus/agent/status/status_deriver.py +96 -0
  47. autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
  48. autobyteus/agent/status/status_update_utils.py +73 -0
  49. autobyteus/agent/streaming/__init__.py +52 -5
  50. autobyteus/agent/streaming/adapters/__init__.py +18 -0
  51. autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
  52. autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
  53. autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
  54. autobyteus/agent/streaming/agent_event_stream.py +3 -183
  55. autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
  56. autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
  57. autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
  58. autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
  59. autobyteus/agent/streaming/events/__init__.py +6 -0
  60. autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
  61. autobyteus/agent/streaming/events/stream_events.py +141 -0
  62. autobyteus/agent/streaming/handlers/__init__.py +15 -0
  63. autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
  64. autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
  65. autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
  66. autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
  67. autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
  68. autobyteus/agent/streaming/parser/__init__.py +61 -0
  69. autobyteus/agent/streaming/parser/event_emitter.py +181 -0
  70. autobyteus/agent/streaming/parser/events.py +4 -0
  71. autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
  72. autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
  73. autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
  74. autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
  75. autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
  76. autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
  77. autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
  78. autobyteus/agent/streaming/parser/parser_context.py +227 -0
  79. autobyteus/agent/streaming/parser/parser_factory.py +132 -0
  80. autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
  81. autobyteus/agent/streaming/parser/state_factory.py +62 -0
  82. autobyteus/agent/streaming/parser/states/__init__.py +1 -0
  83. autobyteus/agent/streaming/parser/states/base_state.py +60 -0
  84. autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
  85. autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
  86. autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
  87. autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
  88. autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
  89. autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
  90. autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
  91. autobyteus/agent/streaming/parser/states/text_state.py +78 -0
  92. autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
  93. autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
  94. autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
  95. autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
  96. autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
  97. autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
  98. autobyteus/agent/streaming/parser/strategies/base.py +24 -0
  99. autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
  100. autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
  101. autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
  102. autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
  103. autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
  104. autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
  105. autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
  106. autobyteus/agent/streaming/parser/tool_constants.py +7 -0
  107. autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
  108. autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
  109. autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
  110. autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
  111. autobyteus/agent/streaming/queue_streamer.py +3 -57
  112. autobyteus/agent/streaming/segments/__init__.py +5 -0
  113. autobyteus/agent/streaming/segments/segment_events.py +82 -0
  114. autobyteus/agent/streaming/stream_event_payloads.py +2 -223
  115. autobyteus/agent/streaming/stream_events.py +3 -140
  116. autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
  117. autobyteus/agent/streaming/streaming_response_handler.py +4 -0
  118. autobyteus/agent/streaming/streams/__init__.py +5 -0
  119. autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
  120. autobyteus/agent/streaming/utils/__init__.py +5 -0
  121. autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
  122. autobyteus/agent/system_prompt_processor/__init__.py +2 -0
  123. autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
  124. autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
  125. autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
  126. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
  127. autobyteus/agent/token_budget.py +56 -0
  128. autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
  129. autobyteus/agent/tool_invocation.py +16 -40
  130. autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
  131. autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
  132. autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
  133. autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
  134. autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
  135. autobyteus/agent/utils/wait_for_idle.py +12 -14
  136. autobyteus/agent/workspace/base_workspace.py +6 -27
  137. autobyteus/agent_team/agent_team.py +3 -3
  138. autobyteus/agent_team/agent_team_builder.py +1 -41
  139. autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
  140. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
  141. autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
  142. autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
  143. autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
  144. autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +1 -2
  145. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +4 -4
  146. autobyteus/agent_team/context/agent_team_config.py +6 -3
  147. autobyteus/agent_team/context/agent_team_context.py +25 -3
  148. autobyteus/agent_team/context/agent_team_runtime_state.py +9 -6
  149. autobyteus/agent_team/events/__init__.py +11 -0
  150. autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
  151. autobyteus/agent_team/events/agent_team_events.py +16 -0
  152. autobyteus/agent_team/events/event_store.py +57 -0
  153. autobyteus/agent_team/factory/agent_team_factory.py +8 -0
  154. autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
  155. autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
  156. autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
  157. autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
  158. autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
  159. autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
  160. autobyteus/agent_team/status/__init__.py +14 -0
  161. autobyteus/agent_team/status/agent_team_status.py +18 -0
  162. autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
  163. autobyteus/agent_team/status/status_deriver.py +62 -0
  164. autobyteus/agent_team/status/status_update_utils.py +42 -0
  165. autobyteus/agent_team/streaming/__init__.py +2 -2
  166. autobyteus/agent_team/streaming/agent_team_event_notifier.py +6 -6
  167. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +4 -4
  168. autobyteus/agent_team/streaming/agent_team_stream_events.py +3 -3
  169. autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
  170. autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
  171. autobyteus/agent_team/task_notification/task_notification_mode.py +19 -0
  172. autobyteus/agent_team/utils/wait_for_idle.py +4 -4
  173. autobyteus/cli/agent_cli.py +18 -10
  174. autobyteus/cli/agent_team_tui/app.py +14 -11
  175. autobyteus/cli/agent_team_tui/state.py +13 -15
  176. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
  177. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +143 -36
  178. autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
  179. autobyteus/cli/agent_team_tui/widgets/shared.py +25 -25
  180. autobyteus/cli/cli_display.py +193 -44
  181. autobyteus/cli/workflow_tui/app.py +9 -10
  182. autobyteus/cli/workflow_tui/state.py +14 -16
  183. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
  184. autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
  185. autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
  186. autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
  187. autobyteus/clients/autobyteus_client.py +94 -1
  188. autobyteus/events/event_types.py +11 -18
  189. autobyteus/llm/api/autobyteus_llm.py +33 -29
  190. autobyteus/llm/api/claude_llm.py +142 -36
  191. autobyteus/llm/api/gemini_llm.py +163 -59
  192. autobyteus/llm/api/grok_llm.py +1 -1
  193. autobyteus/llm/api/minimax_llm.py +26 -0
  194. autobyteus/llm/api/mistral_llm.py +113 -87
  195. autobyteus/llm/api/ollama_llm.py +9 -42
  196. autobyteus/llm/api/openai_compatible_llm.py +127 -91
  197. autobyteus/llm/api/openai_llm.py +3 -3
  198. autobyteus/llm/api/openai_responses_llm.py +324 -0
  199. autobyteus/llm/api/zhipu_llm.py +21 -2
  200. autobyteus/llm/autobyteus_provider.py +70 -60
  201. autobyteus/llm/base_llm.py +85 -81
  202. autobyteus/llm/converters/__init__.py +14 -0
  203. autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
  204. autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
  205. autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
  206. autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
  207. autobyteus/llm/extensions/base_extension.py +6 -12
  208. autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
  209. autobyteus/llm/llm_factory.py +282 -204
  210. autobyteus/llm/lmstudio_provider.py +60 -49
  211. autobyteus/llm/models.py +35 -2
  212. autobyteus/llm/ollama_provider.py +60 -49
  213. autobyteus/llm/ollama_provider_resolver.py +0 -1
  214. autobyteus/llm/prompt_renderers/__init__.py +19 -0
  215. autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
  216. autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
  217. autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
  218. autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
  219. autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
  220. autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
  221. autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
  222. autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
  223. autobyteus/llm/providers.py +1 -3
  224. autobyteus/llm/token_counter/claude_token_counter.py +56 -25
  225. autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
  226. autobyteus/llm/token_counter/openai_token_counter.py +24 -5
  227. autobyteus/llm/token_counter/token_counter_factory.py +12 -5
  228. autobyteus/llm/utils/llm_config.py +6 -12
  229. autobyteus/llm/utils/media_payload_formatter.py +27 -20
  230. autobyteus/llm/utils/messages.py +55 -3
  231. autobyteus/llm/utils/response_types.py +3 -0
  232. autobyteus/llm/utils/tool_call_delta.py +31 -0
  233. autobyteus/memory/__init__.py +35 -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 +205 -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/path_resolver.py +27 -0
  247. autobyteus/memory/policies/__init__.py +5 -0
  248. autobyteus/memory/policies/compaction_policy.py +16 -0
  249. autobyteus/memory/restore/__init__.py +1 -0
  250. autobyteus/memory/restore/working_context_snapshot_bootstrapper.py +61 -0
  251. autobyteus/memory/retrieval/__init__.py +7 -0
  252. autobyteus/memory/retrieval/memory_bundle.py +11 -0
  253. autobyteus/memory/retrieval/retriever.py +13 -0
  254. autobyteus/memory/store/__init__.py +9 -0
  255. autobyteus/memory/store/base_store.py +14 -0
  256. autobyteus/memory/store/file_store.py +98 -0
  257. autobyteus/memory/store/working_context_snapshot_store.py +28 -0
  258. autobyteus/memory/tool_interaction_builder.py +46 -0
  259. autobyteus/memory/turn_tracker.py +9 -0
  260. autobyteus/memory/working_context_snapshot.py +69 -0
  261. autobyteus/memory/working_context_snapshot_serializer.py +135 -0
  262. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
  263. autobyteus/multimedia/audio/api/gemini_audio_client.py +109 -16
  264. autobyteus/multimedia/audio/audio_client_factory.py +47 -9
  265. autobyteus/multimedia/audio/audio_model.py +2 -1
  266. autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
  267. autobyteus/multimedia/image/api/gemini_image_client.py +39 -17
  268. autobyteus/multimedia/image/api/openai_image_client.py +125 -43
  269. autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
  270. autobyteus/multimedia/image/image_client_factory.py +47 -15
  271. autobyteus/multimedia/image/image_model.py +5 -2
  272. autobyteus/multimedia/providers.py +3 -2
  273. autobyteus/skills/loader.py +71 -0
  274. autobyteus/skills/model.py +11 -0
  275. autobyteus/skills/registry.py +70 -0
  276. autobyteus/task_management/tools/todo_tools/add_todo.py +2 -2
  277. autobyteus/task_management/tools/todo_tools/create_todo_list.py +2 -2
  278. autobyteus/task_management/tools/todo_tools/update_todo_status.py +2 -2
  279. autobyteus/tools/__init__.py +34 -47
  280. autobyteus/tools/base_tool.py +7 -0
  281. autobyteus/tools/file/__init__.py +2 -6
  282. autobyteus/tools/file/patch_file.py +149 -0
  283. autobyteus/tools/file/read_file.py +36 -5
  284. autobyteus/tools/file/write_file.py +4 -1
  285. autobyteus/tools/functional_tool.py +43 -6
  286. autobyteus/tools/mcp/__init__.py +2 -0
  287. autobyteus/tools/mcp/config_service.py +5 -1
  288. autobyteus/tools/mcp/server/__init__.py +2 -0
  289. autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
  290. autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
  291. autobyteus/tools/mcp/server_instance_manager.py +8 -1
  292. autobyteus/tools/mcp/types.py +61 -0
  293. autobyteus/tools/multimedia/audio_tools.py +70 -17
  294. autobyteus/tools/multimedia/download_media_tool.py +18 -4
  295. autobyteus/tools/multimedia/image_tools.py +246 -62
  296. autobyteus/tools/operation_executor/journal_manager.py +107 -0
  297. autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
  298. autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
  299. autobyteus/tools/operation_executor/operation_executor.py +58 -0
  300. autobyteus/tools/registry/tool_definition.py +43 -2
  301. autobyteus/tools/skill/load_skill.py +50 -0
  302. autobyteus/tools/terminal/__init__.py +45 -0
  303. autobyteus/tools/terminal/ansi_utils.py +32 -0
  304. autobyteus/tools/terminal/background_process_manager.py +233 -0
  305. autobyteus/tools/terminal/output_buffer.py +105 -0
  306. autobyteus/tools/terminal/prompt_detector.py +63 -0
  307. autobyteus/tools/terminal/pty_session.py +241 -0
  308. autobyteus/tools/terminal/session_factory.py +20 -0
  309. autobyteus/tools/terminal/terminal_session_manager.py +226 -0
  310. autobyteus/tools/terminal/tools/__init__.py +13 -0
  311. autobyteus/tools/terminal/tools/get_process_output.py +81 -0
  312. autobyteus/tools/terminal/tools/run_bash.py +109 -0
  313. autobyteus/tools/terminal/tools/start_background_process.py +104 -0
  314. autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
  315. autobyteus/tools/terminal/types.py +54 -0
  316. autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
  317. autobyteus/tools/terminal/wsl_utils.py +156 -0
  318. autobyteus/tools/transaction_management/backup_handler.py +48 -0
  319. autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
  320. autobyteus/tools/usage/__init__.py +1 -2
  321. autobyteus/tools/usage/formatters/__init__.py +17 -1
  322. autobyteus/tools/usage/formatters/base_formatter.py +8 -0
  323. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
  324. autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
  325. autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
  326. autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
  327. autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
  328. autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
  329. autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
  330. autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
  331. autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
  332. autobyteus/tools/usage/registries/__init__.py +1 -3
  333. autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
  334. autobyteus/tools/usage/tool_schema_provider.py +51 -0
  335. autobyteus/tools/web/__init__.py +4 -0
  336. autobyteus/tools/web/read_url_tool.py +80 -0
  337. autobyteus/utils/diff_utils.py +271 -0
  338. autobyteus/utils/download_utils.py +109 -0
  339. autobyteus/utils/file_utils.py +57 -2
  340. autobyteus/utils/gemini_helper.py +64 -0
  341. autobyteus/utils/gemini_model_mapping.py +71 -0
  342. autobyteus/utils/llm_output_formatter.py +75 -0
  343. autobyteus/utils/tool_call_format.py +36 -0
  344. autobyteus/workflow/agentic_workflow.py +3 -3
  345. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
  346. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
  347. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
  348. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +3 -9
  349. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
  350. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
  351. autobyteus/workflow/context/workflow_context.py +3 -3
  352. autobyteus/workflow/context/workflow_runtime_state.py +5 -5
  353. autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
  354. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
  355. autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
  356. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
  357. autobyteus/workflow/runtime/workflow_runtime.py +8 -8
  358. autobyteus/workflow/runtime/workflow_worker.py +3 -3
  359. autobyteus/workflow/status/__init__.py +11 -0
  360. autobyteus/workflow/status/workflow_status.py +19 -0
  361. autobyteus/workflow/status/workflow_status_manager.py +48 -0
  362. autobyteus/workflow/streaming/__init__.py +2 -2
  363. autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
  364. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
  365. autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
  366. autobyteus/workflow/utils/wait_for_idle.py +4 -4
  367. autobyteus-1.3.0.dist-info/METADATA +293 -0
  368. autobyteus-1.3.0.dist-info/RECORD +606 -0
  369. {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/WHEEL +1 -1
  370. {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/top_level.txt +0 -1
  371. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
  372. autobyteus/agent/hooks/__init__.py +0 -16
  373. autobyteus/agent/hooks/base_phase_hook.py +0 -78
  374. autobyteus/agent/hooks/hook_definition.py +0 -36
  375. autobyteus/agent/hooks/hook_meta.py +0 -37
  376. autobyteus/agent/hooks/hook_registry.py +0 -106
  377. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
  378. autobyteus/agent/phases/__init__.py +0 -18
  379. autobyteus/agent/phases/discover.py +0 -53
  380. autobyteus/agent/phases/manager.py +0 -265
  381. autobyteus/agent/phases/transition_decorator.py +0 -40
  382. autobyteus/agent/phases/transition_info.py +0 -33
  383. autobyteus/agent/remote_agent.py +0 -244
  384. autobyteus/agent/workspace/workspace_definition.py +0 -36
  385. autobyteus/agent/workspace/workspace_meta.py +0 -37
  386. autobyteus/agent/workspace/workspace_registry.py +0 -72
  387. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
  388. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
  389. autobyteus/agent_team/phases/__init__.py +0 -11
  390. autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
  391. autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
  392. autobyteus/llm/api/bedrock_llm.py +0 -92
  393. autobyteus/llm/api/groq_llm.py +0 -94
  394. autobyteus/llm/api/nvidia_llm.py +0 -108
  395. autobyteus/llm/utils/token_pricing_config.py +0 -87
  396. autobyteus/rpc/__init__.py +0 -73
  397. autobyteus/rpc/client/__init__.py +0 -17
  398. autobyteus/rpc/client/abstract_client_connection.py +0 -124
  399. autobyteus/rpc/client/client_connection_manager.py +0 -153
  400. autobyteus/rpc/client/sse_client_connection.py +0 -306
  401. autobyteus/rpc/client/stdio_client_connection.py +0 -280
  402. autobyteus/rpc/config/__init__.py +0 -13
  403. autobyteus/rpc/config/agent_server_config.py +0 -153
  404. autobyteus/rpc/config/agent_server_registry.py +0 -152
  405. autobyteus/rpc/hosting.py +0 -244
  406. autobyteus/rpc/protocol.py +0 -244
  407. autobyteus/rpc/server/__init__.py +0 -20
  408. autobyteus/rpc/server/agent_server_endpoint.py +0 -181
  409. autobyteus/rpc/server/base_method_handler.py +0 -40
  410. autobyteus/rpc/server/method_handlers.py +0 -259
  411. autobyteus/rpc/server/sse_server_handler.py +0 -182
  412. autobyteus/rpc/server/stdio_server_handler.py +0 -151
  413. autobyteus/rpc/server_main.py +0 -198
  414. autobyteus/rpc/transport_type.py +0 -13
  415. autobyteus/tools/bash/__init__.py +0 -2
  416. autobyteus/tools/bash/bash_executor.py +0 -100
  417. autobyteus/tools/browser/__init__.py +0 -2
  418. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
  419. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
  420. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
  421. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
  422. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
  423. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
  424. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
  425. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
  426. autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
  427. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
  428. autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
  429. autobyteus/tools/browser/standalone/__init__.py +0 -6
  430. autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  431. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
  432. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
  433. autobyteus/tools/browser/standalone/navigate_to.py +0 -84
  434. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -101
  435. autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -169
  436. autobyteus/tools/browser/standalone/webpage_reader.py +0 -105
  437. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -105
  438. autobyteus/tools/file/edit_file.py +0 -200
  439. autobyteus/tools/file/list_directory.py +0 -168
  440. autobyteus/tools/file/search_files.py +0 -188
  441. autobyteus/tools/timer.py +0 -175
  442. autobyteus/tools/usage/parsers/__init__.py +0 -22
  443. autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
  444. autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
  445. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
  446. autobyteus/tools/usage/parsers/base_parser.py +0 -41
  447. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
  448. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
  449. autobyteus/tools/usage/parsers/exceptions.py +0 -13
  450. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
  451. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
  452. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
  453. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
  454. autobyteus/workflow/phases/__init__.py +0 -11
  455. autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
  456. autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
  457. autobyteus-1.2.1.dist-info/METADATA +0 -205
  458. autobyteus-1.2.1.dist-info/RECORD +0 -511
  459. examples/__init__.py +0 -1
  460. examples/agent_team/__init__.py +0 -1
  461. examples/discover_phase_transitions.py +0 -104
  462. examples/run_agentic_software_engineer.py +0 -239
  463. examples/run_browser_agent.py +0 -262
  464. examples/run_google_slides_agent.py +0 -287
  465. examples/run_mcp_browser_client.py +0 -174
  466. examples/run_mcp_google_slides_client.py +0 -270
  467. examples/run_mcp_list_tools.py +0 -189
  468. examples/run_poem_writer.py +0 -284
  469. examples/run_sqlite_agent.py +0 -295
  470. /autobyteus/{tools/browser/session_aware → skills}/__init__.py +0 -0
  471. /autobyteus/tools/{browser/session_aware/factory → skill}/__init__.py +0 -0
  472. {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -8,9 +8,11 @@ from autobyteus.agent.events import (
8
8
  AgentReadyEvent, # MODIFIED: Renamed from AgentStartedEvent
9
9
  AgentStoppedEvent,
10
10
  AgentErrorEvent,
11
+ AgentIdleEvent,
12
+ ShutdownRequestedEvent,
11
13
  LifecycleEvent
12
14
  )
13
- from autobyteus.agent.phases import AgentOperationalPhase # Import new phase enum
15
+ from autobyteus.agent.status.status_enum import AgentStatus # Import new status enum
14
16
 
15
17
  if TYPE_CHECKING:
16
18
  from autobyteus.agent.context import AgentContext
@@ -20,8 +22,8 @@ logger = logging.getLogger(__name__)
20
22
  class LifecycleEventLogger(AgentEventHandler):
21
23
  """
22
24
  Logs various lifecycle events for an agent.
23
- This handler does not modify agent state directly; phase changes are managed
24
- by AgentPhaseManager.
25
+ This handler does not modify agent state directly; status changes are projected
26
+ from events.
25
27
  """
26
28
 
27
29
  async def handle(self,
@@ -32,33 +34,39 @@ class LifecycleEventLogger(AgentEventHandler):
32
34
 
33
35
  Args:
34
36
  event: The lifecycle event object (AgentReadyEvent, AgentStoppedEvent, etc.).
35
- context: The composite AgentContext (used for agent_id and current phase).
37
+ context: The composite AgentContext (used for agent_id and current status).
36
38
  """
37
39
 
38
40
  agent_id = context.agent_id
39
- # MODIFIED: Use current_phase instead of status
40
- current_phase_val = context.current_phase.value if context.current_phase else "None (Phase not set)"
41
+ # MODIFIED: Use current_status instead of status
42
+ current_status_val = context.current_status.value if context.current_status else "None (Status not set)"
41
43
 
42
44
  if isinstance(event, AgentReadyEvent): # MODIFIED: Check for AgentReadyEvent
43
- logger.info(f"Agent '{agent_id}' Logged AgentReadyEvent. Current agent phase: {current_phase_val}") # MODIFIED log message
45
+ logger.info(f"Agent '{agent_id}' Logged AgentReadyEvent. Current agent status: {current_status_val}") # MODIFIED log message
44
46
 
45
47
  elif isinstance(event, AgentStoppedEvent):
46
- logger.info(f"Agent '{agent_id}' Logged AgentStoppedEvent. Current agent phase: {current_phase_val}")
48
+ logger.info(f"Agent '{agent_id}' Logged AgentStoppedEvent. Current agent status: {current_status_val}")
49
+
50
+ elif isinstance(event, AgentIdleEvent):
51
+ logger.info(f"Agent '{agent_id}' Logged AgentIdleEvent. Current agent status: {current_status_val}")
52
+
53
+ elif isinstance(event, ShutdownRequestedEvent):
54
+ logger.info(f"Agent '{agent_id}' Logged ShutdownRequestedEvent. Current agent status: {current_status_val}")
47
55
 
48
56
  elif isinstance(event, AgentErrorEvent):
49
57
  logger.error(
50
58
  f"Agent '{agent_id}' Logged AgentErrorEvent: {event.error_message}. "
51
- f"Details: {event.exception_details}. Current agent phase: {current_phase_val}"
59
+ f"Details: {event.exception_details}. Current agent status: {current_status_val}"
52
60
  )
53
61
 
54
62
  else: # pragma: no cover
55
63
  if isinstance(event, LifecycleEvent):
56
64
  logger.warning(
57
65
  f"LifecycleEventLogger for agent '{agent_id}' received an unhandled "
58
- f"specific LifecycleEvent type: {type(event)}. Event: {event}. Current phase: {current_phase_val}"
66
+ f"specific LifecycleEvent type: {type(event)}. Event: {event}. Current status: {current_status_val}"
59
67
  )
60
68
  else:
61
69
  logger.warning(
62
70
  f"LifecycleEventLogger for agent '{agent_id}' received an "
63
- f"unexpected event type: {type(event)}. Event: {event}. Current phase: {current_phase_val}"
71
+ f"unexpected event type: {type(event)}. Event: {event}. Current status: {current_status_val}"
64
72
  )
@@ -6,7 +6,6 @@ from autobyteus.agent.handlers.base_event_handler import AgentEventHandler
6
6
  from autobyteus.agent.events import LLMCompleteResponseReceivedEvent
7
7
  from autobyteus.llm.utils.response_types import CompleteResponse
8
8
  from autobyteus.agent.llm_response_processor import BaseLLMResponseProcessor
9
- from autobyteus.tools.usage.parsers.exceptions import ToolUsageParseException
10
9
 
11
10
 
12
11
  if TYPE_CHECKING:
@@ -49,8 +48,8 @@ class LLMCompleteResponseReceivedEventHandler(AgentEventHandler):
49
48
  any_processor_took_action = False
50
49
 
51
50
  notifier: Optional['AgentExternalEventNotifier'] = None
52
- if context.phase_manager:
53
- notifier = context.phase_manager.notifier
51
+ if context.status_manager:
52
+ notifier = context.status_manager.notifier
54
53
 
55
54
  if not notifier: # pragma: no cover
56
55
  logger.error(f"Agent '{agent_id}': Notifier not available in LLMCompleteResponseReceivedEventHandler. Cannot emit complete response event.")
@@ -63,8 +62,15 @@ class LLMCompleteResponseReceivedEventHandler(AgentEventHandler):
63
62
  f"Proceeding to treat LLM response as output for this leg."
64
63
  )
65
64
  else:
65
+ valid_processors = []
66
+ for p in processor_instances_to_try:
67
+ if isinstance(p, BaseLLMResponseProcessor):
68
+ valid_processors.append(p)
69
+ else:
70
+ logger.error(f"Agent '{agent_id}': Invalid LLM response processor type in config: {type(p)}. Skipping.")
71
+
66
72
  # Sort processors by their order attribute
67
- sorted_processors = sorted(processor_instances_to_try, key=lambda p: p.get_order())
73
+ sorted_processors = sorted(valid_processors, key=lambda p: p.get_order())
68
74
  processor_names = [p.get_name() for p in sorted_processors]
69
75
  logger.debug(f"Agent '{agent_id}': Attempting LLM response processing in order: {processor_names}")
70
76
 
@@ -94,17 +100,6 @@ class LLMCompleteResponseReceivedEventHandler(AgentEventHandler):
94
100
  else:
95
101
  logger.debug(f"Agent '{agent_id}': LLMResponseProcessor '{processor_name_for_log}' did not handle the response.")
96
102
 
97
- except ToolUsageParseException as e_parse:
98
- # This is the key change: Catch the specific parsing exception
99
- logger.warning(f"Agent '{agent_id}': LLMResponseProcessor '{processor_name_for_log}' failed to parse tool usage: {e_parse}")
100
- if notifier:
101
- notifier.notify_agent_error_output_generation(
102
- error_source=f"LLMResponseProcessor.{processor_name_for_log}",
103
- error_message="The model's response contained a malformed tool call that could not be understood.",
104
- error_details=str(e_parse)
105
- )
106
- # A parsing failure should not prevent other processors from running.
107
-
108
103
  except Exception as e: # pragma: no cover
109
104
  logger.error(f"Agent '{agent_id}': Error while using LLMResponseProcessor '{processor_name_for_log}': {e}. This processor is skipped.", exc_info=True)
110
105
  if notifier:
@@ -1,13 +1,21 @@
1
1
  # file: autobyteus/autobyteus/agent/handlers/llm_user_message_ready_event_handler.py
2
2
  import logging
3
3
  import traceback
4
- from typing import TYPE_CHECKING, cast, Optional, List
4
+ import uuid
5
+ from typing import TYPE_CHECKING, Optional, List
5
6
 
6
7
  from autobyteus.agent.handlers.base_event_handler import AgentEventHandler
7
- from autobyteus.agent.events import LLMUserMessageReadyEvent, LLMCompleteResponseReceivedEvent
8
+ from autobyteus.agent.events import LLMUserMessageReadyEvent, LLMCompleteResponseReceivedEvent, PendingToolInvocationEvent
8
9
  from autobyteus.llm.user_message import LLMUserMessage
9
10
  from autobyteus.llm.utils.response_types import ChunkResponse, CompleteResponse
10
11
  from autobyteus.llm.utils.token_usage import TokenUsage
12
+ from autobyteus.agent.streaming.streaming_response_handler import StreamingResponseHandler
13
+ from autobyteus.agent.streaming.streaming_handler_factory import StreamingResponseHandlerFactory
14
+ from autobyteus.agent.streaming.parser.events import SegmentEvent, SegmentType
15
+ from autobyteus.agent.tool_invocation import ToolInvocationTurn
16
+ from autobyteus.agent.llm_request_assembler import LLMRequestAssembler
17
+ from autobyteus.agent.token_budget import apply_compaction_policy, resolve_token_budget
18
+ from autobyteus.llm.prompt_renderers.openai_chat_renderer import OpenAIChatRenderer
11
19
 
12
20
  if TYPE_CHECKING:
13
21
  from autobyteus.agent.context import AgentContext
@@ -18,9 +26,8 @@ logger = logging.getLogger(__name__)
18
26
  class LLMUserMessageReadyEventHandler(AgentEventHandler):
19
27
  """
20
28
  Handles LLMUserMessageReadyEvents by sending the prepared LLMUserMessage
21
- to the LLM, emitting AGENT_DATA_ASSISTANT_CHUNK events via the notifier
22
- for each chunk, emitting AGENT_DATA_ASSISTANT_CHUNK_STREAM_END upon completion,
23
- and then enqueuing an LLMCompleteResponseReceivedEvent with the full aggregated response.
29
+ to the LLM, passing the stream through StreamingResponseHandler for safe parsing,
30
+ emitting filtered chunks via the notifier, and finally enqueuing the complete response.
24
31
  """
25
32
 
26
33
  def __init__(self):
@@ -37,8 +44,8 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
37
44
  if context.state.llm_instance is None:
38
45
  error_msg = f"Agent '{agent_id}' received LLMUserMessageReadyEvent but LLM instance is not yet initialized."
39
46
  logger.critical(error_msg)
40
- if context.phase_manager and context.phase_manager.notifier:
41
- context.phase_manager.notifier.notify_agent_error_output_generation( # USE RENAMED METHOD
47
+ if context.status_manager and context.status_manager.notifier:
48
+ context.status_manager.notifier.notify_agent_error_output_generation(
42
49
  error_source="LLMUserMessageReadyEventHandler.pre_llm_check",
43
50
  error_message=error_msg
44
51
  )
@@ -48,8 +55,13 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
48
55
  logger.info(f"Agent '{agent_id}' handling LLMUserMessageReadyEvent: '{llm_user_message.content}'")
49
56
  logger.debug(f"Agent '{agent_id}' preparing to send full message to LLM:\n---\n{llm_user_message.content}\n---")
50
57
 
51
- context.state.add_message_to_history({"role": "user", "content": llm_user_message.content})
58
+ memory_manager = getattr(context.state, "memory_manager", None)
59
+ active_turn_id = getattr(context.state, "active_turn_id", None)
60
+ if memory_manager and not active_turn_id:
61
+ active_turn_id = memory_manager.start_turn()
62
+ context.state.active_turn_id = active_turn_id
52
63
 
64
+ # Initialize aggregators
53
65
  complete_response_text = ""
54
66
  complete_reasoning_text = ""
55
67
  token_usage: Optional[TokenUsage] = None
@@ -57,66 +69,192 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
57
69
  complete_audio_urls: List[str] = []
58
70
  complete_video_urls: List[str] = []
59
71
 
72
+ # Get notifier for emitting events
60
73
  notifier: Optional['AgentExternalEventNotifier'] = None
61
- if context.phase_manager:
62
- notifier = context.phase_manager.notifier
74
+ if context.status_manager:
75
+ notifier = context.status_manager.notifier
63
76
 
64
77
  if not notifier: # pragma: no cover
65
78
  logger.error(f"Agent '{agent_id}': Notifier not available in LLMUserMessageReadyEventHandler. Cannot emit chunk events.")
66
79
 
80
+ # Callback for segment events from streaming parser
81
+ def emit_segment_event(event: SegmentEvent):
82
+ if notifier:
83
+ try:
84
+ notifier.notify_agent_segment_event(event.to_dict())
85
+ except Exception as e:
86
+ logger.error(f"Agent '{agent_id}': Error notifying segment event: {e}", exc_info=True)
87
+
88
+ # Collect tool names from agent state/config
89
+ tool_names: List[str] = []
90
+ if context.state.tool_instances:
91
+ tool_names = list(context.state.tool_instances.keys())
92
+ elif context.config.tools:
93
+ for tool in context.config.tools:
94
+ if isinstance(tool, str):
95
+ tool_names.append(tool)
96
+ elif hasattr(tool, "get_name"):
97
+ try:
98
+ tool_names.append(tool.get_name())
99
+ except Exception: # pragma: no cover - defensive
100
+ logger.warning(
101
+ "Agent '%s': Failed to resolve tool name from %s.",
102
+ agent_id,
103
+ type(tool),
104
+ )
105
+ else: # pragma: no cover - defensive
106
+ logger.warning(
107
+ "Agent '%s': Unsupported tool entry in config: %s.",
108
+ agent_id,
109
+ type(tool),
110
+ )
111
+
112
+ # Get provider from LLM instance
113
+ provider = context.state.llm_instance.model.provider if context.state.llm_instance else None
114
+
115
+ # Create streaming handler via factory (all configuration encapsulated)
116
+ handler_result = StreamingResponseHandlerFactory.create(
117
+ tool_names=tool_names,
118
+ provider=provider,
119
+ on_segment_event=emit_segment_event,
120
+ agent_id=agent_id,
121
+ )
122
+ streaming_handler = handler_result.handler
123
+
124
+ logger.info(
125
+ "Agent '%s': Streaming handler selected: %s",
126
+ agent_id,
127
+ streaming_handler.__class__.__name__,
128
+ )
129
+
130
+ # Prepare arguments for stream_user_message
131
+ stream_kwargs = {}
132
+ if handler_result.tool_schemas:
133
+ stream_kwargs["tools"] = handler_result.tool_schemas
134
+ logger.info(
135
+ "Agent '%s': Passing %d tool schemas to LLM API (Provider: %s)",
136
+ agent_id,
137
+ len(handler_result.tool_schemas),
138
+ provider,
139
+ )
140
+
141
+ if not memory_manager:
142
+ raise RuntimeError(f"Agent '{agent_id}' requires a memory manager to assemble LLM requests.")
143
+
144
+ llm_config = getattr(context.state.llm_instance, "config", None)
145
+ llm_model = getattr(context.state.llm_instance, "model", None)
146
+
147
+ renderer = getattr(context.state.llm_instance, "_renderer", None) or OpenAIChatRenderer()
148
+ assembler = LLMRequestAssembler(
149
+ memory_manager=memory_manager,
150
+ renderer=renderer,
151
+ )
152
+ system_prompt = (
153
+ context.state.processed_system_prompt
154
+ or context.state.llm_instance.config.system_message
155
+ )
156
+ request = await assembler.prepare_request(
157
+ processed_user_input=llm_user_message,
158
+ current_turn_id=active_turn_id,
159
+ system_prompt=system_prompt,
160
+ )
161
+
162
+ # State for manual reasoning parts (since they might come from outside the parser)
163
+ segment_id_prefix = f"turn_{uuid.uuid4().hex}:"
164
+ current_reasoning_part_id = None
165
+
67
166
  try:
68
- async for chunk_response in context.state.llm_instance.stream_user_message(llm_user_message):
167
+ async for chunk_response in context.state.llm_instance.stream_messages(
168
+ request.messages,
169
+ rendered_payload=request.rendered_payload,
170
+ **stream_kwargs,
171
+ ):
69
172
  if not isinstance(chunk_response, ChunkResponse):
70
173
  logger.warning(f"Agent '{agent_id}' received unexpected chunk type: {type(chunk_response)} during LLM stream. Expected ChunkResponse.")
71
174
  continue
72
175
 
176
+ # Aggregate full raw content
73
177
  if chunk_response.content:
74
178
  complete_response_text += chunk_response.content
75
179
  if chunk_response.reasoning:
76
180
  complete_reasoning_text += chunk_response.reasoning
77
181
 
182
+ # Collect usage and media from final chunks
78
183
  if chunk_response.is_complete:
79
184
  if chunk_response.usage:
80
185
  token_usage = chunk_response.usage
81
186
  logger.debug(f"Agent '{agent_id}' received final chunk with token usage: {token_usage}")
82
187
  if chunk_response.image_urls:
83
188
  complete_image_urls.extend(chunk_response.image_urls)
84
- logger.debug(f"Agent '{agent_id}' received final chunk with {len(chunk_response.image_urls)} image URLs.")
85
189
  if chunk_response.audio_urls:
86
190
  complete_audio_urls.extend(chunk_response.audio_urls)
87
- logger.debug(f"Agent '{agent_id}' received final chunk with {len(chunk_response.audio_urls)} audio URLs.")
88
191
  if chunk_response.video_urls:
89
192
  complete_video_urls.extend(chunk_response.video_urls)
90
- logger.debug(f"Agent '{agent_id}' received final chunk with {len(chunk_response.video_urls)} video URLs.")
91
193
 
92
- if notifier:
93
- try:
94
- # The chunk object now contains both content and reasoning
95
- notifier.notify_agent_data_assistant_chunk(chunk_response)
96
- except Exception as e_notify:
97
- logger.error(f"Agent '{agent_id}': Error notifying assistant chunk generated: {e_notify}", exc_info=True)
98
-
99
- if notifier:
100
- try:
101
- notifier.notify_agent_data_assistant_chunk_stream_end()
102
- except Exception as e_notify_end:
103
- logger.error(f"Agent '{agent_id}': Error notifying assistant chunk stream end: {e_notify_end}", exc_info=True)
194
+ # Handle Reasoning (Manual Segment Management)
195
+ if chunk_response.reasoning:
196
+ if current_reasoning_part_id is None:
197
+ current_reasoning_part_id = f"{segment_id_prefix}reasoning_{uuid.uuid4().hex}"
198
+ # Emit SEGMENT_START for reasoning
199
+ start_event = SegmentEvent.start(
200
+ segment_id=current_reasoning_part_id,
201
+ segment_type=SegmentType.REASONING
202
+ )
203
+ emit_segment_event(start_event)
204
+
205
+ # Emit SEGMENT_CONTENT for reasoning delta
206
+ content_event = SegmentEvent.content(
207
+ segment_id=current_reasoning_part_id,
208
+ delta=chunk_response.reasoning
209
+ )
210
+ emit_segment_event(content_event)
104
211
 
105
- logger.debug(f"Agent '{agent_id}' LLM stream completed. Full response length: {len(complete_response_text)}. Reasoning length: {len(complete_reasoning_text)}. Chunk stream ended event emitted.")
106
- if complete_reasoning_text:
107
- logger.debug(f"Agent '{agent_id}' aggregated full LLM reasoning:\n---\n{complete_reasoning_text}\n---")
108
- logger.debug(f"Agent '{agent_id}' aggregated full LLM response:\n---\n{complete_response_text}\n---")
212
+ # Handle Content & Tool Calls (Through Handler)
213
+ # Pass the full ChunkResponse object to support both text and tool call streams
214
+ streaming_handler.feed(chunk_response)
215
+
216
+ # End of stream loop
109
217
 
218
+ # Finalize the stream parser to get any held-back content
219
+ streaming_handler.finalize()
220
+
221
+ # After finalization, enqueue any parsed tool invocations.
222
+ if tool_names:
223
+ tool_invocations = streaming_handler.get_all_invocations()
224
+ if tool_invocations:
225
+ context.state.active_multi_tool_call_turn = ToolInvocationTurn(
226
+ invocations=tool_invocations
227
+ )
228
+ logger.info(
229
+ "Agent '%s': Parsed %d tool invocations from streaming parser.",
230
+ agent_id,
231
+ len(tool_invocations),
232
+ )
233
+ for invocation in tool_invocations:
234
+ if active_turn_id and not invocation.turn_id:
235
+ invocation.turn_id = active_turn_id
236
+ if memory_manager:
237
+ memory_manager.ingest_tool_intent(invocation, turn_id=active_turn_id)
238
+ await context.input_event_queues.enqueue_tool_invocation_request(
239
+ PendingToolInvocationEvent(tool_invocation=invocation)
240
+ )
241
+
242
+ # Close any open reasoning segment
243
+ if current_reasoning_part_id:
244
+ end_event = SegmentEvent.end(segment_id=current_reasoning_part_id)
245
+ emit_segment_event(end_event)
246
+
247
+ logger.debug(f"Agent '{agent_id}' LLM stream completed. Full response length: {len(complete_response_text)}.")
248
+ if complete_reasoning_text:
249
+ logger.debug(f"Agent '{agent_id}' aggregated full LLM reasoning.")
250
+
110
251
  except Exception as e:
111
252
  logger.error(f"Agent '{agent_id}' error during LLM stream: {e}", exc_info=True)
112
253
  error_message_for_output = f"Error processing your request with the LLM: {str(e)}"
113
254
 
114
255
  logger.warning(f"Agent '{agent_id}' LLM stream error. Error message for output: {error_message_for_output}")
115
- context.state.add_message_to_history({"role": "assistant", "content": error_message_for_output, "is_error": True})
116
-
117
256
  if notifier:
118
257
  try:
119
- notifier.notify_agent_data_assistant_chunk_stream_end()
120
258
  notifier.notify_agent_error_output_generation(
121
259
  error_source="LLMUserMessageReadyEventHandler.stream_user_message",
122
260
  error_message=error_message_for_output,
@@ -131,22 +269,10 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
131
269
  is_error=True
132
270
  )
133
271
  await context.input_event_queues.enqueue_internal_system_event(llm_complete_event_on_error)
134
- logger.info(f"Agent '{agent_id}' enqueued LLMCompleteResponseReceivedEvent with error details from LLMUserMessageReadyEventHandler.")
272
+ logger.info(f"Agent '{agent_id}' enqueued LLMCompleteResponseReceivedEvent with error details.")
135
273
  return
136
274
 
137
- # Add message to history with reasoning and multimodal data
138
- history_entry = {"role": "assistant", "content": complete_response_text}
139
- if complete_reasoning_text:
140
- history_entry["reasoning"] = complete_reasoning_text
141
- if complete_image_urls:
142
- history_entry["image_urls"] = complete_image_urls
143
- if complete_audio_urls:
144
- history_entry["audio_urls"] = complete_audio_urls
145
- if complete_video_urls:
146
- history_entry["video_urls"] = complete_video_urls
147
- context.state.add_message_to_history(history_entry)
148
-
149
- # Create complete response with reasoning and multimodal data
275
+ # Create complete response
150
276
  complete_response_obj = CompleteResponse(
151
277
  content=complete_response_text,
152
278
  reasoning=complete_reasoning_text,
@@ -155,9 +281,23 @@ class LLMUserMessageReadyEventHandler(AgentEventHandler):
155
281
  audio_urls=complete_audio_urls,
156
282
  video_urls=complete_video_urls
157
283
  )
284
+ if memory_manager and active_turn_id:
285
+ memory_manager.ingest_assistant_response(
286
+ complete_response_obj,
287
+ turn_id=active_turn_id,
288
+ source_event="LLMCompleteResponseReceivedEvent",
289
+ )
290
+ if token_usage and llm_config and llm_model:
291
+ budget = resolve_token_budget(llm_model, llm_config, memory_manager.compaction_policy)
292
+ if budget:
293
+ apply_compaction_policy(memory_manager.compaction_policy, budget)
294
+ if memory_manager.compactor and memory_manager.compaction_policy.should_compact(
295
+ token_usage.prompt_tokens,
296
+ budget.input_budget,
297
+ ):
298
+ memory_manager.request_compaction()
158
299
  llm_complete_event = LLMCompleteResponseReceivedEvent(
159
300
  complete_response=complete_response_obj
160
301
  )
161
302
  await context.input_event_queues.enqueue_internal_system_event(llm_complete_event)
162
303
  logger.info(f"Agent '{agent_id}' enqueued LLMCompleteResponseReceivedEvent from LLMUserMessageReadyEventHandler.")
163
-
@@ -62,16 +62,6 @@ class ToolExecutionApprovalEventHandler(AgentEventHandler):
62
62
  )
63
63
 
64
64
  denial_reason_str = event.reason or "No specific reason provided."
65
- denial_content_for_history = f"Tool execution denied by user/system. Reason: {denial_reason_str}"
66
-
67
- context.state.add_message_to_history({
68
- "role": "tool",
69
- "tool_call_id": event.tool_invocation_id,
70
- "name": retrieved_invocation.name,
71
- "content": denial_content_for_history,
72
- })
73
- logger.debug(f"Agent '{context.agent_id}': Added 'tool' role denial message to history for '{retrieved_invocation.name}' (ID: {event.tool_invocation_id}).")
74
-
75
65
  prompt_content_for_llm = (
76
66
  f"The request to use the tool '{retrieved_invocation.name}' "
77
67
  f"(with arguments: {json.dumps(retrieved_invocation.arguments or {})}) was denied. "
@@ -1,12 +1,12 @@
1
1
  # file: autobyteus/autobyteus/agent/handlers/tool_invocation_request_event_handler.py
2
2
  import logging
3
- import json
4
3
  import traceback
5
4
  from typing import TYPE_CHECKING, Optional
6
5
 
7
6
  from autobyteus.agent.handlers.base_event_handler import AgentEventHandler
8
7
  from autobyteus.agent.events import PendingToolInvocationEvent, ToolResultEvent
9
8
  from autobyteus.agent.tool_invocation import ToolInvocation
9
+ from autobyteus.utils.llm_output_formatter import format_to_clean_string
10
10
 
11
11
  if TYPE_CHECKING:
12
12
  from autobyteus.agent.context import AgentContext
@@ -46,10 +46,35 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
46
46
  except Exception as e_notify:
47
47
  logger.error(f"Agent '{agent_id}': Error notifying tool auto-execution: {e_notify}", exc_info=True)
48
48
 
49
+ # Run tool invocation preprocessors (if any) before execution
50
+ processors = context.config.tool_invocation_preprocessors
51
+ if processors:
52
+ # Filter valid processors first to avoid sorting crashes (checking for get_order attribute)
53
+ valid_processors = [p for p in processors if hasattr(p, 'get_order')]
54
+ sorted_processors = sorted(valid_processors, key=lambda p: p.get_order())
55
+ for processor in sorted_processors:
56
+ try:
57
+ tool_invocation = await processor.process(tool_invocation, context)
58
+ tool_name = tool_invocation.name
59
+ arguments = tool_invocation.arguments
60
+ invocation_id = tool_invocation.id
61
+ except Exception as e:
62
+ error_message = f"Error in tool invocation preprocessor '{processor.get_name()}' for tool '{tool_name}': {e}"
63
+ logger.error(f"Agent '{agent_id}': {error_message}", exc_info=True)
64
+ result_event = ToolResultEvent(
65
+ tool_name=tool_name,
66
+ result=None,
67
+ error=error_message,
68
+ tool_invocation_id=invocation_id,
69
+ turn_id=tool_invocation.turn_id,
70
+ )
71
+ await context.input_event_queues.enqueue_tool_result(result_event)
72
+ return
73
+
49
74
  logger.info(f"Agent '{agent_id}' executing tool directly: '{tool_name}' (ID: {invocation_id}) with args: {arguments}")
50
75
 
51
76
  try:
52
- args_str = json.dumps(arguments)
77
+ args_str = format_to_clean_string(arguments)
53
78
  except TypeError:
54
79
  args_str = str(arguments)
55
80
 
@@ -71,13 +96,13 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
71
96
  if not tool_instance:
72
97
  error_message = f"Tool '{tool_name}' not found or configured for agent '{agent_id}'."
73
98
  logger.error(error_message)
74
- result_event = ToolResultEvent(tool_name=tool_name, result=None, error=error_message, tool_invocation_id=invocation_id)
75
- context.add_message_to_history({
76
- "role": "tool",
77
- "tool_call_id": invocation_id,
78
- "name": tool_name,
79
- "content": f"Error: Tool '{tool_name}' execution failed. Reason: {error_message}",
80
- })
99
+ result_event = ToolResultEvent(
100
+ tool_name=tool_name,
101
+ result=None,
102
+ error=error_message,
103
+ tool_invocation_id=invocation_id,
104
+ turn_id=tool_invocation.turn_id,
105
+ )
81
106
  log_msg_error = f"[TOOL_ERROR_DIRECT] {error_message}"
82
107
  if notifier:
83
108
  try:
@@ -97,20 +122,19 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
97
122
  execution_result = await tool_instance.execute(context=context, **arguments)
98
123
 
99
124
  try:
100
- result_json_for_log = json.dumps(execution_result)
125
+ result_json_for_log = format_to_clean_string(execution_result)
101
126
  except (TypeError, ValueError):
102
- result_json_for_log = json.dumps(str(execution_result))
127
+ result_json_for_log = format_to_clean_string(str(execution_result))
103
128
 
104
129
  logger.info(f"Tool '{tool_name}' (ID: {invocation_id}) executed by agent '{agent_id}'.")
105
- result_event = ToolResultEvent(tool_name=tool_name, result=execution_result, error=None, tool_invocation_id=invocation_id)
106
-
107
- history_content = str(execution_result)
108
- context.add_message_to_history({
109
- "role": "tool",
110
- "tool_call_id": invocation_id,
111
- "name": tool_name,
112
- "content": history_content,
113
- })
130
+ result_event = ToolResultEvent(
131
+ tool_name=tool_name,
132
+ result=execution_result,
133
+ error=None,
134
+ tool_invocation_id=invocation_id,
135
+ tool_args=arguments,
136
+ turn_id=tool_invocation.turn_id,
137
+ )
114
138
  log_msg_result = f"[TOOL_RESULT_DIRECT] {result_json_for_log}"
115
139
  if notifier:
116
140
  try:
@@ -124,13 +148,13 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
124
148
  error_message = f"Error executing tool '{tool_name}' (ID: {invocation_id}): {str(e)}"
125
149
  error_details = traceback.format_exc()
126
150
  logger.error(f"Agent '{agent_id}' {error_message}", exc_info=True)
127
- result_event = ToolResultEvent(tool_name=tool_name, result=None, error=error_message, tool_invocation_id=invocation_id)
128
- context.add_message_to_history({
129
- "role": "tool",
130
- "tool_call_id": invocation_id,
131
- "name": tool_name,
132
- "content": f"Error: Tool '{tool_name}' execution failed. Reason: {error_message}",
133
- })
151
+ result_event = ToolResultEvent(
152
+ tool_name=tool_name,
153
+ result=None,
154
+ error=error_message,
155
+ tool_invocation_id=invocation_id,
156
+ turn_id=tool_invocation.turn_id,
157
+ )
134
158
  log_msg_exception = f"[TOOL_EXCEPTION_DIRECT] {error_message}\nDetails:\n{error_details}"
135
159
  if notifier:
136
160
  try:
@@ -161,8 +185,8 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
161
185
  agent_id = context.agent_id
162
186
 
163
187
  notifier: Optional['AgentExternalEventNotifier'] = None
164
- if context.phase_manager:
165
- notifier = context.phase_manager.notifier
188
+ if context.status_manager:
189
+ notifier = context.status_manager.notifier
166
190
 
167
191
  if not notifier:
168
192
  logger.error(f"Agent '{agent_id}': Notifier not available in ToolInvocationRequestEventHandler. Output events for tool approval/logging will be lost.")
@@ -175,25 +199,6 @@ class ToolInvocationRequestEventHandler(AgentEventHandler):
175
199
 
176
200
  context.store_pending_tool_invocation(tool_invocation)
177
201
 
178
- try:
179
- arguments_json_str = json.dumps(tool_invocation.arguments or {})
180
- except TypeError:
181
- logger.warning(f"Could not serialize args for history tool_call for '{tool_invocation.name}'. Using empty dict string.")
182
- arguments_json_str = "{}"
183
-
184
- context.add_message_to_history({
185
- "role": "assistant",
186
- "content": None,
187
- "tool_calls": [{
188
- "id": tool_invocation.id,
189
- "type": "function",
190
- "function": {
191
- "name": tool_invocation.name,
192
- "arguments": arguments_json_str
193
- }
194
- }]
195
- })
196
-
197
202
  approval_data = {
198
203
  "invocation_id": tool_invocation.id,
199
204
  "tool_name": tool_invocation.name,