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
@@ -1,20 +1,22 @@
1
1
  import asyncio
2
2
  import logging
3
3
  import sys
4
- from typing import Optional, List, Dict, Any
4
+ from typing import Optional
5
5
  import json
6
6
 
7
- from autobyteus.agent.phases.phase_enum import AgentOperationalPhase
7
+ from autobyteus.agent.status.status_enum import AgentStatus
8
8
  from autobyteus.agent.streaming.stream_events import StreamEvent, StreamEventType
9
9
  from autobyteus.agent.streaming.stream_event_payloads import (
10
10
  AssistantChunkData,
11
11
  AssistantCompleteResponseData,
12
12
  ToolInvocationApprovalRequestedData,
13
13
  ToolInteractionLogEntryData,
14
- AgentOperationalPhaseTransitionData,
14
+ AgentStatusUpdateData,
15
15
  ErrorEventData,
16
16
  ToolInvocationAutoExecutingData,
17
+ SegmentEventData,
17
18
  )
19
+ from autobyteus.agent.streaming.parser.events import SegmentEventType, SegmentType
18
20
 
19
21
  logger = logging.getLogger(__name__)
20
22
 
@@ -30,14 +32,21 @@ class InteractiveCLIDisplay:
30
32
  self.current_line_empty = True
31
33
  self.agent_has_spoken_this_turn = False
32
34
  self.pending_approval_data: Optional[ToolInvocationApprovalRequestedData] = None
35
+ self.approval_prompt_shown: bool = False
36
+ self.current_status: Optional[AgentStatus] = None
37
+ self.awaiting_approval: bool = False
33
38
  self.is_thinking = False
34
39
  self.is_in_content_block = False
40
+ self._segment_types_by_id = {}
41
+ self._saw_segment_event = False
35
42
 
36
43
  def reset_turn_state(self):
37
44
  """Resets flags that are tracked on a per-turn basis."""
38
45
  self._end_thinking_block()
39
46
  self.agent_has_spoken_this_turn = False
40
47
  self.is_in_content_block = False
48
+ self._segment_types_by_id.clear()
49
+ self._saw_segment_event = False
41
50
 
42
51
  def _ensure_new_line(self):
43
52
  """Ensures the cursor is on a new line if the current one isn't empty."""
@@ -54,10 +63,148 @@ class InteractiveCLIDisplay:
54
63
  self.is_thinking = False
55
64
  self.current_line_empty = False
56
65
 
