autobyteus 1.2.1__py3-none-any.whl → 1.3.0__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 (472) hide show
  1. autobyteus/agent/agent.py +15 -5
  2. autobyteus/agent/bootstrap_steps/__init__.py +3 -3
  3. autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +5 -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/working_context_snapshot_restore_step.py +38 -0
  8. autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +2 -4
  9. autobyteus/agent/context/agent_config.py +47 -20
  10. autobyteus/agent/context/agent_context.py +23 -18
  11. autobyteus/agent/context/agent_runtime_state.py +21 -19
  12. autobyteus/agent/events/__init__.py +16 -1
  13. autobyteus/agent/events/agent_events.py +43 -3
  14. autobyteus/agent/events/agent_input_event_queue_manager.py +79 -26
  15. autobyteus/agent/events/event_store.py +57 -0
  16. autobyteus/agent/events/notifiers.py +69 -59
  17. autobyteus/agent/events/worker_event_dispatcher.py +21 -64
  18. autobyteus/agent/factory/agent_factory.py +83 -6
  19. autobyteus/agent/handlers/__init__.py +2 -0
  20. autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +51 -34
  21. autobyteus/agent/handlers/bootstrap_event_handler.py +155 -0
  22. autobyteus/agent/handlers/inter_agent_message_event_handler.py +10 -0
  23. autobyteus/agent/handlers/lifecycle_event_logger.py +19 -11
  24. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +10 -15
  25. autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +188 -48
  26. autobyteus/agent/handlers/tool_execution_approval_event_handler.py +0 -10
  27. autobyteus/agent/handlers/tool_invocation_request_event_handler.py +53 -48
  28. autobyteus/agent/handlers/tool_result_event_handler.py +7 -8
  29. autobyteus/agent/handlers/user_input_message_event_handler.py +10 -3
  30. autobyteus/agent/input_processor/memory_ingest_input_processor.py +44 -0
  31. autobyteus/agent/lifecycle/__init__.py +12 -0
  32. autobyteus/agent/lifecycle/base_processor.py +109 -0
  33. autobyteus/agent/lifecycle/events.py +35 -0
  34. autobyteus/agent/lifecycle/processor_definition.py +36 -0
  35. autobyteus/agent/lifecycle/processor_registry.py +106 -0
  36. autobyteus/agent/llm_request_assembler.py +98 -0
  37. autobyteus/agent/llm_response_processor/__init__.py +1 -8
  38. autobyteus/agent/message/context_file_type.py +1 -1
  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 -183
  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 +82 -0
  114. autobyteus/agent/streaming/stream_event_payloads.py +2 -223
  115. autobyteus/agent/streaming/stream_events.py +3 -140
  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 +1 -2
  145. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +4 -4
  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 +9 -6
  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 +6 -6
  167. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +4 -4
  168. autobyteus/agent_team/streaming/agent_team_stream_events.py +3 -3
  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/task_notification_mode.py +19 -0
  172. autobyteus/agent_team/utils/wait_for_idle.py +4 -4
  173. autobyteus/cli/agent_cli.py +18 -10
  174. autobyteus/cli/agent_team_tui/app.py +14 -11
  175. autobyteus/cli/agent_team_tui/state.py +13 -15
  176. autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
  177. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +143 -36
  178. autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
  179. autobyteus/cli/agent_team_tui/widgets/shared.py +25 -25
  180. autobyteus/cli/cli_display.py +193 -44
  181. autobyteus/cli/workflow_tui/app.py +9 -10
  182. autobyteus/cli/workflow_tui/state.py +14 -16
  183. autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
  184. autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
  185. autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
  186. autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
  187. autobyteus/clients/autobyteus_client.py +94 -1
  188. autobyteus/events/event_types.py +11 -18
  189. autobyteus/llm/api/autobyteus_llm.py +33 -29
  190. autobyteus/llm/api/claude_llm.py +142 -36
  191. autobyteus/llm/api/gemini_llm.py +163 -59
  192. autobyteus/llm/api/grok_llm.py +1 -1
  193. autobyteus/llm/api/minimax_llm.py +26 -0
  194. autobyteus/llm/api/mistral_llm.py +113 -87
  195. autobyteus/llm/api/ollama_llm.py +9 -42
  196. autobyteus/llm/api/openai_compatible_llm.py +127 -91
  197. autobyteus/llm/api/openai_llm.py +3 -3
  198. autobyteus/llm/api/openai_responses_llm.py +324 -0
  199. autobyteus/llm/api/zhipu_llm.py +21 -2
  200. autobyteus/llm/autobyteus_provider.py +70 -60
  201. autobyteus/llm/base_llm.py +85 -81
  202. autobyteus/llm/converters/__init__.py +14 -0
  203. autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
  204. autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
  205. autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
  206. autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
  207. autobyteus/llm/extensions/base_extension.py +6 -12
  208. autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
  209. autobyteus/llm/llm_factory.py +282 -204
  210. autobyteus/llm/lmstudio_provider.py +60 -49
  211. autobyteus/llm/models.py +35 -2
  212. autobyteus/llm/ollama_provider.py +60 -49
  213. autobyteus/llm/ollama_provider_resolver.py +0 -1
  214. autobyteus/llm/prompt_renderers/__init__.py +19 -0
  215. autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
  216. autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
  217. autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
  218. autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
  219. autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
  220. autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
  221. autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
  222. autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
  223. autobyteus/llm/providers.py +1 -3
  224. autobyteus/llm/token_counter/claude_token_counter.py +56 -25
  225. autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
  226. autobyteus/llm/token_counter/openai_token_counter.py +24 -5
  227. autobyteus/llm/token_counter/token_counter_factory.py +12 -5
  228. autobyteus/llm/utils/llm_config.py +6 -12
  229. autobyteus/llm/utils/media_payload_formatter.py +27 -20
  230. autobyteus/llm/utils/messages.py +55 -3
  231. autobyteus/llm/utils/response_types.py +3 -0
  232. autobyteus/llm/utils/tool_call_delta.py +31 -0
  233. autobyteus/memory/__init__.py +35 -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 +205 -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/path_resolver.py +27 -0
  247. autobyteus/memory/policies/__init__.py +5 -0
  248. autobyteus/memory/policies/compaction_policy.py +16 -0
  249. autobyteus/memory/restore/__init__.py +1 -0
  250. autobyteus/memory/restore/working_context_snapshot_bootstrapper.py +61 -0
  251. autobyteus/memory/retrieval/__init__.py +7 -0
  252. autobyteus/memory/retrieval/memory_bundle.py +11 -0
  253. autobyteus/memory/retrieval/retriever.py +13 -0
  254. autobyteus/memory/store/__init__.py +9 -0
  255. autobyteus/memory/store/base_store.py +14 -0
  256. autobyteus/memory/store/file_store.py +98 -0
  257. autobyteus/memory/store/working_context_snapshot_store.py +28 -0
  258. autobyteus/memory/tool_interaction_builder.py +46 -0
  259. autobyteus/memory/turn_tracker.py +9 -0
  260. autobyteus/memory/working_context_snapshot.py +69 -0
  261. autobyteus/memory/working_context_snapshot_serializer.py +135 -0
  262. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
  263. autobyteus/multimedia/audio/api/gemini_audio_client.py +109 -16
  264. autobyteus/multimedia/audio/audio_client_factory.py +47 -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 +39 -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/tools/todo_tools/add_todo.py +2 -2
  277. autobyteus/task_management/tools/todo_tools/create_todo_list.py +2 -2
  278. autobyteus/task_management/tools/todo_tools/update_todo_status.py +2 -2
  279. autobyteus/tools/__init__.py +34 -47
  280. autobyteus/tools/base_tool.py +7 -0
  281. autobyteus/tools/file/__init__.py +2 -6
  282. autobyteus/tools/file/patch_file.py +149 -0
  283. autobyteus/tools/file/read_file.py +36 -5
  284. autobyteus/tools/file/write_file.py +4 -1
  285. autobyteus/tools/functional_tool.py +43 -6
  286. autobyteus/tools/mcp/__init__.py +2 -0
  287. autobyteus/tools/mcp/config_service.py +5 -1
  288. autobyteus/tools/mcp/server/__init__.py +2 -0
  289. autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
  290. autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
  291. autobyteus/tools/mcp/server_instance_manager.py +8 -1
  292. autobyteus/tools/mcp/types.py +61 -0
  293. autobyteus/tools/multimedia/audio_tools.py +70 -17
  294. autobyteus/tools/multimedia/download_media_tool.py +18 -4
  295. autobyteus/tools/multimedia/image_tools.py +246 -62
  296. autobyteus/tools/operation_executor/journal_manager.py +107 -0
  297. autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
  298. autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
  299. autobyteus/tools/operation_executor/operation_executor.py +58 -0
  300. autobyteus/tools/registry/tool_definition.py +43 -2
  301. autobyteus/tools/skill/load_skill.py +50 -0
  302. autobyteus/tools/terminal/__init__.py +45 -0
  303. autobyteus/tools/terminal/ansi_utils.py +32 -0
  304. autobyteus/tools/terminal/background_process_manager.py +233 -0
  305. autobyteus/tools/terminal/output_buffer.py +105 -0
  306. autobyteus/tools/terminal/prompt_detector.py +63 -0
  307. autobyteus/tools/terminal/pty_session.py +241 -0
  308. autobyteus/tools/terminal/session_factory.py +20 -0
  309. autobyteus/tools/terminal/terminal_session_manager.py +226 -0
  310. autobyteus/tools/terminal/tools/__init__.py +13 -0
  311. autobyteus/tools/terminal/tools/get_process_output.py +81 -0
  312. autobyteus/tools/terminal/tools/run_bash.py +109 -0
  313. autobyteus/tools/terminal/tools/start_background_process.py +104 -0
  314. autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
  315. autobyteus/tools/terminal/types.py +54 -0
  316. autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
  317. autobyteus/tools/terminal/wsl_utils.py +156 -0
  318. autobyteus/tools/transaction_management/backup_handler.py +48 -0
  319. autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
  320. autobyteus/tools/usage/__init__.py +1 -2
  321. autobyteus/tools/usage/formatters/__init__.py +17 -1
  322. autobyteus/tools/usage/formatters/base_formatter.py +8 -0
  323. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
  324. autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
  325. autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
  326. autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
  327. autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
  328. autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
  329. autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
  330. autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
  331. autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
  332. autobyteus/tools/usage/registries/__init__.py +1 -3
  333. autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
  334. autobyteus/tools/usage/tool_schema_provider.py +51 -0
  335. autobyteus/tools/web/__init__.py +4 -0
  336. autobyteus/tools/web/read_url_tool.py +80 -0
  337. autobyteus/utils/diff_utils.py +271 -0
  338. autobyteus/utils/download_utils.py +109 -0
  339. autobyteus/utils/file_utils.py +57 -2
  340. autobyteus/utils/gemini_helper.py +64 -0
  341. autobyteus/utils/gemini_model_mapping.py +71 -0
  342. autobyteus/utils/llm_output_formatter.py +75 -0
  343. autobyteus/utils/tool_call_format.py +36 -0
  344. autobyteus/workflow/agentic_workflow.py +3 -3
  345. autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
  346. autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
  347. autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
  348. autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +3 -9
  349. autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
  350. autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
  351. autobyteus/workflow/context/workflow_context.py +3 -3
  352. autobyteus/workflow/context/workflow_runtime_state.py +5 -5
  353. autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
  354. autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
  355. autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
  356. autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
  357. autobyteus/workflow/runtime/workflow_runtime.py +8 -8
  358. autobyteus/workflow/runtime/workflow_worker.py +3 -3
  359. autobyteus/workflow/status/__init__.py +11 -0
  360. autobyteus/workflow/status/workflow_status.py +19 -0
  361. autobyteus/workflow/status/workflow_status_manager.py +48 -0
  362. autobyteus/workflow/streaming/__init__.py +2 -2
  363. autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
  364. autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
  365. autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
  366. autobyteus/workflow/utils/wait_for_idle.py +4 -4
  367. autobyteus-1.3.0.dist-info/METADATA +293 -0
  368. autobyteus-1.3.0.dist-info/RECORD +606 -0
  369. {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/WHEEL +1 -1
  370. {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/top_level.txt +0 -1
  371. autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
  372. autobyteus/agent/hooks/__init__.py +0 -16
  373. autobyteus/agent/hooks/base_phase_hook.py +0 -78
  374. autobyteus/agent/hooks/hook_definition.py +0 -36
  375. autobyteus/agent/hooks/hook_meta.py +0 -37
  376. autobyteus/agent/hooks/hook_registry.py +0 -106
  377. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
  378. autobyteus/agent/phases/__init__.py +0 -18
  379. autobyteus/agent/phases/discover.py +0 -53
  380. autobyteus/agent/phases/manager.py +0 -265
  381. autobyteus/agent/phases/transition_decorator.py +0 -40
  382. autobyteus/agent/phases/transition_info.py +0 -33
  383. autobyteus/agent/remote_agent.py +0 -244
  384. autobyteus/agent/workspace/workspace_definition.py +0 -36
  385. autobyteus/agent/workspace/workspace_meta.py +0 -37
  386. autobyteus/agent/workspace/workspace_registry.py +0 -72
  387. autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
  388. autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
  389. autobyteus/agent_team/phases/__init__.py +0 -11
  390. autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
  391. autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
  392. autobyteus/llm/api/bedrock_llm.py +0 -92
  393. autobyteus/llm/api/groq_llm.py +0 -94
  394. autobyteus/llm/api/nvidia_llm.py +0 -108
  395. autobyteus/llm/utils/token_pricing_config.py +0 -87
  396. autobyteus/rpc/__init__.py +0 -73
  397. autobyteus/rpc/client/__init__.py +0 -17
  398. autobyteus/rpc/client/abstract_client_connection.py +0 -124
  399. autobyteus/rpc/client/client_connection_manager.py +0 -153
  400. autobyteus/rpc/client/sse_client_connection.py +0 -306
  401. autobyteus/rpc/client/stdio_client_connection.py +0 -280
  402. autobyteus/rpc/config/__init__.py +0 -13
  403. autobyteus/rpc/config/agent_server_config.py +0 -153
  404. autobyteus/rpc/config/agent_server_registry.py +0 -152
  405. autobyteus/rpc/hosting.py +0 -244
  406. autobyteus/rpc/protocol.py +0 -244
  407. autobyteus/rpc/server/__init__.py +0 -20
  408. autobyteus/rpc/server/agent_server_endpoint.py +0 -181
  409. autobyteus/rpc/server/base_method_handler.py +0 -40
  410. autobyteus/rpc/server/method_handlers.py +0 -259
  411. autobyteus/rpc/server/sse_server_handler.py +0 -182
  412. autobyteus/rpc/server/stdio_server_handler.py +0 -151
  413. autobyteus/rpc/server_main.py +0 -198
  414. autobyteus/rpc/transport_type.py +0 -13
  415. autobyteus/tools/bash/__init__.py +0 -2
  416. autobyteus/tools/bash/bash_executor.py +0 -100
  417. autobyteus/tools/browser/__init__.py +0 -2
  418. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
  419. autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
  420. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
  421. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
  422. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
  423. autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
  424. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
  425. autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
  426. autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
  427. autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
  428. autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
  429. autobyteus/tools/browser/standalone/__init__.py +0 -6
  430. autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
  431. autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
  432. autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
  433. autobyteus/tools/browser/standalone/navigate_to.py +0 -84
  434. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -101
  435. autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -169
  436. autobyteus/tools/browser/standalone/webpage_reader.py +0 -105
  437. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -105
  438. autobyteus/tools/file/edit_file.py +0 -200
  439. autobyteus/tools/file/list_directory.py +0 -168
  440. autobyteus/tools/file/search_files.py +0 -188
  441. autobyteus/tools/timer.py +0 -175
  442. autobyteus/tools/usage/parsers/__init__.py +0 -22
  443. autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
  444. autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
  445. autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
  446. autobyteus/tools/usage/parsers/base_parser.py +0 -41
  447. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
  448. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
  449. autobyteus/tools/usage/parsers/exceptions.py +0 -13
  450. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
  451. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
  452. autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
  453. autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
  454. autobyteus/workflow/phases/__init__.py +0 -11
  455. autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
  456. autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
  457. autobyteus-1.2.1.dist-info/METADATA +0 -205
  458. autobyteus-1.2.1.dist-info/RECORD +0 -511
  459. examples/__init__.py +0 -1
  460. examples/agent_team/__init__.py +0 -1
  461. examples/discover_phase_transitions.py +0 -104
  462. examples/run_agentic_software_engineer.py +0 -239
  463. examples/run_browser_agent.py +0 -262
  464. examples/run_google_slides_agent.py +0 -287
  465. examples/run_mcp_browser_client.py +0 -174
  466. examples/run_mcp_google_slides_client.py +0 -270
  467. examples/run_mcp_list_tools.py +0 -189
  468. examples/run_poem_writer.py +0 -284
  469. examples/run_sqlite_agent.py +0 -295
  470. /autobyteus/{tools/browser/session_aware → skills}/__init__.py +0 -0
  471. /autobyteus/tools/{browser/session_aware/factory → skill}/__init__.py +0 -0
  472. {autobyteus-1.2.1.dist-info → autobyteus-1.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,14 +1,81 @@
1
1
  import os
2
2
  import logging
3
- from typing import Optional, List
3
+ from typing import Optional, List, Dict, Tuple, Any
4
+ from pathlib import Path
4
5
 
5
6
  from autobyteus.tools.base_tool import BaseTool
6
7
  from autobyteus.utils.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
7
8
  from autobyteus.tools.tool_category import ToolCategory
8
9
  from autobyteus.multimedia.image import image_client_factory, ImageModel, ImageClientFactory
10
+ from autobyteus.multimedia.image.base_image_client import BaseImageClient
11
+ from autobyteus.utils.download_utils import download_file_from_url
12
+ from autobyteus.utils.file_utils import resolve_safe_path
9
13
 
10
14
  logger = logging.getLogger(__name__)
11
15
 
16
+ def _get_workspace_root(context) -> str:
17
+ if not context.workspace:
18
+ error_msg = (
19
+ f"Relative path provided, but no workspace is configured for agent '{context.agent_id}'. "
20
+ "A workspace is required to resolve relative paths."
21
+ )
22
+ logger.error(error_msg)
23
+ raise ValueError(error_msg)
24
+
25
+ base_path = context.workspace.get_base_path()
26
+ if not base_path or not isinstance(base_path, str):
27
+ error_msg = (
28
+ f"Agent '{context.agent_id}' has a configured workspace, but it provided an invalid base path "
29
+ f"('{base_path}'). Cannot resolve relative paths."
30
+ )
31
+ logger.error(error_msg)
32
+ raise ValueError(error_msg)
33
+
34
+ return base_path
35
+
36
+
37
+ class _SharedImageClientManager:
38
+ """
39
+ Internal manager to share image client instances between tools (e.g., Generate and Edit)
40
+ WITHIN the same agent instance.
41
+
42
+ It keys clients by (agent_id, model_identifier). This ensures that:
43
+ 1. Multiple tools (Generate/Edit) used by Agent A share the same client (preserving session/context).
44
+ 2. Agent B gets a completely separate client instance, preventing state leakage between agents.
45
+ """
46
+ # Key: (agent_id, model_identifier) -> Client Instance
47
+ _clients: Dict[Tuple[str, str], BaseImageClient] = {}
48
+ # Key: (agent_id, model_identifier) -> Reference Count
49
+ _ref_counts: Dict[Tuple[str, str], int] = {}
50
+
51
+ @classmethod
52
+ def get_client(cls, agent_id: str, model_identifier: str) -> BaseImageClient:
53
+ key = (agent_id, model_identifier)
54
+
55
+ if key not in cls._clients:
56
+ logger.info(f"SharedImageClientManager: Creating new client for model '{model_identifier}' scoped to agent '{agent_id}'.")
57
+ cls._clients[key] = image_client_factory.create_image_client(model_identifier=model_identifier)
58
+ cls._ref_counts[key] = 0
59
+
60
+ cls._ref_counts[key] += 1
61
+ logger.debug(f"SharedImageClientManager: Client for '{model_identifier}' (Agent: {agent_id}) ref count incremented to {cls._ref_counts[key]}")
62
+ return cls._clients[key]
63
+
64
+ @classmethod
65
+ async def release_client(cls, agent_id: str, model_identifier: str) -> None:
66
+ key = (agent_id, model_identifier)
67
+
68
+ if key in cls._ref_counts:
69
+ cls._ref_counts[key] -= 1
70
+ logger.debug(f"SharedImageClientManager: Client for '{model_identifier}' (Agent: {agent_id}) ref count decremented to {cls._ref_counts[key]}")
71
+
72
+ if cls._ref_counts[key] <= 0:
73
+ logger.info(f"SharedImageClientManager: Cleaning up client for '{model_identifier}' (Agent: {agent_id})")
74
+ client = cls._clients.pop(key, None)
75
+ del cls._ref_counts[key]
76
+ if client:
77
+ await client.cleanup()
78
+
12
79
 
13
80
  def _get_configured_model_identifier(env_var: str, default_model: Optional[str] = None) -> str:
14
81
  """
@@ -52,13 +119,34 @@ def _build_dynamic_image_schema(base_params: List[ParameterDefinition], model_en
52
119
  return schema
53
120
 
54
121
 
122
+ def _get_model_description_suffix(model_env_var: str, default_model: str) -> str:
123
+ """
124
+ Fetches the configured model's specific description suffix, if available.
125
+ """
126
+ try:
127
+ model_identifier = _get_configured_model_identifier(model_env_var, default_model)
128
+ ImageClientFactory.ensure_initialized()
129
+ model = ImageModel[model_identifier]
130
+ if model.description:
131
+ return f"\n\n**MODEL SPECIFIC CAPABILITIES:** {model.description}"
132
+ except Exception:
133
+ # Fail gracefully if model lookup fails; rely on base tool description
134
+ pass
135
+ return ""
136
+
137
+
55
138
  class GenerateImageTool(BaseTool):
56
139
  """
57
140
  An agent tool for generating images from a text prompt using a pre-configured model.
58
141
  """
59
142
  CATEGORY = ToolCategory.MULTIMEDIA
60
143
  MODEL_ENV_VAR = "DEFAULT_IMAGE_GENERATION_MODEL"
61
- DEFAULT_MODEL = "gpt-image-1"
144
+ DEFAULT_MODEL = "gpt-image-1.5"
145
+
146
+ def __init__(self, config=None):
147
+ super().__init__(config)
148
+ self._client: Optional[BaseImageClient] = None
149
+ self._model_identifier: Optional[str] = None
62
150
 
63
151
  @classmethod
64
152
  def get_name(cls) -> str:
@@ -66,11 +154,19 @@ class GenerateImageTool(BaseTool):
66
154
 
67
155
  @classmethod
68
156
  def get_description(cls) -> str:
69
- return (
70
- "Generates one or more images based on a textual description (prompt) using the system's default image model. "
71
- "Can optionally accept reference images to influence the style or content. "
72
- "Returns a list of URLs to the generated images upon success."
157
+ base_desc = (
158
+ "Generates one or more images based on a textual description (prompt). "
159
+ "This versatile tool handles both creation from scratch and modification of existing images. "
160
+ "If 'input_images' are provided, it serves as a powerful editing and variation engine. "
161
+ "Use cases include: creating or editing posters, modifying scene elements (e.g., 'add a cat to the sofa'), "
162
+ "style transfer (e.g., 'turn this photo into an oil painting'), generating variations of a design, "
163
+ "or any imaging task requiring consistency with an input reference (e.g., preserving a specific composition or background while changing the subject). "
164
+ "Saves the generated image to the specified local file path and returns the path. "
165
+ "Please refer to the specific capabilities of the configured model below to check if it supports "
166
+ "input images for variations/editing."
73
167
  )
168
+ suffix = _get_model_description_suffix(cls.MODEL_ENV_VAR, cls.DEFAULT_MODEL)
169
+ return f"{base_desc}{suffix}"
74
170
 
75
171
  @classmethod
76
172
  def get_argument_schema(cls) -> Optional[ParameterSchema]:
@@ -82,37 +178,71 @@ class GenerateImageTool(BaseTool):
82
178
  required=True
83
179
  ),
84
180
  ParameterDefinition(
85
- name="input_image_urls",
181
+ name="input_images",
86
182
  param_type=ParameterType.STRING,
87
- description="Optional. A comma-separated string of URLs to reference images. The generated image will try to match the style or content of these images.",
183
+ description="Optional. A comma-separated string of image locations (URLs or file paths).",
88
184
  required=False
185
+ ),
186
+ ParameterDefinition(
187
+ name="output_file_path",
188
+ param_type=ParameterType.STRING,
189
+ description=(
190
+ "Required. The local file path (relative to workspace) where the generated image should be saved. "
191
+ "Example: 'assets/images/result.png'"
192
+ ),
193
+ required=True
89
194
  )
90
195
  ]
91
196
  return _build_dynamic_image_schema(base_params, cls.MODEL_ENV_VAR, cls.DEFAULT_MODEL)
92
197
 
93
- async def _execute(self, context, prompt: str, input_image_urls: Optional[str] = None, generation_config: Optional[dict] = None) -> List[str]:
94
- model_identifier = _get_configured_model_identifier(self.MODEL_ENV_VAR, self.DEFAULT_MODEL)
95
- logger.info(f"generate_image executing with configured model '{model_identifier}'.")
96
- client = None
97
- try:
98
- urls_list = None
99
- if input_image_urls:
100
- urls_list = [url.strip() for url in input_image_urls.split(',') if url.strip()]
101
-
102
- client = image_client_factory.create_image_client(model_identifier=model_identifier)
103
- response = await client.generate_image(
104
- prompt=prompt,
105
- input_image_urls=urls_list,
106
- generation_config=generation_config
107
- )
108
-
109
- if not response.image_urls:
110
- raise ValueError("Image generation failed to return any image URLs.")
111
-
112
- return response.image_urls
113
- finally:
114
- if client:
115
- await client.cleanup()
198
+ async def _execute(
199
+ self,
200
+ context,
201
+ prompt: str,
202
+ output_file_path: str,
203
+ input_images: Optional[str] = None,
204
+ generation_config: Optional[dict] = None,
205
+ ) -> Any:
206
+ # 1. Resolve Model ID
207
+ if not self._model_identifier:
208
+ self._model_identifier = _get_configured_model_identifier(self.MODEL_ENV_VAR, self.DEFAULT_MODEL)
209
+
210
+ logger.info(f"generate_image executing with configured model '{self._model_identifier}' for agent '{context.agent_id}'.")
211
+
212
+ # 2. Obtain Shared Client (Scoped to Agent ID)
213
+ if self._client is None:
214
+ self._client = _SharedImageClientManager.get_client(context.agent_id, self._model_identifier)
215
+
216
+ # 3. Process Inputs
217
+ urls_list = None
218
+ if input_images:
219
+ urls_list = [url.strip() for url in input_images.split(',') if url.strip()]
220
+
221
+ # 4. Execute Generation (client enforces single image where applicable)
222
+ response = await self._client.generate_image(
223
+ prompt=prompt,
224
+ input_image_urls=urls_list,
225
+ generation_config=generation_config
226
+ )
227
+
228
+ if not response.image_urls:
229
+ raise ValueError("Image generation failed to return any image URLs.")
230
+
231
+ first_url = response.image_urls[0]
232
+
233
+ if not output_file_path:
234
+ raise ValueError("output_file_path is required but was not provided.")
235
+
236
+ # 5. Save to File
237
+ resolved_path = resolve_safe_path(output_file_path, _get_workspace_root(context))
238
+ await download_file_from_url(first_url, resolved_path)
239
+
240
+ return {"file_path": str(resolved_path)}
241
+
242
+ async def cleanup(self) -> None:
243
+ if self._client and self._model_identifier and self.agent_id:
244
+ await _SharedImageClientManager.release_client(self.agent_id, self._model_identifier)
245
+ self._client = None
116
246
 
117
247
 
118
248
  class EditImageTool(BaseTool):
@@ -121,7 +251,12 @@ class EditImageTool(BaseTool):
121
251
  """
122
252
  CATEGORY = ToolCategory.MULTIMEDIA
123
253
  MODEL_ENV_VAR = "DEFAULT_IMAGE_EDIT_MODEL"
124
- DEFAULT_MODEL = "gpt-image-1"
254
+ DEFAULT_MODEL = "gpt-image-1.5"
255
+
256
+ def __init__(self, config=None):
257
+ super().__init__(config)
258
+ self._client: Optional[BaseImageClient] = None
259
+ self._model_identifier: Optional[str] = None
125
260
 
126
261
  @classmethod
127
262
  def get_name(cls) -> str:
@@ -129,11 +264,13 @@ class EditImageTool(BaseTool):
129
264
 
130
265
  @classmethod
131
266
  def get_description(cls) -> str:
132
- return (
133
- "Edits an existing image based on a textual description (prompt) using the system's default image model. "
267
+ base_desc = (
268
+ "Edits an existing image based on a textual description (prompt)"
134
269
  "A mask can be provided to specify the exact area to edit (inpainting). "
135
- "Returns a list of URLs to the edited images."
270
+ "Saves the edited image to the specified local file path and returns the path."
136
271
  )
272
+ suffix = _get_model_description_suffix(cls.MODEL_ENV_VAR, cls.DEFAULT_MODEL)
273
+ return f"{base_desc}{suffix}"
137
274
 
138
275
  @classmethod
139
276
  def get_argument_schema(cls) -> Optional[ParameterSchema]:
@@ -145,41 +282,88 @@ class EditImageTool(BaseTool):
145
282
  required=True
146
283
  ),
147
284
  ParameterDefinition(
148
- name="input_image_urls",
285
+ name="input_images",
149
286
  param_type=ParameterType.STRING,
150
- description="A comma-separated string of URLs to the source images that need to be edited. Some models may only use the first URL.",
287
+ description=(
288
+ "A comma-separated string of image locations (URLs or file paths) to be edited. Logic for providing this:\n"
289
+ "1. **Has Context & Image IN Context:** OMIT.\n"
290
+ "2. **Has Context & Image NOT in Context:** PROVIDE.\n"
291
+ "3. **No Context & Supports Input:** PROVIDE.\n"
292
+ "4. **No Context & No Input Support:** OMIT."
293
+ ),
294
+ required=False
295
+ ),
296
+ ParameterDefinition(
297
+ name="output_file_path",
298
+ param_type=ParameterType.STRING,
299
+ description=(
300
+ "Required. The local file path (relative to workspace) where the edited image should be saved. "
301
+ "Example: 'assets/images/edited_result.png'"
302
+ ),
151
303
  required=True
152
304
  ),
153
305
  ParameterDefinition(
154
- name="mask_image_url",
306
+ name="mask_image",
155
307
  param_type=ParameterType.STRING,
156
- description="Optional. A URL to a mask image (PNG). The transparent areas of this mask define where the input image should be edited.",
308
+ description=(
309
+ "Optional. Path or URL to a mask image (PNG) for inpainting. "
310
+ "Transparent areas are regenerated; opaque areas stay unchanged."
311
+ ),
157
312
  required=False
158
- )
313
+ ),
159
314
  ]
160
315
  return _build_dynamic_image_schema(base_params, cls.MODEL_ENV_VAR, cls.DEFAULT_MODEL)
161
316
 
162
- async def _execute(self, context, prompt: str, input_image_urls: str, generation_config: Optional[dict] = None, mask_image_url: Optional[str] = None) -> List[str]:
163
- model_identifier = _get_configured_model_identifier(self.MODEL_ENV_VAR, self.DEFAULT_MODEL)
164
- logger.info(f"edit_image executing with configured model '{model_identifier}'.")
165
- client = None
166
- try:
167
- urls_list = [url.strip() for url in input_image_urls.split(',') if url.strip()]
168
- if not urls_list:
169
- raise ValueError("The 'input_image_urls' parameter cannot be empty.")
170
-
171
- client = image_client_factory.create_image_client(model_identifier=model_identifier)
172
- response = await client.edit_image(
173
- prompt=prompt,
174
- input_image_urls=urls_list,
175
- mask_url=mask_image_url,
176
- generation_config=generation_config
177
- )
317
+ async def _execute(
318
+ self,
319
+ context,
320
+ prompt: str,
321
+ output_file_path: str,
322
+ input_images: Optional[str] = None,
323
+ generation_config: Optional[dict] = None,
324
+ mask_image: Optional[str] = None,
325
+ ) -> Any:
326
+ # 1. Resolve Model ID
327
+ if not self._model_identifier:
328
+ self._model_identifier = _get_configured_model_identifier(self.MODEL_ENV_VAR, self.DEFAULT_MODEL)
329
+
330
+ logger.info(f"edit_image executing with configured model '{self._model_identifier}' for agent '{context.agent_id}'.")
331
+
332
+ # 2. Obtain Shared Client (Scoped to Agent ID)
333
+ if self._client is None:
334
+ self._client = _SharedImageClientManager.get_client(context.agent_id, self._model_identifier)
335
+
336
+ # 3. Process Inputs
337
+ urls_list = []
338
+ if input_images:
339
+ urls_list = [url.strip() for url in input_images.split(',') if url.strip()]
340
+
341
+ # 4. Execute Edit
342
+ # Note: If urls_list is empty, we still call edit_image.
343
+ # Conversational clients will interpret this as a text-only follow-up.
344
+ # Stateless API clients may throw an error if they enforce input images, which is expected behavior.
345
+ response = await self._client.edit_image(
346
+ prompt=prompt,
347
+ input_image_urls=urls_list,
348
+ mask_url=mask_image,
349
+ generation_config=generation_config
350
+ )
351
+
352
+ if not response.image_urls:
353
+ raise ValueError("Image editing failed to return any image URLs.")
354
+
355
+ if not output_file_path:
356
+ raise ValueError("output_file_path is required but was not provided.")
357
+
358
+ first_url = response.image_urls[0]
359
+
360
+ # 5. Save to File
361
+ resolved_path = resolve_safe_path(output_file_path, _get_workspace_root(context))
362
+ await download_file_from_url(first_url, resolved_path)
178
363
 
179
- if not response.image_urls:
180
- raise ValueError("Image editing failed to return any image URLs.")
364
+ return {"file_path": str(resolved_path)}
181
365
 
182
- return response.image_urls
183
- finally:
184
- if client:
185
- await client.cleanup()
366
+ async def cleanup(self) -> None:
367
+ if self._client and self._model_identifier and self.agent_id:
368
+ await _SharedImageClientManager.release_client(self.agent_id, self._model_identifier)
369
+ self._client = None
@@ -0,0 +1,107 @@
1
+ """
2
+ File: tools/operation_executor/journal_manager.py
3
+
4
+ This module provides the JournalManager class that handles the journaling of operations for recovery purposes.
5
+ It works in collaboration with the OperationEventProducer to emit real-time events every time an operation is journaled.
6
+ """
7
+ import os
8
+ import json
9
+ from datetime import datetime
10
+ from tools.operation.operation import Operation
11
+ from tools.operation_executor.operation_event_producer import OperationEventProducer
12
+
13
+ class JournalManager:
14
+ """
15
+ Manages the journaling of operations for recovery purposes.
16
+ Collaborates with the OperationEventProducer to emit real-time events every time an operation is journaled.
17
+ """
18
+
19
+ def __init__(self, journal_path: str, event_producer: OperationEventProducer):
20
+ """
21
+ Initializes the JournalManager with a specified journal path and an event producer.
22
+
23
+ Args:
24
+ journal_path (str): The path where the journal files will be stored.
25
+ event_producer (OperationEventProducer): The event producer to emit real-time events.
26
+ """
27
+ self.journal_path = journal_path
28
+ self.event_producer = event_producer
29
+ os.makedirs(journal_path, exist_ok=True)
30
+
31
+ def initialize_journal(self, transaction_id: str, user: str = None, description: str = None) -> None:
32
+ """
33
+ Prepares the journal for a new transaction.
34
+
35
+ Args:
36
+ transaction_id (str): The unique identifier for the transaction.
37
+ user (str): The user who initiated the transaction. Default is None.
38
+ description (str): Description or purpose of the transaction. Default is None.
39
+ """
40
+ journal_file = os.path.join(self.journal_path, f"{transaction_id}.json")
41
+ with open(journal_file, 'w') as file:
42
+ data = {
43
+ "transaction_id": transaction_id,
44
+ "start_time": datetime.now().isoformat(),
45
+ "user": user,
46
+ "description": description,
47
+ "operations": []
48
+ }
49
+ json.dump(data, file)
50
+ self.event_producer.emit_event(f"Journal initialized for transaction {transaction_id}")
51
+
52
+
53
+ def record_operation(self, operation: Operation) -> None:
54
+ """
55
+ Records a given operation in the journal.
56
+
57
+ Args:
58
+ operation (Operation): The operation to be recorded.
59
+ """
60
+ transaction_id = operation.transaction_id
61
+ journal_file = os.path.join(self.journal_path, f"{transaction_id}.json")
62
+ with open(journal_file, 'r+') as file:
63
+ data = json.load(file)
64
+ data["operations"].append(operation.to_dict())
65
+ file.seek(0)
66
+ json.dump(data, file)
67
+ self.event_producer.emit_event(f"Operation {operation} recorded in journal for transaction {transaction_id}")
68
+
69
+ def finalize_journal(self, transaction_id: str, status: str, error_message: str = None) -> None:
70
+ """
71
+ Marks the transaction as complete in the journal.
72
+
73
+ Args:
74
+ transaction_id (str): The unique identifier for the transaction.
75
+ status (str): The final status of the transaction (e.g., "committed", "rolled_back").
76
+ error_message (str): Any error message associated with the transaction's end. Default is None.
77
+ """
78
+ journal_file = os.path.join(self.journal_path, f"{transaction_id}.json")
79
+ with open(journal_file, 'r+') as file:
80
+ data = json.load(file)
81
+ data["end_time"] = datetime.now().isoformat()
82
+ data["status"] = status
83
+ if error_message:
84
+ data["error_message"] = error_message
85
+ file.seek(0)
86
+ json.dump(data, file)
87
+ self.event_producer.emit_event(f"Journal finalized with status {status} for transaction {transaction_id}")
88
+
89
+
90
+ def log_error(self, transaction_id: str, error_message: str) -> None:
91
+ """
92
+ Logs any errors encountered during the transaction's lifecycle.
93
+
94
+ Args:
95
+ transaction_id (str): The unique identifier for the transaction.
96
+ error_message (str): The error message to be logged.
97
+ """
98
+ journal_file = os.path.join(self.journal_path, f"{transaction_id}.json")
99
+ with open(journal_file, 'r+') as file:
100
+ data = json.load(file)
101
+ data.setdefault("errors", []).append({
102
+ "error_message": error_message,
103
+ "timestamp": datetime.now().isoformat()
104
+ })
105
+ file.seek(0)
106
+ json.dump(data, file)
107
+ self.event_producer.emit_event(f"Error logged for transaction {transaction_id}: {error_message}")
@@ -0,0 +1,57 @@
1
+ # tools/coordinator/operation_event_buffer.py
2
+
3
+ """
4
+ Module for buffering operation events.
5
+
6
+ The OperationEventBuffer provides a mechanism to temporarily store recent operation events.
7
+ This ensures that frontend services, which might miss real-time updates, can retrieve the latest events.
8
+ """
9
+
10
+ from typing import List
11
+
12
+ class OperationEventBuffer:
13
+ """
14
+ Class to buffer operation events.
15
+
16
+ Attributes:
17
+ events (List[str]): A list to store recent operation events.
18
+ max_size (int): Maximum number of events the buffer can store.
19
+
20
+ Methods:
21
+ add_event(event: str): Adds a new event to the buffer.
22
+ get_recent_events() -> List[str]: Returns a list of recent events.
23
+ """
24
+
25
+ def __init__(self, max_size: int = 100):
26
+ """
27
+ Initialize the OperationEventBuffer.
28
+
29
+ Args:
30
+ max_size (int, optional): Maximum number of events the buffer can store.
31
+ Defaults to 100.
32
+ """
33
+ self.events = []
34
+ self.max_size = max_size
35
+
36
+ def add_event(self, event: str) -> None:
37
+ """
38
+ Add a new event to the buffer.
39
+
40
+ If the buffer reaches its max_size, it will remove the oldest event.
41
+
42
+ Args:
43
+ event (str): The event string to be added to the buffer.
44
+ """
45
+ if len(self.events) >= self.max_size:
46
+ self.events.pop(0)
47
+ self.events.append(event)
48
+
49
+ def get_recent_events(self) -> List[str]:
50
+ """
51
+ Retrieve the list of recent events.
52
+
53
+ Returns:
54
+ List[str]: List of recent events stored in the buffer.
55
+ """
56
+ return self.events
57
+
@@ -0,0 +1,29 @@
1
+ #code_start#
2
+
3
+ # File path: tools/operation_executor/operation_event_producer.py
4
+
5
+ from autobyteus.tools.operation_executor.operation_event_buffer import OperationEventBuffer
6
+
7
+
8
+ class OperationEventProducer:
9
+ """
10
+ Class responsible for emitting real-time events for every operation executed or undone.
11
+ """
12
+
13
+ def __init__(self, event_buffer: OperationEventBuffer):
14
+ """
15
+ Initializes the OperationEventProducer with the OperationEventBuffer.
16
+
17
+ Args:
18
+ event_buffer (OperationEventBuffer): The buffer where events will be stored.
19
+ """
20
+ self.event_buffer = event_buffer
21
+
22
+ def emit_event(self, event: str):
23
+ """
24
+ Emit a real-time event for an operation.
25
+
26
+ Args:
27
+ event (str): Event to be emitted.
28
+ """
29
+ self.event_buffer.add_event(event)
@@ -0,0 +1,58 @@
1
+ """
2
+ # tools/operation_executor/operation_executor.py
3
+ Module to handle the execution and potential reversion of operations.
4
+ """
5
+
6
+ from typing import List
7
+ from tools.operation.operation import Operation
8
+ # Note: The below imports are placeholders, actual implementations would need to be linked.
9
+ # from journal_manager import JournalManager
10
+ # from operation_event_producer import OperationEventProducer
11
+
12
+ class OperationExecutor:
13
+ """
14
+ Manages the execution and potential reversion of operations.
15
+ Interacts with the JournalManager and OperationEventProducer for logging and event emission.
16
+ """
17
+
18
+ def __init__(self):
19
+ """
20
+ Initializes the OperationExecutor with an empty operations list.
21
+ """
22
+ self.operations: List[Operation] = []
23
+ # Assuming instances of JournalManager and OperationEventProducer are passed or instantiated here.
24
+ # self.journal_manager = JournalManager()
25
+ # self.event_producer = OperationEventProducer()
26
+
27
+ def add_operation(self, operation: Operation):
28
+ """
29
+ Adds an operation to the list of operations to be executed.
30
+
31
+ Args:
32
+ operation (Operation): The operation to be added.
33
+ """
34
+ self.operations.append(operation)
35
+
36
+ def execute_operations(self, transaction_id: str):
37
+ """
38
+ Executes all operations added to the executor. Logs and emits events for each operation.
39
+
40
+ Args:
41
+ transaction_id (str): The ID of the current transaction.
42
+ """
43
+ # self.journal_manager.initialize_journal(transaction_id)
44
+ for operation in self.operations:
45
+ operation.execute()
46
+ # Log the operation and emit event
47
+ # self.journal_manager.record_operation(operation)
48
+ # self.event_producer.emit_event(f"Operation {operation} executed.")
49
+
50
+ def rollback_operations(self):
51
+ """
52
+ Reverts all executed operations. This is done in reverse order to ensure the correct undoing of operations.
53
+ """
54
+ for operation in reversed(self.operations):
55
+ operation.undo()
56
+ # Emit event for rollback
57
+ # self.event_producer.emit_event(f"Operation {operation} rolled back.")
58
+