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
@@ -15,23 +15,35 @@ from .tool_config import ToolConfig # Configuration data object, primarily for c
15
15
  from .tool_origin import ToolOrigin
16
16
  from .tool_category import ToolCategory
17
17
 
18
+ # Tool Formatting Registration Support
19
+ # Tool Formatting Registration Support
20
+ from autobyteus.tools.usage.registries.tool_formatting_registry import ToolFormattingRegistry, register_tool_formatter
21
+ from autobyteus.tools.usage.registries.tool_formatter_pair import ToolFormatterPair
22
+ from autobyteus.tools.usage.formatters.base_formatter import BaseSchemaFormatter, BaseExampleFormatter
23
+
24
+
18
25
  logger = logging.getLogger(__name__)
19
26
 
20
27
  # --- Re-export specific tools for easier access ---
21
28
 
22
29
  # Functional tools (decorated functions are now instances)
23
- from .bash.bash_executor import bash_executor
24
- from .file.file_reader import file_reader
25
- from .file.file_writer import file_writer
26
- from .file.file_editor import file_edit
30
+ from .file.read_file import read_file
31
+ from .file.write_file import write_file
32
+ from .file.patch_file import patch_file
33
+ from .skill.load_skill import load_skill
34
+
35
+ # Terminal tools (PTY-based stateful terminal)
36
+ from .terminal.tools.run_bash import run_bash
37
+ from .terminal.tools.start_background_process import start_background_process
38
+ from .terminal.tools.get_process_output import get_process_output
39
+ from .terminal.tools.stop_background_process import stop_background_process
27
40
 
28
41
  # General Class-based tools
29
42
  try:
30
- from .google_search import GoogleSearch
43
+ from .search_tool import Search
31
44
  except ModuleNotFoundError as import_err:
32
- logger.warning("GoogleSearch tool not available: %s", import_err)
33
- GoogleSearch = None
34
- from .timer import Timer
45
+ logger.warning("Search tool not available: %s", import_err)
46
+ Search = None
35
47
  try:
36
48
  from .multimedia.image_tools import GenerateImageTool, EditImageTool
37
49
  except ModuleNotFoundError as import_err:
@@ -44,38 +56,19 @@ except ModuleNotFoundError as import_err:
44
56
  logger.warning("Media reader tool not available: %s", import_err)
45
57
  ReadMediaFile = None
46
58
  try:
47
- from .download_media_tool import DownloadMediaTool
59
+ from autobyteus.multimedia.download_media_tool import DownloadMediaTool
48
60
  except ModuleNotFoundError as import_err:
49
61
  logger.warning("Download media tool not available: %s", import_err)
50
62
  DownloadMediaTool = None
51
63
 
52
- # Standalone Browser tools
53
- try:
54
- from .browser.standalone.navigate_to import NavigateTo as StandaloneNavigateTo # Alias to avoid name clash
55
- from .browser.standalone.webpage_reader import WebPageReader as StandaloneWebPageReader # Alias
56
- from .browser.standalone.webpage_screenshot_taker import WebPageScreenshotTaker as StandaloneWebPageScreenshotTaker # Alias
57
- from .browser.standalone.webpage_image_downloader import WebPageImageDownloader
58
- from .browser.standalone.web_page_pdf_generator import WebPagePDFGenerator
59
- except ModuleNotFoundError as import_err:
60
- logger.warning('Standalone browser tools not available: %s', import_err)
61
- StandaloneNavigateTo = None
62
- StandaloneWebPageReader = None
63
- StandaloneWebPageScreenshotTaker = None
64
- WebPageImageDownloader = None
65
- WebPagePDFGenerator = None
66
-
67
- # Session-Aware Browser tools
64
+ # Web tools
68
65
  try:
69
- from .browser.session_aware.browser_session_aware_navigate_to import BrowserSessionAwareNavigateTo
70
- from .browser.session_aware.browser_session_aware_web_element_trigger import BrowserSessionAwareWebElementTrigger
71
- from .browser.session_aware.browser_session_aware_webpage_reader import BrowserSessionAwareWebPageReader
72
- from .browser.session_aware.browser_session_aware_webpage_screenshot_taker import BrowserSessionAwareWebPageScreenshotTaker
66
+ from .web.read_url_tool import ReadUrl
73
67
  except ModuleNotFoundError as import_err:
74
- logger.warning('Session-aware browser tools not available: %s', import_err)
75
- BrowserSessionAwareNavigateTo = None
76
- BrowserSessionAwareWebElementTrigger = None
77
- BrowserSessionAwareWebPageReader = None
78
- BrowserSessionAwareWebPageScreenshotTaker = None
68
+ logger.warning("ReadUrl tool not available: %s", import_err)
69
+ ReadUrl = None
70
+
71
+
79
72
 
80
73
 
81
74
  __all__ = [
@@ -90,29 +83,27 @@ __all__ = [
90
83
  "ToolCategory",
91
84
 
92
85
  # Re-exported functional tool instances
93
- "bash_executor",
94
- "file_reader",
95
- "file_writer",
96
- "file_edit",
86
+ "run_bash",
87
+ "start_background_process",
88
+ "get_process_output",
89
+ "stop_background_process",
90
+ "read_file",
91
+ "write_file",
92
+ "patch_file",
93
+ "load_skill",
97
94
 
98
95
  # Re-exported general class-based tools
99
- "GoogleSearch",
100
- "Timer",
96
+ "Search",
101
97
  "GenerateImageTool",
102
98
  "EditImageTool",
103
99
  "ReadMediaFile",
104
100
  "DownloadMediaTool",
105
101
 
106
- # Re-exported Standalone Browser tools
107
- "StandaloneNavigateTo",
108
- "StandaloneWebPageReader",
109
- "StandaloneWebPageScreenshotTaker",
110
- "WebPageImageDownloader",
111
- "WebPagePDFGenerator",
112
-
113
- # Re-exported Session-Aware Browser tools
114
- "BrowserSessionAwareNavigateTo",
115
- "BrowserSessionAwareWebElementTrigger",
116
- "BrowserSessionAwareWebPageReader",
117
- "BrowserSessionAwareWebPageScreenshotTaker",
102
+ # Re-exported Web tools
103
+ "ReadUrl",
104
+
105
+ # Tool Formatting
106
+ "register_tool_formatter",
107
+ "BaseSchemaFormatter",
108
+ "BaseExampleFormatter",
118
109
  ]
@@ -174,6 +174,13 @@ class BaseTool(ABC, EventEmitter, metaclass=ToolMeta):
174
174
  async def _execute(self, context: 'AgentContext', **kwargs) -> Any:
175
175
  raise NotImplementedError("Subclasses must implement the '_execute' method.")
176
176
 
177
+ async def cleanup(self) -> None:
178
+ """
179
+ Lifecycle hook invoked during agent shutdown to release resources held by the tool.
180
+ Default implementation is a no-op.
181
+ """
182
+ return None
183
+
177
184
  @classmethod
178
185
  def tool_usage(cls) -> str:
179
186
  logger.warning("BaseTool.tool_usage() is deprecated. Tool usage is now generated by formatters.")
@@ -0,0 +1,9 @@
1
+ from .patch_file import patch_file
2
+ from .read_file import read_file
3
+ from .write_file import write_file
4
+
5
+ __all__ = [
6
+ "patch_file",
7
+ "read_file",
8
+ "write_file",
9
+ ]
@@ -0,0 +1,149 @@
1
+ import os
2
+ import logging
3
+ from typing import TYPE_CHECKING, List
4
+
5
+ from pydantic import Field
6
+
7
+ from autobyteus.tools.functional_tool import tool
8
+ from autobyteus.tools.tool_category import ToolCategory
9
+ from autobyteus.utils.diff_utils import apply_unified_diff, PatchApplicationError
10
+
11
+ if TYPE_CHECKING:
12
+ from autobyteus.agent.context import AgentContext
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ def _resolve_file_path(context: 'AgentContext', path: str) -> str:
18
+ """Resolves an absolute path for the given input, using the agent workspace when needed."""
19
+ if os.path.isabs(path):
20
+ final_path = path
21
+ logger.debug("patch_file: provided path '%s' is absolute.", path)
22
+ else:
23
+ if not context.workspace:
24
+ error_msg = ("Relative path '%s' provided, but no workspace is configured for agent '%s'. "
25
+ "A workspace is required to resolve relative paths.")
26
+ logger.error(error_msg, path, context.agent_id)
27
+ raise ValueError(error_msg % (path, context.agent_id))
28
+ base_path = context.workspace.get_base_path()
29
+ if not base_path or not isinstance(base_path, str):
30
+ error_msg = ("Agent '%s' has a configured workspace, but it provided an invalid base path ('%s'). "
31
+ "Cannot resolve relative path '%s'.")
32
+ logger.error(error_msg, context.agent_id, base_path, path)
33
+ raise ValueError(error_msg % (context.agent_id, base_path, path))
34
+ final_path = os.path.join(base_path, path)
35
+ logger.debug("patch_file: resolved relative path '%s' against workspace base '%s' to '%s'.", path, base_path, final_path)
36
+
37
+ normalized_path = os.path.normpath(final_path)
38
+ logger.debug("patch_file: normalized path to '%s'.", normalized_path)
39
+ return normalized_path
40
+
41
+
42
+ @tool(name="patch_file", category=ToolCategory.FILE_SYSTEM)
43
+ async def patch_file(
44
+ context: 'AgentContext',
45
+ path: str = Field(..., description="Path to the target file."),
46
+ patch: str = Field(
47
+ ...,
48
+ description=(
49
+ "Unified diff hunks describing edits to apply. "
50
+ "Example:\n"
51
+ "--- a/sample.txt\n"
52
+ "+++ b/sample.txt\n"
53
+ "@@ -1,2 +1,2 @@\n"
54
+ "-old line\n"
55
+ "+new line\n"
56
+ " unchanged line"
57
+ ),
58
+ ),
59
+ ) -> str:
60
+ """Applies a unified diff patch to update a text file without overwriting unrelated content.
61
+
62
+ Args:
63
+ path: Path to the target file. Relative paths are resolved against the agent workspace when available.
64
+ patch: Unified diff patch describing the edits to apply.
65
+
66
+ Raises:
67
+ FileNotFoundError: If the file does not exist.
68
+ PatchApplicationError: If the patch content cannot be applied cleanly.
69
+ IOError: If file reading or writing fails.
70
+ """
71
+ logger.debug("patch_file: requested patch for agent '%s' on path '%s'.", context.agent_id, path)
72
+ return_path = os.path.normpath(path)
73
+
74
+ # Detailed logging for debugging patch content
75
+ logger.info("patch_file: ===== PATCH ARGUMENT DEBUG START =====")
76
+ logger.info("patch_file: raw patch repr: %r", patch)
77
+ logger.info("patch_file: patch length: %d chars", len(patch) if patch else 0)
78
+ patch_lines = patch.splitlines(keepends=True) if patch else []
79
+ for i, line in enumerate(patch_lines, 1):
80
+ prefix = line[0] if line else '<empty>'
81
+ logger.info("patch_file: line %d: prefix=%r content=%r", i, prefix, line)
82
+ logger.info("patch_file: ===== PATCH ARGUMENT DEBUG END =====")
83
+
84
+ final_path = _resolve_file_path(context, path)
85
+
86
+ file_exists = os.path.exists(final_path)
87
+ if not file_exists:
88
+ raise FileNotFoundError(f"The file at resolved path {final_path} does not exist.")
89
+
90
+ try:
91
+ original_lines: List[str]
92
+ if file_exists:
93
+ with open(final_path, 'r', encoding='utf-8') as source:
94
+ original_lines = source.read().splitlines(keepends=True)
95
+ else:
96
+ original_lines = []
97
+
98
+ # Log original file content for comparison
99
+ logger.info("patch_file: ===== ORIGINAL FILE DEBUG START =====")
100
+ for i, line in enumerate(original_lines, 1):
101
+ logger.info("patch_file: original line %d: %r", i, line)
102
+ logger.info("patch_file: ===== ORIGINAL FILE DEBUG END =====")
103
+
104
+ patched_lines = None
105
+ patch_error = None
106
+ retry_strategies = [
107
+ (0, False),
108
+ (1, False),
109
+ (1, True),
110
+ (2, True),
111
+ ]
112
+ for fuzz_factor, ignore_whitespace in retry_strategies:
113
+ try:
114
+ patched_lines = apply_unified_diff(
115
+ original_lines,
116
+ patch,
117
+ fuzz_factor=fuzz_factor,
118
+ ignore_whitespace=ignore_whitespace,
119
+ )
120
+ if (fuzz_factor, ignore_whitespace) != (0, False):
121
+ logger.info(
122
+ "patch_file: applied with fuzz=%d ignore_whitespace=%s.",
123
+ fuzz_factor,
124
+ ignore_whitespace,
125
+ )
126
+ break
127
+ except PatchApplicationError as patch_err:
128
+ patch_error = patch_err
129
+ logger.warning(
130
+ "patch_file: patch failed with fuzz=%d ignore_whitespace=%s: %s",
131
+ fuzz_factor,
132
+ ignore_whitespace,
133
+ patch_err,
134
+ )
135
+ continue
136
+ if patched_lines is None:
137
+ raise patch_error or PatchApplicationError("Patch could not be applied.")
138
+
139
+ with open(final_path, 'w', encoding='utf-8') as destination:
140
+ destination.writelines(patched_lines)
141
+
142
+ logger.info("patch_file: successfully applied patch to '%s'.", final_path)
143
+ return f"File patched successfully at {return_path}"
144
+ except PatchApplicationError as patch_err:
145
+ logger.error("patch_file: failed to apply patch to '%s': %s", final_path, patch_err, exc_info=True)
146
+ raise patch_err
147
+ except Exception as exc: # pragma: no cover - general safeguard
148
+ logger.error("patch_file: unexpected error while patching '%s': %s", final_path, exc, exc_info=True)
149
+ raise IOError(f"Could not patch file at '{final_path}': {exc}")
@@ -1,6 +1,8 @@
1
1
  import os
2
2
  import logging
3
- from typing import TYPE_CHECKING
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ from pydantic import Field
4
6
 
5
7
  from autobyteus.tools import tool
6
8
  from autobyteus.tools.tool_category import ToolCategory
@@ -10,16 +12,33 @@ if TYPE_CHECKING:
10
12
 
11
13
  logger = logging.getLogger(__name__)
12
14
 
13
- @tool(name="FileReader", category=ToolCategory.FILE_SYSTEM)
14
- async def file_reader(context: 'AgentContext', path: str) -> str:
15
+ @tool(name="read_file", category=ToolCategory.FILE_SYSTEM)
16
+ async def read_file(
17
+ context: 'AgentContext',
18
+ path: str,
19
+ start_line: Optional[int] = None,
20
+ end_line: Optional[int] = None,
21
+ include_line_numbers: bool = Field(
22
+ True,
23
+ description="If true, prefix each returned line with its line number (default).",
24
+ ),
25
+ ) -> str:
15
26
  """
16
- Reads content from a specified file.
27
+ Reads content from a specified file. Supports optional 1-based inclusive line ranges via start_line/end_line.
28
+ Each returned line is prefixed with its line number when include_line_numbers is true.
17
29
  'path' is the path to the file. If relative, it must be resolved against a configured agent workspace.
18
- Raises ValueError if a relative path is given without a valid workspace.
30
+ Raises ValueError if a relative path is given without a valid workspace or if line range arguments are invalid.
19
31
  Raises FileNotFoundError if the file does not exist.
20
32
  Raises IOError if file reading fails for other reasons.
21
33
  """
22
- logger.debug(f"Functional FileReader tool for agent {context.agent_id}, initial path: {path}")
34
+ logger.debug(f"Functional read_file tool for agent {context.agent_id}, initial path: {path}")
35
+
36
+ if start_line is not None and start_line < 1:
37
+ raise ValueError(f"start_line must be >= 1 when provided; got {start_line}.")
38
+ if end_line is not None and end_line < 1:
39
+ raise ValueError(f"end_line must be >= 1 when provided; got {end_line}.")
40
+ if start_line is not None and end_line is not None and end_line < start_line:
41
+ raise ValueError(f"end_line ({end_line}) must be >= start_line ({start_line}).")
23
42
 
24
43
  final_path: str
25
44
  if os.path.isabs(path):
@@ -48,7 +67,19 @@ async def file_reader(context: 'AgentContext', path: str) -> str:
48
67
 
49
68
  try:
50
69
  with open(final_path, 'r', encoding='utf-8') as file:
51
- content = file.read()
70
+ selected_lines = []
71
+ for line_no, line in enumerate(file, start=1):
72
+ if start_line is not None and line_no < start_line:
73
+ continue
74
+ if end_line is not None and line_no > end_line:
75
+ break
76
+ if include_line_numbers:
77
+ line_text = line.rstrip('\n')
78
+ line_suffix = '\n' if line.endswith('\n') else ''
79
+ selected_lines.append(f"{line_no}: {line_text}{line_suffix}")
80
+ else:
81
+ selected_lines.append(line)
82
+ content = ''.join(selected_lines)
52
83
  logger.info(f"File successfully read from '{final_path}' for agent '{context.agent_id}'.")
53
84
  return content
54
85
  except Exception as e:
@@ -10,8 +10,8 @@ if TYPE_CHECKING:
10
10
 
11
11
  logger = logging.getLogger(__name__)
12
12
 
13
- @tool(name="FileWriter", category=ToolCategory.FILE_SYSTEM)
14
- async def file_writer(context: 'AgentContext', path: str, content: str) -> str:
13
+ @tool(name="write_file", category=ToolCategory.FILE_SYSTEM)
14
+ async def write_file(context: 'AgentContext', path: str, content: str) -> str:
15
15
  """
16
16
  Creates or overwrites a file with specified content.
17
17
  'path' is the path where the file will be written. If relative, it must be resolved against a configured agent workspace.
@@ -20,11 +20,13 @@ async def file_writer(context: 'AgentContext', path: str, content: str) -> str:
20
20
  Raises ValueError if a relative path is given without a valid workspace.
21
21
  Raises IOError if file writing fails.
22
22
  """
23
- logger.debug(f"Functional FileWriter tool for agent {context.agent_id}, initial path: {path}")
23
+ logger.debug(f"Functional write_file tool for agent {context.agent_id}, initial path: {path}")
24
24
 
25
25
  final_path: str
26
+ return_path: str
26
27
  if os.path.isabs(path):
27
28
  final_path = path
29
+ return_path = final_path
28
30
  logger.debug(f"Path '{path}' is absolute. Using it directly.")
29
31
  else:
30
32
  if not context.workspace:
@@ -39,6 +41,7 @@ async def file_writer(context: 'AgentContext', path: str, content: str) -> str:
39
41
  raise ValueError(error_msg)
40
42
 
41
43
  final_path = os.path.join(base_path, path)
44
+ return_path = os.path.normpath(path)
42
45
  logger.debug(f"Path '{path}' is relative. Resolved to '{final_path}' using workspace base path '{base_path}'.")
43
46
 
44
47
  try:
@@ -53,7 +56,7 @@ async def file_writer(context: 'AgentContext', path: str, content: str) -> str:
53
56
  file.write(content)
54
57
 
55
58
  logger.info(f"File successfully written to '{final_path}' for agent '{context.agent_id}'.")
56
- return f"File created/updated at {final_path}"
59
+ return f"File created/updated at {return_path}"
57
60
  except Exception as e:
58
61
  logger.error(f"Error writing file to final path '{final_path}' for agent {context.agent_id}: {e}", exc_info=True)
59
62
  raise IOError(f"Could not write file at '{final_path}': {str(e)}")
@@ -99,7 +99,7 @@ def _python_type_to_json_schema(py_type: Any) -> Optional[Dict[str, Any]]:
99
99
  if py_type is float: return {"type": "number"}
100
100
  if py_type is bool: return {"type": "boolean"}
101
101
  if py_type is dict: return {"type": "object"}
102
- if py_type is list: return {"type": "array", "items": True}
102
+ if py_type is list: return {"type": "array", "items": {}} # Use empty dict for 'any'
103
103
 
104
104
  origin_type = get_origin(py_type)
105
105
  if origin_type is Union:
@@ -111,8 +111,8 @@ def _python_type_to_json_schema(py_type: Any) -> Optional[Dict[str, Any]]:
111
111
  list_args = get_args(py_type)
112
112
  if list_args and len(list_args) == 1:
113
113
  item_schema = _python_type_to_json_schema(list_args[0])
114
- return {"type": "array", "items": item_schema if item_schema else True}
115
- return {"type": "array", "items": True}
114
+ return {"type": "array", "items": item_schema if item_schema else {}}
115
+ return {"type": "array", "items": {}} # Use empty dict for 'any'
116
116
  if origin_type is Dict or origin_type is dict: return {"type": "object"}
117
117
  logger.debug(f"Could not map Python type {py_type} to a simple JSON schema for array items.")
118
118
  return None
@@ -141,18 +141,26 @@ def _get_parameter_type_from_hint(py_type: Any, param_name: str) -> Tuple[Parame
141
141
  list_args = get_args(actual_type)
142
142
  if list_args and len(list_args) == 1:
143
143
  array_item_js_schema = _python_type_to_json_schema(list_args[0])
144
- if not array_item_js_schema:
145
- array_item_js_schema = True
144
+ # FIX: For an untyped list, the item schema should be None, not True.
145
+ # An empty dict `{}` is a valid JSON schema for 'any'.
146
+ if array_item_js_schema is None:
147
+ array_item_js_schema = {}
146
148
  return param_type_enum, array_item_js_schema
147
149
 
148
150
  mapped_type = _TYPE_MAPPING.get(actual_type)
149
151
  if mapped_type:
150
- item_schema_for_array = True if mapped_type == ParameterType.ARRAY else None
152
+ item_schema_for_array = {} if mapped_type == ParameterType.ARRAY else None
151
153
  return mapped_type, item_schema_for_array
152
154
 
153
155
  logger.warning(f"Unmapped type hint {py_type} (actual_type: {actual_type}) for param '{param_name}'. Defaulting to ParameterType.STRING.")
154
156
  return ParameterType.STRING, None
155
157
 
158
+
159
+ try:
160
+ from pydantic.fields import FieldInfo
161
+ except ImportError:
162
+ FieldInfo = None # type: ignore
163
+
156
164
  def _parse_signature(sig: inspect.Signature, tool_name: str) -> Tuple[TypingList[str], bool, bool, ParameterSchema]:
157
165
  func_param_names = []
158
166
  expects_context = False
@@ -173,26 +181,51 @@ def _parse_signature(sig: inspect.Signature, tool_name: str) -> Tuple[TypingList
173
181
  param_type_enum, item_schema = _get_parameter_type_from_hint(param_type_hint, param_name)
174
182
 
175
183
  is_required = param_obj.default == inspect.Parameter.empty
176
- if get_origin(param_type_hint) is Union and type(None) in get_args(param_type_hint):
177
- is_required = False
178
-
184
+ default_val = param_obj.default if param_obj.default != inspect.Parameter.empty else None
185
+
186
+ # --- Pydantic Field Extraction Logic ---
179
187
  param_desc = f"Parameter '{param_name}' for tool '{tool_name}'."
180
188
  param_name_lower = param_name.lower()
181
189
  if "path" in param_name_lower or "file" in param_name_lower or "dir" in param_name_lower or "folder" in param_name_lower:
182
- param_desc += " This is expected to be a path."
190
+ param_desc += " This is expected to be a path."
191
+
192
+ if FieldInfo and isinstance(param_obj.default, FieldInfo):
193
+ field_info = param_obj.default
194
+
195
+ # 1. Description
196
+ if field_info.description:
197
+ param_desc = field_info.description
183
198
 
199
+ # 2. Default Value & Requiredness
200
+ # If PydanticUndefined (or similar sentinel), it means required.
201
+ # Otherwise, use the default value from Field.
202
+ # Note: Pydantic v1 uses Undefined, v2 uses PydanticUndefined.
203
+ # We check if it is the special undefined value via representation or direct check.
204
+
205
+ # Simple heuristic for "Undefined" without importing the specific sentinel
206
+ if str(field_info.default) == "PydanticUndefined" or field_info.default == ...:
207
+ is_required = True
208
+ default_val = None
209
+ else:
210
+ is_required = False
211
+ default_val = field_info.default
212
+
213
+ if get_origin(param_type_hint) is Union and type(None) in get_args(param_type_hint):
214
+ is_required = False
215
+
184
216
  schema_param = ParameterDefinition(
185
217
  name=param_name,
186
218
  param_type=param_type_enum,
187
219
  description=param_desc,
188
220
  required=is_required,
189
- default_value=param_obj.default if param_obj.default != inspect.Parameter.empty else None,
221
+ default_value=default_val,
190
222
  array_item_schema=item_schema
191
223
  )
192
224
  generated_arg_schema.add_parameter(schema_param)
193
225
 
194
226
  return func_param_names, expects_context, expects_tool_state, generated_arg_schema
195
227
 
228
+
196
229
  # --- The refactored @tool decorator ---
197
230
 
198
231
  def tool(
@@ -215,6 +248,11 @@ def tool(
215
248
 
216
249
  final_arg_schema = argument_schema if argument_schema is not None else gen_arg_schema
217
250
 
251
+ def _current_description() -> str:
252
+ """Recompute the description from the latest docstring/override."""
253
+ latest_doc = inspect.getdoc(func)
254
+ return description or (latest_doc.split('\n\n')[0] if latest_doc else f"Functional tool: {tool_name}")
255
+
218
256
  def factory(inst_config: Optional[ToolConfig] = None) -> FunctionalTool:
219
257
  return FunctionalTool(
220
258
  original_func=func,
@@ -232,12 +270,13 @@ def tool(
232
270
  tool_def = ToolDefinition(
233
271
  name=tool_name,
234
272
  description=tool_desc,
235
- argument_schema=final_arg_schema,
236
- config_schema=config_schema,
273
+ argument_schema_provider=lambda: final_arg_schema,
274
+ config_schema_provider=lambda: config_schema,
237
275
  custom_factory=factory,
238
276
  tool_class=None,
239
277
  origin=ToolOrigin.LOCAL,
240
- category=category
278
+ category=category,
279
+ description_provider=_current_description
241
280
  )
242
281
  default_tool_registry.register_tool(tool_def)
243
282
 
@@ -19,6 +19,7 @@ from .types import (
19
19
  BaseMcpConfig,
20
20
  StdioMcpServerConfig,
21
21
  StreamableHttpMcpServerConfig,
22
+ WebsocketMcpServerConfig,
22
23
  McpTransportType,
23
24
  McpServerInstanceKey,
24
25
  )
@@ -37,6 +38,7 @@ __all__ = [
37
38
  "BaseMcpConfig",
38
39
  "StdioMcpServerConfig",
39
40
  "StreamableHttpMcpServerConfig",
41
+ "WebsocketMcpServerConfig",
40
42
  "McpTransportType",
41
43
  "McpServerInstanceKey",
42
44
  # Services and Managers
@@ -9,6 +9,7 @@ from .types import (
9
9
  BaseMcpConfig,
10
10
  StdioMcpServerConfig,
11
11
  StreamableHttpMcpServerConfig,
12
+ WebsocketMcpServerConfig,
12
13
  McpTransportType
13
14
  )
14
15
  from autobyteus.utils.singleton import SingletonMeta
@@ -49,7 +50,8 @@ class McpConfigService(metaclass=SingletonMeta):
49
50
 
50
51
  transport_specific_params_key_map = {
51
52
  McpTransportType.STDIO: "stdio_params",
52
- McpTransportType.STREAMABLE_HTTP: "streamable_http_params"
53
+ McpTransportType.STREAMABLE_HTTP: "streamable_http_params",
54
+ McpTransportType.WEBSOCKET: "websocket_params",
53
55
  }
54
56
 
55
57
  if transport_type in transport_specific_params_key_map:
@@ -74,6 +76,8 @@ class McpConfigService(metaclass=SingletonMeta):
74
76
  return StdioMcpServerConfig(**constructor_params)
75
77
  elif transport_type == McpTransportType.STREAMABLE_HTTP:
76
78
  return StreamableHttpMcpServerConfig(**constructor_params)
79
+ elif transport_type == McpTransportType.WEBSOCKET:
80
+ return WebsocketMcpServerConfig(**constructor_params)
77
81
  else:
78
82
  raise ValueError(f"Unsupported McpTransportType '{transport_type}' for server '{server_id}'.")
79
83
  except TypeError as e:
@@ -5,6 +5,7 @@ This package contains the core abstractions for managing connections to remote M
5
5
  from .base_managed_mcp_server import BaseManagedMcpServer, ServerState
6
6
  from .stdio_managed_mcp_server import StdioManagedMcpServer
7
7
  from .http_managed_mcp_server import HttpManagedMcpServer
8
+ from .websocket_managed_mcp_server import WebsocketManagedMcpServer
8
9
  from .proxy import McpServerProxy
9
10
 
10
11
  __all__ = [
@@ -12,5 +13,6 @@ __all__ = [
12
13
  "ServerState",
13
14
  "StdioManagedMcpServer",
14
15
  "HttpManagedMcpServer",
16
+ "WebsocketManagedMcpServer",
15
17
  "McpServerProxy",
16
18
  ]
@@ -23,7 +23,7 @@ class HttpManagedMcpServer(BaseManagedMcpServer):
23
23
  config = cast(StreamableHttpMcpServerConfig, self._config)
24
24
 
25
25
  logger.debug(f"Establishing HTTP connection for server '{self.server_id}' to URL: {config.url}")
26
- read_stream, write_stream = await self._exit_stack.enter_async_context(
26
+ read_stream, write_stream, _ = await self._exit_stack.enter_async_context(
27
27
  streamablehttp_client(config.url, headers=config.headers)
28
28
  )
29
29
  session = await self._exit_stack.enter_async_context(ClientSession(read_stream, write_stream))