57
- def _display_tool_approval_prompt(self):
58
- """Displays the tool approval prompt using stored pending data."""
59
- if not self.pending_approval_data:
66
+ def _ensure_agent_prefix(self):
67
+ """Prints the Agent prefix once per turn."""
68
+ if not self.agent_has_spoken_this_turn:
69
+ self._ensure_new_line()
70
+ sys.stdout.write("Agent:\n")
71
+ sys.stdout.flush()
72
+ self.agent_has_spoken_this_turn = True
73
+ self.current_line_empty = True
74
+
75
+ def _handle_segment_event(self, segment_event: SegmentEventData):
76
+ """Render segment events emitted by the streaming parser."""
77
+ try:
78
+ event_type = SegmentEventType(segment_event.event_type)
79
+ except ValueError:
80
+ logger.debug(f"CLI Display: Unknown segment event type '{segment_event.event_type}'.")
81
+ return
82
+
83
+ self._saw_segment_event = True
84
+
85
+ segment_type = None
86
+ if segment_event.segment_type:
87
+ try:
88
+ segment_type = SegmentType(segment_event.segment_type)
89
+ except ValueError:
90
+ logger.debug(f"CLI Display: Unknown segment type '{segment_event.segment_type}'.")
91
+
92
+ if segment_type is None and segment_event.segment_id in self._segment_types_by_id:
93
+ segment_type = self._segment_types_by_id.get(segment_event.segment_id)
94
+
95
+ metadata = {}
96
+ if isinstance(segment_event.payload, dict):
97
+ metadata = segment_event.payload.get("metadata", {}) or {}
98
+
99
+ if event_type == SegmentEventType.START:
100
+ if segment_type is not None:
101
+ self._segment_types_by_id[segment_event.segment_id] = segment_type
102
+
103
+ if segment_type != SegmentType.REASONING:
104
+ self._end_thinking_block()
105
+
106
+ self._ensure_agent_prefix()
107
+
108
+ if segment_type == SegmentType.REASONING:
109
+ if not self.is_thinking:
110
+ sys.stdout.write("<Thinking>\n")
111
+ sys.stdout.flush()
112
+ self.is_thinking = True
113
+ self.current_line_empty = True
114
+ return
115
+
116
+ if segment_type == SegmentType.WRITE_FILE:
117
+ path = metadata.get("path", "")
118
+ header = f"<write_file path=\"{path}\">" if path else "<write_file>"
119
+ sys.stdout.write(f"{header}\n")
120
+ sys.stdout.flush()
121
+ self.current_line_empty = True
122
+ self.is_in_content_block = True
123
+ return
124
+
125
+ if segment_type == SegmentType.RUN_BASH:
126
+ sys.stdout.write("<run_bash>\n")
127
+ sys.stdout.flush()
128
+ self.current_line_empty = True
129
+ self.is_in_content_block = True
130
+ return
131
+
132
+ if segment_type == SegmentType.TOOL_CALL:
133
+ tool_name = metadata.get("tool_name", "")
134
+ header = f"<tool name=\"{tool_name}\">" if tool_name else "<tool>"
135
+ sys.stdout.write(f"{header}\n")
136
+ sys.stdout.flush()
137
+ self.current_line_empty = True
138
+ self.is_in_content_block = True
139
+ return
140
+
141
+ # Text segment start does not need a visible marker.
142
+ self.is_in_content_block = True
143
+ return
144
+
145
+ if event_type == SegmentEventType.CONTENT:
146
+ if segment_type == SegmentType.REASONING:
147
+ if not self.is_thinking:
148
+ self._ensure_agent_prefix()
149
+ sys.stdout.write("<Thinking>\n")
150
+ sys.stdout.flush()
151
+ self.is_thinking = True
152
+ delta = segment_event.payload.get("delta", "")
153
+ sys.stdout.write(str(delta))
154
+ sys.stdout.flush()
155
+ self.current_line_empty = str(delta).endswith("\n")
156
+ return
157
+
158
+ delta = segment_event.payload.get("delta", "")
159
+ if delta:
160
+ self._ensure_agent_prefix()
161
+ sys.stdout.write(str(delta))
162
+ sys.stdout.flush()
163
+ self.current_line_empty = str(delta).endswith("\n")
164
+ self.is_in_content_block = True
60
165
  return
166
+
167
+ if event_type == SegmentEventType.END:
168
+ if segment_type == SegmentType.REASONING:
169
+ self._end_thinking_block()
170
+ self._segment_types_by_id.pop(segment_event.segment_id, None)
171
+ return
172
+
173
+ if segment_type == SegmentType.WRITE_FILE:
174
+ sys.stdout.write("\n</write_file>\n")
175
+ sys.stdout.flush()
176
+ self.current_line_empty = True
177
+ self.is_in_content_block = False
178
+ self._segment_types_by_id.pop(segment_event.segment_id, None)
179
+ return
180
+
181
+ if segment_type == SegmentType.RUN_BASH:
182
+ sys.stdout.write("\n</run_bash>\n")
183
+ sys.stdout.flush()
184
+ self.current_line_empty = True
185
+ self.is_in_content_block = False
186
+ self._segment_types_by_id.pop(segment_event.segment_id, None)
187
+ return
188
+
189
+ if segment_type == SegmentType.TOOL_CALL:
190
+ sys.stdout.write("\n</tool>\n")
191
+ sys.stdout.flush()
192
+ self.current_line_empty = True
193
+ self.is_in_content_block = False
194
+ self._segment_types_by_id.pop(segment_event.segment_id, None)
195
+ return
196
+
197
+ if segment_type == SegmentType.TEXT:
198
+ self.is_in_content_block = False
199
+ self._segment_types_by_id.pop(segment_event.segment_id, None)
200
+ return
201
+
202
+ self._segment_types_by_id.pop(segment_event.segment_id, None)
203
+
204
+ def get_approval_prompt(self) -> Optional[str]:
205
+ """Returns the tool approval prompt string using stored pending data."""
206
+ if not self.pending_approval_data:
207
+ return None
61
208
 
