autobyteus 1.2.0__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 (512) 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 +23 -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 +74 -60
  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/message/send_message_to.py +5 -4
  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 -178
  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 +81 -0
  114. autobyteus/agent/streaming/stream_event_payloads.py +2 -198
  115. autobyteus/agent/streaming/stream_events.py +3 -128
  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 +5 -6
  145. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +15 -15
  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 +11 -8
  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 +10 -10
  167. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +7 -7
  168. autobyteus/agent_team/streaming/agent_team_stream_events.py +11 -11
  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/activation_policy.py +1 -1
  172. autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +22 -22
  173. autobyteus/agent_team/task_notification/task_notification_mode.py +20 -1
  174. autobyteus/agent_team/utils/wait_for_idle.py +4 -4
  175. autobyteus/cli/agent_cli.py +18 -10
  176. autobyteus/cli/agent_team_tui/app.py +18 -15
  177. autobyteus/cli/agent_team_tui/state.py +21 -23
  178. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
  179. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +146 -39
  180. autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
  181. autobyteus/cli/agent_team_tui/widgets/shared.py +26 -26
  182. autobyteus/cli/agent_team_tui/widgets/{task_board_panel.py → task_plan_panel.py} +5 -5
  183. autobyteus/cli/cli_display.py +193 -44
  184. autobyteus/cli/workflow_tui/app.py +9 -10
  185. autobyteus/cli/workflow_tui/state.py +14 -16
  186. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
  187. autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
  188. autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
  189. autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
  190. autobyteus/clients/autobyteus_client.py +94 -1
  191. autobyteus/events/event_types.py +15 -21
  192. autobyteus/llm/api/autobyteus_llm.py +33 -29
  193. autobyteus/llm/api/claude_llm.py +142 -36
  194. autobyteus/llm/api/gemini_llm.py +163 -59
  195. autobyteus/llm/api/grok_llm.py +1 -1
  196. autobyteus/llm/api/minimax_llm.py +26 -0
  197. autobyteus/llm/api/mistral_llm.py +113 -87
  198. autobyteus/llm/api/ollama_llm.py +9 -42
  199. autobyteus/llm/api/openai_compatible_llm.py +127 -91
  200. autobyteus/llm/api/openai_llm.py +3 -3
  201. autobyteus/llm/api/openai_responses_llm.py +324 -0
  202. autobyteus/llm/api/zhipu_llm.py +21 -2
  203. autobyteus/llm/autobyteus_provider.py +70 -60
  204. autobyteus/llm/base_llm.py +85 -81
  205. autobyteus/llm/converters/__init__.py +14 -0
  206. autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
  207. autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
  208. autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
  209. autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
  210. autobyteus/llm/extensions/base_extension.py +6 -12
  211. autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
  212. autobyteus/llm/llm_factory.py +282 -204
  213. autobyteus/llm/lmstudio_provider.py +60 -49
  214. autobyteus/llm/models.py +35 -2
  215. autobyteus/llm/ollama_provider.py +60 -49
  216. autobyteus/llm/ollama_provider_resolver.py +0 -1
  217. autobyteus/llm/prompt_renderers/__init__.py +19 -0
  218. autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
  219. autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
  220. autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
  221. autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
  222. autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
  223. autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
  224. autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
  225. autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
  226. autobyteus/llm/providers.py +1 -3
  227. autobyteus/llm/token_counter/claude_token_counter.py +56 -25
  228. autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
  229. autobyteus/llm/token_counter/openai_token_counter.py +24 -5
  230. autobyteus/llm/token_counter/token_counter_factory.py +12 -5
  231. autobyteus/llm/utils/llm_config.py +6 -12
  232. autobyteus/llm/utils/media_payload_formatter.py +27 -20
  233. autobyteus/llm/utils/messages.py +55 -3
  234. autobyteus/llm/utils/response_types.py +3 -0
  235. autobyteus/llm/utils/tool_call_delta.py +31 -0
  236. autobyteus/memory/__init__.py +32 -0
  237. autobyteus/memory/active_transcript.py +69 -0
  238. autobyteus/memory/compaction/__init__.py +9 -0
  239. autobyteus/memory/compaction/compaction_result.py +8 -0
  240. autobyteus/memory/compaction/compactor.py +89 -0
  241. autobyteus/memory/compaction/summarizer.py +11 -0
  242. autobyteus/memory/compaction_snapshot_builder.py +84 -0
  243. autobyteus/memory/memory_manager.py +183 -0
  244. autobyteus/memory/models/__init__.py +14 -0
  245. autobyteus/memory/models/episodic_item.py +41 -0
  246. autobyteus/memory/models/memory_types.py +7 -0
  247. autobyteus/memory/models/raw_trace_item.py +79 -0
  248. autobyteus/memory/models/semantic_item.py +41 -0
  249. autobyteus/memory/models/tool_interaction.py +20 -0
  250. autobyteus/memory/policies/__init__.py +5 -0
  251. autobyteus/memory/policies/compaction_policy.py +16 -0
  252. autobyteus/memory/retrieval/__init__.py +7 -0
  253. autobyteus/memory/retrieval/memory_bundle.py +11 -0
  254. autobyteus/memory/retrieval/retriever.py +13 -0
  255. autobyteus/memory/store/__init__.py +7 -0
  256. autobyteus/memory/store/base_store.py +14 -0
  257. autobyteus/memory/store/file_store.py +98 -0
  258. autobyteus/memory/tool_interaction_builder.py +46 -0
  259. autobyteus/memory/turn_tracker.py +9 -0
  260. autobyteus/multimedia/audio/api/__init__.py +3 -2
  261. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
  262. autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
  263. autobyteus/multimedia/audio/api/openai_audio_client.py +112 -0
  264. autobyteus/multimedia/audio/audio_client_factory.py +84 -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 +38 -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/__init__.py +43 -20
  277. autobyteus/task_management/{base_task_board.py → base_task_plan.py} +16 -13
  278. autobyteus/task_management/converters/__init__.py +2 -2
  279. autobyteus/task_management/converters/{task_board_converter.py → task_plan_converter.py} +13 -13
  280. autobyteus/task_management/events.py +7 -7
  281. autobyteus/task_management/{in_memory_task_board.py → in_memory_task_plan.py} +34 -22
  282. autobyteus/task_management/schemas/__init__.py +3 -0
  283. autobyteus/task_management/schemas/task_status_report.py +2 -2
  284. autobyteus/task_management/schemas/todo_definition.py +15 -0
  285. autobyteus/task_management/todo.py +29 -0
  286. autobyteus/task_management/todo_list.py +75 -0
  287. autobyteus/task_management/tools/__init__.py +24 -8
  288. autobyteus/task_management/tools/task_tools/__init__.py +19 -0
  289. autobyteus/task_management/tools/{assign_task_to.py → task_tools/assign_task_to.py} +18 -18
  290. autobyteus/task_management/tools/{publish_task.py → task_tools/create_task.py} +16 -18
  291. autobyteus/task_management/tools/{publish_tasks.py → task_tools/create_tasks.py} +19 -19
  292. autobyteus/task_management/tools/{get_my_tasks.py → task_tools/get_my_tasks.py} +15 -15
  293. autobyteus/task_management/tools/{get_task_board_status.py → task_tools/get_task_plan_status.py} +16 -16
  294. autobyteus/task_management/tools/{update_task_status.py → task_tools/update_task_status.py} +16 -16
  295. autobyteus/task_management/tools/todo_tools/__init__.py +18 -0
  296. autobyteus/task_management/tools/todo_tools/add_todo.py +78 -0
  297. autobyteus/task_management/tools/todo_tools/create_todo_list.py +79 -0
  298. autobyteus/task_management/tools/todo_tools/get_todo_list.py +55 -0
  299. autobyteus/task_management/tools/todo_tools/update_todo_status.py +85 -0
  300. autobyteus/tools/__init__.py +43 -52
  301. autobyteus/tools/base_tool.py +7 -0
  302. autobyteus/tools/file/__init__.py +9 -0
  303. autobyteus/tools/file/patch_file.py +149 -0
  304. autobyteus/tools/file/{file_reader.py → read_file.py} +38 -7
  305. autobyteus/tools/file/{file_writer.py → write_file.py} +7 -4
  306. autobyteus/tools/functional_tool.py +53 -14
  307. autobyteus/tools/mcp/__init__.py +2 -0
  308. autobyteus/tools/mcp/config_service.py +5 -1
  309. autobyteus/tools/mcp/server/__init__.py +2 -0
  310. autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
  311. autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
  312. autobyteus/tools/mcp/server_instance_manager.py +8 -1
  313. autobyteus/tools/mcp/tool.py +3 -3
  314. autobyteus/tools/mcp/tool_registrar.py +5 -2
  315. autobyteus/tools/mcp/types.py +61 -0
  316. autobyteus/tools/multimedia/__init__.py +2 -1
  317. autobyteus/tools/multimedia/audio_tools.py +72 -19
  318. autobyteus/tools/{download_media_tool.py → multimedia/download_media_tool.py} +21 -7
  319. autobyteus/tools/multimedia/image_tools.py +248 -64
  320. autobyteus/tools/multimedia/media_reader_tool.py +1 -1
  321. autobyteus/tools/operation_executor/journal_manager.py +107 -0
  322. autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
  323. autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
  324. autobyteus/tools/operation_executor/operation_executor.py +58 -0
  325. autobyteus/tools/registry/tool_definition.py +108 -14
  326. autobyteus/tools/registry/tool_registry.py +29 -0
  327. autobyteus/tools/search/__init__.py +17 -0
  328. autobyteus/tools/search/base_strategy.py +35 -0
  329. autobyteus/tools/search/client.py +24 -0
  330. autobyteus/tools/search/factory.py +81 -0
  331. autobyteus/tools/search/google_cse_strategy.py +68 -0
  332. autobyteus/tools/search/providers.py +10 -0
  333. autobyteus/tools/search/serpapi_strategy.py +65 -0
  334. autobyteus/tools/search/serper_strategy.py +87 -0
  335. autobyteus/tools/search_tool.py +83 -0
  336. autobyteus/tools/skill/load_skill.py +50 -0
  337. autobyteus/tools/terminal/__init__.py +45 -0
  338. autobyteus/tools/terminal/ansi_utils.py +32 -0
  339. autobyteus/tools/terminal/background_process_manager.py +233 -0
  340. autobyteus/tools/terminal/output_buffer.py +105 -0
  341. autobyteus/tools/terminal/prompt_detector.py +63 -0
  342. autobyteus/tools/terminal/pty_session.py +241 -0
  343. autobyteus/tools/terminal/session_factory.py +20 -0
  344. autobyteus/tools/terminal/terminal_session_manager.py +226 -0
  345. autobyteus/tools/terminal/tools/__init__.py +13 -0
  346. autobyteus/tools/terminal/tools/get_process_output.py +81 -0
  347. autobyteus/tools/terminal/tools/run_bash.py +109 -0
  348. autobyteus/tools/terminal/tools/start_background_process.py +104 -0
  349. autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
  350. autobyteus/tools/terminal/types.py +54 -0
  351. autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
  352. autobyteus/tools/terminal/wsl_utils.py +156 -0
  353. autobyteus/tools/tool_meta.py +4 -24
  354. autobyteus/tools/transaction_management/backup_handler.py +48 -0
  355. autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
  356. autobyteus/tools/usage/__init__.py +1 -2
  357. autobyteus/tools/usage/formatters/__init__.py +17 -1
  358. autobyteus/tools/usage/formatters/base_formatter.py +8 -0
  359. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
  360. autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
  361. autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
  362. autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
  363. autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
  364. autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
  365. autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
  366. autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
  367. autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
  368. autobyteus/tools/usage/registries/__init__.py +1 -3
  369. autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
  370. autobyteus/tools/usage/tool_schema_provider.py +51 -0
  371. autobyteus/tools/web/__init__.py +4 -0
  372. autobyteus/tools/web/read_url_tool.py +80 -0
  373. autobyteus/utils/diff_utils.py +271 -0
  374. autobyteus/utils/download_utils.py +109 -0
  375. autobyteus/utils/file_utils.py +57 -2
  376. autobyteus/utils/gemini_helper.py +56 -0
  377. autobyteus/utils/gemini_model_mapping.py +71 -0
  378. autobyteus/utils/llm_output_formatter.py +75 -0
  379. autobyteus/utils/tool_call_format.py +36 -0
  380. autobyteus/workflow/agentic_workflow.py +3 -3
  381. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
  382. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
  383. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
  384. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +4 -11
  385. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
  386. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
  387. autobyteus/workflow/context/workflow_context.py +3 -3
  388. autobyteus/workflow/context/workflow_runtime_state.py +5 -5
  389. autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
  390. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
  391. autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
  392. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
  393. autobyteus/workflow/runtime/workflow_runtime.py +8 -8
  394. autobyteus/workflow/runtime/workflow_worker.py +3 -3
  395. autobyteus/workflow/status/__init__.py +11 -0
  396. autobyteus/workflow/status/workflow_status.py +19 -0
  397. autobyteus/workflow/status/workflow_status_manager.py +48 -0
  398. autobyteus/workflow/streaming/__init__.py +2 -2
  399. autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
  400. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
  401. autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
  402. autobyteus/workflow/utils/wait_for_idle.py +4 -4
  403. autobyteus-1.2.3.dist-info/METADATA +293 -0
  404. autobyteus-1.2.3.dist-info/RECORD +600 -0
  405. {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
  406. {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/top_level.txt +0 -1
  407. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
  408. autobyteus/agent/hooks/__init__.py +0 -16
  409. autobyteus/agent/hooks/base_phase_hook.py +0 -78
  410. autobyteus/agent/hooks/hook_definition.py +0 -36
  411. autobyteus/agent/hooks/hook_meta.py +0 -37
  412. autobyteus/agent/hooks/hook_registry.py +0 -106
  413. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
  414. autobyteus/agent/phases/__init__.py +0 -18
  415. autobyteus/agent/phases/discover.py +0 -53
  416. autobyteus/agent/phases/manager.py +0 -265
  417. autobyteus/agent/phases/transition_decorator.py +0 -40
  418. autobyteus/agent/phases/transition_info.py +0 -33
  419. autobyteus/agent/remote_agent.py +0 -244
  420. autobyteus/agent/workspace/workspace_definition.py +0 -36
  421. autobyteus/agent/workspace/workspace_meta.py +0 -37
  422. autobyteus/agent/workspace/workspace_registry.py +0 -72
  423. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
  424. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
  425. autobyteus/agent_team/phases/__init__.py +0 -11
  426. autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
  427. autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
  428. autobyteus/llm/api/bedrock_llm.py +0 -92
  429. autobyteus/llm/api/groq_llm.py +0 -94
  430. autobyteus/llm/api/nvidia_llm.py +0 -108
  431. autobyteus/llm/utils/token_pricing_config.py +0 -87
  432. autobyteus/person/examples/sample_persons.py +0 -14
  433. autobyteus/person/examples/sample_roles.py +0 -14
  434. autobyteus/person/person.py +0 -29
  435. autobyteus/person/role.py +0 -14
  436. autobyteus/rpc/__init__.py +0 -73
  437. autobyteus/rpc/client/__init__.py +0 -17
  438. autobyteus/rpc/client/abstract_client_connection.py +0 -124
  439. autobyteus/rpc/client/client_connection_manager.py +0 -153
  440. autobyteus/rpc/client/sse_client_connection.py +0 -306
  441. autobyteus/rpc/client/stdio_client_connection.py +0 -280
  442. autobyteus/rpc/config/__init__.py +0 -13
  443. autobyteus/rpc/config/agent_server_config.py +0 -153
  444. autobyteus/rpc/config/agent_server_registry.py +0 -152
  445. autobyteus/rpc/hosting.py +0 -244
  446. autobyteus/rpc/protocol.py +0 -244
  447. autobyteus/rpc/server/__init__.py +0 -20
  448. autobyteus/rpc/server/agent_server_endpoint.py +0 -181
  449. autobyteus/rpc/server/base_method_handler.py +0 -40
  450. autobyteus/rpc/server/method_handlers.py +0 -259
  451. autobyteus/rpc/server/sse_server_handler.py +0 -182
  452. autobyteus/rpc/server/stdio_server_handler.py +0 -151
  453. autobyteus/rpc/server_main.py +0 -198
  454. autobyteus/rpc/transport_type.py +0 -13
  455. autobyteus/tools/bash/__init__.py +0 -2
  456. autobyteus/tools/bash/bash_executor.py +0 -100
  457. autobyteus/tools/browser/__init__.py +0 -2
  458. autobyteus/tools/browser/session_aware/__init__.py +0 -0
  459. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
  460. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
  461. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
  462. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
  463. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
  464. autobyteus/tools/browser/session_aware/factory/__init__.py +0 -0
  465. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
  466. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
  467. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
  468. autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
  469. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
  470. autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
  471. autobyteus/tools/browser/standalone/__init__.py +0 -6
  472. autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  473. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
  474. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
  475. autobyteus/tools/browser/standalone/navigate_to.py +0 -80
  476. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -97
  477. autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -165
  478. autobyteus/tools/browser/standalone/webpage_reader.py +0 -101
  479. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -101
  480. autobyteus/tools/file/file_editor.py +0 -200
  481. autobyteus/tools/google_search.py +0 -149
  482. autobyteus/tools/timer.py +0 -171
  483. autobyteus/tools/usage/parsers/__init__.py +0 -22
  484. autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
  485. autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
  486. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
  487. autobyteus/tools/usage/parsers/base_parser.py +0 -41
  488. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
  489. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
  490. autobyteus/tools/usage/parsers/exceptions.py +0 -13
  491. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
  492. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
  493. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
  494. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
  495. autobyteus/workflow/phases/__init__.py +0 -11
  496. autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
  497. autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
  498. autobyteus-1.2.0.dist-info/METADATA +0 -205
  499. autobyteus-1.2.0.dist-info/RECORD +0 -496
  500. examples/__init__.py +0 -1
  501. examples/agent_team/__init__.py +0 -1
  502. examples/discover_phase_transitions.py +0 -104
  503. examples/run_browser_agent.py +0 -262
  504. examples/run_google_slides_agent.py +0 -287
  505. examples/run_mcp_browser_client.py +0 -174
  506. examples/run_mcp_google_slides_client.py +0 -270
  507. examples/run_mcp_list_tools.py +0 -189
  508. examples/run_poem_writer.py +0 -284
  509. examples/run_sqlite_agent.py +0 -295
  510. /autobyteus/{person → skills}/__init__.py +0 -0
  511. /autobyteus/{person/examples → tools/skill}/__init__.py +0 -0
  512. {autobyteus-1.2.0.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)
@@ -35,26 +35,8 @@ class ToolMeta(ABCMeta):
35
35
  logger.error(f"Tool class {name} ({tool_name}) must return a valid string from get_description(). Skipping registration.")
36
36
  return
37
37
 
38
- argument_schema: ParameterSchema = None
39
- try:
40
- argument_schema = cls.get_argument_schema()
41
- if argument_schema is not None and not isinstance(argument_schema, ParameterSchema):
42
- logger.error(f"Tool class {name} ({tool_name}) get_argument_schema() must return a ParameterSchema or None. Got {type(argument_schema)}. Skipping registration.")
43
- return
44
- except Exception as e:
45
- logger.error(f"Tool class {name} ({tool_name}) failed to provide argument_schema via get_argument_schema(): {e}. Skipping registration.", exc_info=True)
46
- return
38
+ # Note: We do not call the schema methods here. We pass them as providers.
47
39
 
48
- instantiation_config_schema: ParameterSchema = None
49
- if hasattr(cls, 'get_config_schema'):
50
- try:
51
- instantiation_config_schema = cls.get_config_schema()
52
- if instantiation_config_schema is not None and not isinstance(instantiation_config_schema, ParameterSchema):
53
- logger.warning(f"Tool class {name} ({tool_name}) get_config_schema() returned non-ParameterSchema type: {type(instantiation_config_schema)}. Treating as no config schema.")
54
- instantiation_config_schema = None
55
- except Exception as e:
56
- logger.warning(f"Tool class {name} ({tool_name}) has get_config_schema() but it failed: {e}. Assuming no instantiation config.")
57
-
58
40
  # Get category from class attribute, defaulting to "General"
59
41
  category_str = getattr(cls, 'CATEGORY', ToolCategory.GENERAL)
60
42
 
@@ -64,16 +46,14 @@ class ToolMeta(ABCMeta):
64
46
  description=general_description,
65
47
  tool_class=cls,
66
48
  custom_factory=None,
67
- argument_schema=argument_schema,
68
- config_schema=instantiation_config_schema,
49
+ argument_schema_provider=cls.get_argument_schema,
50
+ config_schema_provider=cls.get_config_schema,
69
51
  origin=ToolOrigin.LOCAL,
70
52
  category=category_str
71
53
  )
72
54
  default_tool_registry.register_tool(definition)
73
55
 
74
- arg_schema_info = f"args: {len(argument_schema) if argument_schema else '0'}"
75
- config_info = f"inst_config: {len(instantiation_config_schema) if instantiation_config_schema else '0'}"
76
- logger.info(f"Auto-registered tool: '{tool_name}' from class {name} ({arg_schema_info}, {config_info})")
56
+ logger.info(f"Auto-registered tool: '{tool_name}' from class {name}")
77
57
 
78
58
  except AttributeError as e:
79
59
  logger.error(f"Tool class {name} is missing a required method ({e}). Skipping registration.")