autobyteus 1.2.0__py3-none-any.whl → 1.2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +23 -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 +74 -60
- 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/message/send_message_to.py +5 -4
- 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 -178
- 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 -198
- autobyteus/agent/streaming/stream_events.py +3 -128
- 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 +5 -6
- autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +15 -15
- 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 +11 -8
- 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 +10 -10
- autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +7 -7
- autobyteus/agent_team/streaming/agent_team_stream_events.py +11 -11
- 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/activation_policy.py +1 -1
- autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +22 -22
- autobyteus/agent_team/task_notification/task_notification_mode.py +20 -1
- autobyteus/agent_team/utils/wait_for_idle.py +4 -4
- autobyteus/cli/agent_cli.py +18 -10
- autobyteus/cli/agent_team_tui/app.py +18 -15
- autobyteus/cli/agent_team_tui/state.py +21 -23
- autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +15 -15
- autobyteus/cli/agent_team_tui/widgets/focus_pane.py +146 -39
- autobyteus/cli/agent_team_tui/widgets/renderables.py +1 -1
- autobyteus/cli/agent_team_tui/widgets/shared.py +26 -26
- autobyteus/cli/agent_team_tui/widgets/{task_board_panel.py → task_plan_panel.py} +5 -5
- 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 +15 -21
- 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/__init__.py +3 -2
- autobyteus/multimedia/audio/api/autobyteus_audio_client.py +19 -5
- autobyteus/multimedia/audio/api/gemini_audio_client.py +108 -16
- autobyteus/multimedia/audio/api/openai_audio_client.py +112 -0
- autobyteus/multimedia/audio/audio_client_factory.py +84 -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/__init__.py +43 -20
- autobyteus/task_management/{base_task_board.py → base_task_plan.py} +16 -13
- autobyteus/task_management/converters/__init__.py +2 -2
- autobyteus/task_management/converters/{task_board_converter.py → task_plan_converter.py} +13 -13
- autobyteus/task_management/events.py +7 -7
- autobyteus/task_management/{in_memory_task_board.py → in_memory_task_plan.py} +34 -22
- autobyteus/task_management/schemas/__init__.py +3 -0
- autobyteus/task_management/schemas/task_status_report.py +2 -2
- autobyteus/task_management/schemas/todo_definition.py +15 -0
- autobyteus/task_management/todo.py +29 -0
- autobyteus/task_management/todo_list.py +75 -0
- autobyteus/task_management/tools/__init__.py +24 -8
- autobyteus/task_management/tools/task_tools/__init__.py +19 -0
- autobyteus/task_management/tools/{assign_task_to.py → task_tools/assign_task_to.py} +18 -18
- autobyteus/task_management/tools/{publish_task.py → task_tools/create_task.py} +16 -18
- autobyteus/task_management/tools/{publish_tasks.py → task_tools/create_tasks.py} +19 -19
- autobyteus/task_management/tools/{get_my_tasks.py → task_tools/get_my_tasks.py} +15 -15
- autobyteus/task_management/tools/{get_task_board_status.py → task_tools/get_task_plan_status.py} +16 -16
- autobyteus/task_management/tools/{update_task_status.py → task_tools/update_task_status.py} +16 -16
- autobyteus/task_management/tools/todo_tools/__init__.py +18 -0
- autobyteus/task_management/tools/todo_tools/add_todo.py +78 -0
- autobyteus/task_management/tools/todo_tools/create_todo_list.py +79 -0
- autobyteus/task_management/tools/todo_tools/get_todo_list.py +55 -0
- autobyteus/task_management/tools/todo_tools/update_todo_status.py +85 -0
- autobyteus/tools/__init__.py +43 -52
- autobyteus/tools/base_tool.py +7 -0
- autobyteus/tools/file/__init__.py +9 -0
- autobyteus/tools/file/patch_file.py +149 -0
- autobyteus/tools/file/{file_reader.py → read_file.py} +38 -7
- autobyteus/tools/file/{file_writer.py → write_file.py} +7 -4
- autobyteus/tools/functional_tool.py +53 -14
- 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/tool.py +3 -3
- autobyteus/tools/mcp/tool_registrar.py +5 -2
- autobyteus/tools/mcp/types.py +61 -0
- autobyteus/tools/multimedia/__init__.py +2 -1
- autobyteus/tools/multimedia/audio_tools.py +72 -19
- autobyteus/tools/{download_media_tool.py → multimedia/download_media_tool.py} +21 -7
- autobyteus/tools/multimedia/image_tools.py +248 -64
- autobyteus/tools/multimedia/media_reader_tool.py +1 -1
- 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 +108 -14
- autobyteus/tools/registry/tool_registry.py +29 -0
- autobyteus/tools/search/__init__.py +17 -0
- autobyteus/tools/search/base_strategy.py +35 -0
- autobyteus/tools/search/client.py +24 -0
- autobyteus/tools/search/factory.py +81 -0
- autobyteus/tools/search/google_cse_strategy.py +68 -0
- autobyteus/tools/search/providers.py +10 -0
- autobyteus/tools/search/serpapi_strategy.py +65 -0
- autobyteus/tools/search/serper_strategy.py +87 -0
- autobyteus/tools/search_tool.py +83 -0
- 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/tool_meta.py +4 -24
- 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 +4 -11
- 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.0.dist-info → autobyteus-1.2.3.dist-info}/WHEEL +1 -1
- {autobyteus-1.2.0.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/person/examples/sample_persons.py +0 -14
- autobyteus/person/examples/sample_roles.py +0 -14
- autobyteus/person/person.py +0 -29
- autobyteus/person/role.py +0 -14
- 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/__init__.py +0 -0
- 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/__init__.py +0 -0
- 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 -80
- autobyteus/tools/browser/standalone/web_page_pdf_generator.py +0 -97
- autobyteus/tools/browser/standalone/webpage_image_downloader.py +0 -165
- autobyteus/tools/browser/standalone/webpage_reader.py +0 -101
- autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +0 -101
- autobyteus/tools/file/file_editor.py +0 -200
- autobyteus/tools/google_search.py +0 -149
- autobyteus/tools/timer.py +0 -171
- 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.0.dist-info/METADATA +0 -205
- autobyteus-1.2.0.dist-info/RECORD +0 -496
- examples/__init__.py +0 -1
- examples/agent_team/__init__.py +0 -1
- examples/discover_phase_transitions.py +0 -104
- 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/{person → skills}/__init__.py +0 -0
- /autobyteus/{person/examples → tools/skill}/__init__.py +0 -0
- {autobyteus-1.2.0.dist-info → autobyteus-1.2.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/agent/phases/manager.py
|
|
2
|
-
import asyncio
|
|
3
|
-
import logging
|
|
4
|
-
from typing import TYPE_CHECKING, Optional, Dict, Any
|
|
5
|
-
|
|
6
|
-
from .phase_enum import AgentOperationalPhase
|
|
7
|
-
from .transition_decorator import phase_transition
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from autobyteus.agent.context import AgentContext
|
|
11
|
-
from autobyteus.agent.tool_invocation import ToolInvocation
|
|
12
|
-
from autobyteus.agent.events.notifiers import AgentExternalEventNotifier
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
logger = logging.getLogger(__name__)
|
|
16
|
-
|
|
17
|
-
class AgentPhaseManager:
|
|
18
|
-
"""
|
|
19
|
-
Manages the operational phase of an agent, uses an AgentExternalEventNotifier
|
|
20
|
-
to signal phase changes externally, and executes phase transition hooks.
|
|
21
|
-
"""
|
|
22
|
-
def __init__(self, context: 'AgentContext', notifier: 'AgentExternalEventNotifier'):
|
|
23
|
-
self.context: 'AgentContext' = context
|
|
24
|
-
self.notifier: 'AgentExternalEventNotifier' = notifier
|
|
25
|
-
|
|
26
|
-
self.context.current_phase = AgentOperationalPhase.UNINITIALIZED
|
|
27
|
-
|
|
28
|
-
logger.debug(f"AgentPhaseManager initialized for agent_id '{self.context.agent_id}'. "
|
|
29
|
-
f"Initial phase: {self.context.current_phase.value}. Uses provided notifier.")
|
|
30
|
-
|
|
31
|
-
async def _execute_hooks(self, old_phase: AgentOperationalPhase, new_phase: AgentOperationalPhase):
|
|
32
|
-
"""Asynchronously executes hooks that match the given phase transition."""
|
|
33
|
-
hooks_to_run = [
|
|
34
|
-
hook for hook in self.context.config.phase_hooks
|
|
35
|
-
if hook.source_phase == old_phase and hook.target_phase == new_phase
|
|
36
|
-
]
|
|
37
|
-
|
|
38
|
-
if not hooks_to_run:
|
|
39
|
-
return
|
|
40
|
-
|
|
41
|
-
hook_names = [hook.__class__.__name__ for hook in hooks_to_run]
|
|
42
|
-
logger.info(f"Agent '{self.context.agent_id}': Executing {len(hooks_to_run)} hooks for transition "
|
|
43
|
-
f"'{old_phase.value}' -> '{new_phase.value}': {hook_names}")
|
|
44
|
-
|
|
45
|
-
for hook in hooks_to_run:
|
|
46
|
-
try:
|
|
47
|
-
await hook.execute(self.context)
|
|
48
|
-
logger.debug(f"Agent '{self.context.agent_id}': Hook '{hook.__class__.__name__}' executed successfully.")
|
|
49
|
-
except Exception as e:
|
|
50
|
-
logger.error(f"Agent '{self.context.agent_id}': Error executing phase transition hook "
|
|
51
|
-
f"'{hook.__class__.__name__}' for '{old_phase.value}' -> '{new_phase.value}': {e}",
|
|
52
|
-
exc_info=True)
|
|
53
|
-
# We log the error but do not halt the agent's phase transition.
|
|
54
|
-
|
|
55
|
-
async def _transition_phase(self, new_phase: AgentOperationalPhase,
|
|
56
|
-
notify_method_name: str,
|
|
57
|
-
additional_data: Optional[Dict[str, Any]] = None):
|
|
58
|
-
"""
|
|
59
|
-
Private async helper to change the agent's phase, execute hooks, and then
|
|
60
|
-
call the appropriate notifier method. Hooks are now awaited.
|
|
61
|
-
"""
|
|
62
|
-
if not isinstance(new_phase, AgentOperationalPhase):
|
|
63
|
-
logger.error(f"AgentPhaseManager for '{self.context.agent_id}' received invalid type for new_phase: {type(new_phase)}. Must be AgentOperationalPhase.")
|
|
64
|
-
return
|
|
65
|
-
|
|
66
|
-
old_phase = self.context.current_phase
|
|
67
|
-
|
|
68
|
-
if old_phase == new_phase:
|
|
69
|
-
logger.debug(f"AgentPhaseManager for '{self.context.agent_id}': already in phase {new_phase.value}. No transition.")
|
|
70
|
-
return
|
|
71
|
-
|
|
72
|
-
logger.info(f"Agent '{self.context.agent_id}' phase transitioning from {old_phase.value} to {new_phase.value}.")
|
|
73
|
-
self.context.current_phase = new_phase
|
|
74
|
-
|
|
75
|
-
# Execute and wait for hooks to complete *before* notifying externally.
|
|
76
|
-
await self._execute_hooks(old_phase, new_phase)
|
|
77
|
-
|
|
78
|
-
notifier_method = getattr(self.notifier, notify_method_name, None)
|
|
79
|
-
if notifier_method and callable(notifier_method):
|
|
80
|
-
notify_args = {"old_phase": old_phase}
|
|
81
|
-
if additional_data:
|
|
82
|
-
notify_args.update(additional_data)
|
|
83
|
-
|
|
84
|
-
notifier_method(**notify_args)
|
|
85
|
-
else:
|
|
86
|
-
logger.error(f"AgentPhaseManager for '{self.context.agent_id}': Notifier method '{notify_method_name}' not found or not callable on {type(self.notifier).__name__}.")
|
|
87
|
-
|
|
88
|
-
@phase_transition(
|
|
89
|
-
source_phases=[AgentOperationalPhase.SHUTDOWN_COMPLETE, AgentOperationalPhase.ERROR],
|
|
90
|
-
target_phase=AgentOperationalPhase.UNINITIALIZED,
|
|
91
|
-
description="Triggered when the agent runtime is started or restarted after being in a terminal state."
|
|
92
|
-
)
|
|
93
|
-
async def notify_runtime_starting_and_uninitialized(self) -> None:
|
|
94
|
-
if self.context.current_phase == AgentOperationalPhase.UNINITIALIZED:
|
|
95
|
-
await self._transition_phase(AgentOperationalPhase.UNINITIALIZED, "notify_phase_uninitialized_entered")
|
|
96
|
-
elif self.context.current_phase.is_terminal():
|
|
97
|
-
await self._transition_phase(AgentOperationalPhase.UNINITIALIZED, "notify_phase_uninitialized_entered")
|
|
98
|
-
else:
|
|
99
|
-
logger.warning(f"Agent '{self.context.agent_id}' notify_runtime_starting_and_uninitialized called in unexpected phase: {self.context.current_phase.value}")
|
|
100
|
-
|
|
101
|
-
@phase_transition(
|
|
102
|
-
source_phases=[AgentOperationalPhase.UNINITIALIZED],
|
|
103
|
-
target_phase=AgentOperationalPhase.BOOTSTRAPPING,
|
|
104
|
-
description="Occurs when the agent's internal bootstrapping process begins."
|
|
105
|
-
)
|
|
106
|
-
async def notify_bootstrapping_started(self) -> None:
|
|
107
|
-
await self._transition_phase(AgentOperationalPhase.BOOTSTRAPPING, "notify_phase_bootstrapping_started")
|
|
108
|
-
|
|
109
|
-
@phase_transition(
|
|
110
|
-
source_phases=[AgentOperationalPhase.BOOTSTRAPPING],
|
|
111
|
-
target_phase=AgentOperationalPhase.IDLE,
|
|
112
|
-
description="Occurs when the agent successfully completes bootstrapping and is ready for input."
|
|
113
|
-
)
|
|
114
|
-
async def notify_initialization_complete(self) -> None:
|
|
115
|
-
if self.context.current_phase.is_initializing() or self.context.current_phase == AgentOperationalPhase.UNINITIALIZED:
|
|
116
|
-
# This will now be a BOOTSTRAPPING -> IDLE transition
|
|
117
|
-
await self._transition_phase(AgentOperationalPhase.IDLE, "notify_phase_idle_entered")
|
|
118
|
-
else:
|
|
119
|
-
logger.warning(f"Agent '{self.context.agent_id}' notify_initialization_complete called in unexpected phase: {self.context.current_phase.value}")
|
|
120
|
-
|
|
121
|
-
@phase_transition(
|
|
122
|
-
source_phases=[
|
|
123
|
-
AgentOperationalPhase.IDLE, AgentOperationalPhase.ANALYZING_LLM_RESPONSE,
|
|
124
|
-
AgentOperationalPhase.PROCESSING_TOOL_RESULT, AgentOperationalPhase.EXECUTING_TOOL,
|
|
125
|
-
AgentOperationalPhase.TOOL_DENIED
|
|
126
|
-
],
|
|
127
|
-
target_phase=AgentOperationalPhase.PROCESSING_USER_INPUT,
|
|
128
|
-
description="Fires when the agent begins processing a new user message or inter-agent message."
|
|
129
|
-
)
|
|
130
|
-
async def notify_processing_input_started(self, trigger_info: Optional[str] = None) -> None:
|
|
131
|
-
if self.context.current_phase in [AgentOperationalPhase.IDLE, AgentOperationalPhase.ANALYZING_LLM_RESPONSE, AgentOperationalPhase.PROCESSING_TOOL_RESULT, AgentOperationalPhase.EXECUTING_TOOL, AgentOperationalPhase.TOOL_DENIED]:
|
|
132
|
-
data = {"trigger_info": trigger_info} if trigger_info else {}
|
|
133
|
-
await self._transition_phase(AgentOperationalPhase.PROCESSING_USER_INPUT, "notify_phase_processing_user_input_started", additional_data=data)
|
|
134
|
-
elif self.context.current_phase == AgentOperationalPhase.PROCESSING_USER_INPUT:
|
|
135
|
-
logger.debug(f"Agent '{self.context.agent_id}' already in PROCESSING_USER_INPUT phase.")
|
|
136
|
-
else:
|
|
137
|
-
logger.warning(f"Agent '{self.context.agent_id}' notify_processing_input_started called in unexpected phase: {self.context.current_phase.value}")
|
|
138
|
-
|
|
139
|
-
@phase_transition(
|
|
140
|
-
source_phases=[AgentOperationalPhase.PROCESSING_USER_INPUT, AgentOperationalPhase.PROCESSING_TOOL_RESULT],
|
|
141
|
-
target_phase=AgentOperationalPhase.AWAITING_LLM_RESPONSE,
|
|
142
|
-
description="Occurs just before the agent makes a call to the LLM."
|
|
143
|
-
)
|
|
144
|
-
async def notify_awaiting_llm_response(self) -> None:
|
|
145
|
-
await self._transition_phase(AgentOperationalPhase.AWAITING_LLM_RESPONSE, "notify_phase_awaiting_llm_response_started")
|
|
146
|
-
|
|
147
|
-
@phase_transition(
|
|
148
|
-
source_phases=[AgentOperationalPhase.AWAITING_LLM_RESPONSE],
|
|
149
|
-
target_phase=AgentOperationalPhase.ANALYZING_LLM_RESPONSE,
|
|
150
|
-
description="Occurs after the agent has received a complete response from the LLM and begins to analyze it."
|
|
151
|
-
)
|
|
152
|
-
async def notify_analyzing_llm_response(self) -> None:
|
|
153
|
-
await self._transition_phase(AgentOperationalPhase.ANALYZING_LLM_RESPONSE, "notify_phase_analyzing_llm_response_started")
|
|
154
|
-
|
|
155
|
-
@phase_transition(
|
|
156
|
-
source_phases=[AgentOperationalPhase.ANALYZING_LLM_RESPONSE],
|
|
157
|
-
target_phase=AgentOperationalPhase.AWAITING_TOOL_APPROVAL,
|
|
158
|
-
description="Occurs if the agent proposes a tool use that requires manual user approval."
|
|
159
|
-
)
|
|
160
|
-
async def notify_tool_execution_pending_approval(self, tool_invocation: 'ToolInvocation') -> None:
|
|
161
|
-
await self._transition_phase(AgentOperationalPhase.AWAITING_TOOL_APPROVAL, "notify_phase_awaiting_tool_approval_started")
|
|
162
|
-
|
|
163
|
-
@phase_transition(
|
|
164
|
-
source_phases=[AgentOperationalPhase.AWAITING_TOOL_APPROVAL],
|
|
165
|
-
target_phase=AgentOperationalPhase.EXECUTING_TOOL,
|
|
166
|
-
description="Occurs after a pending tool use has been approved and is about to be executed."
|
|
167
|
-
)
|
|
168
|
-
async def notify_tool_execution_resumed_after_approval(self, approved: bool, tool_name: Optional[str]) -> None:
|
|
169
|
-
if approved and tool_name:
|
|
170
|
-
await self._transition_phase(AgentOperationalPhase.EXECUTING_TOOL, "notify_phase_executing_tool_started", additional_data={"tool_name": tool_name})
|
|
171
|
-
else:
|
|
172
|
-
logger.info(f"Agent '{self.context.agent_id}' tool execution denied for '{tool_name}'. Transitioning to allow LLM to process denial.")
|
|
173
|
-
await self.notify_tool_denied(tool_name)
|
|
174
|
-
|
|
175
|
-
@phase_transition(
|
|
176
|
-
source_phases=[AgentOperationalPhase.AWAITING_TOOL_APPROVAL],
|
|
177
|
-
target_phase=AgentOperationalPhase.TOOL_DENIED,
|
|
178
|
-
description="Occurs after a pending tool use has been denied by the user."
|
|
179
|
-
)
|
|
180
|
-
async def notify_tool_denied(self, tool_name: Optional[str]) -> None:
|
|
181
|
-
"""Notifies that a tool execution has been denied."""
|
|
182
|
-
await self._transition_phase(
|
|
183
|
-
AgentOperationalPhase.TOOL_DENIED,
|
|
184
|
-
"notify_phase_tool_denied_started",
|
|
185
|
-
additional_data={"tool_name": tool_name, "denial_for_tool": tool_name}
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
@phase_transition(
|
|
189
|
-
source_phases=[AgentOperationalPhase.ANALYZING_LLM_RESPONSE],
|
|
190
|
-
target_phase=AgentOperationalPhase.EXECUTING_TOOL,
|
|
191
|
-
description="Occurs when an agent with auto-approval executes a tool."
|
|
192
|
-
)
|
|
193
|
-
async def notify_tool_execution_started(self, tool_name: str) -> None:
|
|
194
|
-
await self._transition_phase(AgentOperationalPhase.EXECUTING_TOOL, "notify_phase_executing_tool_started", additional_data={"tool_name": tool_name})
|
|
195
|
-
|
|
196
|
-
@phase_transition(
|
|
197
|
-
source_phases=[AgentOperationalPhase.EXECUTING_TOOL],
|
|
198
|
-
target_phase=AgentOperationalPhase.PROCESSING_TOOL_RESULT,
|
|
199
|
-
description="Fires after a tool has finished executing and the agent begins processing its result."
|
|
200
|
-
)
|
|
201
|
-
async def notify_processing_tool_result(self, tool_name: str) -> None:
|
|
202
|
-
await self._transition_phase(AgentOperationalPhase.PROCESSING_TOOL_RESULT, "notify_phase_processing_tool_result_started", additional_data={"tool_name": tool_name})
|
|
203
|
-
|
|
204
|
-
@phase_transition(
|
|
205
|
-
source_phases=[
|
|
206
|
-
AgentOperationalPhase.PROCESSING_USER_INPUT, AgentOperationalPhase.ANALYZING_LLM_RESPONSE,
|
|
207
|
-
AgentOperationalPhase.PROCESSING_TOOL_RESULT
|
|
208
|
-
],
|
|
209
|
-
target_phase=AgentOperationalPhase.IDLE,
|
|
210
|
-
description="Occurs when an agent completes a processing cycle and is waiting for new input."
|
|
211
|
-
)
|
|
212
|
-
async def notify_processing_complete_and_idle(self) -> None:
|
|
213
|
-
if not self.context.current_phase.is_terminal() and self.context.current_phase != AgentOperationalPhase.IDLE:
|
|
214
|
-
await self._transition_phase(AgentOperationalPhase.IDLE, "notify_phase_idle_entered")
|
|
215
|
-
elif self.context.current_phase == AgentOperationalPhase.IDLE:
|
|
216
|
-
logger.debug(f"Agent '{self.context.agent_id}' processing complete, already IDLE.")
|
|
217
|
-
else:
|
|
218
|
-
logger.warning(f"Agent '{self.context.agent_id}' notify_processing_complete_and_idle called in unexpected phase: {self.context.current_phase.value}")
|
|
219
|
-
|
|
220
|
-
@phase_transition(
|
|
221
|
-
source_phases=[
|
|
222
|
-
AgentOperationalPhase.UNINITIALIZED, AgentOperationalPhase.BOOTSTRAPPING, AgentOperationalPhase.IDLE,
|
|
223
|
-
AgentOperationalPhase.PROCESSING_USER_INPUT, AgentOperationalPhase.AWAITING_LLM_RESPONSE,
|
|
224
|
-
AgentOperationalPhase.ANALYZING_LLM_RESPONSE, AgentOperationalPhase.AWAITING_TOOL_APPROVAL,
|
|
225
|
-
AgentOperationalPhase.TOOL_DENIED, AgentOperationalPhase.EXECUTING_TOOL,
|
|
226
|
-
AgentOperationalPhase.PROCESSING_TOOL_RESULT, AgentOperationalPhase.SHUTTING_DOWN
|
|
227
|
-
],
|
|
228
|
-
target_phase=AgentOperationalPhase.ERROR,
|
|
229
|
-
description="A catch-all transition that can occur from any non-terminal state if an unrecoverable error happens."
|
|
230
|
-
)
|
|
231
|
-
async def notify_error_occurred(self, error_message: str, error_details: Optional[str] = None) -> None:
|
|
232
|
-
if self.context.current_phase != AgentOperationalPhase.ERROR:
|
|
233
|
-
data = {"error_message": error_message, "error_details": error_details}
|
|
234
|
-
await self._transition_phase(AgentOperationalPhase.ERROR, "notify_phase_error_entered", additional_data=data)
|
|
235
|
-
else:
|
|
236
|
-
logger.debug(f"Agent '{self.context.agent_id}' already in ERROR phase when another error notified: {error_message}")
|
|
237
|
-
|
|
238
|
-
@phase_transition(
|
|
239
|
-
source_phases=[
|
|
240
|
-
AgentOperationalPhase.UNINITIALIZED, AgentOperationalPhase.BOOTSTRAPPING, AgentOperationalPhase.IDLE,
|
|
241
|
-
AgentOperationalPhase.PROCESSING_USER_INPUT, AgentOperationalPhase.AWAITING_LLM_RESPONSE,
|
|
242
|
-
AgentOperationalPhase.ANALYZING_LLM_RESPONSE, AgentOperationalPhase.AWAITING_TOOL_APPROVAL,
|
|
243
|
-
AgentOperationalPhase.TOOL_DENIED, AgentOperationalPhase.EXECUTING_TOOL,
|
|
244
|
-
AgentOperationalPhase.PROCESSING_TOOL_RESULT
|
|
245
|
-
],
|
|
246
|
-
target_phase=AgentOperationalPhase.SHUTTING_DOWN,
|
|
247
|
-
description="Fires when the agent begins its graceful shutdown sequence."
|
|
248
|
-
)
|
|
249
|
-
async def notify_shutdown_initiated(self) -> None:
|
|
250
|
-
if not self.context.current_phase.is_terminal():
|
|
251
|
-
await self._transition_phase(AgentOperationalPhase.SHUTTING_DOWN, "notify_phase_shutting_down_started")
|
|
252
|
-
else:
|
|
253
|
-
logger.debug(f"Agent '{self.context.agent_id}' shutdown initiated but already in a terminal phase: {self.context.current_phase.value}")
|
|
254
|
-
|
|
255
|
-
@phase_transition(
|
|
256
|
-
source_phases=[AgentOperationalPhase.SHUTTING_DOWN],
|
|
257
|
-
target_phase=AgentOperationalPhase.SHUTDOWN_COMPLETE,
|
|
258
|
-
description="The final transition when the agent has successfully shut down and released its resources."
|
|
259
|
-
)
|
|
260
|
-
async def notify_final_shutdown_complete(self) -> None:
|
|
261
|
-
final_phase = AgentOperationalPhase.ERROR if self.context.current_phase == AgentOperationalPhase.ERROR else AgentOperationalPhase.SHUTDOWN_COMPLETE
|
|
262
|
-
if final_phase == AgentOperationalPhase.ERROR:
|
|
263
|
-
await self._transition_phase(AgentOperationalPhase.ERROR, "notify_phase_error_entered", additional_data={"error_message": "Shutdown completed with agent in error state."})
|
|
264
|
-
else:
|
|
265
|
-
await self._transition_phase(AgentOperationalPhase.SHUTDOWN_COMPLETE, "notify_phase_shutdown_completed")
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/agent/phases/transition_decorator.py
|
|
2
|
-
import functools
|
|
3
|
-
from typing import List, Callable
|
|
4
|
-
|
|
5
|
-
from .phase_enum import AgentOperationalPhase
|
|
6
|
-
from .transition_info import PhaseTransitionInfo
|
|
7
|
-
|
|
8
|
-
def phase_transition(
|
|
9
|
-
source_phases: List[AgentOperationalPhase],
|
|
10
|
-
target_phase: AgentOperationalPhase,
|
|
11
|
-
description: str
|
|
12
|
-
) -> Callable:
|
|
13
|
-
"""
|
|
14
|
-
A decorator to annotate methods in AgentPhaseManager that cause a phase transition.
|
|
15
|
-
|
|
16
|
-
This decorator does not alter the method's execution. It attaches a
|
|
17
|
-
PhaseTransitionInfo object to the method, making the transition discoverable
|
|
18
|
-
via introspection.
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
source_phases: A list of valid source phases from which this transition can occur.
|
|
22
|
-
target_phase: The phase the agent will be in after this transition.
|
|
23
|
-
description: A human-readable description of what causes this transition.
|
|
24
|
-
"""
|
|
25
|
-
def decorator(func: Callable) -> Callable:
|
|
26
|
-
@functools.wraps(func)
|
|
27
|
-
def wrapper(*args, **kwargs):
|
|
28
|
-
return func(*args, **kwargs)
|
|
29
|
-
|
|
30
|
-
# Attach the metadata to the function object itself.
|
|
31
|
-
# We sort source phases for consistent representation.
|
|
32
|
-
sorted_sources = tuple(sorted(source_phases, key=lambda p: p.value))
|
|
33
|
-
setattr(wrapper, '_transition_info', PhaseTransitionInfo(
|
|
34
|
-
source_phases=sorted_sources,
|
|
35
|
-
target_phase=target_phase,
|
|
36
|
-
description=description,
|
|
37
|
-
triggering_method=func.__name__
|
|
38
|
-
))
|
|
39
|
-
return wrapper
|
|
40
|
-
return decorator
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/agent/phases/transition_info.py
|
|
2
|
-
import logging
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from typing import List, Tuple
|
|
5
|
-
|
|
6
|
-
from .phase_enum import AgentOperationalPhase
|
|
7
|
-
|
|
8
|
-
logger = logging.getLogger(__name__)
|
|
9
|
-
|
|
10
|
-
@dataclass(frozen=True)
|
|
11
|
-
class PhaseTransitionInfo:
|
|
12
|
-
"""
|
|
13
|
-
A dataclass representing a valid, discoverable phase transition.
|
|
14
|
-
|
|
15
|
-
This object provides the necessary metadata for users to understand what
|
|
16
|
-
kinds of phase hooks they can create.
|
|
17
|
-
|
|
18
|
-
Attributes:
|
|
19
|
-
source_phases: A list of possible source phases for this transition.
|
|
20
|
-
target_phase: The single target phase for this transition.
|
|
21
|
-
description: A human-readable description of when this transition occurs.
|
|
22
|
-
triggering_method: The name of the method in AgentPhaseManager that triggers this.
|
|
23
|
-
"""
|
|
24
|
-
source_phases: Tuple[AgentOperationalPhase, ...]
|
|
25
|
-
target_phase: AgentOperationalPhase
|
|
26
|
-
description: str
|
|
27
|
-
triggering_method: str
|
|
28
|
-
|
|
29
|
-
def __repr__(self) -> str:
|
|
30
|
-
sources = ", ".join(f"'{p.value}'" for p in self.source_phases)
|
|
31
|
-
return (f"<PhaseTransitionInfo sources=[{sources}] -> "
|
|
32
|
-
f"target='{self.target_phase.value}' "
|
|
33
|
-
f"triggered_by='{self.triggering_method}'>")
|
autobyteus/agent/remote_agent.py
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/agent/remote_agent.py
|
|
2
|
-
import asyncio
|
|
3
|
-
import logging
|
|
4
|
-
import uuid # For generating default request IDs if ProtocolMessage doesn't
|
|
5
|
-
from typing import Optional, Dict, Any, AsyncIterator
|
|
6
|
-
|
|
7
|
-
from autobyteus.agent.agent import Agent
|
|
8
|
-
from autobyteus.agent.phases import AgentOperationalPhase
|
|
9
|
-
from autobyteus.agent.message.agent_input_user_message import AgentInputUserMessage
|
|
10
|
-
from autobyteus.agent.message.inter_agent_message import InterAgentMessage
|
|
11
|
-
from autobyteus.rpc.client import default_client_connection_manager, AbstractClientConnection
|
|
12
|
-
from autobyteus.rpc.protocol import ProtocolMessage, MessageType, RequestType, ResponseType, ErrorCode
|
|
13
|
-
from autobyteus.rpc.config import AgentServerConfig, default_agent_server_registry
|
|
14
|
-
from autobyteus.rpc.transport_type import TransportType # For type checking config
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
logger = logging.getLogger(__name__)
|
|
18
|
-
|
|
19
|
-
class RemoteAgentProxy(Agent):
|
|
20
|
-
"""
|
|
21
|
-
Provides an Agent-like interface for interacting with a remote Agent Server.
|
|
22
|
-
It handles RPC communication and capability discovery.
|
|
23
|
-
Can target a specific agent on a multi-agent gateway server if target_agent_id_on_server is provided.
|
|
24
|
-
"""
|
|
25
|
-
def __init__(self,
|
|
26
|
-
server_config_id: str,
|
|
27
|
-
target_agent_id_on_server: Optional[str] = None, # Added for multi-agent servers
|
|
28
|
-
loop: Optional[asyncio.AbstractEventLoop] = None):
|
|
29
|
-
"""
|
|
30
|
-
Initializes the RemoteAgentProxy.
|
|
31
|
-
|
|
32
|
-
Args:
|
|
33
|
-
server_config_id: The ID of the AgentServerConfig in the AgentServerRegistry
|
|
34
|
-
that specifies how to connect to the remote agent server/gateway.
|
|
35
|
-
target_agent_id_on_server: Optional. If the server_config_id points to a multi-agent
|
|
36
|
-
gateway, this specifies the ID of the target agent on that
|
|
37
|
-
server. This ID is used for routing by the server.
|
|
38
|
-
loop: The asyncio event loop. If None, the running loop is used.
|
|
39
|
-
"""
|
|
40
|
-
self.server_config_id: str = server_config_id
|
|
41
|
-
self.target_agent_id_on_server: Optional[str] = target_agent_id_on_server
|
|
42
|
-
|
|
43
|
-
self._client_connection_manager = default_client_connection_manager
|
|
44
|
-
self._connection: Optional[AbstractClientConnection] = None
|
|
45
|
-
self._server_config: Optional[AgentServerConfig] = None # Will store the resolved config
|
|
46
|
-
self._loop = loop or asyncio.get_running_loop()
|
|
47
|
-
|
|
48
|
-
self._remote_agent_id_from_discovery: Optional[str] = None
|
|
49
|
-
self._remote_capabilities: Dict[str, Any] = {}
|
|
50
|
-
self._remote_status: AgentOperationalPhase = AgentOperationalPhase.UNINITIALIZED
|
|
51
|
-
|
|
52
|
-
# For Agent compatibility:
|
|
53
|
-
# If target_agent_id_on_server is known, use it for a more descriptive initial proxy agent_id.
|
|
54
|
-
# This will be overwritten by the actual agent_id from discovery.
|
|
55
|
-
default_proxy_id_suffix = target_agent_id_on_server or server_config_id
|
|
56
|
-
self.agent_id: str = f"remote_proxy_for_{default_proxy_id_suffix}"
|
|
57
|
-
self.context = None
|
|
58
|
-
|
|
59
|
-
self._is_initialized: bool = False
|
|
60
|
-
self._initialization_lock = asyncio.Lock()
|
|
61
|
-
|
|
62
|
-
logger.info(f"RemoteAgentProxy for server_id '{server_config_id}' (Targeting: {target_agent_id_on_server or 'N/A'}) created. Not yet initialized.")
|
|
63
|
-
|
|
64
|
-
async def _ensure_initialized(self):
|
|
65
|
-
async with self._initialization_lock:
|
|
66
|
-
if self._is_initialized:
|
|
67
|
-
return
|
|
68
|
-
|
|
69
|
-
if not self._connection or not self._connection.is_connected:
|
|
70
|
-
logger.info(f"RemoteAgentProxy '{self.agent_id}': Attempting connection to server_config_id '{self.server_config_id}'.")
|
|
71
|
-
# Resolve server_config here as it's needed for SSE event URL construction too
|
|
72
|
-
self._server_config = default_agent_server_registry.get_config(self.server_config_id)
|
|
73
|
-
if not self._server_config:
|
|
74
|
-
raise ValueError(f"AgentServerConfig not found for ID '{self.server_config_id}'.")
|
|
75
|
-
self._connection = await self._client_connection_manager.get_connection(self.server_config_id)
|
|
76
|
-
|
|
77
|
-
await self._discover_capabilities() # This will use self.target_agent_id_on_server
|
|
78
|
-
self._is_initialized = True
|
|
79
|
-
logger.info(f"RemoteAgentProxy '{self.agent_id}' initialized. Discovered Remote Agent ID: '{self._remote_agent_id_from_discovery}'.")
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
async def _discover_capabilities(self):
|
|
83
|
-
if not self._connection:
|
|
84
|
-
raise ConnectionError("Cannot discover capabilities: not connected.")
|
|
85
|
-
|
|
86
|
-
params_for_discovery: Dict[str, Any] = {}
|
|
87
|
-
if self.target_agent_id_on_server:
|
|
88
|
-
params_for_discovery["target_agent_id"] = self.target_agent_id_on_server
|
|
89
|
-
|
|
90
|
-
request_msg = ProtocolMessage.create_request(
|
|
91
|
-
method=RequestType.DISCOVER_CAPABILITIES,
|
|
92
|
-
params=params_for_discovery if params_for_discovery else None
|
|
93
|
-
)
|
|
94
|
-
logger.debug(f"RemoteAgentProxy '{self.agent_id}': Sending discover_capabilities request with params: {params_for_discovery}.")
|
|
95
|
-
|
|
96
|
-
response_msg = await self._connection.send_request(request_msg)
|
|
97
|
-
|
|
98
|
-
if response_msg.type == MessageType.RESPONSE and response_msg.result:
|
|
99
|
-
self._remote_agent_id_from_discovery = response_msg.result.get("agent_id")
|
|
100
|
-
# Update proxy's agent_id to the actual discovered ID for better logging/identification
|
|
101
|
-
if self._remote_agent_id_from_discovery:
|
|
102
|
-
self.agent_id = self._remote_agent_id_from_discovery
|
|
103
|
-
|
|
104
|
-
self._remote_capabilities = response_msg.result.get("capabilities_details", {}) # Use detailed map
|
|
105
|
-
initial_status_str = response_msg.result.get("status") # 'status' key for legacy, but should be 'phase'
|
|
106
|
-
initial_phase_str = response_msg.result.get("phase", initial_status_str) # Prefer 'phase'
|
|
107
|
-
if initial_phase_str:
|
|
108
|
-
try: self._remote_status = AgentOperationalPhase(initial_phase_str)
|
|
109
|
-
except ValueError: logger.warning(f"Invalid phase '{initial_phase_str}' from discovery."); self._remote_status = AgentOperationalPhase.UNINITIALIZED
|
|
110
|
-
logger.info(f"RemoteAgentProxy (now ID: '{self.agent_id}'): Capabilities discovered. Remote Caps: {list(self._remote_capabilities.keys())}")
|
|
111
|
-
elif response_msg.type == MessageType.ERROR and response_msg.error:
|
|
112
|
-
err = response_msg.error
|
|
113
|
-
logger.error(f"RemoteAgentProxy '{self.agent_id}': Error discovering capabilities: {err.code} - {err.message}")
|
|
114
|
-
raise RuntimeError(f"Failed to discover remote agent capabilities: {err.message}")
|
|
115
|
-
else:
|
|
116
|
-
logger.error(f"RemoteAgentProxy '{self.agent_id}': Unexpected response during capability discovery: {response_msg.to_json_str()}")
|
|
117
|
-
raise RuntimeError("Unexpected response from remote agent during capability discovery.")
|
|
118
|
-
|
|
119
|
-
async def _invoke_remote_method(self, method_name: str, method_params: Optional[Dict[str, Any]] = None) -> Any:
|
|
120
|
-
await self._ensure_initialized()
|
|
121
|
-
if not self._connection:
|
|
122
|
-
raise ConnectionError("Not connected to remote agent.")
|
|
123
|
-
|
|
124
|
-
# Construct parameters for the INVOKE_METHOD RPC call itself
|
|
125
|
-
rpc_params: Dict[str, Any] = {
|
|
126
|
-
"method_name": method_name,
|
|
127
|
-
"method_params": method_params or {}
|
|
128
|
-
}
|
|
129
|
-
if self.target_agent_id_on_server:
|
|
130
|
-
rpc_params["target_agent_id"] = self.target_agent_id_on_server
|
|
131
|
-
|
|
132
|
-
request_msg = ProtocolMessage.create_request(
|
|
133
|
-
method=RequestType.INVOKE_METHOD,
|
|
134
|
-
params=rpc_params
|
|
135
|
-
)
|
|
136
|
-
log_method_params = str(method_params)[:100] + "..." if method_params and len(str(method_params)) > 100 else method_params
|
|
137
|
-
logger.debug(f"RemoteAgentProxy '{self.agent_id}': Invoking remote method '{method_name}' (Targeting: {self.target_agent_id_on_server or 'default'}) with params: {log_method_params}")
|
|
138
|
-
|
|
139
|
-
response_msg = await self._connection.send_request(request_msg)
|
|
140
|
-
|
|
141
|
-
if response_msg.type == MessageType.RESPONSE:
|
|
142
|
-
logger.debug(f"RemoteAgentProxy '{self.agent_id}': Received successful response for '{method_name}'.")
|
|
143
|
-
return response_msg.result
|
|
144
|
-
elif response_msg.type == MessageType.ERROR and response_msg.error:
|
|
145
|
-
err = response_msg.error
|
|
146
|
-
logger.error(f"RemoteAgentProxy '{self.agent_id}': Error invoking remote method '{method_name}': {err.code} - {err.message}")
|
|
147
|
-
raise RuntimeError(f"Error from remote agent on method '{method_name}': {err.message}")
|
|
148
|
-
else:
|
|
149
|
-
logger.error(f"RemoteAgentProxy '{self.agent_id}': Unexpected response invoking method '{method_name}': {response_msg.to_json_str()}")
|
|
150
|
-
raise RuntimeError(f"Unexpected response from remote agent invoking '{method_name}'.")
|
|
151
|
-
|
|
152
|
-
async def post_user_message(self, agent_input_user_message: AgentInputUserMessage) -> None:
|
|
153
|
-
params = {"agent_input_user_message": agent_input_user_message.to_dict()}
|
|
154
|
-
await self._invoke_remote_method("post_user_message", params)
|
|
155
|
-
logger.debug(f"RemoteAgentProxy '{self.agent_id}': post_user_message request sent.")
|
|
156
|
-
|
|
157
|
-
async def post_inter_agent_message(self, inter_agent_message: InterAgentMessage) -> None:
|
|
158
|
-
params = { "inter_agent_message": {
|
|
159
|
-
"recipient_role_name": inter_agent_message.recipient_role_name,
|
|
160
|
-
"recipient_agent_id": inter_agent_message.recipient_agent_id,
|
|
161
|
-
"content": inter_agent_message.content,
|
|
162
|
-
"message_type": str(inter_agent_message.message_type.value),
|
|
163
|
-
"sender_agent_id": inter_agent_message.sender_agent_id,
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
await self._invoke_remote_method("post_inter_agent_message", params)
|
|
167
|
-
logger.debug(f"RemoteAgentProxy '{self.agent_id}': post_inter_agent_message request sent.")
|
|
168
|
-
|
|
169
|
-
async def post_tool_execution_approval(self,
|
|
170
|
-
tool_invocation_id: str,
|
|
171
|
-
is_approved: bool,
|
|
172
|
-
reason: Optional[str] = None) -> None:
|
|
173
|
-
params = { "tool_invocation_id": tool_invocation_id, "is_approved": is_approved, "reason": reason}
|
|
174
|
-
await self._invoke_remote_method("post_tool_execution_approval", params)
|
|
175
|
-
logger.debug(f"RemoteAgentProxy '{self.agent_id}': post_tool_execution_approval sent.")
|
|
176
|
-
|
|
177
|
-
def get_current_phase(self) -> AgentOperationalPhase:
|
|
178
|
-
if not self._is_initialized:
|
|
179
|
-
logger.warning(f"RemoteAgentProxy '{self.agent_id}': get_current_phase called before initialization.")
|
|
180
|
-
# Returns cached status updated by discovery or potentially by SSE events.
|
|
181
|
-
return self._remote_status
|
|
182
|
-
|
|
183
|
-
@property
|
|
184
|
-
def is_running(self) -> bool:
|
|
185
|
-
# A remote agent is "running" if it's not in a terminal state or uninitialized.
|
|
186
|
-
if self._remote_status:
|
|
187
|
-
return not self._remote_status.is_terminal() and self._remote_status != AgentOperationalPhase.UNINITIALIZED
|
|
188
|
-
return False
|
|
189
|
-
|
|
190
|
-
def start(self) -> None:
|
|
191
|
-
# For RemoteAgentProxy, start() implies ensuring connection and readiness.
|
|
192
|
-
# The actual remote agent lifecycle is independent.
|
|
193
|
-
if not self._is_initialized:
|
|
194
|
-
logger.info(f"RemoteAgentProxy '{self.agent_id}': start() called. Ensuring initialization (async).")
|
|
195
|
-
if self._loop.is_running(): asyncio.create_task(self._ensure_initialized())
|
|
196
|
-
else:
|
|
197
|
-
try: self._loop.run_until_complete(self._ensure_initialized())
|
|
198
|
-
except RuntimeError as e:
|
|
199
|
-
if "cannot be nested" in str(e): logger.warning("RemoteAgentProxy.start() in sync context with running loop.")
|
|
200
|
-
else: raise
|
|
201
|
-
|
|
202
|
-
async def stop(self, timeout: float = 10.0) -> None:
|
|
203
|
-
logger.info(f"RemoteAgentProxy '{self.agent_id}': stop() called. Closing connection to '{self.server_config_id}'.")
|
|
204
|
-
if self._connection:
|
|
205
|
-
await self._connection.close()
|
|
206
|
-
self._connection = None
|
|
207
|
-
self._is_initialized = False
|
|
208
|
-
self._remote_status = AgentOperationalPhase.SHUTDOWN_COMPLETE
|
|
209
|
-
|
|
210
|
-
def get_event_queues(self):
|
|
211
|
-
logger.warning("RemoteAgentProxy does not provide direct access to remote event queues.")
|
|
212
|
-
return None
|
|
213
|
-
|
|
214
|
-
async def stream_events(self) -> AsyncIterator[ProtocolMessage]:
|
|
215
|
-
"""
|
|
216
|
-
Streams server-pushed events if connected via SSE.
|
|
217
|
-
"""
|
|
218
|
-
await self._ensure_initialized() # Ensures self._connection and self._server_config are set
|
|
219
|
-
if not self._connection:
|
|
220
|
-
raise ConnectionError("Not connected to remote agent.")
|
|
221
|
-
if not self._server_config or self._server_config.transport_type != TransportType.SSE:
|
|
222
|
-
logger.warning(f"Event streaming only supported for SSE transport. Current: {self._server_config.transport_type if self._server_config else 'Unknown'}")
|
|
223
|
-
if False: yield # Make it an async generator
|
|
224
|
-
return
|
|
225
|
-
|
|
226
|
-
logger.info(f"RemoteAgentProxy '{self.agent_id}': Starting to stream events (Target: {self.target_agent_id_on_server or 'default'}).")
|
|
227
|
-
async for event in self._connection.events():
|
|
228
|
-
# Update remote status if a phase transition event is received
|
|
229
|
-
if event.type == MessageType.EVENT and event.event_type == "agent_phase_transition" and event.payload:
|
|
230
|
-
new_phase_str = event.payload.get("new_phase")
|
|
231
|
-
if new_phase_str:
|
|
232
|
-
try:
|
|
233
|
-
self._remote_status = AgentOperationalPhase(new_phase_str)
|
|
234
|
-
logger.debug(f"RemoteAgentProxy '{self.agent_id}': Remote phase updated to {self._remote_status.value}")
|
|
235
|
-
except ValueError:
|
|
236
|
-
logger.warning(f"Received invalid phase '{new_phase_str}' via SSE event.")
|
|
237
|
-
yield event
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
def __repr__(self) -> str:
|
|
241
|
-
conn_status = self._connection.is_connected if self._connection else False
|
|
242
|
-
return (f"<RemoteAgentProxy effective_id='{self.agent_id}' "
|
|
243
|
-
f"(DiscoveredRemoteID: {self._remote_agent_id_from_discovery or 'N/A'}) "
|
|
244
|
-
f"server_cfg='{self.server_config_id}' target_on_server='{self.target_agent_id_on_server or 'N/A'}' connected={conn_status}>")
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module defines the WorkspaceDefinition class, which encapsulates the metadata
|
|
3
|
-
for a specific type of agent workspace.
|
|
4
|
-
"""
|
|
5
|
-
import logging
|
|
6
|
-
from typing import Type, Optional, TYPE_CHECKING
|
|
7
|
-
from autobyteus.utils.parameter_schema import ParameterSchema
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from autobyteus.agent.workspace.base_workspace import BaseAgentWorkspace
|
|
11
|
-
|
|
12
|
-
logger = logging.getLogger(__name__)
|
|
13
|
-
|
|
14
|
-
class WorkspaceDefinition:
|
|
15
|
-
"""Represents the definition of a discoverable and creatable agent workspace type."""
|
|
16
|
-
def __init__(self,
|
|
17
|
-
workspace_type_name: str,
|
|
18
|
-
description: str,
|
|
19
|
-
workspace_class: Type['BaseAgentWorkspace'],
|
|
20
|
-
config_schema: ParameterSchema):
|
|
21
|
-
if not all([workspace_type_name, description, workspace_class, config_schema is not None]):
|
|
22
|
-
raise ValueError("All parameters for WorkspaceDefinition are required.")
|
|
23
|
-
|
|
24
|
-
self.workspace_type_name = workspace_type_name
|
|
25
|
-
self.description = description
|
|
26
|
-
self.workspace_class = workspace_class
|
|
27
|
-
self.config_schema = config_schema
|
|
28
|
-
logger.debug(f"WorkspaceDefinition created for type '{workspace_type_name}'.")
|
|
29
|
-
|
|
30
|
-
def to_dict(self) -> dict:
|
|
31
|
-
"""Serializes the definition to a dictionary for API exposure."""
|
|
32
|
-
return {
|
|
33
|
-
"workspace_type_name": self.workspace_type_name,
|
|
34
|
-
"description": self.description,
|
|
35
|
-
"config_schema": self.config_schema.to_dict()
|
|
36
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module contains the metaclass for BaseAgentWorkspace for automatic registration.
|
|
3
|
-
"""
|
|
4
|
-
import logging
|
|
5
|
-
from abc import ABCMeta
|
|
6
|
-
from .workspace_registry import default_workspace_registry
|
|
7
|
-
from .workspace_definition import WorkspaceDefinition
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger(__name__)
|
|
10
|
-
|
|
11
|
-
class WorkspaceMeta(ABCMeta):
|
|
12
|
-
"""Metaclass to automatically register concrete BaseAgentWorkspace subclasses."""
|
|
13
|
-
def __init__(cls, name, bases, dct):
|
|
14
|
-
super().__init__(name, bases, dct)
|
|
15
|
-
|
|
16
|
-
if name == 'BaseAgentWorkspace' or getattr(cls, "__abstractmethods__", None):
|
|
17
|
-
logger.debug(f"Skipping registration for abstract workspace class: {name}")
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
try:
|
|
21
|
-
workspace_type_name = cls.get_workspace_type_name()
|
|
22
|
-
description = cls.get_description()
|
|
23
|
-
config_schema = cls.get_config_schema()
|
|
24
|
-
|
|
25
|
-
definition = WorkspaceDefinition(
|
|
26
|
-
workspace_type_name=workspace_type_name,
|
|
27
|
-
description=description,
|
|
28
|
-
workspace_class=cls,
|
|
29
|
-
config_schema=config_schema
|
|
30
|
-
)
|
|
31
|
-
default_workspace_registry.register(definition)
|
|
32
|
-
config_params_info = f"config_params: {len(config_schema) if config_schema else 0}"
|
|
33
|
-
logger.info(f"Auto-registered workspace: '{workspace_type_name}' from class {name} ({config_params_info})")
|
|
34
|
-
except AttributeError as e:
|
|
35
|
-
logger.error(f"Workspace class {name} is missing a required static/class method ({e}). Skipping registration.")
|
|
36
|
-
except Exception as e:
|
|
37
|
-
logger.error(f"Failed to auto-register workspace class {name}: {e}", exc_info=True)
|