62
209
  try:
63
210
  args_str = json.dumps(self.pending_approval_data.arguments, indent=2)
@@ -69,31 +216,17 @@ class InteractiveCLIDisplay:
69
216
  f"Tool Call: '{self.pending_approval_data.tool_name}' requests permission to run with arguments:\n"
70
217
  f"{args_str}\nApprove? (y/n): "
71
218
  )
72
- sys.stdout.write(prompt_message)
73
- sys.stdout.flush()
74
- self.current_line_empty = False
219
+ return prompt_message
220
+
221
+ def clear_pending_approval(self):
222
+ self.pending_approval_data = None
223
+ self.approval_prompt_shown = False
75
224
 
76
225
  async def handle_stream_event(self, event: StreamEvent):
77
226
  """Processes a single StreamEvent and updates the CLI display."""
78
- # A block of thinking ends if any event other than a reasoning chunk arrives.
79
- is_reasoning_only_chunk = (
80
- event.event_type == StreamEventType.ASSISTANT_CHUNK and
81
- isinstance(event.data, AssistantChunkData) and
82
- bool(event.data.reasoning) and not bool(event.data.content)
83
- )
84
- if not is_reasoning_only_chunk:
85
- self._end_thinking_block()
86
-
87
- # Most events should start on a new line.
88
- if event.event_type != StreamEventType.ASSISTANT_CHUNK:
89
- self._ensure_new_line()
90
-
91
- if event.event_type in [
92
- StreamEventType.AGENT_IDLE,
93
- StreamEventType.ERROR_EVENT,
94
- StreamEventType.TOOL_INVOCATION_APPROVAL_REQUESTED,
95
- ]:
96
- self.agent_turn_complete_event.set()
227
+ if event.event_type == StreamEventType.SEGMENT_EVENT and isinstance(event.data, SegmentEventData):
228
+ self._handle_segment_event(event.data)
229
+ return
97
230
 
98
231
  if event.event_type == StreamEventType.ASSISTANT_CHUNK and isinstance(event.data, AssistantChunkData):
99
232
  # If this is the first output from the agent this turn, print the "Agent: " prefix.
@@ -110,7 +243,7 @@ class InteractiveCLIDisplay:
110
243
  sys.stdout.write("<Thinking>\n")
111
244
  sys.stdout.flush()
112
245
  self.is_thinking = True
113
- self.current_line_empty = True # We just printed a newline
246
+ self.current_line_empty = True
114
247
 
115
248
  sys.stdout.write(event.data.reasoning)
116
249
  sys.stdout.flush()
@@ -119,7 +252,7 @@ class InteractiveCLIDisplay:
119
252
  # Stream content to stdout.
120
253
  if event.data.content:
121
254
  if not self.is_in_content_block:
122
- self._ensure_new_line() # Ensures content starts on a new line after </Thinking>
255
+ self._ensure_new_line()
123
256
  self.is_in_content_block = True
124
257
  sys.stdout.write(event.data.content)
125
258
  sys.stdout.flush()
@@ -132,11 +265,15 @@ class InteractiveCLIDisplay:
132
265
  f"[Token Usage: Prompt={usage.prompt_tokens}, "
133
266
  f"Completion={usage.completion_tokens}, Total={usage.total_tokens}]"
134
267
  )
268
+ return
135
269
 
