autobyteus 1.2.1__py3-none-any.whl → 1.2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (466) hide show
  1. autobyteus/agent/agent.py +15 -5
  2. autobyteus/agent/bootstrap_steps/__init__.py +1 -3
  3. autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +3 -59
  4. autobyteus/agent/bootstrap_steps/base_bootstrap_step.py +1 -4
  5. autobyteus/agent/bootstrap_steps/mcp_server_prewarming_step.py +1 -3
  6. autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +16 -13
  7. autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +2 -4
  8. autobyteus/agent/context/agent_config.py +43 -20
  9. autobyteus/agent/context/agent_context.py +23 -18
  10. autobyteus/agent/context/agent_runtime_state.py +19 -19
  11. autobyteus/agent/events/__init__.py +16 -1
  12. autobyteus/agent/events/agent_events.py +43 -3
  13. autobyteus/agent/events/agent_input_event_queue_manager.py +79 -26
  14. autobyteus/agent/events/event_store.py +57 -0
  15. autobyteus/agent/events/notifiers.py +69 -59
  16. autobyteus/agent/events/worker_event_dispatcher.py +21 -64
  17. autobyteus/agent/factory/agent_factory.py +52 -0
  18. autobyteus/agent/handlers/__init__.py +2 -0
  19. autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +51 -34
  20. autobyteus/agent/handlers/bootstrap_event_handler.py +155 -0
  21. autobyteus/agent/handlers/inter_agent_message_event_handler.py +10 -0
  22. autobyteus/agent/handlers/lifecycle_event_logger.py +19 -11
  23. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +10 -15
  24. autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +188 -48
  25. autobyteus/agent/handlers/tool_execution_approval_event_handler.py +0 -10
  26. autobyteus/agent/handlers/tool_invocation_request_event_handler.py +53 -48
  27. autobyteus/agent/handlers/tool_result_event_handler.py +7 -8
  28. autobyteus/agent/handlers/user_input_message_event_handler.py +10 -3
  29. autobyteus/agent/input_processor/memory_ingest_input_processor.py +40 -0
  30. autobyteus/agent/lifecycle/__init__.py +12 -0
  31. autobyteus/agent/lifecycle/base_processor.py +109 -0
  32. autobyteus/agent/lifecycle/events.py +35 -0
  33. autobyteus/agent/lifecycle/processor_definition.py +36 -0
  34. autobyteus/agent/lifecycle/processor_registry.py +106 -0
  35. autobyteus/agent/llm_request_assembler.py +98 -0
  36. autobyteus/agent/llm_response_processor/__init__.py +1 -8
  37. autobyteus/agent/message/context_file_type.py +1 -1
  38. autobyteus/agent/runtime/agent_runtime.py +29 -21
  39. autobyteus/agent/runtime/agent_worker.py +98 -19
  40. autobyteus/agent/shutdown_steps/__init__.py +2 -0
  41. autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
  42. autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
  43. autobyteus/agent/status/__init__.py +14 -0
  44. autobyteus/agent/status/manager.py +93 -0
  45. autobyteus/agent/status/status_deriver.py +96 -0
  46. autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
  47. autobyteus/agent/status/status_update_utils.py +73 -0
  48. autobyteus/agent/streaming/__init__.py +52 -5
  49. autobyteus/agent/streaming/adapters/__init__.py +18 -0
  50. autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
  51. autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
  52. autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
  53. autobyteus/agent/streaming/agent_event_stream.py +3 -183
  54. autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
  55. autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
  56. autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
  57. autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
  58. autobyteus/agent/streaming/events/__init__.py +6 -0
  59. autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
  60. autobyteus/agent/streaming/events/stream_events.py +141 -0
  61. autobyteus/agent/streaming/handlers/__init__.py +15 -0
  62. autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
  63. autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
  64. autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
  65. autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
  66. autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
  67. autobyteus/agent/streaming/parser/__init__.py +61 -0
  68. autobyteus/agent/streaming/parser/event_emitter.py +181 -0
  69. autobyteus/agent/streaming/parser/events.py +4 -0
  70. autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
  71. autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
  72. autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
  73. autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
  74. autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
  75. autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
  76. autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
  77. autobyteus/agent/streaming/parser/parser_context.py +227 -0
  78. autobyteus/agent/streaming/parser/parser_factory.py +132 -0
  79. autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
  80. autobyteus/agent/streaming/parser/state_factory.py +62 -0
  81. autobyteus/agent/streaming/parser/states/__init__.py +1 -0
  82. autobyteus/agent/streaming/parser/states/base_state.py +60 -0
  83. autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
  84. autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
  85. autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
  86. autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
  87. autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
  88. autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
  89. autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
  90. autobyteus/agent/streaming/parser/states/text_state.py +78 -0
  91. autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
  92. autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
  93. autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
  94. autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
  95. autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
  96. autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
  97. autobyteus/agent/streaming/parser/strategies/base.py +24 -0
  98. autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
  99. autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
  100. autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
  101. autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
  102. autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
  103. autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
  104. autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
  105. autobyteus/agent/streaming/parser/tool_constants.py +7 -0
  106. autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
  107. autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
  108. autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
  109. autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
  110. autobyteus/agent/streaming/queue_streamer.py +3 -57
  111. autobyteus/agent/streaming/segments/__init__.py +5 -0
  112. autobyteus/agent/streaming/segments/segment_events.py +81 -0
  113. autobyteus/agent/streaming/stream_event_payloads.py +2 -223
  114. autobyteus/agent/streaming/stream_events.py +3 -140
  115. autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
  116. autobyteus/agent/streaming/streaming_response_handler.py +4 -0
  117. autobyteus/agent/streaming/streams/__init__.py +5 -0
  118. autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
  119. autobyteus/agent/streaming/utils/__init__.py +5 -0
  120. autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
  121. autobyteus/agent/system_prompt_processor/__init__.py +2 -0
  122. autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
  123. autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
  124. autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
  125. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
  126. autobyteus/agent/token_budget.py +56 -0
  127. autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
  128. autobyteus/agent/tool_invocation.py +16 -40
  129. autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
  130. autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
  131. autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
  132. autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
  133. autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
  134. autobyteus/agent/utils/wait_for_idle.py +12 -14
  135. autobyteus/agent/workspace/base_workspace.py +6 -27
  136. autobyteus/agent_team/agent_team.py +3 -3
  137. autobyteus/agent_team/agent_team_builder.py +1 -41
  138. autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
  139. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
  140. autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
  141. autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
  142. autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
  143. autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +1 -2
  144. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +4 -4
  145. autobyteus/agent_team/context/agent_team_config.py +6 -3
  146. autobyteus/agent_team/context/agent_team_context.py +25 -3
  147. autobyteus/agent_team/context/agent_team_runtime_state.py +9 -6
  148. autobyteus/agent_team/events/__init__.py +11 -0
  149. autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
  150. autobyteus/agent_team/events/agent_team_events.py +16 -0
  151. autobyteus/agent_team/events/event_store.py +57 -0
  152. autobyteus/agent_team/factory/agent_team_factory.py +8 -0
  153. autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
  154. autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
  155. autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
  156. autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
  157. autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
  158. autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
  159. autobyteus/agent_team/status/__init__.py +14 -0
  160. autobyteus/agent_team/status/agent_team_status.py +18 -0
  161. autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
  162. autobyteus/agent_team/status/status_deriver.py +62 -0
  163. autobyteus/agent_team/status/status_update_utils.py +42 -0
  164. autobyteus/agent_team/streaming/__init__.py +2 -2
  165. autobyteus/agent_team/streaming/agent_team_event_notifier.py +6 -6
  166. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +4 -4
  167. autobyteus/agent_team/streaming/agent_team_stream_events.py +3 -3
  168. autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
  169. autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
  170. autobyteus/agent_team/task_notification/task_notification_mode.py +19 -0
  171. autobyteus/agent_team/utils/wait_for_idle.py +4 -4
  172. autobyteus/cli/agent_cli.py +18 -10
  173. autobyteus/cli/agent_team_tui/app.py +14 -11
  174. autobyteus/cli/agent_team_tui/state.py +13 -15
  175. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
  176. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +143 -36
  177. autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
  178. autobyteus/cli/agent_team_tui/widgets/shared.py +25 -25
  179. autobyteus/cli/cli_display.py +193 -44
  180. autobyteus/cli/workflow_tui/app.py +9 -10
  181. autobyteus/cli/workflow_tui/state.py +14 -16
  182. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
  183. autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
  184. autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
  185. autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
  186. autobyteus/clients/autobyteus_client.py +94 -1
  187. autobyteus/events/event_types.py +11 -18
  188. autobyteus/llm/api/autobyteus_llm.py +33 -29
  189. autobyteus/llm/api/claude_llm.py +142 -36
  190. autobyteus/llm/api/gemini_llm.py +163 -59
  191. autobyteus/llm/api/grok_llm.py +1 -1
  192. autobyteus/llm/api/minimax_llm.py +26 -0
  193. autobyteus/llm/api/mistral_llm.py +113 -87
  194. autobyteus/llm/api/ollama_llm.py +9 -42
  195. autobyteus/llm/api/openai_compatible_llm.py +127 -91
  196. autobyteus/llm/api/openai_llm.py +3 -3
  197. autobyteus/llm/api/openai_responses_llm.py +324 -0
  198. autobyteus/llm/api/zhipu_llm.py +21 -2
  199. autobyteus/llm/autobyteus_provider.py +70 -60
  200. autobyteus/llm/base_llm.py +85 -81
  201. autobyteus/llm/converters/__init__.py +14 -0
  202. autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
  203. autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
  204. autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
  205. autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
  206. autobyteus/llm/extensions/base_extension.py +6 -12
  207. autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
  208. autobyteus/llm/llm_factory.py +282 -204
  209. autobyteus/llm/lmstudio_provider.py +60 -49
  210. autobyteus/llm/models.py +35 -2
  211. autobyteus/llm/ollama_provider.py +60 -49
  212. autobyteus/llm/ollama_provider_resolver.py +0 -1
  213. autobyteus/llm/prompt_renderers/__init__.py +19 -0
  214. autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
  215. autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
  216. autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
  217. autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
  218. autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
  219. autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
  220. autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
  221. autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
  222. autobyteus/llm/providers.py +1 -3
  223. autobyteus/llm/token_counter/claude_token_counter.py +56 -25
  224. autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
  225. autobyteus/llm/token_counter/openai_token_counter.py +24 -5
  226. autobyteus/llm/token_counter/token_counter_factory.py +12 -5
  227. autobyteus/llm/utils/llm_config.py +6 -12
  228. autobyteus/llm/utils/media_payload_formatter.py +27 -20
  229. autobyteus/llm/utils/messages.py +55 -3
  230. autobyteus/llm/utils/response_types.py +3 -0
  231. autobyteus/llm/utils/tool_call_delta.py +31 -0
  232. autobyteus/memory/__init__.py +32 -0
  233. autobyteus/memory/active_transcript.py +69 -0
  234. autobyteus/memory/compaction/__init__.py +9 -0
  235. autobyteus/memory/compaction/compaction_result.py +8 -0
  236. autobyteus/memory/compaction/compactor.py +89 -0
  237. autobyteus/memory/compaction/summarizer.py +11 -0
  238. autobyteus/memory/compaction_snapshot_builder.py +84 -0
  239. autobyteus/memory/memory_manager.py +183 -0
  240. autobyteus/memory/models/__init__.py +14 -0
  241. autobyteus/memory/models/episodic_item.py +41 -0
  242. autobyteus/memory/models/memory_types.py +7 -0
  243. autobyteus/memory/models/raw_trace_item.py +79 -0
  244. autobyteus/memory/models/semantic_item.py +41 -0
  245. autobyteus/memory/models/tool_interaction.py +20 -0
  246. autobyteus/memory/policies/__init__.py +5 -0
  247. autobyteus/memory/policies/compaction_policy.py +16 -0
  248. autobyteus/memory/retrieval/__init__.py +7 -0
  249. autobyteus/memory/retrieval/memory_bundle.py +11 -0
  250. autobyteus/memory/retrieval/retriever.py +13 -0
  251. autobyteus/memory/store/__init__.py +7 -0
  252. autobyteus/memory/store/base_store.py +14 -0
  253. autobyteus/memory/store/file_store.py +98 -0
  254. autobyteus/memory/tool_interaction_builder.py +46 -0
  255. autobyteus/memory/turn_tracker.py +9 -0
  256. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
  257. autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
  258. autobyteus/multimedia/audio/audio_client_factory.py +47 -9
  259. autobyteus/multimedia/audio/audio_model.py +2 -1
  260. autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
  261. autobyteus/multimedia/image/api/gemini_image_client.py +38 -17
  262. autobyteus/multimedia/image/api/openai_image_client.py +125 -43
  263. autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
  264. autobyteus/multimedia/image/image_client_factory.py +47 -15
  265. autobyteus/multimedia/image/image_model.py +5 -2
  266. autobyteus/multimedia/providers.py +3 -2
  267. autobyteus/skills/loader.py +71 -0
  268. autobyteus/skills/model.py +11 -0
  269. autobyteus/skills/registry.py +70 -0
  270. autobyteus/task_management/tools/todo_tools/add_todo.py +2 -2
  271. autobyteus/task_management/tools/todo_tools/create_todo_list.py +2 -2
  272. autobyteus/task_management/tools/todo_tools/update_todo_status.py +2 -2
  273. autobyteus/tools/__init__.py +34 -47
  274. autobyteus/tools/base_tool.py +7 -0
  275. autobyteus/tools/file/__init__.py +2 -6
  276. autobyteus/tools/file/patch_file.py +149 -0
  277. autobyteus/tools/file/read_file.py +36 -5
  278. autobyteus/tools/file/write_file.py +4 -1
  279. autobyteus/tools/functional_tool.py +43 -6
  280. autobyteus/tools/mcp/__init__.py +2 -0
  281. autobyteus/tools/mcp/config_service.py +5 -1
  282. autobyteus/tools/mcp/server/__init__.py +2 -0
  283. autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
  284. autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
  285. autobyteus/tools/mcp/server_instance_manager.py +8 -1
  286. autobyteus/tools/mcp/types.py +61 -0
  287. autobyteus/tools/multimedia/audio_tools.py +70 -17
  288. autobyteus/tools/multimedia/download_media_tool.py +18 -4
  289. autobyteus/tools/multimedia/image_tools.py +246 -62
  290. autobyteus/tools/operation_executor/journal_manager.py +107 -0
  291. autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
  292. autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
  293. autobyteus/tools/operation_executor/operation_executor.py +58 -0
  294. autobyteus/tools/registry/tool_definition.py +43 -2
  295. autobyteus/tools/skill/load_skill.py +50 -0
  296. autobyteus/tools/terminal/__init__.py +45 -0
  297. autobyteus/tools/terminal/ansi_utils.py +32 -0
  298. autobyteus/tools/terminal/background_process_manager.py +233 -0
  299. autobyteus/tools/terminal/output_buffer.py +105 -0
  300. autobyteus/tools/terminal/prompt_detector.py +63 -0
  301. autobyteus/tools/terminal/pty_session.py +241 -0
  302. autobyteus/tools/terminal/session_factory.py +20 -0
  303. autobyteus/tools/terminal/terminal_session_manager.py +226 -0
  304. autobyteus/tools/terminal/tools/__init__.py +13 -0
  305. autobyteus/tools/terminal/tools/get_process_output.py +81 -0
  306. autobyteus/tools/terminal/tools/run_bash.py +109 -0
  307. autobyteus/tools/terminal/tools/start_background_process.py +104 -0
  308. autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
  309. autobyteus/tools/terminal/types.py +54 -0
  310. autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
  311. autobyteus/tools/terminal/wsl_utils.py +156 -0
  312. autobyteus/tools/transaction_management/backup_handler.py +48 -0
  313. autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
  314. autobyteus/tools/usage/__init__.py +1 -2
  315. autobyteus/tools/usage/formatters/__init__.py +17 -1
  316. autobyteus/tools/usage/formatters/base_formatter.py +8 -0
  317. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
  318. autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
  319. autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
  320. autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
  321. autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
  322. autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
  323. autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
  324. autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
  325. autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
  326. autobyteus/tools/usage/registries/__init__.py +1 -3
  327. autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
  328. autobyteus/tools/usage/tool_schema_provider.py +51 -0
  329. autobyteus/tools/web/__init__.py +4 -0
  330. autobyteus/tools/web/read_url_tool.py +80 -0
  331. autobyteus/utils/diff_utils.py +271 -0
  332. autobyteus/utils/download_utils.py +109 -0
  333. autobyteus/utils/file_utils.py +57 -2
  334. autobyteus/utils/gemini_helper.py +56 -0
  335. autobyteus/utils/gemini_model_mapping.py +71 -0
  336. autobyteus/utils/llm_output_formatter.py +75 -0
  337. autobyteus/utils/tool_call_format.py +36 -0
  338. autobyteus/workflow/agentic_workflow.py +3 -3
  339. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
  340. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
  341. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
  342. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +3 -9
  343. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
  344. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
  345. autobyteus/workflow/context/workflow_context.py +3 -3
  346. autobyteus/workflow/context/workflow_runtime_state.py +5 -5
  347. autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
  348. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
  349. autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
  350. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
  351. autobyteus/workflow/runtime/workflow_runtime.py +8 -8
  352. autobyteus/workflow/runtime/workflow_worker.py +3 -3
  353. autobyteus/workflow/status/__init__.py +11 -0
  354. autobyteus/workflow/status/workflow_status.py +19 -0
  355. autobyteus/workflow/status/workflow_status_manager.py +48 -0
  356. autobyteus/workflow/streaming/__init__.py +2 -2
  357. autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
  358. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
  359. autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
  360. autobyteus/workflow/utils/wait_for_idle.py +4 -4
  361. autobyteus-1.2.3.dist-info/METADATA +293 -0
  362. autobyteus-1.2.3.dist-info/RECORD +600 -0
  363. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
  364. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/top_level.txt +0 -1
  365. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
  366. autobyteus/agent/hooks/__init__.py +0 -16
  367. autobyteus/agent/hooks/base_phase_hook.py +0 -78
  368. autobyteus/agent/hooks/hook_definition.py +0 -36
  369. autobyteus/agent/hooks/hook_meta.py +0 -37
  370. autobyteus/agent/hooks/hook_registry.py +0 -106
  371. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
  372. autobyteus/agent/phases/__init__.py +0 -18
  373. autobyteus/agent/phases/discover.py +0 -53
  374. autobyteus/agent/phases/manager.py +0 -265
  375. autobyteus/agent/phases/transition_decorator.py +0 -40
  376. autobyteus/agent/phases/transition_info.py +0 -33
  377. autobyteus/agent/remote_agent.py +0 -244
  378. autobyteus/agent/workspace/workspace_definition.py +0 -36
  379. autobyteus/agent/workspace/workspace_meta.py +0 -37
  380. autobyteus/agent/workspace/workspace_registry.py +0 -72
  381. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
  382. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
  383. autobyteus/agent_team/phases/__init__.py +0 -11
  384. autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
  385. autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
  386. autobyteus/llm/api/bedrock_llm.py +0 -92
  387. autobyteus/llm/api/groq_llm.py +0 -94
  388. autobyteus/llm/api/nvidia_llm.py +0 -108
  389. autobyteus/llm/utils/token_pricing_config.py +0 -87
  390. autobyteus/rpc/__init__.py +0 -73
  391. autobyteus/rpc/client/__init__.py +0 -17
  392. autobyteus/rpc/client/abstract_client_connection.py +0 -124
  393. autobyteus/rpc/client/client_connection_manager.py +0 -153
  394. autobyteus/rpc/client/sse_client_connection.py +0 -306
  395. autobyteus/rpc/client/stdio_client_connection.py +0 -280
  396. autobyteus/rpc/config/__init__.py +0 -13
  397. autobyteus/rpc/config/agent_server_config.py +0 -153
  398. autobyteus/rpc/config/agent_server_registry.py +0 -152
  399. autobyteus/rpc/hosting.py +0 -244
  400. autobyteus/rpc/protocol.py +0 -244
  401. autobyteus/rpc/server/__init__.py +0 -20
  402. autobyteus/rpc/server/agent_server_endpoint.py +0 -181
  403. autobyteus/rpc/server/base_method_handler.py +0 -40
  404. autobyteus/rpc/server/method_handlers.py +0 -259
  405. autobyteus/rpc/server/sse_server_handler.py +0 -182
  406. autobyteus/rpc/server/stdio_server_handler.py +0 -151
  407. autobyteus/rpc/server_main.py +0 -198
  408. autobyteus/rpc/transport_type.py +0 -13
  409. autobyteus/tools/bash/__init__.py +0 -2
  410. autobyteus/tools/bash/bash_executor.py +0 -100
  411. autobyteus/tools/browser/__init__.py +0 -2
  412. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
  413. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
  414. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
  415. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
  416. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
  417. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
  418. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
  419. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
  420. autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
  421. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
  422. autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
  423. autobyteus/tools/browser/standalone/__init__.py +0 -6
  424. autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  425. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
  426. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
  427. autobyteus/tools/browser/standalone/navigate_to.py +0 -84
  428. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -101
  429. autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -169
  430. autobyteus/tools/browser/standalone/webpage_reader.py +0 -105
  431. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -105
  432. autobyteus/tools/file/edit_file.py +0 -200
  433. autobyteus/tools/file/list_directory.py +0 -168
  434. autobyteus/tools/file/search_files.py +0 -188
  435. autobyteus/tools/timer.py +0 -175
  436. autobyteus/tools/usage/parsers/__init__.py +0 -22
  437. autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
  438. autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
  439. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
  440. autobyteus/tools/usage/parsers/base_parser.py +0 -41
  441. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
  442. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
  443. autobyteus/tools/usage/parsers/exceptions.py +0 -13
  444. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
  445. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
  446. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
  447. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
  448. autobyteus/workflow/phases/__init__.py +0 -11
  449. autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
  450. autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
  451. autobyteus-1.2.1.dist-info/METADATA +0 -205
  452. autobyteus-1.2.1.dist-info/RECORD +0 -511
  453. examples/__init__.py +0 -1
  454. examples/agent_team/__init__.py +0 -1
  455. examples/discover_phase_transitions.py +0 -104
  456. examples/run_agentic_software_engineer.py +0 -239
  457. examples/run_browser_agent.py +0 -262
  458. examples/run_google_slides_agent.py +0 -287
  459. examples/run_mcp_browser_client.py +0 -174
  460. examples/run_mcp_google_slides_client.py +0 -270
  461. examples/run_mcp_list_tools.py +0 -189
  462. examples/run_poem_writer.py +0 -284
  463. examples/run_sqlite_agent.py +0 -295
  464. /autobyteus/{tools/browser/session_aware → skills}/__init__.py +0 -0
  465. /autobyteus/tools/{browser/session_aware/factory → skill}/__init__.py +0 -0
  466. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,104 @@
