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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (466) hide show
  1. autobyteus/agent/agent.py +15 -5
  2. autobyteus/agent/bootstrap_steps/__init__.py +1 -3
  3. autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +3 -59
  4. autobyteus/agent/bootstrap_steps/base_bootstrap_step.py +1 -4
  5. autobyteus/agent/bootstrap_steps/mcp_server_prewarming_step.py +1 -3
  6. autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +16 -13
  7. autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +2 -4
  8. autobyteus/agent/context/agent_config.py +43 -20
  9. autobyteus/agent/context/agent_context.py +23 -18
  10. autobyteus/agent/context/agent_runtime_state.py +19 -19
  11. autobyteus/agent/events/__init__.py +16 -1
  12. autobyteus/agent/events/agent_events.py +43 -3
  13. autobyteus/agent/events/agent_input_event_queue_manager.py +79 -26
  14. autobyteus/agent/events/event_store.py +57 -0
  15. autobyteus/agent/events/notifiers.py +69 -59
  16. autobyteus/agent/events/worker_event_dispatcher.py +21 -64
  17. autobyteus/agent/factory/agent_factory.py +52 -0
  18. autobyteus/agent/handlers/__init__.py +2 -0
  19. autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +51 -34
  20. autobyteus/agent/handlers/bootstrap_event_handler.py +155 -0
  21. autobyteus/agent/handlers/inter_agent_message_event_handler.py +10 -0
  22. autobyteus/agent/handlers/lifecycle_event_logger.py +19 -11
  23. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +10 -15
  24. autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +188 -48
  25. autobyteus/agent/handlers/tool_execution_approval_event_handler.py +0 -10
  26. autobyteus/agent/handlers/tool_invocation_request_event_handler.py +53 -48
  27. autobyteus/agent/handlers/tool_result_event_handler.py +7 -8
  28. autobyteus/agent/handlers/user_input_message_event_handler.py +10 -3
  29. autobyteus/agent/input_processor/memory_ingest_input_processor.py +40 -0
  30. autobyteus/agent/lifecycle/__init__.py +12 -0
  31. autobyteus/agent/lifecycle/base_processor.py +109 -0
  32. autobyteus/agent/lifecycle/events.py +35 -0
  33. autobyteus/agent/lifecycle/processor_definition.py +36 -0
  34. autobyteus/agent/lifecycle/processor_registry.py +106 -0
  35. autobyteus/agent/llm_request_assembler.py +98 -0
  36. autobyteus/agent/llm_response_processor/__init__.py +1 -8
  37. autobyteus/agent/message/context_file_type.py +1 -1
  38. autobyteus/agent/runtime/agent_runtime.py +29 -21
  39. autobyteus/agent/runtime/agent_worker.py +98 -19
  40. autobyteus/agent/shutdown_steps/__init__.py +2 -0
  41. autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
  42. autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
  43. autobyteus/agent/status/__init__.py +14 -0
  44. autobyteus/agent/status/manager.py +93 -0
  45. autobyteus/agent/status/status_deriver.py +96 -0
  46. autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
  47. autobyteus/agent/status/status_update_utils.py +73 -0
  48. autobyteus/agent/streaming/__init__.py +52 -5
  49. autobyteus/agent/streaming/adapters/__init__.py +18 -0
  50. autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
  51. autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
  52. autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
  53. autobyteus/agent/streaming/agent_event_stream.py +3 -183
  54. autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
  55. autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
  56. autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
  57. autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
  58. autobyteus/agent/streaming/events/__init__.py +6 -0
  59. autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
  60. autobyteus/agent/streaming/events/stream_events.py +141 -0
  61. autobyteus/agent/streaming/handlers/__init__.py +15 -0
  62. autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
  63. autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
  64. autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
  65. autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
  66. autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
  67. autobyteus/agent/streaming/parser/__init__.py +61 -0
  68. autobyteus/agent/streaming/parser/event_emitter.py +181 -0
  69. autobyteus/agent/streaming/parser/events.py +4 -0
  70. autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
  71. autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
  72. autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
  73. autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
  74. autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
  75. autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
  76. autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
  77. autobyteus/agent/streaming/parser/parser_context.py +227 -0
  78. autobyteus/agent/streaming/parser/parser_factory.py +132 -0
  79. autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
  80. autobyteus/agent/streaming/parser/state_factory.py +62 -0
  81. autobyteus/agent/streaming/parser/states/__init__.py +1 -0
  82. autobyteus/agent/streaming/parser/states/base_state.py +60 -0
  83. autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
  84. autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
  85. autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
  86. autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
  87. autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
  88. autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
  89. autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
  90. autobyteus/agent/streaming/parser/states/text_state.py +78 -0
  91. autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
  92. autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
  93. autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
  94. autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
  95. autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
  96. autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
  97. autobyteus/agent/streaming/parser/strategies/base.py +24 -0
  98. autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
  99. autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
  100. autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
  101. autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
  102. autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
  103. autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
  104. autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
  105. autobyteus/agent/streaming/parser/tool_constants.py +7 -0
  106. autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
  107. autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
  108. autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
  109. autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
  110. autobyteus/agent/streaming/queue_streamer.py +3 -57
  111. autobyteus/agent/streaming/segments/__init__.py +5 -0
  112. autobyteus/agent/streaming/segments/segment_events.py +81 -0
  113. autobyteus/agent/streaming/stream_event_payloads.py +2 -223
  114. autobyteus/agent/streaming/stream_events.py +3 -140
  115. autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
  116. autobyteus/agent/streaming/streaming_response_handler.py +4 -0
  117. autobyteus/agent/streaming/streams/__init__.py +5 -0
  118. autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
  119. autobyteus/agent/streaming/utils/__init__.py +5 -0
  120. autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
  121. autobyteus/agent/system_prompt_processor/__init__.py +2 -0
  122. autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
  123. autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
  124. autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
  125. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
  126. autobyteus/agent/token_budget.py +56 -0
  127. autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
  128. autobyteus/agent/tool_invocation.py +16 -40
  129. autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
  130. autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
  131. autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
  132. autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
  133. autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
  134. autobyteus/agent/utils/wait_for_idle.py +12 -14
  135. autobyteus/agent/workspace/base_workspace.py +6 -27
  136. autobyteus/agent_team/agent_team.py +3 -3
  137. autobyteus/agent_team/agent_team_builder.py +1 -41
  138. autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
  139. autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
  140. autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
  141. autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
  142. autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
  143. autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +1 -2
  144. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +4 -4
  145. autobyteus/agent_team/context/agent_team_config.py +6 -3
  146. autobyteus/agent_team/context/agent_team_context.py +25 -3
  147. autobyteus/agent_team/context/agent_team_runtime_state.py +9 -6
  148. autobyteus/agent_team/events/__init__.py +11 -0
  149. autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
  150. autobyteus/agent_team/events/agent_team_events.py +16 -0
  151. autobyteus/agent_team/events/event_store.py +57 -0
  152. autobyteus/agent_team/factory/agent_team_factory.py +8 -0
  153. autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
  154. autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
  155. autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
  156. autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
  157. autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
  158. autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
  159. autobyteus/agent_team/status/__init__.py +14 -0
  160. autobyteus/agent_team/status/agent_team_status.py +18 -0
  161. autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
  162. autobyteus/agent_team/status/status_deriver.py +62 -0
  163. autobyteus/agent_team/status/status_update_utils.py +42 -0
  164. autobyteus/agent_team/streaming/__init__.py +2 -2
  165. autobyteus/agent_team/streaming/agent_team_event_notifier.py +6 -6
  166. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +4 -4
  167. autobyteus/agent_team/streaming/agent_team_stream_events.py +3 -3
  168. autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
  169. autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
  170. autobyteus/agent_team/task_notification/task_notification_mode.py +19 -0
  171. autobyteus/agent_team/utils/wait_for_idle.py +4 -4
  172. autobyteus/cli/agent_cli.py +18 -10
  173. autobyteus/cli/agent_team_tui/app.py +14 -11
  174. autobyteus/cli/agent_team_tui/state.py +13 -15
  175. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
  176. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +143 -36
  177. autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
  178. autobyteus/cli/agent_team_tui/widgets/shared.py +25 -25
  179. autobyteus/cli/cli_display.py +193 -44
  180. autobyteus/cli/workflow_tui/app.py +9 -10
  181. autobyteus/cli/workflow_tui/state.py +14 -16
  182. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
  183. autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
  184. autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
  185. autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
  186. autobyteus/clients/autobyteus_client.py +94 -1
  187. autobyteus/events/event_types.py +11 -18
  188. autobyteus/llm/api/autobyteus_llm.py +33 -29
  189. autobyteus/llm/api/claude_llm.py +142 -36
  190. autobyteus/llm/api/gemini_llm.py +163 -59
  191. autobyteus/llm/api/grok_llm.py +1 -1
  192. autobyteus/llm/api/minimax_llm.py +26 -0
  193. autobyteus/llm/api/mistral_llm.py +113 -87
  194. autobyteus/llm/api/ollama_llm.py +9 -42
  195. autobyteus/llm/api/openai_compatible_llm.py +127 -91
  196. autobyteus/llm/api/openai_llm.py +3 -3
  197. autobyteus/llm/api/openai_responses_llm.py +324 -0
  198. autobyteus/llm/api/zhipu_llm.py +21 -2
  199. autobyteus/llm/autobyteus_provider.py +70 -60
  200. autobyteus/llm/base_llm.py +85 -81
  201. autobyteus/llm/converters/__init__.py +14 -0
  202. autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
  203. autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
  204. autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
  205. autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
  206. autobyteus/llm/extensions/base_extension.py +6 -12
  207. autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
  208. autobyteus/llm/llm_factory.py +282 -204
  209. autobyteus/llm/lmstudio_provider.py +60 -49
  210. autobyteus/llm/models.py +35 -2
  211. autobyteus/llm/ollama_provider.py +60 -49
  212. autobyteus/llm/ollama_provider_resolver.py +0 -1
  213. autobyteus/llm/prompt_renderers/__init__.py +19 -0
  214. autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
  215. autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
  216. autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
  217. autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
  218. autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
  219. autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
  220. autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
  221. autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
  222. autobyteus/llm/providers.py +1 -3
  223. autobyteus/llm/token_counter/claude_token_counter.py +56 -25
  224. autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
  225. autobyteus/llm/token_counter/openai_token_counter.py +24 -5
  226. autobyteus/llm/token_counter/token_counter_factory.py +12 -5
  227. autobyteus/llm/utils/llm_config.py +6 -12
  228. autobyteus/llm/utils/media_payload_formatter.py +27 -20
  229. autobyteus/llm/utils/messages.py +55 -3
  230. autobyteus/llm/utils/response_types.py +3 -0
  231. autobyteus/llm/utils/tool_call_delta.py +31 -0
  232. autobyteus/memory/__init__.py +32 -0
  233. autobyteus/memory/active_transcript.py +69 -0
  234. autobyteus/memory/compaction/__init__.py +9 -0
  235. autobyteus/memory/compaction/compaction_result.py +8 -0
  236. autobyteus/memory/compaction/compactor.py +89 -0
  237. autobyteus/memory/compaction/summarizer.py +11 -0
  238. autobyteus/memory/compaction_snapshot_builder.py +84 -0
  239. autobyteus/memory/memory_manager.py +183 -0
  240. autobyteus/memory/models/__init__.py +14 -0
  241. autobyteus/memory/models/episodic_item.py +41 -0
  242. autobyteus/memory/models/memory_types.py +7 -0
  243. autobyteus/memory/models/raw_trace_item.py +79 -0
  244. autobyteus/memory/models/semantic_item.py +41 -0
  245. autobyteus/memory/models/tool_interaction.py +20 -0
  246. autobyteus/memory/policies/__init__.py +5 -0
  247. autobyteus/memory/policies/compaction_policy.py +16 -0
  248. autobyteus/memory/retrieval/__init__.py +7 -0
  249. autobyteus/memory/retrieval/memory_bundle.py +11 -0
  250. autobyteus/memory/retrieval/retriever.py +13 -0
  251. autobyteus/memory/store/__init__.py +7 -0
  252. autobyteus/memory/store/base_store.py +14 -0
  253. autobyteus/memory/store/file_store.py +98 -0
  254. autobyteus/memory/tool_interaction_builder.py +46 -0
  255. autobyteus/memory/turn_tracker.py +9 -0
  256. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
  257. autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
  258. autobyteus/multimedia/audio/audio_client_factory.py +47 -9
  259. autobyteus/multimedia/audio/audio_model.py +2 -1
  260. autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
  261. autobyteus/multimedia/image/api/gemini_image_client.py +38 -17
  262. autobyteus/multimedia/image/api/openai_image_client.py +125 -43
  263. autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
  264. autobyteus/multimedia/image/image_client_factory.py +47 -15
  265. autobyteus/multimedia/image/image_model.py +5 -2
  266. autobyteus/multimedia/providers.py +3 -2
  267. autobyteus/skills/loader.py +71 -0
  268. autobyteus/skills/model.py +11 -0
  269. autobyteus/skills/registry.py +70 -0
  270. autobyteus/task_management/tools/todo_tools/add_todo.py +2 -2
  271. autobyteus/task_management/tools/todo_tools/create_todo_list.py +2 -2
  272. autobyteus/task_management/tools/todo_tools/update_todo_status.py +2 -2
  273. autobyteus/tools/__init__.py +34 -47
  274. autobyteus/tools/base_tool.py +7 -0
  275. autobyteus/tools/file/__init__.py +2 -6
  276. autobyteus/tools/file/patch_file.py +149 -0
  277. autobyteus/tools/file/read_file.py +36 -5
  278. autobyteus/tools/file/write_file.py +4 -1
  279. autobyteus/tools/functional_tool.py +43 -6
  280. autobyteus/tools/mcp/__init__.py +2 -0
  281. autobyteus/tools/mcp/config_service.py +5 -1
  282. autobyteus/tools/mcp/server/__init__.py +2 -0
  283. autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
  284. autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
  285. autobyteus/tools/mcp/server_instance_manager.py +8 -1
  286. autobyteus/tools/mcp/types.py +61 -0
  287. autobyteus/tools/multimedia/audio_tools.py +70 -17
  288. autobyteus/tools/multimedia/download_media_tool.py +18 -4
  289. autobyteus/tools/multimedia/image_tools.py +246 -62
  290. autobyteus/tools/operation_executor/journal_manager.py +107 -0
  291. autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
  292. autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
  293. autobyteus/tools/operation_executor/operation_executor.py +58 -0
  294. autobyteus/tools/registry/tool_definition.py +43 -2
  295. autobyteus/tools/skill/load_skill.py +50 -0
  296. autobyteus/tools/terminal/__init__.py +45 -0
  297. autobyteus/tools/terminal/ansi_utils.py +32 -0
  298. autobyteus/tools/terminal/background_process_manager.py +233 -0
  299. autobyteus/tools/terminal/output_buffer.py +105 -0
  300. autobyteus/tools/terminal/prompt_detector.py +63 -0
  301. autobyteus/tools/terminal/pty_session.py +241 -0
  302. autobyteus/tools/terminal/session_factory.py +20 -0
  303. autobyteus/tools/terminal/terminal_session_manager.py +226 -0
  304. autobyteus/tools/terminal/tools/__init__.py +13 -0
  305. autobyteus/tools/terminal/tools/get_process_output.py +81 -0
  306. autobyteus/tools/terminal/tools/run_bash.py +109 -0
  307. autobyteus/tools/terminal/tools/start_background_process.py +104 -0
  308. autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
  309. autobyteus/tools/terminal/types.py +54 -0
  310. autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
  311. autobyteus/tools/terminal/wsl_utils.py +156 -0
  312. autobyteus/tools/transaction_management/backup_handler.py +48 -0
  313. autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
  314. autobyteus/tools/usage/__init__.py +1 -2
  315. autobyteus/tools/usage/formatters/__init__.py +17 -1
  316. autobyteus/tools/usage/formatters/base_formatter.py +8 -0
  317. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
  318. autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
  319. autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
  320. autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
  321. autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
  322. autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
  323. autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
  324. autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
  325. autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
  326. autobyteus/tools/usage/registries/__init__.py +1 -3
  327. autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
  328. autobyteus/tools/usage/tool_schema_provider.py +51 -0
  329. autobyteus/tools/web/__init__.py +4 -0
  330. autobyteus/tools/web/read_url_tool.py +80 -0
  331. autobyteus/utils/diff_utils.py +271 -0
  332. autobyteus/utils/download_utils.py +109 -0
  333. autobyteus/utils/file_utils.py +57 -2
  334. autobyteus/utils/gemini_helper.py +56 -0
  335. autobyteus/utils/gemini_model_mapping.py +71 -0
  336. autobyteus/utils/llm_output_formatter.py +75 -0
  337. autobyteus/utils/tool_call_format.py +36 -0
  338. autobyteus/workflow/agentic_workflow.py +3 -3
  339. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
  340. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
  341. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
  342. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +3 -9
  343. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
  344. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
  345. autobyteus/workflow/context/workflow_context.py +3 -3
  346. autobyteus/workflow/context/workflow_runtime_state.py +5 -5
  347. autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
  348. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
  349. autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
  350. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
  351. autobyteus/workflow/runtime/workflow_runtime.py +8 -8
  352. autobyteus/workflow/runtime/workflow_worker.py +3 -3
  353. autobyteus/workflow/status/__init__.py +11 -0
  354. autobyteus/workflow/status/workflow_status.py +19 -0
  355. autobyteus/workflow/status/workflow_status_manager.py +48 -0
  356. autobyteus/workflow/streaming/__init__.py +2 -2
  357. autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
  358. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
  359. autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
  360. autobyteus/workflow/utils/wait_for_idle.py +4 -4
  361. autobyteus-1.2.3.dist-info/METADATA +293 -0
  362. autobyteus-1.2.3.dist-info/RECORD +600 -0
  363. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
  364. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/top_level.txt +0 -1
  365. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
  366. autobyteus/agent/hooks/__init__.py +0 -16
  367. autobyteus/agent/hooks/base_phase_hook.py +0 -78
  368. autobyteus/agent/hooks/hook_definition.py +0 -36
  369. autobyteus/agent/hooks/hook_meta.py +0 -37
  370. autobyteus/agent/hooks/hook_registry.py +0 -106
  371. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
  372. autobyteus/agent/phases/__init__.py +0 -18
  373. autobyteus/agent/phases/discover.py +0 -53
  374. autobyteus/agent/phases/manager.py +0 -265
  375. autobyteus/agent/phases/transition_decorator.py +0 -40
  376. autobyteus/agent/phases/transition_info.py +0 -33
  377. autobyteus/agent/remote_agent.py +0 -244
  378. autobyteus/agent/workspace/workspace_definition.py +0 -36
  379. autobyteus/agent/workspace/workspace_meta.py +0 -37
  380. autobyteus/agent/workspace/workspace_registry.py +0 -72
  381. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
  382. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
  383. autobyteus/agent_team/phases/__init__.py +0 -11
  384. autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
  385. autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
  386. autobyteus/llm/api/bedrock_llm.py +0 -92
  387. autobyteus/llm/api/groq_llm.py +0 -94
  388. autobyteus/llm/api/nvidia_llm.py +0 -108
  389. autobyteus/llm/utils/token_pricing_config.py +0 -87
  390. autobyteus/rpc/__init__.py +0 -73
  391. autobyteus/rpc/client/__init__.py +0 -17
  392. autobyteus/rpc/client/abstract_client_connection.py +0 -124
  393. autobyteus/rpc/client/client_connection_manager.py +0 -153
  394. autobyteus/rpc/client/sse_client_connection.py +0 -306
  395. autobyteus/rpc/client/stdio_client_connection.py +0 -280
  396. autobyteus/rpc/config/__init__.py +0 -13
  397. autobyteus/rpc/config/agent_server_config.py +0 -153
  398. autobyteus/rpc/config/agent_server_registry.py +0 -152
  399. autobyteus/rpc/hosting.py +0 -244
  400. autobyteus/rpc/protocol.py +0 -244
  401. autobyteus/rpc/server/__init__.py +0 -20
  402. autobyteus/rpc/server/agent_server_endpoint.py +0 -181
  403. autobyteus/rpc/server/base_method_handler.py +0 -40
  404. autobyteus/rpc/server/method_handlers.py +0 -259
  405. autobyteus/rpc/server/sse_server_handler.py +0 -182
  406. autobyteus/rpc/server/stdio_server_handler.py +0 -151
  407. autobyteus/rpc/server_main.py +0 -198
  408. autobyteus/rpc/transport_type.py +0 -13
  409. autobyteus/tools/bash/__init__.py +0 -2
  410. autobyteus/tools/bash/bash_executor.py +0 -100
  411. autobyteus/tools/browser/__init__.py +0 -2
  412. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
  413. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
  414. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
  415. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
  416. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
  417. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
  418. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
  419. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
  420. autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
  421. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
  422. autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
  423. autobyteus/tools/browser/standalone/__init__.py +0 -6
  424. autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  425. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
  426. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
  427. autobyteus/tools/browser/standalone/navigate_to.py +0 -84
  428. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -101
  429. autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -169
  430. autobyteus/tools/browser/standalone/webpage_reader.py +0 -105
  431. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -105
  432. autobyteus/tools/file/edit_file.py +0 -200
  433. autobyteus/tools/file/list_directory.py +0 -168
  434. autobyteus/tools/file/search_files.py +0 -188
  435. autobyteus/tools/timer.py +0 -175
  436. autobyteus/tools/usage/parsers/__init__.py +0 -22
  437. autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
  438. autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
  439. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
  440. autobyteus/tools/usage/parsers/base_parser.py +0 -41
  441. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
  442. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
  443. autobyteus/tools/usage/parsers/exceptions.py +0 -13
  444. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
  445. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
  446. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
  447. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
  448. autobyteus/workflow/phases/__init__.py +0 -11
  449. autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
  450. autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
  451. autobyteus-1.2.1.dist-info/METADATA +0 -205
  452. autobyteus-1.2.1.dist-info/RECORD +0 -511
  453. examples/__init__.py +0 -1
  454. examples/agent_team/__init__.py +0 -1
  455. examples/discover_phase_transitions.py +0 -104
  456. examples/run_agentic_software_engineer.py +0 -239
  457. examples/run_browser_agent.py +0 -262
  458. examples/run_google_slides_agent.py +0 -287
  459. examples/run_mcp_browser_client.py +0 -174
  460. examples/run_mcp_google_slides_client.py +0 -270
  461. examples/run_mcp_list_tools.py +0 -189
  462. examples/run_poem_writer.py +0 -284
  463. examples/run_sqlite_agent.py +0 -295
  464. /autobyteus/{tools/browser/session_aware → skills}/__init__.py +0 -0
  465. /autobyteus/tools/{browser/session_aware/factory → skill}/__init__.py +0 -0
  466. {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,71 @@
1
+ import os
2
+ import logging
3
+ import re
4
+ from typing import Optional
5
+ from autobyteus.skills.model import Skill
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ class SkillLoader:
10
+ """
11
+ Responsible for loading and parsing SKILL.md files.
12
+ Designed to be forgiving of minor formatting variations in LLM-generated content.
13
+ """
14
+
15
+ @staticmethod
16
+ def load_skill(path: str) -> Skill:
17
+ """
18
+ Loads a skill from a given directory path.
19
+ """
20
+ if not os.path.isdir(path):
21
+ raise FileNotFoundError(f"Skill directory not found: {path}")
22
+
23
+ skill_file = os.path.join(path, "SKILL.md")
24
+ if not os.path.exists(skill_file):
25
+ raise FileNotFoundError(f"SKILL.md not found in {path}")
26
+
27
+ try:
28
+ with open(skill_file, 'r', encoding='utf-8') as f:
29
+ raw_content = f.read()
30
+ except Exception as e:
31
+ raise IOError(f"Failed to read SKILL.md at {skill_file}: {e}")
32
+
33
+ return SkillLoader._parse_skill(raw_content, path)
34
+
35
+ @staticmethod
36
+ def _parse_skill(raw_content: str, root_path: str) -> Skill:
37
+ """
38
+ Parses the content of a SKILL.md file.
39
+ Extracts metadata from the frontmatter block (delimited by ---).
40
+ """
41
+ # Extract the frontmatter block
42
+ # Using a regex that is forgiving of whitespace around delimiters
43
+ match = re.search(r'^\s*---\s*\n(.*?)\n\s*---\s*\n(.*)', raw_content, re.DOTALL | re.MULTILINE)
44
+
45
+ if not match:
46
+ raise ValueError("Invalid SKILL.md format: Could not find frontmatter block delimited by '---'")
47
+
48
+ frontmatter_text = match.group(1)
49
+ body_content = match.group(2).strip()
50
+
51
+ # Parse frontmatter lines (Key: Value)
52
+ metadata = {}
53
+ for line in frontmatter_text.splitlines():
54
+ if ":" in line:
55
+ key, value = line.split(":", 1)
56
+ metadata[key.strip().lower()] = value.strip()
57
+
58
+ name = metadata.get("name")
59
+ description = metadata.get("description")
60
+
61
+ if not name:
62
+ raise ValueError("Missing 'name' in SKILL.md metadata")
63
+ if not description:
64
+ raise ValueError("Missing 'description' in SKILL.md metadata")
65
+
66
+ return Skill(
67
+ name=name,
68
+ description=description,
69
+ content=body_content,
70
+ root_path=root_path
71
+ )
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+
3
+ @dataclass
4
+ class Skill:
5
+ """
6
+ Represents a loaded skill.
7
+ """
8
+ name: str
9
+ description: str
10
+ content: str # The body of the SKILL.md file
11
+ root_path: str # The absolute path to the skill directory
@@ -0,0 +1,70 @@
1
+ import os
2
+ import logging
3
+ from typing import Dict, List, Optional
4
+ from autobyteus.utils.singleton import SingletonMeta
5
+ from autobyteus.skills.model import Skill
6
+ from autobyteus.skills.loader import SkillLoader
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ class SkillRegistry(metaclass=SingletonMeta):
11
+ """
12
+ A singleton registry for managing and discovering agent skills.
13
+ """
14
+
15
+ def __init__(self):
16
+ self._skills: Dict[str, Skill] = {}
17
+ logger.info("SkillRegistry initialized.")
18
+
19
+ def register_skill_from_path(self, path: str) -> Skill:
20
+ """
21
+ Loads a skill from the given path and registers it.
22
+ If a skill with the same name already exists, it will be overwritten.
23
+ """
24
+ try:
25
+ skill = SkillLoader.load_skill(path)
26
+ self._skills[skill.name] = skill
27
+ logger.info(f"Skill '{skill.name}' registered from path: {path}")
28
+ return skill
29
+ except Exception as e:
30
+ logger.error(f"Failed to register skill from path '{path}': {e}")
31
+ raise
32
+
33
+ def discover_skills(self, directory_path: str):
34
+ """
35
+ Scans a directory for skill subdirectories (those containing SKILL.md)
36
+ and registers them.
37
+ """
38
+ if not os.path.isdir(directory_path):
39
+ logger.warning(f"Discovery directory not found: {directory_path}")
40
+ return
41
+
42
+ logger.debug(f"Discovering skills in: {directory_path}")
43
+ for entry in os.scandir(directory_path):
44
+ if entry.is_dir():
45
+ skill_md_path = os.path.join(entry.path, "SKILL.md")
46
+ if os.path.exists(skill_md_path):
47
+ try:
48
+ self.register_skill_from_path(entry.path)
49
+ except Exception:
50
+ # Continue discovering other skills even if one fails
51
+ continue
52
+
53
+ def get_skill(self, name: str) -> Optional[Skill]:
54
+ """
55
+ Retrieves a skill by its name.
56
+ """
57
+ return self._skills.get(name)
58
+
59
+ def list_skills(self) -> List[Skill]:
60
+ """
61
+ Returns a list of all registered skills.
62
+ """
63
+ return list(self._skills.values())
64
+
65
+ def clear(self):
66
+ """
67
+ Clears all registered skills. Primarily for testing.
68
+ """
69
+ self._skills.clear()
70
+ logger.debug("SkillRegistry cleared.")
@@ -16,11 +16,11 @@ if TYPE_CHECKING:
16
16
  logger = logging.getLogger(__name__)
17
17
 
18
18
  def _notify_todo_update(context: 'AgentContext'):
19
- if context.phase_manager and context.phase_manager.notifier:
19
+ if context.status_manager and context.status_manager.notifier:
20
20
  todo_list = context.state.todo_list
21
21
  if todo_list:
22
22
  todos_for_llm = [todo.model_dump(mode='json') for todo in todo_list.get_all_todos()]
23
- context.phase_manager.notifier.notify_agent_data_todo_list_updated(todos_for_llm)
23
+ context.status_manager.notifier.notify_agent_data_todo_list_updated(todos_for_llm)
24
24
  logger.debug(f"Agent '{context.agent_id}': Notified ToDo list update with {len(todos_for_llm)} items.")
25
25
 
26
26
  class AddToDo(BaseTool):
@@ -17,11 +17,11 @@ if TYPE_CHECKING:
17
17
  logger = logging.getLogger(__name__)
18
18
 
19
19
  def _notify_todo_update(context: 'AgentContext'):
20
- if context.phase_manager and context.phase_manager.notifier:
20
+ if context.status_manager and context.status_manager.notifier:
21
21
  todo_list = context.state.todo_list
22
22
  if todo_list:
23
23
  todos_for_llm = [todo.model_dump(mode='json') for todo in todo_list.get_all_todos()]
24
- context.phase_manager.notifier.notify_agent_data_todo_list_updated(todos_for_llm)
24
+ context.status_manager.notifier.notify_agent_data_todo_list_updated(todos_for_llm)
25
25
  logger.debug(f"Agent '{context.agent_id}': Notified ToDo list update with {len(todos_for_llm)} items.")
26
26
 
27
27
  class CreateToDoList(BaseTool):
@@ -13,11 +13,11 @@ if TYPE_CHECKING:
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
15
  def _notify_todo_update(context: 'AgentContext'):
16
- if context.phase_manager and context.phase_manager.notifier:
16
+ if context.status_manager and context.status_manager.notifier:
17
17
  todo_list = context.state.todo_list
18
18
  if todo_list:
19
19
  todos_for_llm = [todo.model_dump(mode='json') for todo in todo_list.get_all_todos()]
20
- context.phase_manager.notifier.notify_agent_data_todo_list_updated(todos_for_llm)
20
+ context.status_manager.notifier.notify_agent_data_todo_list_updated(todos_for_llm)
21
21
  logger.debug(f"Agent '{context.agent_id}': Notified ToDo list update with {len(todos_for_llm)} items.")
22
22
 
23
23
  class UpdateToDoStatus(BaseTool):
@@ -15,17 +15,28 @@ 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
30
  from .file.read_file import read_file
25
31
  from .file.write_file import write_file
26
- from .file.edit_file import edit_file
27
- from .file.search_files import search_files
28
- from .file.list_directory import list_directory
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
29
40
 
30
41
  # General Class-based tools
31
42
  try:
@@ -33,7 +44,6 @@ try:
33
44
  except ModuleNotFoundError as import_err:
34
45
  logger.warning("Search tool not available: %s", import_err)
35
46
  Search = None
36
- from .timer import Timer
37
47
  try:
38
48
  from .multimedia.image_tools import GenerateImageTool, EditImageTool
39
49
  except ModuleNotFoundError as import_err:
@@ -51,33 +61,14 @@ except ModuleNotFoundError as import_err:
51
61
  logger.warning("Download media tool not available: %s", import_err)
52
62
  DownloadMediaTool = None
53
63
 
54
- # Standalone Browser tools
55
- try:
56
- from .browser.standalone.navigate_to import NavigateTo as StandaloneNavigateTo # Alias to avoid name clash
57
- from .browser.standalone.webpage_reader import WebPageReader as StandaloneWebPageReader # Alias
58
- from .browser.standalone.webpage_screenshot_taker import WebPageScreenshotTaker as StandaloneWebPageScreenshotTaker # Alias
59
- from .browser.standalone.webpage_image_downloader import WebPageImageDownloader
60
- from .browser.standalone.web_page_pdf_generator import WebPagePDFGenerator
61
- except ModuleNotFoundError as import_err:
62
- logger.warning('Standalone browser tools not available: %s', import_err)
63
- StandaloneNavigateTo = None
64
- StandaloneWebPageReader = None
65
- StandaloneWebPageScreenshotTaker = None
66
- WebPageImageDownloader = None
67
- WebPagePDFGenerator = None
68
-
69
- # Session-Aware Browser tools
64
+ # Web tools
70
65
  try:
71
- from .browser.session_aware.browser_session_aware_navigate_to import BrowserSessionAwareNavigateTo
72
- from .browser.session_aware.browser_session_aware_web_element_trigger import BrowserSessionAwareWebElementTrigger
73
- from .browser.session_aware.browser_session_aware_webpage_reader import BrowserSessionAwareWebPageReader
74
- from .browser.session_aware.browser_session_aware_webpage_screenshot_taker import BrowserSessionAwareWebPageScreenshotTaker
66
+ from .web.read_url_tool import ReadUrl
75
67
  except ModuleNotFoundError as import_err:
76
- logger.warning('Session-aware browser tools not available: %s', import_err)
77
- BrowserSessionAwareNavigateTo = None
78
- BrowserSessionAwareWebElementTrigger = None
79
- BrowserSessionAwareWebPageReader = None
80
- BrowserSessionAwareWebPageScreenshotTaker = None
68
+ logger.warning("ReadUrl tool not available: %s", import_err)
69
+ ReadUrl = None
70
+
71
+
81
72
 
82
73
 
83
74
  __all__ = [
@@ -92,31 +83,27 @@ __all__ = [
92
83
  "ToolCategory",
93
84
 
94
85
  # Re-exported functional tool instances
95
- "bash_executor",
86
+ "run_bash",
87
+ "start_background_process",
88
+ "get_process_output",
89
+ "stop_background_process",
96
90
  "read_file",
97
91
  "write_file",
98
- "edit_file",
99
- "search_files",
100
- "list_directory",
92
+ "patch_file",
93
+ "load_skill",
101
94
 
102
95
  # Re-exported general class-based tools
103
96
  "Search",
104
- "Timer",
105
97
  "GenerateImageTool",
106
98
  "EditImageTool",
107
99
  "ReadMediaFile",
108
100
  "DownloadMediaTool",
109
101
 
110
- # Re-exported Standalone Browser tools
111
- "StandaloneNavigateTo",
112
- "StandaloneWebPageReader",
113
- "StandaloneWebPageScreenshotTaker",
114
- "WebPageImageDownloader",
115
- "WebPagePDFGenerator",
116
-
117
- # Re-exported Session-Aware Browser tools
118
- "BrowserSessionAwareNavigateTo",
119
- "BrowserSessionAwareWebElementTrigger",
120
- "BrowserSessionAwareWebPageReader",
121
- "BrowserSessionAwareWebPageScreenshotTaker",
102
+ # Re-exported Web tools
103
+ "ReadUrl",
104
+
105
+ # Tool Formatting
106
+ "register_tool_formatter",
107
+ "BaseSchemaFormatter",
108
+ "BaseExampleFormatter",
122
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.")
@@ -1,13 +1,9 @@
1
- from .edit_file import edit_file
1
+ from .patch_file import patch_file
2
2
  from .read_file import read_file
3
3
  from .write_file import write_file
4
- from .search_files import search_files
5
- from .list_directory import list_directory
6
4
 
7
5
  __all__ = [
8
- "edit_file",
6
+ "patch_file",
9
7
  "read_file",
10
8
  "write_file",
11
- "search_files",
12
- "list_directory",
13
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
@@ -11,15 +13,32 @@ if TYPE_CHECKING:
11
13
  logger = logging.getLogger(__name__)
12
14
 
13
15
  @tool(name="read_file", category=ToolCategory.FILE_SYSTEM)
14
- async def read_file(context: 'AgentContext', path: str) -> str:
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
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 read_file(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:
@@ -23,8 +23,10 @@ async def write_file(context: 'AgentContext', path: str, content: str) -> str:
23
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 write_file(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 write_file(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)}")