136
- elif event.event_type == StreamEventType.ASSISTANT_COMPLETE_RESPONSE and isinstance(event.data, AssistantCompleteResponseData):
270
+ self._end_thinking_block()
271
+ self._ensure_new_line()
272
+
273
+ if event.event_type == StreamEventType.ASSISTANT_COMPLETE_RESPONSE and isinstance(event.data, AssistantCompleteResponseData):
137
274
  # The reasoning has already been streamed. Do not log it again.
138
275
 
139
- if not self.agent_has_spoken_this_turn:
276
+ if not self._saw_segment_event and not self.agent_has_spoken_this_turn:
140
277
  # This case handles responses that might not have streamed any content chunks (e.g., only a tool call).
141
278
  # We still need to ensure the agent's turn is visibly terminated with a newline.
142
279
  self._ensure_new_line()
@@ -159,7 +296,8 @@ class InteractiveCLIDisplay:
159
296
 
160
297
  elif event.event_type == StreamEventType.TOOL_INVOCATION_APPROVAL_REQUESTED and isinstance(event.data, ToolInvocationApprovalRequestedData):
161
298
  self.pending_approval_data = event.data
162
- self._display_tool_approval_prompt()
299
+ if self.awaiting_approval or self.current_status == AgentStatus.AWAITING_TOOL_APPROVAL:
300
+ self.agent_turn_complete_event.set()
163
301
 
164
302
  elif event.event_type == StreamEventType.TOOL_INVOCATION_AUTO_EXECUTING and isinstance(event.data, ToolInvocationAutoExecutingData):
165
303
  tool_name = event.data.tool_name
@@ -175,30 +313,41 @@ class InteractiveCLIDisplay:
175
313
  f"[Tool Log ({event.data.tool_name} | {event.data.tool_invocation_id})]: {event.data.log_entry}"
176
314
  )
177
315
 
178
- elif event.event_type == StreamEventType.AGENT_OPERATIONAL_PHASE_TRANSITION and isinstance(event.data, AgentOperationalPhaseTransitionData):
179
- if event.data.new_phase == AgentOperationalPhase.EXECUTING_TOOL:
316
+ elif event.event_type == StreamEventType.AGENT_STATUS_UPDATED and isinstance(event.data, AgentStatusUpdateData):
317
+ self.current_status = event.data.new_status
318
+ if event.data.new_status == AgentStatus.AWAITING_TOOL_APPROVAL:
319
+ self.awaiting_approval = True
320
+ if self.pending_approval_data:
321
+ self.agent_turn_complete_event.set()
322
+ else:
323
+ self.awaiting_approval = False
324
+
325
+ if event.data.new_status in {AgentStatus.IDLE, AgentStatus.ERROR}:
326
+ self.agent_turn_complete_event.set()
327
+
328
+ if event.data.new_status == AgentStatus.EXECUTING_TOOL:
180
329
  tool_name = event.data.tool_name or "a tool"
181
330
  sys.stdout.write(f"Agent: Waiting for tool '{tool_name}' to complete...\n")
182
331
  sys.stdout.flush()
183
332
  self.current_line_empty = True
184
333
  self.agent_has_spoken_this_turn = True
185
- elif event.data.new_phase == AgentOperationalPhase.BOOTSTRAPPING:
334
+ elif event.data.new_status == AgentStatus.IDLE:
335
+ logger.info("[Agent is now idle.]")
336
+ elif event.data.new_status == AgentStatus.BOOTSTRAPPING:
186
337
  logger.info("[Agent is initializing...]")
187
- elif event.data.new_phase == AgentOperationalPhase.TOOL_DENIED:
338
+ elif event.data.new_status == AgentStatus.TOOL_DENIED:
188
339
  tool_name = event.data.tool_name or "a tool"
189
340
  logger.info(f"[Tool '{tool_name}' was denied by user. Agent is reconsidering.]")
190
341
  else:
191
- phase_msg = f"[Agent Status: {event.data.new_phase.value}"
342
+ status_msg = f"[Agent Status: {event.data.new_status.value}"
192
343
  if event.data.tool_name:
193
- phase_msg += f" ({event.data.tool_name})"
194
- phase_msg += "]"
195
- logger.info(phase_msg)
344
+ status_msg += f" ({event.data.tool_name})"
345
+ status_msg += "]"
346
+ logger.info(status_msg)
196
347
 
197
348
  elif event.event_type == StreamEventType.ERROR_EVENT and isinstance(event.data, ErrorEventData):
198
349
  logger.error(f"[Error: {event.data.message} (Source: {event.data.source})]")
199
-
200
- elif event.event_type == StreamEventType.AGENT_IDLE:
201
- logger.info("[Agent is now idle.]")
350
+ self.agent_turn_complete_event.set()
202
351
 
203
352
  else:
204
353
  # Add logging for unhandled events for better debugging
@@ -16,8 +16,7 @@ from autobyteus.workflow.agentic_workflow import AgenticWorkflow
16
16
  from autobyteus.workflow.streaming.workflow_event_stream import WorkflowEventStream
17
17
  from autobyteus.agent.message.agent_input_user_message import AgentInputUserMessage
18
18
  from autobyteus.agent.streaming.stream_events import StreamEventType as AgentStreamEventType
19
- from autobyteus.agent.streaming.stream_event_payloads import AssistantChunkData
20
- from autobyteus.workflow.streaming.workflow_stream_event_payloads import AgentEventRebroadcastPayload, WorkflowPhaseTransitionData
19
+ from autobyteus.workflow.streaming.workflow_stream_event_payloads import AgentEventRebroadcastPayload
21
20
 
22
21
  from .state import TUIStateStore
23
22
  from .widgets.agent_list_sidebar import AgentListSidebar
@@ -139,12 +138,12 @@ class WorkflowApp(App):
139
138
 
140
139
  # Fetch fresh data from the store for the update
141
140
  tree_data = self.store.get_tree_data()
142
- agent_phases = self.store._agent_phases
143
- workflow_phases = self.store._workflow_phases
141
+ agent_statuses = self.store._agent_statuses
142
+ workflow_statuses = self.store._workflow_statuses
144
143
  speaking_agents = self.store._speaking_agents
145
144
 
146
145
  # Update sidebar
147
- sidebar.update_tree(tree_data, agent_phases, workflow_phases, speaking_agents)
146
+ sidebar.update_tree(tree_data, agent_statuses, workflow_statuses, speaking_agents)
148
147
 
149
148
  # Intelligently update the focus pane
150
149
  focused_data = self.focused_node_data
@@ -156,12 +155,12 @@ class WorkflowApp(App):
156
155
  node_data=focused_data,
157
156
  history=history,
158
157
  pending_approval=None,
159
- all_agent_phases=agent_phases,
160
- all_workflow_phases=workflow_phases
158
+ all_agent_statuses=agent_statuses,
159
+ all_workflow_statuses=workflow_statuses
161
160
  )
162
161
  elif focused_data and focused_data.get("type") == 'agent':
163
162
  # For agents, we only need to update the title status, not the whole log.
164
- focus_pane.update_current_node_status(agent_phases, workflow_phases)
163
+ focus_pane.update_current_node_status(agent_statuses, workflow_statuses)
165
164
 
166
165
 
167
166
  async def watch_focused_node_data(self, new_node_data: Optional[Dict[str, Any]]):
@@ -181,8 +180,8 @@ class WorkflowApp(App):
181
180
  node_data=new_node_data,
182
181
  history=history,
183
182
  pending_approval=pending_approval,
184
- all_agent_phases=self.store._agent_phases,
185
- all_workflow_phases=self.store._workflow_phases
183
+ all_agent_statuses=self.store._agent_statuses,
184
+ all_workflow_statuses=self.store._workflow_statuses
186
185
  )
187
186
 
188
187
  sidebar.update_selection(node_name)
@@ -8,15 +8,15 @@ import copy
8
8
 
9
9
  from autobyteus.agent.context import AgentConfig
