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
@@ -1,101 +0,0 @@
1
- """
2
- File: autobyteus/tools/browser/standalone/webpage_reader.py
3
- This module provides a WebPageReader tool for reading and cleaning HTML content from webpages.
4
- """
5
-
6
- import logging
7
- from typing import Optional, TYPE_CHECKING, Any
8
- from autobyteus.tools.base_tool import BaseTool
9
- from autobyteus.tools.tool_config import ToolConfig
10
- from autobyteus.utils.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
11
- from autobyteus.tools.tool_category import ToolCategory
12
- from brui_core.ui_integrator import UIIntegrator
13
- from autobyteus.utils.html_cleaner import clean, CleaningMode
14
-
15
- if TYPE_CHECKING:
16
- from autobyteus.agent.context import AgentContext
17
-
18
- logger = logging.getLogger(__name__)
19
-
20
- class WebPageReader(BaseTool, UIIntegrator):
21
- """
22
- A class that reads and cleans the HTML content from a given webpage using Playwright.
23
- """
24
- CATEGORY = ToolCategory.WEB
25
-
26
- def __init__(self, config: Optional[ToolConfig] = None):
27
- BaseTool.__init__(self, config=config)
28
- UIIntegrator.__init__(self)
29
-
30
- cleaning_mode_to_use = CleaningMode.THOROUGH
31
- if config:
32
- cleaning_mode_value = config.get('cleaning_mode')
33
- if cleaning_mode_value:
34
- if isinstance(cleaning_mode_value, str):
35
- try:
36
- cleaning_mode_to_use = CleaningMode(cleaning_mode_value.upper())
37
- except ValueError:
38
- logger.warning(f"Invalid cleaning_mode string '{cleaning_mode_value}' in config for WebPageReader. Using THOROUGH.")
39
- cleaning_mode_to_use = CleaningMode.THOROUGH
40
- elif isinstance(cleaning_mode_value, CleaningMode):
41
- cleaning_mode_to_use = cleaning_mode_value
42
- else:
43
- logger.warning(f"Invalid type for cleaning_mode in config for WebPageReader. Using THOROUGH.")
44
-
45
- self.cleaning_mode = cleaning_mode_to_use
46
- logger.debug(f"WebPageReader initialized with cleaning_mode: {self.cleaning_mode}")
47
-
48
- @classmethod
49
- def get_description(cls) -> str:
50
- return "Reads and cleans the HTML content from a given webpage URL using Playwright."
51
-
52
- @classmethod
53
- def get_argument_schema(cls) -> Optional[ParameterSchema]:
54
- """Schema for arguments passed to the execute method."""
55
- schema = ParameterSchema()
56
- schema.add_parameter(ParameterDefinition(
57
- name="url",
58
- param_type=ParameterType.STRING,
59
- description="The URL of the webpage to read content from.",
60
- required=True
61
- ))
62
- return schema
63
-
64
- @classmethod
65
- def get_config_schema(cls) -> Optional[ParameterSchema]:
66
- """Schema for parameters to configure the WebPageReader instance itself."""
67
- schema = ParameterSchema()
68
- schema.add_parameter(ParameterDefinition(
69
- name="cleaning_mode",
70
- param_type=ParameterType.ENUM,
71
- description="Level of HTML content cleanup for webpage content. BASIC or THOROUGH.",
72
- required=False,
73
- default_value="THOROUGH",
74
- enum_values=[mode.name for mode in CleaningMode]
75
- ))
76
- return schema
77
-
78
- async def _execute(self, context: 'AgentContext', url: str) -> str:
79
- logger.info(f"WebPageReader executing for agent {context.agent_id} with URL: '{url}'")
80
-
81
- try:
82
- await self.initialize()
83
- if not self.page:
84
- logger.error("Playwright page not initialized in WebPageReader.")
85
- raise RuntimeError("Playwright page not available for WebPageReader.")
86
-
87
- await self.page.goto(url, timeout=60000, wait_until="domcontentloaded")
88
- page_content = await self.page.content()
89
-
90
- cleaned_content = clean(page_content, mode=self.cleaning_mode)
91
-
92
- return f'''here is the html of the web page
93
- <WebPageContentStart>
94
- {cleaned_content}
95
- </WebPageContentEnd>
96
- '''
97
- except Exception as e:
98
- logger.error(f"Error reading webpage at URL '{url}': {e}", exc_info=True)
99
- raise RuntimeError(f"WebPageReader failed for URL '{url}': {str(e)}")
100
- finally:
101
- await self.close()
@@ -1,101 +0,0 @@
1
- from typing import Optional, TYPE_CHECKING, Any
2
- from autobyteus.tools.base_tool import BaseTool
3
- from autobyteus.tools.tool_config import ToolConfig
4
- from autobyteus.utils.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
5
- from autobyteus.tools.tool_category import ToolCategory
6
- from brui_core.ui_integrator import UIIntegrator
7
- import logging
8
- import os
9
-
10
- if TYPE_CHECKING:
11
- from autobyteus.agent.context import AgentContext
12
-
13
- logger = logging.getLogger(__name__)
14
-
15
- class WebPageScreenshotTaker(BaseTool, UIIntegrator):
16
- """
17
- A class that takes a screenshot of a given webpage using Playwright and saves it.
18
- """
19
- CATEGORY = ToolCategory.WEB
20
-
21
- def __init__(self, config: Optional[ToolConfig] = None):
22
- BaseTool.__init__(self, config=config)
23
- UIIntegrator.__init__(self)
24
-
25
- self.full_page: bool = True
26
- self.image_format: str = "png"
27
-
28
- if config:
29
- self.full_page = config.get('full_page', True)
30
- self.image_format = str(config.get('image_format', 'png')).lower()
31
- if self.image_format not in ["png", "jpeg"]:
32
- logger.warning(f"Invalid image_format '{self.image_format}' in config. Defaulting to 'png'.")
33
- self.image_format = "png"
34
- logger.debug(f"WebPageScreenshotTaker initialized. Full page: {self.full_page}, Format: {self.image_format}")
35
-
36
- @classmethod
37
- def get_description(cls) -> str:
38
- return "Takes a screenshot of a given webpage URL using Playwright and saves it to the specified file path. Returns the absolute path of the saved screenshot."
39
-
40
- @classmethod
41
- def get_argument_schema(cls) -> Optional[ParameterSchema]:
42
- schema = ParameterSchema()
43
- schema.add_parameter(ParameterDefinition(
44
- name="url",
45
- param_type=ParameterType.STRING,
46
- description="The URL of the webpage to take a screenshot of.",
47
- required=True
48
- ))
49
- schema.add_parameter(ParameterDefinition(
50
- name="file_path",
51
- param_type=ParameterType.STRING,
52
- description="The local file path (including filename and extension, e.g., 'screenshots/page.png') where the screenshot will be saved.",
53
- required=True
54
- ))
55
- return schema
56
-
57
- @classmethod
58
- def get_config_schema(cls) -> Optional[ParameterSchema]:
59
- schema = ParameterSchema()
60
- schema.add_parameter(ParameterDefinition(
61
- name="full_page",
62
- param_type=ParameterType.BOOLEAN,
63
- description="Whether to capture the full scrollable page content or just the visible viewport by default for this instance.",
64
- required=False,
65
- default_value=True
66
- ))
67
- schema.add_parameter(ParameterDefinition(
68
- name="image_format",
69
- param_type=ParameterType.ENUM,
70
- description="Default image format for screenshots taken by this instance (png or jpeg).",
71
- required=False,
72
- default_value="png",
73
- enum_values=["png", "jpeg"]
74
- ))
75
- return schema
76
-
77
- async def _execute(self, context: 'AgentContext', url: str, file_path: str) -> str:
78
- logger.info(f"WebPageScreenshotTaker for agent {context.agent_id} taking screenshot of '{url}', saving to '{file_path}'.")
79
-
80
- output_dir = os.path.dirname(file_path)
81
- if output_dir:
82
- os.makedirs(output_dir, exist_ok=True)
83
-
84
- try:
85
- await self.initialize()
86
- if not self.page:
87
- logger.error("Playwright page not initialized in WebPageScreenshotTaker.")
88
- raise RuntimeError("Playwright page not available for WebPageScreenshotTaker.")
89
-
90
- await self.page.goto(url, wait_until="networkidle", timeout=60000)
91
-
92
- await self.page.screenshot(path=file_path, full_page=self.full_page, type=self.image_format) # type: ignore
93
-
94
- absolute_file_path = os.path.abspath(file_path)
95
- logger.info(f"Screenshot saved successfully to {absolute_file_path}")
96
- return absolute_file_path
97
- except Exception as e:
98
- logger.error(f"Error taking screenshot of URL '{url}': {e}", exc_info=True)
99
- raise RuntimeError(f"WebPageScreenshotTaker failed for URL '{url}': {str(e)}")
100
- finally:
101
- await self.close()
@@ -1,200 +0,0 @@
1
- import os
2
- import re
3
- import logging
4
- from typing import TYPE_CHECKING, List
5
-
6
- from autobyteus.tools.functional_tool import tool
7
- from autobyteus.tools.tool_category import ToolCategory
8
-
9
- if TYPE_CHECKING:
10
- from autobyteus.agent.context import AgentContext
11
-
12
- logger = logging.getLogger(__name__)
13
-
14
- _HUNK_HEADER_RE = re.compile(r"^@@ -(?P<old_start>\d+)(?:,(?P<old_count>\d+))? \+(?P<new_start>\d+)(?:,(?P<new_count>\d+))? @@")
15
-
16
- class PatchApplicationError(ValueError):
17
- """Raised when a unified diff patch cannot be applied to the target file."""
18
-
19
-
20
- def _resolve_file_path(context: 'AgentContext', path: str) -> str:
21
- """Resolves an absolute path for the given input, using the agent workspace when needed."""
22
- if os.path.isabs(path):
23
- final_path = path
24
- logger.debug("FileEdit: provided path '%s' is absolute.", path)
25
- else:
26
- if not context.workspace:
27
- error_msg = ("Relative path '%s' provided, but no workspace is configured for agent '%s'. "
28
- "A workspace is required to resolve relative paths.")
29
- logger.error(error_msg, path, context.agent_id)
30
- raise ValueError(error_msg % (path, context.agent_id))
31
- base_path = context.workspace.get_base_path()
32
- if not base_path or not isinstance(base_path, str):
33
- error_msg = ("Agent '%s' has a configured workspace, but it provided an invalid base path ('%s'). "
34
- "Cannot resolve relative path '%s'.")
35
- logger.error(error_msg, context.agent_id, base_path, path)
36
- raise ValueError(error_msg % (context.agent_id, base_path, path))
37
- final_path = os.path.join(base_path, path)
38
- logger.debug("FileEdit: resolved relative path '%s' against workspace base '%s' to '%s'.", path, base_path, final_path)
39
-
40
- normalized_path = os.path.normpath(final_path)
41
- logger.debug("FileEdit: normalized path to '%s'.", normalized_path)
42
- return normalized_path
43
-
44
-
45
- def _apply_unified_diff(original_lines: List[str], patch: str) -> List[str]:
46
- """Applies a unified diff patch to the provided original lines and returns the patched lines."""
47
- if not patch or not patch.strip():
48
- raise PatchApplicationError("Patch content is empty; nothing to apply.")
49
-
50
- patched_lines: List[str] = []
51
- orig_idx = 0
52
- patch_lines = patch.splitlines(keepends=True)
53
- line_idx = 0
54
-
55
- while line_idx < len(patch_lines):
56
- line = patch_lines[line_idx]
57
-
58
- if line.startswith('---') or line.startswith('+++'):
59
- logger.debug("FileEdit: skipping diff header line '%s'.", line.strip())
60
- line_idx += 1
61
- continue
62
-
63
- if not line.startswith('@@'):
64
- stripped = line.strip()
65
- if stripped == '':
66
- line_idx += 1
67
- continue
68
- raise PatchApplicationError(f"Unexpected content outside of hunk header: '{stripped}'.")
69
-
70
- match = _HUNK_HEADER_RE.match(line)
71
- if not match:
72
- raise PatchApplicationError(f"Malformed hunk header: '{line.strip()}'.")
73
-
74
- old_start = int(match.group('old_start'))
75
- old_count = int(match.group('old_count') or '1')
76
- new_start = int(match.group('new_start'))
77
- new_count = int(match.group('new_count') or '1')
78
- logger.debug("FileEdit: processing hunk old_start=%s old_count=%s new_start=%s new_count=%s.",
79
- old_start, old_count, new_start, new_count)
80
-
81
- target_idx = old_start - 1 if old_start > 0 else 0
82
- if target_idx > len(original_lines):
83
- raise PatchApplicationError("Patch hunk starts beyond end of file.")
84
- if target_idx < orig_idx:
85
- raise PatchApplicationError("Patch hunks overlap or are out of order.")
86
-
87
- patched_lines.extend(original_lines[orig_idx:target_idx])
88
- orig_idx = target_idx
89
-
90
- line_idx += 1
91
- hunk_consumed = 0
92
- removed = 0
93
- added = 0
94
-
95
- while line_idx < len(patch_lines):
96
- hunk_line = patch_lines[line_idx]
97
- if hunk_line.startswith('@@'):
98
- break
99
-
100
- if hunk_line.startswith('-'):
101
- if orig_idx >= len(original_lines):
102
- raise PatchApplicationError("Patch attempts to remove lines beyond file length.")
103
- if original_lines[orig_idx] != hunk_line[1:]:
104
- raise PatchApplicationError("Patch removal does not match file content.")
105
- orig_idx += 1
106
- hunk_consumed += 1
107
- removed += 1
108
- elif hunk_line.startswith('+'):
109
- patched_lines.append(hunk_line[1:])
110
- added += 1
111
- elif hunk_line.startswith(' '):
112
- if orig_idx >= len(original_lines):
113
- raise PatchApplicationError("Patch context exceeds file length.")
114
- if original_lines[orig_idx] != hunk_line[1:]:
115
- raise PatchApplicationError("Patch context does not match file content.")
116
- patched_lines.append(original_lines[orig_idx])
117
- orig_idx += 1
118
- hunk_consumed += 1
119
- elif hunk_line.startswith('\\'):
120
- if hunk_line.strip() == '\':
121
- if patched_lines:
122
- patched_lines[-1] = patched_lines[-1].rstrip('\n')
123
- else:
124
- raise PatchApplicationError(f"Unsupported patch directive: '{hunk_line.strip()}'.")
125
- elif hunk_line.strip() == '':
126
- patched_lines.append(hunk_line)
127
- else:
128
- raise PatchApplicationError(f"Unsupported patch line: '{hunk_line.strip()}'.")
129
-
130
- line_idx += 1
131
-
132
- consumed_total = hunk_consumed
133
- if old_count == 0:
134
- if consumed_total != 0:
135
- raise PatchApplicationError("Patch expects zero original lines but consumed some context.")
136
- else:
137
- if consumed_total != old_count:
138
- raise PatchApplicationError(
139
- f"Patch expected to consume {old_count} original lines but consumed {consumed_total}.")
140
-
141
- context_lines = consumed_total - removed
142
- expected_new_lines = context_lines + added
143
- if new_count == 0:
144
- if expected_new_lines != 0:
145
- raise PatchApplicationError("Patch declares zero new lines but produced changes.")
146
- else:
147
- if expected_new_lines != new_count:
148
- raise PatchApplicationError(
149
- f"Patch expected to produce {new_count} new lines but produced {expected_new_lines}.")
150
-
151
- patched_lines.extend(original_lines[orig_idx:])
152
- return patched_lines
153
-
154
-
155
- @tool(name="FileEdit", category=ToolCategory.FILE_SYSTEM)
156
- async def file_edit(context: 'AgentContext', path: str, patch: str, create_if_missing: bool = False) -> str:
157
- """Applies a unified diff patch to update a text file without overwriting unrelated content.
158
-
159
- Args:
160
- path: Path to the target file. Relative paths are resolved against the agent workspace when available.
161
- patch: Unified diff patch describing the edits to apply.
162
- create_if_missing: When True, allows applying a patch that introduces content to a non-existent file.
163
-
164
- Raises:
165
- FileNotFoundError: If the file does not exist and create_if_missing is False.
166
- PatchApplicationError: If the patch content cannot be applied cleanly.
167
- IOError: If file reading or writing fails.
168
- """
169
- logger.debug("FileEdit: requested edit for agent '%s' on path '%s'.", context.agent_id, path)
170
- final_path = _resolve_file_path(context, path)
171
-
172
- dir_path = os.path.dirname(final_path)
173
- if dir_path and not os.path.exists(dir_path) and create_if_missing:
174
- os.makedirs(dir_path, exist_ok=True)
175
-
176
- file_exists = os.path.exists(final_path)
177
- if not file_exists and not create_if_missing:
178
- raise FileNotFoundError(f"The file at resolved path {final_path} does not exist.")
179
-
180
- try:
181
- original_lines: List[str]
182
- if file_exists:
183
- with open(final_path, 'r', encoding='utf-8') as source:
184
- original_lines = source.read().splitlines(keepends=True)
185
- else:
186
- original_lines = []
187
-
188
- patched_lines = _apply_unified_diff(original_lines, patch)
189
-
190
- with open(final_path, 'w', encoding='utf-8') as destination:
191
- destination.writelines(patched_lines)
192
-
193
- logger.info("FileEdit: successfully applied patch to '%s'.", final_path)
194
- return f"File edited successfully at {final_path}"
195
- except PatchApplicationError as patch_err:
196
- logger.error("FileEdit: failed to apply patch to '%s': %s", final_path, patch_err, exc_info=True)
197
- raise patch_err
198
- except Exception as exc: # pragma: no cover - general safeguard
199
- logger.error("FileEdit: unexpected error while editing '%s': %s", final_path, exc, exc_info=True)
200
- raise IOError(f"Could not edit file at '{final_path}': {exc}")
@@ -1,149 +0,0 @@
1
- import os
2
- import json
3
- import logging
4
- import aiohttp
5
- from typing import Optional, TYPE_CHECKING, Any, Dict, List
6
-
7
- from autobyteus.tools.base_tool import BaseTool
8
- from autobyteus.tools.tool_config import ToolConfig
9
- from autobyteus.utils.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
10
- from autobyteus.tools.tool_category import ToolCategory
11
-
12
- if TYPE_CHECKING:
13
- from autobyteus.agent.context import AgentContext
14
-
15
- logger = logging.getLogger(__name__)
16
-
17
- class GoogleSearch(BaseTool):
18
- """
19
- Performs a Google search using the Serper.dev API and returns a structured summary of the results.
20
- This tool requires a Serper API key, which should be set in the SERPER_API_KEY environment variable.
21
- """
22
- CATEGORY = ToolCategory.WEB
23
- API_URL = "https://google.serper.dev/search"
24
-
25
- def __init__(self, config: Optional[ToolConfig] = None):
26
- super().__init__(config=config)
27
- self.api_key: Optional[str] = None
28
-
29
- if config:
30
- self.api_key = config.get('api_key')
31
-
32
- if not self.api_key:
33
- self.api_key = os.getenv("SERPER_API_KEY")
34
-
35
- if not self.api_key:
36
- raise ValueError(
37
- "GoogleSearch tool requires a Serper API key. "
38
- "Please provide it via the 'api_key' config parameter or set the 'SERPER_API_KEY' environment variable."
39
- )
40
- logger.debug("GoogleSearch (API-based) tool initialized.")
41
-
42
- @classmethod
43
- def get_name(cls) -> str:
44
- return "GoogleSearch"
45
-
46
- @classmethod
47
- def get_description(cls) -> str:
48
- return (
49
- "Searches Google for a given query using the Serper API. "
50
- "Returns a concise, structured summary of search results, including direct answers and top organic links."
51
- )
52
-
53
- @classmethod
54
- def get_argument_schema(cls) -> Optional[ParameterSchema]:
55
- schema = ParameterSchema()
56
- schema.add_parameter(ParameterDefinition(
57
- name="query",
58
- param_type=ParameterType.STRING,
59
- description="The search query string.",
60
- required=True
61
- ))
62
- schema.add_parameter(ParameterDefinition(
63
- name="num_results",
64
- param_type=ParameterType.INTEGER,
65
- description="The number of organic search results to return.",
66
- required=False,
67
- default_value=5,
68
- min_value=1,
69
- max_value=10
70
- ))
71
- return schema
72
-
73
- @classmethod
74
- def get_config_schema(cls) -> Optional[ParameterSchema]:
75
- schema = ParameterSchema()
76
- schema.add_parameter(ParameterDefinition(
77
- name="api_key",
78
- param_type=ParameterType.STRING,
79
- description="The API key for the Serper.dev service. Overrides the SERPER_API_KEY environment variable.",
80
- required=False
81
- ))
82
- return schema
83
-
84
- def _format_results(self, data: Dict[str, Any]) -> str:
85
- """Formats the JSON response from Serper into a clean string for an LLM."""
86
- summary_parts = []
87
-
88
- # 1. Answer Box (most important for direct questions)
89
- if "answerBox" in data:
90
- answer_box = data["answerBox"]
91
- title = answer_box.get("title", "")
92
- snippet = answer_box.get("snippet") or answer_box.get("answer")
93
- summary_parts.append(f"Direct Answer for '{title}':\n{snippet}")
94
-
95
- # 2. Knowledge Graph (for entity information)
96
- if "knowledgeGraph" in data:
97
- kg = data["knowledgeGraph"]
98
- title = kg.get("title", "")
99
- description = kg.get("description")
100
- summary_parts.append(f"Summary for '{title}':\n{description}")
101
-
102
- # 3. Organic Results (the main search links)
103
- if "organic" in data and data["organic"]:
104
- organic_results = data["organic"]
105
- results_str = "\n".join(
106
- f"{i+1}. {result.get('title', 'No Title')}\n"
107
- f" Link: {result.get('link', 'No Link')}\n"
108
- f" Snippet: {result.get('snippet', 'No Snippet')}"
109
- for i, result in enumerate(organic_results)
110
- )
111
- summary_parts.append(f"Search Results:\n{results_str}")
112
-
113
- if not summary_parts:
114
- return "No relevant information found for the query."
115
-
116
- return "\n\n---\n\n".join(summary_parts)
117
-
118
-
119
- async def _execute(self, context: 'AgentContext', query: str, num_results: int = 5) -> str:
120
- logger.info(f"Executing GoogleSearch (API) for agent {context.agent_id} with query: '{query}'")
121
-
122
- headers = {
123
- 'X-API-KEY': self.api_key,
124
- 'Content-Type': 'application/json'
125
- }
126
- payload = json.dumps({
127
- "q": query,
128
- "num": num_results
129
- })
130
-
131
- try:
132
- async with aiohttp.ClientSession() as session:
133
- async with session.post(self.API_URL, headers=headers, data=payload) as response:
134
- if response.status == 200:
135
- data = await response.json()
136
- return self._format_results(data)
137
- else:
138
- error_text = await response.text()
139
- logger.error(
140
- f"Serper API returned a non-200 status code: {response.status}. "
141
- f"Response: {error_text}"
142
- )
143
- raise RuntimeError(f"API request failed with status {response.status}: {error_text}")
144
- except aiohttp.ClientError as e:
145
- logger.error(f"Network error during GoogleSearch API call: {e}", exc_info=True)
146
- raise RuntimeError(f"A network error occurred: {e}")
147
- except Exception as e:
148
- logger.error(f"An unexpected error occurred in GoogleSearch tool: {e}", exc_info=True)
149
- raise