autobyteus 1.2.1__py3-none-any.whl → 1.2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- autobyteus/agent/agent.py +15 -5
- autobyteus/agent/bootstrap_steps/__init__.py +1 -3
- autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +3 -59
- autobyteus/agent/bootstrap_steps/base_bootstrap_step.py +1 -4
- autobyteus/agent/bootstrap_steps/mcp_server_prewarming_step.py +1 -3
- autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +16 -13
- autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +2 -4
- autobyteus/agent/context/agent_config.py +43 -20
- autobyteus/agent/context/agent_context.py +23 -18
- autobyteus/agent/context/agent_runtime_state.py +19 -19
- autobyteus/agent/events/__init__.py +16 -1
- autobyteus/agent/events/agent_events.py +43 -3
- autobyteus/agent/events/agent_input_event_queue_manager.py +79 -26
- autobyteus/agent/events/event_store.py +57 -0
- autobyteus/agent/events/notifiers.py +69 -59
- autobyteus/agent/events/worker_event_dispatcher.py +21 -64
- autobyteus/agent/factory/agent_factory.py +52 -0
- autobyteus/agent/handlers/__init__.py +2 -0
- autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +51 -34
- autobyteus/agent/handlers/bootstrap_event_handler.py +155 -0
- autobyteus/agent/handlers/inter_agent_message_event_handler.py +10 -0
- autobyteus/agent/handlers/lifecycle_event_logger.py +19 -11
- autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +10 -15
- autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +188 -48
- autobyteus/agent/handlers/tool_execution_approval_event_handler.py +0 -10
- autobyteus/agent/handlers/tool_invocation_request_event_handler.py +53 -48
- autobyteus/agent/handlers/tool_result_event_handler.py +7 -8
- autobyteus/agent/handlers/user_input_message_event_handler.py +10 -3
- autobyteus/agent/input_processor/memory_ingest_input_processor.py +40 -0
- autobyteus/agent/lifecycle/__init__.py +12 -0
- autobyteus/agent/lifecycle/base_processor.py +109 -0
- autobyteus/agent/lifecycle/events.py +35 -0
- autobyteus/agent/lifecycle/processor_definition.py +36 -0
- autobyteus/agent/lifecycle/processor_registry.py +106 -0
- autobyteus/agent/llm_request_assembler.py +98 -0
- autobyteus/agent/llm_response_processor/__init__.py +1 -8
- autobyteus/agent/message/context_file_type.py +1 -1
- autobyteus/agent/runtime/agent_runtime.py +29 -21
- autobyteus/agent/runtime/agent_worker.py +98 -19
- autobyteus/agent/shutdown_steps/__init__.py +2 -0
- autobyteus/agent/shutdown_steps/agent_shutdown_orchestrator.py +2 -0
- autobyteus/agent/shutdown_steps/tool_cleanup_step.py +58 -0
- autobyteus/agent/status/__init__.py +14 -0
- autobyteus/agent/status/manager.py +93 -0
- autobyteus/agent/status/status_deriver.py +96 -0
- autobyteus/agent/{phases/phase_enum.py → status/status_enum.py} +16 -16
- autobyteus/agent/status/status_update_utils.py +73 -0
- autobyteus/agent/streaming/__init__.py +52 -5
- autobyteus/agent/streaming/adapters/__init__.py +18 -0
- autobyteus/agent/streaming/adapters/invocation_adapter.py +184 -0
- autobyteus/agent/streaming/adapters/tool_call_parsing.py +163 -0
- autobyteus/agent/streaming/adapters/tool_syntax_registry.py +67 -0
- autobyteus/agent/streaming/agent_event_stream.py +3 -183
- autobyteus/agent/streaming/api_tool_call/__init__.py +16 -0
- autobyteus/agent/streaming/api_tool_call/file_content_streamer.py +56 -0
- autobyteus/agent/streaming/api_tool_call/json_string_field_extractor.py +175 -0
- autobyteus/agent/streaming/api_tool_call_streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/events/__init__.py +6 -0
- autobyteus/agent/streaming/events/stream_event_payloads.py +284 -0
- autobyteus/agent/streaming/events/stream_events.py +141 -0
- autobyteus/agent/streaming/handlers/__init__.py +15 -0
- autobyteus/agent/streaming/handlers/api_tool_call_streaming_response_handler.py +303 -0
- autobyteus/agent/streaming/handlers/parsing_streaming_response_handler.py +107 -0
- autobyteus/agent/streaming/handlers/pass_through_streaming_response_handler.py +107 -0
- autobyteus/agent/streaming/handlers/streaming_handler_factory.py +177 -0
- autobyteus/agent/streaming/handlers/streaming_response_handler.py +58 -0
- autobyteus/agent/streaming/parser/__init__.py +61 -0
- autobyteus/agent/streaming/parser/event_emitter.py +181 -0
- autobyteus/agent/streaming/parser/events.py +4 -0
- autobyteus/agent/streaming/parser/invocation_adapter.py +4 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/__init__.py +19 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/base.py +32 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/default.py +34 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/gemini.py +31 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/openai.py +64 -0
- autobyteus/agent/streaming/parser/json_parsing_strategies/registry.py +75 -0
- autobyteus/agent/streaming/parser/parser_context.py +227 -0
- autobyteus/agent/streaming/parser/parser_factory.py +132 -0
- autobyteus/agent/streaming/parser/sentinel_format.py +7 -0
- autobyteus/agent/streaming/parser/state_factory.py +62 -0
- autobyteus/agent/streaming/parser/states/__init__.py +1 -0
- autobyteus/agent/streaming/parser/states/base_state.py +60 -0
- autobyteus/agent/streaming/parser/states/custom_xml_tag_run_bash_parsing_state.py +38 -0
- autobyteus/agent/streaming/parser/states/custom_xml_tag_write_file_parsing_state.py +55 -0
- autobyteus/agent/streaming/parser/states/delimited_content_state.py +146 -0
- autobyteus/agent/streaming/parser/states/json_initialization_state.py +144 -0
- autobyteus/agent/streaming/parser/states/json_tool_parsing_state.py +137 -0
- autobyteus/agent/streaming/parser/states/sentinel_content_state.py +30 -0
- autobyteus/agent/streaming/parser/states/sentinel_initialization_state.py +117 -0
- autobyteus/agent/streaming/parser/states/text_state.py +78 -0
- autobyteus/agent/streaming/parser/states/xml_patch_file_tool_parsing_state.py +328 -0
- autobyteus/agent/streaming/parser/states/xml_run_bash_tool_parsing_state.py +129 -0
- autobyteus/agent/streaming/parser/states/xml_tag_initialization_state.py +151 -0
- autobyteus/agent/streaming/parser/states/xml_tool_parsing_state.py +63 -0
- autobyteus/agent/streaming/parser/states/xml_write_file_tool_parsing_state.py +343 -0
- autobyteus/agent/streaming/parser/strategies/__init__.py +17 -0
- autobyteus/agent/streaming/parser/strategies/base.py +24 -0
- autobyteus/agent/streaming/parser/strategies/json_tool_strategy.py +26 -0
- autobyteus/agent/streaming/parser/strategies/registry.py +28 -0
- autobyteus/agent/streaming/parser/strategies/sentinel_strategy.py +23 -0
- autobyteus/agent/streaming/parser/strategies/xml_tag_strategy.py +21 -0
- autobyteus/agent/streaming/parser/stream_scanner.py +167 -0
- autobyteus/agent/streaming/parser/streaming_parser.py +212 -0
- autobyteus/agent/streaming/parser/tool_call_parsing.py +4 -0
- autobyteus/agent/streaming/parser/tool_constants.py +7 -0
- autobyteus/agent/streaming/parser/tool_syntax_registry.py +4 -0
- autobyteus/agent/streaming/parser/xml_tool_parsing_state_registry.py +55 -0
- autobyteus/agent/streaming/parsing_streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/pass_through_streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/queue_streamer.py +3 -57
- autobyteus/agent/streaming/segments/__init__.py +5 -0
- autobyteus/agent/streaming/segments/segment_events.py +81 -0
- autobyteus/agent/streaming/stream_event_payloads.py +2 -223
- autobyteus/agent/streaming/stream_events.py +3 -140
- autobyteus/agent/streaming/streaming_handler_factory.py +4 -0
- autobyteus/agent/streaming/streaming_response_handler.py +4 -0
- autobyteus/agent/streaming/streams/__init__.py +5 -0
- autobyteus/agent/streaming/streams/agent_event_stream.py +197 -0
- autobyteus/agent/streaming/utils/__init__.py +5 -0
- autobyteus/agent/streaming/utils/queue_streamer.py +59 -0
- autobyteus/agent/system_prompt_processor/__init__.py +2 -0
- autobyteus/agent/system_prompt_processor/available_skills_processor.py +96 -0
- autobyteus/agent/system_prompt_processor/base_processor.py +1 -1
- autobyteus/agent/system_prompt_processor/processor_meta.py +15 -2
- autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +39 -58
- autobyteus/agent/token_budget.py +56 -0
- autobyteus/agent/tool_execution_result_processor/memory_ingest_tool_result_processor.py +29 -0
- autobyteus/agent/tool_invocation.py +16 -40
- autobyteus/agent/tool_invocation_preprocessor/__init__.py +9 -0
- autobyteus/agent/tool_invocation_preprocessor/base_preprocessor.py +45 -0
- autobyteus/agent/tool_invocation_preprocessor/processor_definition.py +15 -0
- autobyteus/agent/tool_invocation_preprocessor/processor_meta.py +33 -0
- autobyteus/agent/tool_invocation_preprocessor/processor_registry.py +60 -0
- autobyteus/agent/utils/wait_for_idle.py +12 -14
- autobyteus/agent/workspace/base_workspace.py +6 -27
- autobyteus/agent_team/agent_team.py +3 -3
- autobyteus/agent_team/agent_team_builder.py +1 -41
- autobyteus/agent_team/bootstrap_steps/__init__.py +0 -4
- autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +8 -18
- autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +4 -16
- autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +1 -2
- autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +1 -2
- autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +1 -2
- autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +4 -4
- autobyteus/agent_team/context/agent_team_config.py +6 -3
- autobyteus/agent_team/context/agent_team_context.py +25 -3
- autobyteus/agent_team/context/agent_team_runtime_state.py +9 -6
- autobyteus/agent_team/events/__init__.py +11 -0
- autobyteus/agent_team/events/agent_team_event_dispatcher.py +22 -9
- autobyteus/agent_team/events/agent_team_events.py +16 -0
- autobyteus/agent_team/events/event_store.py +57 -0
- autobyteus/agent_team/factory/agent_team_factory.py +8 -0
- autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +18 -2
- autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +21 -5
- autobyteus/agent_team/handlers/process_user_message_event_handler.py +17 -8
- autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +19 -4
- autobyteus/agent_team/runtime/agent_team_runtime.py +41 -10
- autobyteus/agent_team/runtime/agent_team_worker.py +69 -5
- autobyteus/agent_team/status/__init__.py +14 -0
- autobyteus/agent_team/status/agent_team_status.py +18 -0
- autobyteus/agent_team/status/agent_team_status_manager.py +33 -0
- autobyteus/agent_team/status/status_deriver.py +62 -0
- autobyteus/agent_team/status/status_update_utils.py +42 -0
- autobyteus/agent_team/streaming/__init__.py +2 -2
- autobyteus/agent_team/streaming/agent_team_event_notifier.py +6 -6
- autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +4 -4
- autobyteus/agent_team/streaming/agent_team_stream_events.py +3 -3
- autobyteus/agent_team/system_prompt_processor/__init__.py +6 -0
- autobyteus/agent_team/system_prompt_processor/team_manifest_injector_processor.py +76 -0
- autobyteus/agent_team/task_notification/task_notification_mode.py +19 -0
- autobyteus/agent_team/utils/wait_for_idle.py +4 -4
- autobyteus/cli/agent_cli.py +18 -10
- autobyteus/cli/agent_team_tui/app.py +14 -11
- autobyteus/cli/agent_team_tui/state.py +13 -15
- autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
- autobyteus/cli/agent_team_tui/widgets/focus_pane.py +143 -36
- autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
- autobyteus/cli/agent_team_tui/widgets/shared.py +25 -25
- autobyteus/cli/cli_display.py +193 -44
- autobyteus/cli/workflow_tui/app.py +9 -10
- autobyteus/cli/workflow_tui/state.py +14 -16
- autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +15 -15
- autobyteus/cli/workflow_tui/widgets/focus_pane.py +137 -35
- autobyteus/cli/workflow_tui/widgets/renderables.py +1 -1
- autobyteus/cli/workflow_tui/widgets/shared.py +25 -25
- autobyteus/clients/autobyteus_client.py +94 -1
- autobyteus/events/event_types.py +11 -18
- autobyteus/llm/api/autobyteus_llm.py +33 -29
- autobyteus/llm/api/claude_llm.py +142 -36
- autobyteus/llm/api/gemini_llm.py +163 -59
- autobyteus/llm/api/grok_llm.py +1 -1
- autobyteus/llm/api/minimax_llm.py +26 -0
- autobyteus/llm/api/mistral_llm.py +113 -87
- autobyteus/llm/api/ollama_llm.py +9 -42
- autobyteus/llm/api/openai_compatible_llm.py +127 -91
- autobyteus/llm/api/openai_llm.py +3 -3
- autobyteus/llm/api/openai_responses_llm.py +324 -0
- autobyteus/llm/api/zhipu_llm.py +21 -2
- autobyteus/llm/autobyteus_provider.py +70 -60
- autobyteus/llm/base_llm.py +85 -81
- autobyteus/llm/converters/__init__.py +14 -0
- autobyteus/llm/converters/anthropic_tool_call_converter.py +37 -0
- autobyteus/llm/converters/gemini_tool_call_converter.py +57 -0
- autobyteus/llm/converters/mistral_tool_call_converter.py +37 -0
- autobyteus/llm/converters/openai_tool_call_converter.py +38 -0
- autobyteus/llm/extensions/base_extension.py +6 -12
- autobyteus/llm/extensions/token_usage_tracking_extension.py +45 -18
- autobyteus/llm/llm_factory.py +282 -204
- autobyteus/llm/lmstudio_provider.py +60 -49
- autobyteus/llm/models.py +35 -2
- autobyteus/llm/ollama_provider.py +60 -49
- autobyteus/llm/ollama_provider_resolver.py +0 -1
- autobyteus/llm/prompt_renderers/__init__.py +19 -0
- autobyteus/llm/prompt_renderers/anthropic_prompt_renderer.py +104 -0
- autobyteus/llm/prompt_renderers/autobyteus_prompt_renderer.py +19 -0
- autobyteus/llm/prompt_renderers/base_prompt_renderer.py +10 -0
- autobyteus/llm/prompt_renderers/gemini_prompt_renderer.py +63 -0
- autobyteus/llm/prompt_renderers/mistral_prompt_renderer.py +87 -0
- autobyteus/llm/prompt_renderers/ollama_prompt_renderer.py +51 -0
- autobyteus/llm/prompt_renderers/openai_chat_renderer.py +97 -0
- autobyteus/llm/prompt_renderers/openai_responses_renderer.py +101 -0
- autobyteus/llm/providers.py +1 -3
- autobyteus/llm/token_counter/claude_token_counter.py +56 -25
- autobyteus/llm/token_counter/mistral_token_counter.py +12 -8
- autobyteus/llm/token_counter/openai_token_counter.py +24 -5
- autobyteus/llm/token_counter/token_counter_factory.py +12 -5
- autobyteus/llm/utils/llm_config.py +6 -12
- autobyteus/llm/utils/media_payload_formatter.py +27 -20
- autobyteus/llm/utils/messages.py +55 -3
- autobyteus/llm/utils/response_types.py +3 -0
- autobyteus/llm/utils/tool_call_delta.py +31 -0
- autobyteus/memory/__init__.py +32 -0
- autobyteus/memory/active_transcript.py +69 -0
- autobyteus/memory/compaction/__init__.py +9 -0
- autobyteus/memory/compaction/compaction_result.py +8 -0
- autobyteus/memory/compaction/compactor.py +89 -0
- autobyteus/memory/compaction/summarizer.py +11 -0
- autobyteus/memory/compaction_snapshot_builder.py +84 -0
- autobyteus/memory/memory_manager.py +183 -0
- autobyteus/memory/models/__init__.py +14 -0
- autobyteus/memory/models/episodic_item.py +41 -0
- autobyteus/memory/models/memory_types.py +7 -0
- autobyteus/memory/models/raw_trace_item.py +79 -0
- autobyteus/memory/models/semantic_item.py +41 -0
- autobyteus/memory/models/tool_interaction.py +20 -0
- autobyteus/memory/policies/__init__.py +5 -0
- autobyteus/memory/policies/compaction_policy.py +16 -0
- autobyteus/memory/retrieval/__init__.py +7 -0
- autobyteus/memory/retrieval/memory_bundle.py +11 -0
- autobyteus/memory/retrieval/retriever.py +13 -0
- autobyteus/memory/store/__init__.py +7 -0
- autobyteus/memory/store/base_store.py +14 -0
- autobyteus/memory/store/file_store.py +98 -0
- autobyteus/memory/tool_interaction_builder.py +46 -0
- autobyteus/memory/turn_tracker.py +9 -0
- autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
- autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
- autobyteus/multimedia/audio/audio_client_factory.py +47 -9
- autobyteus/multimedia/audio/audio_model.py +2 -1
- autobyteus/multimedia/image/api/autobyteus_image_client.py +19 -5
- autobyteus/multimedia/image/api/gemini_image_client.py +38 -17
- autobyteus/multimedia/image/api/openai_image_client.py +125 -43
- autobyteus/multimedia/image/autobyteus_image_provider.py +2 -1
- autobyteus/multimedia/image/image_client_factory.py +47 -15
- autobyteus/multimedia/image/image_model.py +5 -2
- autobyteus/multimedia/providers.py +3 -2
- autobyteus/skills/loader.py +71 -0
- autobyteus/skills/model.py +11 -0
- autobyteus/skills/registry.py +70 -0
- autobyteus/task_management/tools/todo_tools/add_todo.py +2 -2
- autobyteus/task_management/tools/todo_tools/create_todo_list.py +2 -2
- autobyteus/task_management/tools/todo_tools/update_todo_status.py +2 -2
- autobyteus/tools/__init__.py +34 -47
- autobyteus/tools/base_tool.py +7 -0
- autobyteus/tools/file/__init__.py +2 -6
- autobyteus/tools/file/patch_file.py +149 -0
- autobyteus/tools/file/read_file.py +36 -5
- autobyteus/tools/file/write_file.py +4 -1
- autobyteus/tools/functional_tool.py +43 -6
- autobyteus/tools/mcp/__init__.py +2 -0
- autobyteus/tools/mcp/config_service.py +5 -1
- autobyteus/tools/mcp/server/__init__.py +2 -0
- autobyteus/tools/mcp/server/http_managed_mcp_server.py +1 -1
- autobyteus/tools/mcp/server/websocket_managed_mcp_server.py +141 -0
- autobyteus/tools/mcp/server_instance_manager.py +8 -1
- autobyteus/tools/mcp/types.py +61 -0
- autobyteus/tools/multimedia/audio_tools.py +70 -17
- autobyteus/tools/multimedia/download_media_tool.py +18 -4
- autobyteus/tools/multimedia/image_tools.py +246 -62
- autobyteus/tools/operation_executor/journal_manager.py +107 -0
- autobyteus/tools/operation_executor/operation_event_buffer.py +57 -0
- autobyteus/tools/operation_executor/operation_event_producer.py +29 -0
- autobyteus/tools/operation_executor/operation_executor.py +58 -0
- autobyteus/tools/registry/tool_definition.py +43 -2
- autobyteus/tools/skill/load_skill.py +50 -0
- autobyteus/tools/terminal/__init__.py +45 -0
- autobyteus/tools/terminal/ansi_utils.py +32 -0
- autobyteus/tools/terminal/background_process_manager.py +233 -0
- autobyteus/tools/terminal/output_buffer.py +105 -0
- autobyteus/tools/terminal/prompt_detector.py +63 -0
- autobyteus/tools/terminal/pty_session.py +241 -0
- autobyteus/tools/terminal/session_factory.py +20 -0
- autobyteus/tools/terminal/terminal_session_manager.py +226 -0
- autobyteus/tools/terminal/tools/__init__.py +13 -0
- autobyteus/tools/terminal/tools/get_process_output.py +81 -0
- autobyteus/tools/terminal/tools/run_bash.py +109 -0
- autobyteus/tools/terminal/tools/start_background_process.py +104 -0
- autobyteus/tools/terminal/tools/stop_background_process.py +67 -0
- autobyteus/tools/terminal/types.py +54 -0
- autobyteus/tools/terminal/wsl_tmux_session.py +221 -0
- autobyteus/tools/terminal/wsl_utils.py +156 -0
- autobyteus/tools/transaction_management/backup_handler.py +48 -0
- autobyteus/tools/transaction_management/operation_lifecycle_manager.py +62 -0
- autobyteus/tools/usage/__init__.py +1 -2
- autobyteus/tools/usage/formatters/__init__.py +17 -1
- autobyteus/tools/usage/formatters/base_formatter.py +8 -0
- autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +2 -2
- autobyteus/tools/usage/formatters/mistral_json_schema_formatter.py +18 -0
- autobyteus/tools/usage/formatters/patch_file_xml_example_formatter.py +64 -0
- autobyteus/tools/usage/formatters/patch_file_xml_schema_formatter.py +31 -0
- autobyteus/tools/usage/formatters/run_bash_xml_example_formatter.py +32 -0
- autobyteus/tools/usage/formatters/run_bash_xml_schema_formatter.py +36 -0
- autobyteus/tools/usage/formatters/write_file_xml_example_formatter.py +53 -0
- autobyteus/tools/usage/formatters/write_file_xml_schema_formatter.py +31 -0
- autobyteus/tools/usage/providers/tool_manifest_provider.py +10 -10
- autobyteus/tools/usage/registries/__init__.py +1 -3
- autobyteus/tools/usage/registries/tool_formatting_registry.py +115 -8
- autobyteus/tools/usage/tool_schema_provider.py +51 -0
- autobyteus/tools/web/__init__.py +4 -0
- autobyteus/tools/web/read_url_tool.py +80 -0
- autobyteus/utils/diff_utils.py +271 -0
- autobyteus/utils/download_utils.py +109 -0
- autobyteus/utils/file_utils.py +57 -2
- autobyteus/utils/gemini_helper.py +56 -0
- autobyteus/utils/gemini_model_mapping.py +71 -0
- autobyteus/utils/llm_output_formatter.py +75 -0
- autobyteus/utils/tool_call_format.py +36 -0
- autobyteus/workflow/agentic_workflow.py +3 -3
- autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +2 -2
- autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +2 -2
- autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +2 -2
- autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +3 -9
- autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +6 -6
- autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +2 -2
- autobyteus/workflow/context/workflow_context.py +3 -3
- autobyteus/workflow/context/workflow_runtime_state.py +5 -5
- autobyteus/workflow/events/workflow_event_dispatcher.py +5 -5
- autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +3 -3
- autobyteus/workflow/handlers/process_user_message_event_handler.py +5 -5
- autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +2 -2
- autobyteus/workflow/runtime/workflow_runtime.py +8 -8
- autobyteus/workflow/runtime/workflow_worker.py +3 -3
- autobyteus/workflow/status/__init__.py +11 -0
- autobyteus/workflow/status/workflow_status.py +19 -0
- autobyteus/workflow/status/workflow_status_manager.py +48 -0
- autobyteus/workflow/streaming/__init__.py +2 -2
- autobyteus/workflow/streaming/workflow_event_notifier.py +7 -7
- autobyteus/workflow/streaming/workflow_stream_event_payloads.py +4 -4
- autobyteus/workflow/streaming/workflow_stream_events.py +3 -3
- autobyteus/workflow/utils/wait_for_idle.py +4 -4
- autobyteus-1.2.3.dist-info/METADATA +293 -0
- autobyteus-1.2.3.dist-info/RECORD +600 -0
- {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
- {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.dist-info}/top_level.txt +0 -1
- autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +0 -57
- autobyteus/agent/hooks/__init__.py +0 -16
- autobyteus/agent/hooks/base_phase_hook.py +0 -78
- autobyteus/agent/hooks/hook_definition.py +0 -36
- autobyteus/agent/hooks/hook_meta.py +0 -37
- autobyteus/agent/hooks/hook_registry.py +0 -106
- autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +0 -103
- autobyteus/agent/phases/__init__.py +0 -18
- autobyteus/agent/phases/discover.py +0 -53
- autobyteus/agent/phases/manager.py +0 -265
- autobyteus/agent/phases/transition_decorator.py +0 -40
- autobyteus/agent/phases/transition_info.py +0 -33
- autobyteus/agent/remote_agent.py +0 -244
- autobyteus/agent/workspace/workspace_definition.py +0 -36
- autobyteus/agent/workspace/workspace_meta.py +0 -37
- autobyteus/agent/workspace/workspace_registry.py +0 -72
- autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +0 -25
- autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +0 -85
- autobyteus/agent_team/phases/__init__.py +0 -11
- autobyteus/agent_team/phases/agent_team_operational_phase.py +0 -19
- autobyteus/agent_team/phases/agent_team_phase_manager.py +0 -48
- autobyteus/llm/api/bedrock_llm.py +0 -92
- autobyteus/llm/api/groq_llm.py +0 -94
- autobyteus/llm/api/nvidia_llm.py +0 -108
- autobyteus/llm/utils/token_pricing_config.py +0 -87
- autobyteus/rpc/__init__.py +0 -73
- autobyteus/rpc/client/__init__.py +0 -17
- autobyteus/rpc/client/abstract_client_connection.py +0 -124
- autobyteus/rpc/client/client_connection_manager.py +0 -153
- autobyteus/rpc/client/sse_client_connection.py +0 -306
- autobyteus/rpc/client/stdio_client_connection.py +0 -280
- autobyteus/rpc/config/__init__.py +0 -13
- autobyteus/rpc/config/agent_server_config.py +0 -153
- autobyteus/rpc/config/agent_server_registry.py +0 -152
- autobyteus/rpc/hosting.py +0 -244
- autobyteus/rpc/protocol.py +0 -244
- autobyteus/rpc/server/__init__.py +0 -20
- autobyteus/rpc/server/agent_server_endpoint.py +0 -181
- autobyteus/rpc/server/base_method_handler.py +0 -40
- autobyteus/rpc/server/method_handlers.py +0 -259
- autobyteus/rpc/server/sse_server_handler.py +0 -182
- autobyteus/rpc/server/stdio_server_handler.py +0 -151
- autobyteus/rpc/server_main.py +0 -198
- autobyteus/rpc/transport_type.py +0 -13
- autobyteus/tools/bash/__init__.py +0 -2
- autobyteus/tools/bash/bash_executor.py +0 -100
- autobyteus/tools/browser/__init__.py +0 -2
- autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +0 -75
- autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +0 -30
- autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +0 -154
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +0 -89
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +0 -107
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +0 -14
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +0 -26
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +0 -14
- autobyteus/tools/browser/session_aware/shared_browser_session.py +0 -11
- autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +0 -25
- autobyteus/tools/browser/session_aware/web_element_action.py +0 -20
- autobyteus/tools/browser/standalone/__init__.py +0 -6
- autobyteus/tools/browser/standalone/factory/__init__.py +0 -0
- autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +0 -25
- autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +0 -14
- autobyteus/tools/browser/standalone/navigate_to.py +0 -84
- autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -101
- autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -169
- autobyteus/tools/browser/standalone/webpage_reader.py +0 -105
- autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -105
- autobyteus/tools/file/edit_file.py +0 -200
- autobyteus/tools/file/list_directory.py +0 -168
- autobyteus/tools/file/search_files.py +0 -188
- autobyteus/tools/timer.py +0 -175
- autobyteus/tools/usage/parsers/__init__.py +0 -22
- autobyteus/tools/usage/parsers/_json_extractor.py +0 -99
- autobyteus/tools/usage/parsers/_string_decoders.py +0 -18
- autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +0 -10
- autobyteus/tools/usage/parsers/base_parser.py +0 -41
- autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +0 -83
- autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +0 -316
- autobyteus/tools/usage/parsers/exceptions.py +0 -13
- autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +0 -77
- autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +0 -149
- autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +0 -59
- autobyteus/tools/usage/registries/tool_usage_parser_registry.py +0 -62
- autobyteus/workflow/phases/__init__.py +0 -11
- autobyteus/workflow/phases/workflow_operational_phase.py +0 -19
- autobyteus/workflow/phases/workflow_phase_manager.py +0 -48
- autobyteus-1.2.1.dist-info/METADATA +0 -205
- autobyteus-1.2.1.dist-info/RECORD +0 -511
- examples/__init__.py +0 -1
- examples/agent_team/__init__.py +0 -1
- examples/discover_phase_transitions.py +0 -104
- examples/run_agentic_software_engineer.py +0 -239
- examples/run_browser_agent.py +0 -262
- examples/run_google_slides_agent.py +0 -287
- examples/run_mcp_browser_client.py +0 -174
- examples/run_mcp_google_slides_client.py +0 -270
- examples/run_mcp_list_tools.py +0 -189
- examples/run_poem_writer.py +0 -284
- examples/run_sqlite_agent.py +0 -295
- /autobyteus/{tools/browser/session_aware → skills}/__init__.py +0 -0
- /autobyteus/tools/{browser/session_aware/factory → skill}/__init__.py +0 -0
- {autobyteus-1.2.1.dist-info → autobyteus-1.2.3.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
|
-
|
|
70
|
-
"Generates one or more images based on a textual description (prompt)
|
|
71
|
-
"
|
|
72
|
-
"
|
|
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="
|
|
181
|
+
name="input_images",
|
|
86
182
|
param_type=ParameterType.STRING,
|
|
87
|
-
description="Optional. A comma-separated string of
|
|
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(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if
|
|
115
|
-
|
|
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
|
-
|
|
133
|
-
"Edits an existing image based on a textual description (prompt)
|
|
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
|
-
"
|
|
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="
|
|
285
|
+
name="input_images",
|
|
149
286
|
param_type=ParameterType.STRING,
|
|
150
|
-
description=
|
|
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="
|
|
306
|
+
name="mask_image",
|
|
155
307
|
param_type=ParameterType.STRING,
|
|
156
|
-
description=
|
|
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(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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
|
-
|
|
180
|
-
raise ValueError("Image editing failed to return any image URLs.")
|
|
364
|
+
return {"file_path": str(resolved_path)}
|
|
181
365
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
+
|