10
10
  from autobyteus.workflow.agentic_workflow import AgenticWorkflow
11
- from autobyteus.agent.phases import AgentOperationalPhase
12
- from autobyteus.workflow.phases import WorkflowOperationalPhase
11
+ from autobyteus.agent.status.status_enum import AgentStatus
12
+ from autobyteus.workflow.status.workflow_status import WorkflowStatus
13
13
  from autobyteus.agent.streaming.stream_events import StreamEvent as AgentStreamEvent, StreamEventType as AgentStreamEventType
14
14
  from autobyteus.agent.streaming.stream_event_payloads import (
15
- AgentOperationalPhaseTransitionData, ToolInvocationApprovalRequestedData,
16
- AssistantChunkData, AssistantCompleteResponseData
15
+ AgentStatusUpdateData, ToolInvocationApprovalRequestedData,
16
+ AssistantCompleteResponseData
17
17
  )
18
18
  from autobyteus.workflow.streaming.workflow_stream_events import WorkflowStreamEvent
19
- from autobyteus.workflow.streaming.workflow_stream_event_payloads import AgentEventRebroadcastPayload, SubWorkflowEventRebroadcastPayload, WorkflowPhaseTransitionData
19
+ from autobyteus.workflow.streaming.workflow_stream_event_payloads import AgentEventRebroadcastPayload, SubWorkflowEventRebroadcastPayload, WorkflowStatusUpdateData
20
20
 
21
21
  logger = logging.getLogger(__name__)
22
22
 
@@ -38,8 +38,8 @@ class TUIStateStore:
38
38
 
39
39
  self._node_roles: Dict[str, str] = self._extract_node_roles(workflow)
40
40
  self._nodes: Dict[str, Any] = self._initialize_root_node()
41
- self._agent_phases: Dict[str, AgentOperationalPhase] = {}
42
- self._workflow_phases: Dict[str, WorkflowOperationalPhase] = {self.workflow_name: WorkflowOperationalPhase.UNINITIALIZED}
41
+ self._agent_statuses: Dict[str, AgentStatus] = {}
42
+ self._workflow_statuses: Dict[str, WorkflowStatus] = {self.workflow_name: WorkflowStatus.UNINITIALIZED}
43
43
  self._agent_event_history: Dict[str, List[AgentStreamEvent]] = {}
44
44
  self._workflow_event_history: Dict[str, List[WorkflowStreamEvent]] = {self.workflow_name: []}
45
45
  self._pending_approvals: Dict[str, ToolInvocationApprovalRequestedData] = {}
@@ -77,8 +77,8 @@ class TUIStateStore:
77
77
  The main entry point for processing events from the backend.
78
78
  This method acts as a reducer, updating the state based on the event.