1
+ """
2
+ start_background_process tool - Start long-running processes.
3
+
4
+ Starts processes like servers (yarn dev, uvicorn) in the background
5
+ and returns immediately with a process ID for later reference.
6
+ """
7
+
8
+ import logging
9
+ from typing import TYPE_CHECKING, Optional
10
+
11
+ from autobyteus.tools import tool
12
+ from autobyteus.tools.tool_category import ToolCategory
13
+
14
+ if TYPE_CHECKING:
15
+ from autobyteus.agent.context import AgentContext
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ def _get_background_manager(context: Optional['AgentContext']):
21
+ """Get or create the background process manager for this agent.
22
+
23
+ Args:
24
+ context: The agent context.
25
+
26
+ Returns:
27
+ BackgroundProcessManager instance.
28
+ """
29
+ from autobyteus.tools.terminal.background_process_manager import BackgroundProcessManager
30
+
31
+ if context is None:
32
+ if not hasattr(_get_background_manager, '_default_manager'):
33
+ _get_background_manager._default_manager = BackgroundProcessManager()
34
+ return _get_background_manager._default_manager
35
+
36
+ if not hasattr(context, '_background_process_manager'):
37
+ context._background_process_manager = BackgroundProcessManager()
38
+
39
+ return context._background_process_manager
40
+
41
+
42
+ def _get_cwd(context: Optional['AgentContext']) -> str:
43
+ """Get the working directory for the process.
44
+
45
+ Args:
46
+ context: The agent context.
47
+
48
+ Returns:
49
+ Working directory path.
50
+ """
51
+ import tempfile
52
+
53
+ if context and hasattr(context, 'workspace') and context.workspace:
54
+ try:
55
+ base_path = context.workspace.get_base_path()
56
+ if base_path and isinstance(base_path, str):
57
+ return base_path
58
+ except Exception:
59
+ pass
60
+
61
+ return tempfile.gettempdir()
62
+
63
+
64
+ @tool(name="start_background_process", category=ToolCategory.SYSTEM)
65
+ async def start_background_process(
66
+ context: Optional['AgentContext'],
67
+ command: str
68
+ ) -> dict:
69
+ """
70
+ Start a long-running process in the background.
71
+
72
+ Use this for servers, watchers, or any process that doesn't
73
+ terminate immediately. The process runs independently and
74
+ you can check its output or stop it later using the returned
75
+ process_id.
76
+
77
+ Args:
78
+ command: The command to run in background.
79
+ Examples: "yarn dev", "uvicorn main:app", "npm start"
80
+
81
+ Returns:
82
+ dict with:
83
+ - process_id: ID to reference this process later
84
+ - status: "started"
85
+
86
+ Examples:
87
+ - start_background_process("yarn dev")
88
+ - start_background_process("uvicorn app:main --reload")
89
+ - start_background_process("python -m http.server 8000")
90
+
91
+ After starting, use:
92
+ - get_process_output(process_id) to check output
93
+ - stop_background_process(process_id) to stop it
94
+ """
95
+ manager = _get_background_manager(context)
96
+ cwd = _get_cwd(context)
97
+
98
+ logger.info(f"Starting background process: {command}")
99
+ process_id = await manager.start_process(command, cwd)
100
+
101
+ return {
102
+ "process_id": process_id,
103
+ "status": "started"
104
+ }
@@ -0,0 +1,67 @@
1
+ """
2
+ stop_background_process tool - Stop background processes.
3
+
4
+ Terminates a background process started with start_background_process.
5
+ """
6
+
7
+ import logging
8
+ from typing import TYPE_CHECKING, Optional
9
+
10
+ from autobyteus.tools import tool
11
+ from autobyteus.tools.tool_category import ToolCategory
12
+
13
+ if TYPE_CHECKING:
14
+ from autobyteus.agent.context import AgentContext
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ def _get_background_manager(context: Optional['AgentContext']):
20
+ """Get the background process manager for this agent."""
21
+ from autobyteus.tools.terminal.background_process_manager import BackgroundProcessManager
22
+
23
+ if context is None:
24
+ if not hasattr(_get_background_manager, '_default_manager'):
25
+ _get_background_manager._default_manager = BackgroundProcessManager()
26
+ return _get_background_manager._default_manager
27
+
28
+ if not hasattr(context, '_background_process_manager'):
29
+ context._background_process_manager = BackgroundProcessManager()
30
+
31
+ return context._background_process_manager
32
+
33
+
34
+ @tool(name="stop_background_process", category=ToolCategory.SYSTEM)
35
+ async def stop_background_process(
36
+ context: Optional['AgentContext'],
37
+ process_id: str
38
+ ) -> dict:
39
+ """
40
+ Stop a background process.
41
+
42
+ Terminates a process that was started with start_background_process.
43
+ Sends SIGTERM first for graceful shutdown, then SIGKILL if the
44
+ process doesn't terminate.
45
+
46
+ Args:
47
+ process_id: ID of the process to stop.
48
+
49
+ Returns:
50
+ dict with:
51
+ - status: "stopped" if process was found and stopped,
52
+ "not_found" if process ID doesn't exist
53
+ - process_id: The process identifier
54
+
55
+ Examples:
56
+ - Stop a dev server when done testing
57
+ - Clean up processes before shutting down
58
+ """
59
+ manager = _get_background_manager(context)
60
+
61
+ logger.info(f"Stopping background process: {process_id}")
62
+ success = await manager.stop_process(process_id)
63
+
64
+ return {
65
+ "status": "stopped" if success else "not_found",
66
+ "process_id": process_id
67
+ }
@@ -0,0 +1,54 @@
1
+ """
2
+ Data types for terminal tools.
3
+
4
+ Contains result types returned by terminal operations.
5
+ """
6
+
7
+ from dataclasses import dataclass
8
+ from typing import Optional
9
+
10
+
11
+ @dataclass
12
+ class TerminalResult:
13
+ """Result from run_bash.
14
+
15
+ Attributes:
16
+ stdout: Standard output captured from the command.
17
+ stderr: Standard error captured from the command (may be mixed with stdout in PTY).
18
+ exit_code: Exit code if available, None if not captured.
19
+ timed_out: True if command exceeded timeout.
20
+ """
21
+ stdout: str
22
+ stderr: str
23
+ exit_code: Optional[int]
24
+ timed_out: bool
25
+
26
+
27
+ @dataclass
28
+ class BackgroundProcessOutput:
29
+ """Result from get_process_output.
30
+
31
+ Attributes:
32
+ output: Recent output lines from the process.
33
+ is_running: True if process is still running.
34
+ process_id: The process identifier.
35
+ """
36
+ output: str
37
+ is_running: bool
38
+ process_id: str
39
+
40
+
41
+ @dataclass
42
+ class ProcessInfo:
43
+ """Information about a background process.
44
+
45
+ Attributes:
46
+ process_id: Unique identifier for the process.
47
+ command: The command that was executed.
48
+ started_at: Unix timestamp when process started.
49
+ is_running: True if process is still running.
50
+ """
51
+ process_id: str
52
+ command: str
53
+ started_at: float
54
+ is_running: bool
@@ -0,0 +1,221 @@
1
+ """
2
+ WSL + tmux backed terminal session implementation for Windows.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import asyncio
8
+ import logging
9
+ import os
10
+ import re
11
+ import subprocess
12
+ from typing import Optional
13
+
14
+ from autobyteus.tools.terminal.wsl_utils import (
15
+ ensure_wsl_available,
16
+ ensure_wsl_distro_available,
17
+ select_wsl_distro,
18
+ windows_path_to_wsl,
19
+ )
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class WslTmuxSession:
25
+ """Terminal session backed by WSL + tmux (no pywinpty)."""
26
+
27
+ def __init__(self, session_id: str):
28
+ self._session_id = session_id
29
+ self._closed = False
30
+ self._wsl_exe: Optional[str] = None
31
+ self._distro: Optional[str] = None
32
+ self._session_name: Optional[str] = None
33
+ self._log_path: Optional[str] = None
34
+ self._output_offset = 0
35
+
36
+ @property
37
+ def session_id(self) -> str:
38
+ return self._session_id
39
+
40
+ @property
41
+ def is_alive(self) -> bool:
42
+ return not self._closed
43
+
44
+ async def start(self, cwd: str) -> None:
45
+ if os.name != "nt":
46
+ raise RuntimeError("WslTmuxSession is only supported on Windows.")
47
+ if self._session_name is not None:
48
+ raise RuntimeError("Session already started.")
49
+
50
+ self._wsl_exe = ensure_wsl_available()
51
+ ensure_wsl_distro_available(self._wsl_exe)
52
+ self._distro = select_wsl_distro(self._wsl_exe)
53
+ self._session_name = self._sanitize_session_name(self._session_id)
54
+
55
+ await asyncio.to_thread(self._ensure_tmux_available)
56
+
57
+ wsl_cwd = windows_path_to_wsl(cwd, wsl_exe=self._wsl_exe)
58
+ await asyncio.to_thread(
59
+ self._run_tmux,
60
+ [
61
+ "new-session",
62
+ "-d",
63
+ "-s",
64
+ self._session_name,
65
+ "-c",
66
+ wsl_cwd,
67
+ "-x",
68
+ "120",
69
+ "-y",
70
+ "40",
71
+ "/bin/bash",
72
+ "--noprofile",
73
+ "--norc",
74
+ "-i",
75
+ ],
76
+ )
77
+ await asyncio.to_thread(
78
+ self._run_tmux,
79
+ ["send-keys", "-t", self._session_name, "export PS1='$ '", "C-m"],
80
+ )
81
+ self._log_path = f"/tmp/autobyteus_tmux_{self._session_name}.log"
82
+ await asyncio.to_thread(self._reset_log)
83
+ await asyncio.to_thread(self._start_pipe)
84
+
85
+ logger.info(
86
+ "Started WSL tmux session %s in %s (distro=%s)",
87
+ self._session_name,
88
+ wsl_cwd,
89
+ self._distro,
90
+ )
91
+
92
+ async def write(self, data: bytes) -> None:
93
+ if self._closed:
94
+ raise RuntimeError("Session is closed")
95
+ if self._session_name is None:
96
+ raise RuntimeError("Session not started")
97
+
98
+ text = data.decode("utf-8", errors="replace")
99
+ text = text.replace("\r\n", "\n").replace("\r", "\n")
100
+
101
+ parts = text.split("\n")
102
+ for idx, part in enumerate(parts):
103
+ if part:
104
+ await asyncio.to_thread(
105
+ self._run_tmux,
106
+ ["send-keys", "-t", self._session_name, "-l", part],
107
+ )
108
+ if idx < len(parts) - 1:
109
+ await asyncio.to_thread(
110
+ self._run_tmux,
111
+ ["send-keys", "-t", self._session_name, "C-m"],
112
+ )
113
+
114
+ async def read(self, timeout: float = 0.1) -> Optional[bytes]:
115
+ if self._closed or self._session_name is None:
116
+ return None
117
+ data = await asyncio.to_thread(self._read_log_delta)
118
+ if not data:
119
+ if timeout:
120
+ await asyncio.sleep(timeout)
121
+ return None
122
+ return data
123
+
124
+ def resize(self, rows: int, cols: int) -> None:
125
+ if self._closed or self._session_name is None:
126
+ return
127
+ rows = max(1, int(rows))
128
+ cols = max(1, int(cols))
129
+ try:
130
+ self._run_tmux(
131
+ ["resize-window", "-t", self._session_name, "-x", str(cols), "-y", str(rows)]
132
+ )
133
+ except Exception as exc:
134
+ logger.debug("Failed to resize tmux session %s: %s", self._session_name, exc)
135
+
136
+ async def close(self) -> None:
137
+ if self._closed:
138
+ return
139
+ self._closed = True
140
+ if self._session_name:
141
+ try:
142
+ await asyncio.to_thread(self._stop_pipe)
143
+ await asyncio.to_thread(
144
+ self._run_tmux, ["kill-session", "-t", self._session_name]
145
+ )
146
+ except Exception:
147
+ pass
148
+ self._session_name = None
149
+ self._log_path = None
150
+ self._output_offset = 0
151
+ logger.info("Closed WSL tmux session %s", self._session_id)
152
+
153
+ def _ensure_tmux_available(self) -> None:
154
+ try:
155
+ self._run_wsl_command(["tmux", "-V"], check=True)
156
+ except RuntimeError as exc:
157
+ raise RuntimeError(
158
+ "tmux is required in the WSL distro. Install with `sudo apt install tmux`."
159
+ ) from exc
160
+
161
+ def _run_tmux(self, args: list[str]) -> subprocess.CompletedProcess:
162
+ return self._run_wsl_command(["tmux", *args], check=True)
163
+
164
+ def _reset_log(self) -> None:
165
+ if not self._log_path:
166
+ return
167
+ self._run_wsl_command(["sh", "-c", f"rm -f {self._log_path}; : > {self._log_path}"], check=True)
168
+ self._output_offset = 0
169
+
170
+ def _start_pipe(self) -> None:
171
+ if not self._log_path:
172
+ return
173
+ cmd = f"tmux pipe-pane -o -t {self._session_name}:0.0 'cat >> {self._log_path}'"
174
+ self._run_wsl_command(["sh", "-c", cmd], check=True)
175
+
176
+ def _stop_pipe(self) -> None:
177
+ if not self._session_name:
178
+ return
179
+ self._run_tmux(["pipe-pane", "-t", f"{self._session_name}:0.0"])
180
+
181
+ def _read_log_delta(self) -> bytes:
182
+ if not self._log_path:
183
+ return b""
184
+ cmd = (
185
+ f"if [ -f {self._log_path} ]; then "
186
+ f"dd if={self._log_path} bs=1 skip={self._output_offset} 2>/dev/null; "
187
+ f"fi"
188
+ )
189
+ result = self._run_wsl_command(["sh", "-c", cmd], check=True)
190
+ data = result.stdout or b""
191
+ self._output_offset += len(data)
192
+ return data
193
+
194
+ def _run_wsl_command(self, args: list[str], check: bool) -> subprocess.CompletedProcess:
195
+ if not self._wsl_exe or not self._distro:
196
+ raise RuntimeError("WSL session not initialized.")
197
+ cmd = [self._wsl_exe, "-d", self._distro, "--exec", *args]
198
+ result = subprocess.run(
199
+ cmd,
200
+ capture_output=True,
201
+ text=False,
202
+ check=False,
203
+ timeout=10,
204
+ )
205
+ if check and result.returncode != 0:
206
+ stderr = self._decode_output(result.stderr)
207
+ raise RuntimeError(stderr or "WSL command failed")
208
+ return result
209
+
210
+ @staticmethod
211
+ def _decode_output(raw: bytes) -> str:
212
+ if not raw:
213
+ return ""
214
+ if b"\x00" in raw:
215
+ return raw.decode("utf-16-le", errors="replace")
216
+ return raw.decode("utf-8", errors="replace")
217
+
218
+ @staticmethod
219
+ def _sanitize_session_name(session_id: str) -> str:
220
+ base = re.sub(r"[^a-zA-Z0-9_-]", "_", session_id)
221
+ return f"autobyteus_{base}"
@@ -0,0 +1,156 @@
1
+ """
2
+ WSL utilities for Windows terminal backend.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import pathlib
8
+ import shutil
9
+ import subprocess
10
+ from typing import List, Optional
11
+
12
+
13
+ _WSL_MISSING_MESSAGE = (
14
+ "WSL is not available. Install it with `wsl --install` and reboot, "
15
+ "then ensure a Linux distro is installed."
16
+ )
17
+
18
+
19
+ def find_wsl_executable() -> Optional[str]:
20
+ """Return the path to wsl.exe (preferred) or wsl if available."""
21
+ return shutil.which("wsl.exe") or shutil.which("wsl")
22
+
23
+
24
+ def _decode_wsl_bytes(raw: bytes) -> str:
25
+ """Decode WSL output that may be UTF-16LE on Windows consoles."""
26
+ if not raw:
27
+ return ""
28
+ if b"\x00" in raw:
29
+ return raw.decode("utf-16-le", errors="replace")
30
+ return raw.decode("utf-8", errors="replace")
31
+
32
+
33
+ def ensure_wsl_available() -> str:
34
+ """Return the WSL executable path or raise with guidance."""
35
+ wsl_exe = find_wsl_executable()
36
+ if not wsl_exe:
37
+ raise RuntimeError(_WSL_MISSING_MESSAGE)
38
+ return wsl_exe
39
+
40
+
41
+ def list_wsl_distros(wsl_exe: str) -> List[str]:
42
+ """Return a list of installed WSL distro names."""
43
+ result = subprocess.run(
44
+ [wsl_exe, "-l", "-q"],
45
+ capture_output=True,
46
+ text=False,
47
+ check=False,
48
+ timeout=5,
49
+ )
50
+ if result.returncode != 0:
51
+ return []
52
+ output = _decode_wsl_bytes(result.stdout)
53
+ return [line.strip() for line in output.splitlines() if line.strip()]
54
+
55
+
56
+ def get_default_wsl_distro(wsl_exe: str) -> Optional[str]:
57
+ """Return the default WSL distro name if available."""
58
+ result = subprocess.run(
59
+ [wsl_exe, "-l", "-v"],
60
+ capture_output=True,
61
+ text=False,
62
+ check=False,
63
+ timeout=5,
64
+ )
65
+ if result.returncode != 0:
66
+ return None
67
+ output = _decode_wsl_bytes(result.stdout)
68
+ for line in output.splitlines():
69
+ stripped = line.strip()
70
+ if stripped.startswith("*"):
71
+ parts = stripped.split()
72
+ if len(parts) >= 2:
73
+ return parts[1]
74
+ return None
75
+
76
+
77
+ def select_wsl_distro(wsl_exe: str) -> str:
78
+ """Select a usable WSL distro, preferring non-Docker defaults."""
79
+ distros = list_wsl_distros(wsl_exe)
80
+ if not distros:
81
+ raise RuntimeError(
82
+ "No WSL distro is installed. Run `wsl --install` "
83
+ "or install a distro from the Microsoft Store."
84
+ )
85
+
86
+ default = get_default_wsl_distro(wsl_exe)
87
+ excluded = {"docker-desktop", "docker-desktop-data"}
88
+
89
+ if default and default not in excluded:
90
+ return default
91
+
92
+ for distro in distros:
93
+ if distro and distro not in excluded:
94
+ return distro
95
+
96
+ return default or distros[0]
97
+
98
+
99
+ def ensure_wsl_distro_available(wsl_exe: str) -> None:
100
+ """Raise if no WSL distro is installed."""
101
+ distros = list_wsl_distros(wsl_exe)
102
+ if not distros:
103
+ raise RuntimeError(
104
+ "No WSL distro is installed. Run `wsl --install` "
105
+ "or install a distro from the Microsoft Store."
106
+ )
107
+
108
+
109
+ def _run_wslpath(wsl_exe: str, path: str) -> Optional[str]:
110
+ """Try to convert a Windows path to WSL path via wslpath."""
111
+ result = subprocess.run(
112
+ [wsl_exe, "wslpath", "-a", "-u", path],
113
+ capture_output=True,
114
+ text=False,
115
+ check=False,
116
+ timeout=5,
117
+ )
118
+ if result.returncode != 0:
119
+ return None
120
+ output = _decode_wsl_bytes(result.stdout).strip()
121
+ return output or None
122
+
123
+
124
+ def _manual_windows_path_to_wsl(path: str) -> str:
125
+ """Manual conversion for Windows drive paths to /mnt/<drive>/..."""
126
+ windows_path = pathlib.PureWindowsPath(path)
127
+
128
+ if windows_path.drive:
129
+ drive_letter = windows_path.drive.rstrip(":").lower()
130
+ parts = windows_path.parts[1:] # strip drive
131
+ if parts:
132
+ return f"/mnt/{drive_letter}/" + "/".join(parts)
133
+ return f"/mnt/{drive_letter}"
134
+
135
+ raise ValueError(f"Unsupported Windows path format: {path}")
136
+
137
+
138
+ def windows_path_to_wsl(path: str, wsl_exe: Optional[str] = None) -> str:
139
+ """Convert a Windows path to a WSL path, with wslpath fallback."""
140
+ if not path:
141
+ raise ValueError("Path must be a non-empty string.")
142
+
143
+ if path.startswith("/"):
144
+ return path
145
+
146
+ if path.startswith("\\\\"):
147
+ raise ValueError("UNC paths are not supported for WSL conversion.")
148
+
149
+ if wsl_exe is None:
150
+ wsl_exe = ensure_wsl_available()
151
+
152
+ wslpath = _run_wslpath(wsl_exe, path)
153
+ if wslpath:
154
+ return wslpath
155
+
156
+ return _manual_windows_path_to_wsl(path)
@@ -0,0 +1,48 @@
1
+ """
2
+ File: tools/coordinator/backup_handler.py
3
+
4
+ Module for handling backups of files during transactional operations.
5
+
6
+ This module provides functionalities to create backups before file
7
+ operations and restore them if needed. The BackupHandler class interacts
8
+ with the BackupLogger to log backup activities.
9
+ """
10
+
11
+ import os
12
+ import shutil
13
+
14
+
15
+ class BackupHandler:
16
+
17
+ def _backup_filename(self, transaction_id: str, filepath: str) -> str:
18
+ """Generate a backup filename based on transaction_id and original filename."""
19
+ dir_name, file_name = os.path.split(filepath)
20
+ backup_name = f"{transaction_id}_backup_{file_name}"
21
+ return os.path.join(dir_name, backup_name)
22
+
23
+ def create_backup(self, transaction_id: str, filepath: str) -> None:
24
+ """
25
+ Create a backup of the given file for the provided transaction_id.
26
+
27
+ Args:
28
+ transaction_id (str): The ID of the current transaction.
29
+ filepath (str): Path to the file that needs to be backed up.
30
+ """
31
+ backup_path = self._backup_filename(transaction_id, filepath)
32
+ shutil.copy2(filepath, backup_path) # Copying file to its backup location.
33
+ self.logger.log_backup_activity(f"Backup created for {filepath} at {backup_path}")
34
+
35
+ def restore_backup(self, transaction_id: str, filepath: str) -> None:
36
+ """
37
+ Restore a file from its backup for the given transaction_id.
38
+
39
+ Args:
40
+ transaction_id (str): The ID of the current transaction.
41
+ filepath (str): Path to the original file that needs to be restored.
42
+ """
43
+ backup_path = self._backup_filename(transaction_id, filepath)
44
+ if os.path.exists(backup_path):
45
+ shutil.move(backup_path, filepath) # Restoring original file from backup.
46
+ self.logger.log_backup_activity(f"Backup at {backup_path} restored to {filepath}")
47
+ else:
48
+ self.logger.log_backup_activity(f"No backup found for {filepath} for transaction {transaction_id}")