79
79
  """
80
- if event.event_source_type == "WORKFLOW" and isinstance(event.data, WorkflowPhaseTransitionData):
81
- self._workflow_phases[self.workflow_name] = event.data.new_phase
80
+ if event.event_source_type == "WORKFLOW" and isinstance(event.data, WorkflowStatusUpdateData):
81
+ self._workflow_statuses[self.workflow_name] = event.data.new_status
82
82
 
83
83
  self._process_event_recursively(event, self.workflow_name)
84
84
 
@@ -113,13 +113,11 @@ class TUIStateStore:
113
113
  self._agent_event_history[agent_name].append(agent_event)
114
114
 
115
115
  # --- State update logic for specific events (applies to both focused and non-focused) ---
116
- if agent_event.event_type == AgentStreamEventType.AGENT_OPERATIONAL_PHASE_TRANSITION:
117
- phase_data: AgentOperationalPhaseTransitionData = agent_event.data
118
- self._agent_phases[agent_name] = phase_data.new_phase
116
+ if agent_event.event_type == AgentStreamEventType.AGENT_STATUS_UPDATED:
117
+ status_data: AgentStatusUpdateData = agent_event.data
118
+ self._agent_statuses[agent_name] = status_data.new_status
119
119
  if agent_name in self._pending_approvals:
120
120
  del self._pending_approvals[agent_name]
121
- elif agent_event.event_type == AgentStreamEventType.AGENT_IDLE:
122
- self._agent_phases[agent_name] = AgentOperationalPhase.IDLE
123
121
  elif agent_event.event_type == AgentStreamEventType.TOOL_INVOCATION_APPROVAL_REQUESTED:
124
122
  self._pending_approvals[agent_name] = agent_event.data
125
123
 
@@ -134,8 +132,8 @@ class TUIStateStore:
134
132
  role = self._node_roles.get(sub_workflow_name, "Sub-Workflow")
135
133
  self._add_node(sub_workflow_name, {"type": "subworkflow", "name": sub_workflow_name, "role": role, "children": {}}, parent_name)
136
134
 
137
- if sub_workflow_event.event_source_type == "WORKFLOW" and isinstance(sub_workflow_event.data, WorkflowPhaseTransitionData):
138
- self._workflow_phases[sub_workflow_name] = sub_workflow_event.data.new_phase
135
+ if sub_workflow_event.event_source_type == "WORKFLOW" and isinstance(sub_workflow_event.data, WorkflowStatusUpdateData):
136
+ self._workflow_statuses[sub_workflow_name] = sub_workflow_event.data.new_status
139
137
 
140
138
  self._process_event_recursively(sub_workflow_event, parent_name=sub_workflow_name)
141
139
 
@@ -10,10 +10,10 @@ from textual.widgets import Static, Tree
10
10
  from textual.widgets.tree import TreeNode
11
11
  from textual.containers import Vertical
12
12
 
13
- from autobyteus.agent.phases import AgentOperationalPhase
14
- from autobyteus.workflow.phases import WorkflowOperationalPhase
13
+ from autobyteus.agent.status.status_enum import AgentStatus
14
+ from autobyteus.workflow.status.workflow_status import WorkflowStatus
15
15
  from .shared import (
16
- AGENT_PHASE_ICONS, WORKFLOW_PHASE_ICONS, SUB_WORKFLOW_ICON,
16
+ AGENT_STATUS_ICONS, WORKFLOW_STATUS_ICONS, SUB_WORKFLOW_ICON,
17
17
  WORKFLOW_ICON, SPEAKING_ICON, DEFAULT_ICON
18
18
  )
19
19
  from .logo import Logo
@@ -45,19 +45,19 @@ class AgentListSidebar(Static):
45
45
  self.post_message(self.NodeSelected(event.node.data))
46
46
  event.stop()
47
47
 
48
- def _build_label(self, name: str, node_data: Dict, agent_phases: Dict, workflow_phases: Dict, speaking_agents: Dict) -> str:
48
+ def _build_label(self, name: str, node_data: Dict, agent_statuses: Dict, workflow_statuses: Dict, speaking_agents: Dict) -> str:
49
49
  """Constructs the display label for a tree node."""
50
50
  node_type = node_data["type"]
51
51
  icon = DEFAULT_ICON
52
52
 
53
53
  if node_type == "agent":
54
- phase = agent_phases.get(name, AgentOperationalPhase.UNINITIALIZED)
55
- icon = SPEAKING_ICON if speaking_agents.get(name) else AGENT_PHASE_ICONS.get(phase, DEFAULT_ICON)
54
+ status = agent_statuses.get(name, AgentStatus.UNINITIALIZED)
55
+ icon = SPEAKING_ICON if speaking_agents.get(name) else AGENT_STATUS_ICONS.get(status, DEFAULT_ICON)
56
56
  label = f"{icon} {name}"
57
57
  elif node_type in ["workflow", "subworkflow"]:
58
- phase = workflow_phases.get(name, WorkflowOperationalPhase.UNINITIALIZED)
58
+ status = workflow_statuses.get(name, WorkflowStatus.UNINITIALIZED)
59
59
  default_icon = WORKFLOW_ICON if node_type == "workflow" else SUB_WORKFLOW_ICON
60
- icon = WORKFLOW_PHASE_ICONS.get(phase, default_icon)
60
+ icon = WORKFLOW_STATUS_ICONS.get(status, default_icon)
61
61
  role = node_data.get("role")
62
62
  label = f"{icon} {role or name}"
63
63
  if role and role != name:
@@ -67,7 +67,7 @@ class AgentListSidebar(Static):
67
67
 
68
68
  return label
69
69
 
70
- def update_tree(self, tree_data: Dict, agent_phases: Dict[str, AgentOperationalPhase], workflow_phases: Dict[str, WorkflowOperationalPhase], speaking_agents: Dict[str, bool]):
70
+ def update_tree(self, tree_data: Dict, agent_statuses: Dict[str, AgentStatus], workflow_statuses: Dict[str, WorkflowStatus], speaking_agents: Dict[str, bool]):
71
71
  """
72
72
  Performs an in-place update of the tree to reflect the new state,
73
73
  avoiding a full rebuild for better performance and preserving UI state like expansion.
@@ -82,17 +82,17 @@ class AgentListSidebar(Static):
82
82
  root_node_data = tree_data[root_name]
83
83
 
84
84
  # Kick off the recursive update from the root.
85
- self._update_node_recursively(tree.root, root_node_data, agent_phases, workflow_phases, speaking_agents)
85
+ self._update_node_recursively(tree.root, root_node_data, agent_statuses, workflow_statuses, speaking_agents)
86
86
 
87
87
  # Ensure the root is expanded on the first run.
88
88
  if not tree.root.is_expanded:
89
89
  tree.root.expand()
90
90
 
91
- def _update_node_recursively(self, ui_node: TreeNode, node_data: Dict, agent_phases: Dict, workflow_phases: Dict, speaking_agents: Dict):
91
+ def _update_node_recursively(self, ui_node: TreeNode, node_data: Dict, agent_statuses: Dict, workflow_statuses: Dict, speaking_agents: Dict):
92
92
  """Recursively updates a node and reconciles its children."""
93
93
  # 1. Update the current node's label and data
94
94
  name = node_data['name']
95
- label = self._build_label(name, node_data, agent_phases, workflow_phases, speaking_agents)
95
+ label = self._build_label(name, node_data, agent_statuses, workflow_statuses, speaking_agents)
96
96
  ui_node.set_label(label)
97
97
  ui_node.data = node_data
98
98
  self._node_map[name] = ui_node # Ensure map is always up-to-date
@@ -106,10 +106,10 @@ class AgentListSidebar(Static):
106
106
  if child_name in existing_ui_children_by_name:
107
107
  # Node exists, so we recursively update it
108
108
  child_ui_node = existing_ui_children_by_name[child_name]
109
- self._update_node_recursively(child_ui_node, child_data, agent_phases, workflow_phases, speaking_agents)
109
+ self._update_node_recursively(child_ui_node, child_data, agent_statuses, workflow_statuses, speaking_agents)
110
110
  else:
111
111
  # Node is new, so we add it
112
- new_child_label = self._build_label(child_name, child_data, agent_phases, workflow_phases, speaking_agents)
112
+ new_child_label = self._build_label(child_name, child_data, agent_statuses, workflow_statuses, speaking_agents)
113
113
  is_leaf = child_data.get("children", {}) == {} and child_data['type'] == 'agent'
114
114
 
115
115
  if is_leaf:
@@ -117,7 +117,7 @@ class AgentListSidebar(Static):
117
117
  else:
118
118
  new_ui_node = ui_node.add(new_child_label, data=child_data)
119
119
  # Since this is a new branch, we must build its children too
120
- self._update_node_recursively(new_ui_node, child_data, agent_phases, workflow_phases, speaking_agents)
120
+ self._update_node_recursively(new_ui_node, child_data, agent_statuses, workflow_statuses, speaking_agents)
121
121
 
122
122
  self._node_map[child_name] = new_ui_node
123
123