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
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/events/event_store.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import logging
|
|
5
|
+
import time
|
|
6
|
+
import uuid
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import List, Optional
|
|
9
|
+
|
|
10
|
+
from autobyteus.agent_team.events.agent_team_events import BaseAgentTeamEvent
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class EventEnvelope:
|
|
17
|
+
event_id: str
|
|
18
|
+
event_type: str
|
|
19
|
+
timestamp: float
|
|
20
|
+
team_id: str
|
|
21
|
+
event: BaseAgentTeamEvent
|
|
22
|
+
correlation_id: Optional[str] = None
|
|
23
|
+
caused_by_event_id: Optional[str] = None
|
|
24
|
+
sequence: int = 0
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AgentTeamEventStore:
|
|
28
|
+
"""
|
|
29
|
+
Simple in-memory event store for agent team events.
|
|
30
|
+
"""
|
|
31
|
+
def __init__(self, team_id: str):
|
|
32
|
+
self._team_id = team_id
|
|
33
|
+
self._events: List[EventEnvelope] = []
|
|
34
|
+
self._sequence: int = 0
|
|
35
|
+
logger.debug(f"AgentTeamEventStore initialized for team_id '{team_id}'.")
|
|
36
|
+
|
|
37
|
+
def append(self,
|
|
38
|
+
event: BaseAgentTeamEvent,
|
|
39
|
+
correlation_id: Optional[str] = None,
|
|
40
|
+
caused_by_event_id: Optional[str] = None) -> EventEnvelope:
|
|
41
|
+
envelope = EventEnvelope(
|
|
42
|
+
event_id=str(uuid.uuid4()),
|
|
43
|
+
event_type=type(event).__name__,
|
|
44
|
+
timestamp=time.time(),
|
|
45
|
+
team_id=self._team_id,
|
|
46
|
+
event=event,
|
|
47
|
+
correlation_id=correlation_id,
|
|
48
|
+
caused_by_event_id=caused_by_event_id,
|
|
49
|
+
sequence=self._sequence,
|
|
50
|
+
)
|
|
51
|
+
self._sequence += 1
|
|
52
|
+
self._events.append(envelope)
|
|
53
|
+
logger.debug(f"Appended event '{envelope.event_type}' to store for team '{self._team_id}'.")
|
|
54
|
+
return envelope
|
|
55
|
+
|
|
56
|
+
def all_events(self) -> List[EventEnvelope]:
|
|
57
|
+
return list(self._events)
|
|
@@ -17,7 +17,11 @@ from autobyteus.agent_team.handlers.inter_agent_message_request_event_handler im
|
|
|
17
17
|
from autobyteus.agent_team.handlers.tool_approval_team_event_handler import ToolApprovalTeamEventHandler
|
|
18
18
|
from autobyteus.agent_team.events.agent_team_events import (
|
|
19
19
|
ProcessUserMessageEvent,
|
|
20
|
+
AgentTeamBootstrapStartedEvent,
|
|
20
21
|
AgentTeamReadyEvent,
|
|
22
|
+
AgentTeamIdleEvent,
|
|
23
|
+
AgentTeamShutdownRequestedEvent,
|
|
24
|
+
AgentTeamStoppedEvent,
|
|
21
25
|
AgentTeamErrorEvent,
|
|
22
26
|
InterAgentMessageRequestEvent,
|
|
23
27
|
ToolApprovalTeamEvent
|
|
@@ -41,7 +45,11 @@ class AgentTeamFactory(metaclass=SingletonMeta):
|
|
|
41
45
|
registry.register(InterAgentMessageRequestEvent, InterAgentMessageRequestEventHandler())
|
|
42
46
|
registry.register(ToolApprovalTeamEvent, ToolApprovalTeamEventHandler())
|
|
43
47
|
lifecycle_handler = LifecycleAgentTeamEventHandler()
|
|
48
|
+
registry.register(AgentTeamBootstrapStartedEvent, lifecycle_handler)
|
|
44
49
|
registry.register(AgentTeamReadyEvent, lifecycle_handler)
|
|
50
|
+
registry.register(AgentTeamIdleEvent, lifecycle_handler)
|
|
51
|
+
registry.register(AgentTeamShutdownRequestedEvent, lifecycle_handler)
|
|
52
|
+
registry.register(AgentTeamStoppedEvent, lifecycle_handler)
|
|
45
53
|
registry.register(AgentTeamErrorEvent, lifecycle_handler)
|
|
46
54
|
return registry
|
|
47
55
|
|
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from autobyteus.agent_team.handlers.base_agent_team_event_handler import BaseAgentTeamEventHandler
|
|
6
|
-
from autobyteus.agent_team.events.agent_team_events import InterAgentMessageRequestEvent
|
|
6
|
+
from autobyteus.agent_team.events.agent_team_events import InterAgentMessageRequestEvent, AgentTeamErrorEvent
|
|
7
7
|
from autobyteus.agent.message.inter_agent_message import InterAgentMessage
|
|
8
8
|
from autobyteus.agent.message.agent_input_user_message import AgentInputUserMessage
|
|
9
9
|
from autobyteus.agent_team.agent_team import AgentTeam
|
|
@@ -24,7 +24,12 @@ class InterAgentMessageRequestEventHandler(BaseAgentTeamEventHandler):
|
|
|
24
24
|
team_manager = context.team_manager
|
|
25
25
|
|
|
26
26
|
if not team_manager:
|
|
27
|
-
|
|
27
|
+
msg = f"Team '{team_id}': TeamManager not found. Cannot route message from '{event.sender_agent_id}' to '{event.recipient_name}'."
|
|
28
|
+
logger.error(msg)
|
|
29
|
+
if context.state.input_event_queues:
|
|
30
|
+
await context.state.input_event_queues.enqueue_internal_system_event(
|
|
31
|
+
AgentTeamErrorEvent(error_message=msg, exception_details="TeamManager is not initialized.")
|
|
32
|
+
)
|
|
28
33
|
return
|
|
29
34
|
|
|
30
35
|
try:
|
|
@@ -32,6 +37,13 @@ class InterAgentMessageRequestEventHandler(BaseAgentTeamEventHandler):
|
|
|
32
37
|
except Exception as e:
|
|
33
38
|
msg = f"Recipient node '{event.recipient_name}' not found or failed to start for message from '{event.sender_agent_id}'. Error: {e}"
|
|
34
39
|
logger.error(f"Team '{team_id}': {msg}", exc_info=True)
|
|
40
|
+
if context.state.input_event_queues:
|
|
41
|
+
await context.state.input_event_queues.enqueue_internal_system_event(
|
|
42
|
+
AgentTeamErrorEvent(
|
|
43
|
+
error_message=f"Team '{team_id}': {msg}",
|
|
44
|
+
exception_details=f"Node '{event.recipient_name}' not found or failed to start."
|
|
45
|
+
)
|
|
46
|
+
)
|
|
35
47
|
return
|
|
36
48
|
|
|
37
49
|
try:
|
|
@@ -59,3 +71,7 @@ class InterAgentMessageRequestEventHandler(BaseAgentTeamEventHandler):
|
|
|
59
71
|
except Exception as e:
|
|
60
72
|
msg = f"Error posting message to node '{event.recipient_name}': {e}"
|
|
61
73
|
logger.error(f"Team '{team_id}': {msg}", exc_info=True)
|
|
74
|
+
if context.state.input_event_queues:
|
|
75
|
+
await context.state.input_event_queues.enqueue_internal_system_event(
|
|
76
|
+
AgentTeamErrorEvent(error_message=f"Team '{team_id}': {msg}", exception_details="Message delivery failed.")
|
|
77
|
+
)
|
|
@@ -3,7 +3,15 @@ import logging
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from autobyteus.agent_team.handlers.base_agent_team_event_handler import BaseAgentTeamEventHandler
|
|
6
|
-
from autobyteus.agent_team.events.agent_team_events import
|
|
6
|
+
from autobyteus.agent_team.events.agent_team_events import (
|
|
7
|
+
BaseAgentTeamEvent,
|
|
8
|
+
AgentTeamBootstrapStartedEvent,
|
|
9
|
+
AgentTeamReadyEvent,
|
|
10
|
+
AgentTeamIdleEvent,
|
|
11
|
+
AgentTeamShutdownRequestedEvent,
|
|
12
|
+
AgentTeamStoppedEvent,
|
|
13
|
+
AgentTeamErrorEvent,
|
|
14
|
+
)
|
|
7
15
|
|
|
8
16
|
if TYPE_CHECKING:
|
|
9
17
|
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
@@ -14,14 +22,22 @@ class LifecycleAgentTeamEventHandler(BaseAgentTeamEventHandler):
|
|
|
14
22
|
"""Logs various lifecycle events for an agent team."""
|
|
15
23
|
async def handle(self, event: BaseAgentTeamEvent, context: 'AgentTeamContext') -> None:
|
|
16
24
|
team_id = context.team_id
|
|
17
|
-
|
|
25
|
+
current_status = context.state.current_status.value
|
|
18
26
|
|
|
19
|
-
if isinstance(event,
|
|
20
|
-
logger.info(f"Team '{team_id}' Logged
|
|
27
|
+
if isinstance(event, AgentTeamBootstrapStartedEvent):
|
|
28
|
+
logger.info(f"Team '{team_id}' Logged AgentTeamBootstrapStartedEvent. Current status: {current_status}")
|
|
29
|
+
elif isinstance(event, AgentTeamReadyEvent):
|
|
30
|
+
logger.info(f"Team '{team_id}' Logged AgentTeamReadyEvent. Current status: {current_status}")
|
|
31
|
+
elif isinstance(event, AgentTeamIdleEvent):
|
|
32
|
+
logger.info(f"Team '{team_id}' Logged AgentTeamIdleEvent. Current status: {current_status}")
|
|
33
|
+
elif isinstance(event, AgentTeamShutdownRequestedEvent):
|
|
34
|
+
logger.info(f"Team '{team_id}' Logged AgentTeamShutdownRequestedEvent. Current status: {current_status}")
|
|
35
|
+
elif isinstance(event, AgentTeamStoppedEvent):
|
|
36
|
+
logger.info(f"Team '{team_id}' Logged AgentTeamStoppedEvent. Current status: {current_status}")
|
|
21
37
|
elif isinstance(event, AgentTeamErrorEvent):
|
|
22
38
|
logger.error(
|
|
23
39
|
f"Team '{team_id}' Logged AgentTeamErrorEvent: {event.error_message}. "
|
|
24
|
-
f"Details: {event.exception_details}. Current
|
|
40
|
+
f"Details: {event.exception_details}. Current status: {current_status}"
|
|
25
41
|
)
|
|
26
42
|
else:
|
|
27
43
|
logger.warning(f"LifecycleAgentTeamEventHandler received unhandled event type: {type(event).__name__}")
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# file: autobyteus/autobyteus/agent_team/handlers/process_user_message_event_handler.py
|
|
2
2
|
import logging
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
4
5
|
from autobyteus.agent_team.handlers.base_agent_team_event_handler import BaseAgentTeamEventHandler
|
|
5
|
-
from autobyteus.agent_team.events.agent_team_events import ProcessUserMessageEvent
|
|
6
|
+
from autobyteus.agent_team.events.agent_team_events import ProcessUserMessageEvent, AgentTeamErrorEvent
|
|
6
7
|
from autobyteus.agent.agent import Agent
|
|
7
8
|
from autobyteus.agent_team.agent_team import AgentTeam
|
|
8
9
|
from autobyteus.agent.message.agent_input_user_message import AgentInputUserMessage
|
|
@@ -15,13 +16,14 @@ logger = logging.getLogger(__name__)
|
|
|
15
16
|
class ProcessUserMessageEventHandler(BaseAgentTeamEventHandler):
|
|
16
17
|
"""Handles user messages by routing them to the specified target agent or sub-team."""
|
|
17
18
|
async def handle(self, event: ProcessUserMessageEvent, context: 'AgentTeamContext') -> None:
|
|
18
|
-
await context.phase_manager.notify_processing_started()
|
|
19
|
-
|
|
20
19
|
team_manager = context.team_manager
|
|
21
20
|
if not team_manager:
|
|
22
21
|
msg = f"Team '{context.team_id}': TeamManager not found. Cannot route message."
|
|
23
22
|
logger.error(msg)
|
|
24
|
-
|
|
23
|
+
if context.state.input_event_queues:
|
|
24
|
+
await context.state.input_event_queues.enqueue_internal_system_event(
|
|
25
|
+
AgentTeamErrorEvent(error_message=msg, exception_details="TeamManager is not initialized.")
|
|
26
|
+
)
|
|
25
27
|
return
|
|
26
28
|
|
|
27
29
|
try:
|
|
@@ -29,7 +31,13 @@ class ProcessUserMessageEventHandler(BaseAgentTeamEventHandler):
|
|
|
29
31
|
except Exception as e:
|
|
30
32
|
msg = f"Team '{context.team_id}': Node '{event.target_agent_name}' not found or failed to start. Cannot route message. Error: {e}"
|
|
31
33
|
logger.error(msg, exc_info=True)
|
|
32
|
-
|
|
34
|
+
if context.state.input_event_queues:
|
|
35
|
+
await context.state.input_event_queues.enqueue_internal_system_event(
|
|
36
|
+
AgentTeamErrorEvent(
|
|
37
|
+
error_message=msg,
|
|
38
|
+
exception_details=f"Node '{event.target_agent_name}' not found or failed to start."
|
|
39
|
+
)
|
|
40
|
+
)
|
|
33
41
|
return
|
|
34
42
|
|
|
35
43
|
if isinstance(target_node, Agent):
|
|
@@ -41,6 +49,7 @@ class ProcessUserMessageEventHandler(BaseAgentTeamEventHandler):
|
|
|
41
49
|
else:
|
|
42
50
|
msg = f"Target node '{event.target_agent_name}' is of an unsupported type: {type(target_node).__name__}"
|
|
43
51
|
logger.error(f"Team '{context.team_id}': {msg}")
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
if context.state.input_event_queues:
|
|
53
|
+
await context.state.input_event_queues.enqueue_internal_system_event(
|
|
54
|
+
AgentTeamErrorEvent(error_message=msg, exception_details="")
|
|
55
|
+
)
|
|
@@ -3,7 +3,7 @@ import logging
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from autobyteus.agent_team.handlers.base_agent_team_event_handler import BaseAgentTeamEventHandler
|
|
6
|
-
from autobyteus.agent_team.events.agent_team_events import ToolApprovalTeamEvent
|
|
6
|
+
from autobyteus.agent_team.events.agent_team_events import ToolApprovalTeamEvent, AgentTeamErrorEvent
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
9
|
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
@@ -21,7 +21,10 @@ class ToolApprovalTeamEventHandler(BaseAgentTeamEventHandler):
|
|
|
21
21
|
if not team_manager:
|
|
22
22
|
msg = f"Team '{team_id}': TeamManager not found. Cannot route approval for agent '{event.agent_name}'."
|
|
23
23
|
logger.error(msg)
|
|
24
|
-
|
|
24
|
+
if context.state.input_event_queues:
|
|
25
|
+
await context.state.input_event_queues.enqueue_internal_system_event(
|
|
26
|
+
AgentTeamErrorEvent(error_message=msg, exception_details="TeamManager is not initialized.")
|
|
27
|
+
)
|
|
25
28
|
return
|
|
26
29
|
|
|
27
30
|
from autobyteus.agent.agent import Agent
|
|
@@ -29,7 +32,13 @@ class ToolApprovalTeamEventHandler(BaseAgentTeamEventHandler):
|
|
|
29
32
|
if not isinstance(target_node, Agent):
|
|
30
33
|
msg = f"Team '{team_id}': Target node '{event.agent_name}' for approval is not an agent."
|
|
31
34
|
logger.error(msg)
|
|
32
|
-
|
|
35
|
+
if context.state.input_event_queues:
|
|
36
|
+
await context.state.input_event_queues.enqueue_internal_system_event(
|
|
37
|
+
AgentTeamErrorEvent(
|
|
38
|
+
error_message=msg,
|
|
39
|
+
exception_details=f"Node '{event.agent_name}' is not an agent."
|
|
40
|
+
)
|
|
41
|
+
)
|
|
33
42
|
return
|
|
34
43
|
|
|
35
44
|
target_agent = target_node
|
|
@@ -37,7 +46,13 @@ class ToolApprovalTeamEventHandler(BaseAgentTeamEventHandler):
|
|
|
37
46
|
if not target_agent:
|
|
38
47
|
msg = f"Team '{team_id}': Target agent '{event.agent_name}' for approval not found or failed to start."
|
|
39
48
|
logger.error(msg)
|
|
40
|
-
|
|
49
|
+
if context.state.input_event_queues:
|
|
50
|
+
await context.state.input_event_queues.enqueue_internal_system_event(
|
|
51
|
+
AgentTeamErrorEvent(
|
|
52
|
+
error_message=msg,
|
|
53
|
+
exception_details=f"Agent '{event.agent_name}' not found or failed to start."
|
|
54
|
+
)
|
|
55
|
+
)
|
|
41
56
|
return
|
|
42
57
|
|
|
43
58
|
logger.info(f"Team '{team_id}': Posting tool approval (Approved: {event.is_approved}) to agent '{event.agent_name}' for invocation '{event.tool_invocation_id}'.")
|
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
|
|
1
2
|
# file: autobyteus/autobyteus/agent_team/runtime/agent_team_runtime.py
|
|
2
3
|
import asyncio
|
|
3
4
|
import logging
|
|
4
|
-
|
|
5
|
+
import traceback
|
|
6
|
+
from typing import TYPE_CHECKING, Optional
|
|
5
7
|
|
|
6
8
|
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
7
|
-
from autobyteus.agent_team.
|
|
9
|
+
from autobyteus.agent_team.status.agent_team_status_manager import AgentTeamStatusManager
|
|
10
|
+
from autobyteus.agent_team.status.status_update_utils import apply_event_and_derive_status
|
|
8
11
|
from autobyteus.agent_team.runtime.agent_team_worker import AgentTeamWorker
|
|
9
|
-
from autobyteus.agent_team.events.agent_team_events import
|
|
12
|
+
from autobyteus.agent_team.events.agent_team_events import (
|
|
13
|
+
BaseAgentTeamEvent,
|
|
14
|
+
AgentTeamErrorEvent,
|
|
15
|
+
AgentTeamStoppedEvent,
|
|
16
|
+
AgentTeamShutdownRequestedEvent,
|
|
17
|
+
)
|
|
10
18
|
from autobyteus.agent_team.streaming.agent_team_event_notifier import AgentTeamExternalEventNotifier
|
|
11
19
|
from autobyteus.agent_team.streaming.agent_event_multiplexer import AgentEventMultiplexer
|
|
12
20
|
|
|
@@ -20,10 +28,11 @@ class AgentTeamRuntime:
|
|
|
20
28
|
def __init__(self, context: AgentTeamContext, event_handler_registry: 'AgentTeamEventHandlerRegistry'):
|
|
21
29
|
self.context = context
|
|
22
30
|
self.notifier = AgentTeamExternalEventNotifier(team_id=self.context.team_id, runtime_ref=self)
|
|
23
|
-
self.phase_manager = AgentTeamPhaseManager(context=self.context, notifier=self.notifier)
|
|
24
31
|
|
|
25
|
-
#
|
|
26
|
-
self.
|
|
32
|
+
# Create the status manager before the worker so external notifications are available during bootstrap.
|
|
33
|
+
self.status_manager: AgentTeamStatusManager = AgentTeamStatusManager(self.context, self.notifier)
|
|
34
|
+
self.context.state.status_manager_ref = self.status_manager
|
|
35
|
+
|
|
27
36
|
|
|
28
37
|
self._worker = AgentTeamWorker(self.context, event_handler_registry)
|
|
29
38
|
|
|
@@ -50,8 +59,22 @@ class AgentTeamRuntime:
|
|
|
50
59
|
logger.info(f"AgentTeamRuntime '{team_id}': Worker thread completed.")
|
|
51
60
|
except Exception as e:
|
|
52
61
|
logger.error(f"AgentTeamRuntime '{team_id}': Worker thread terminated with exception: {e}", exc_info=True)
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
if not self.context.current_status.is_terminal():
|
|
63
|
+
try:
|
|
64
|
+
asyncio.run(self._apply_event_and_derive_status(
|
|
65
|
+
AgentTeamErrorEvent(
|
|
66
|
+
error_message="Worker thread exited unexpectedly.",
|
|
67
|
+
exception_details=traceback.format_exc()
|
|
68
|
+
)
|
|
69
|
+
))
|
|
70
|
+
except Exception as run_e:
|
|
71
|
+
logger.critical(f"AgentTeamRuntime '{team_id}': Failed to emit derived error: {run_e}")
|
|
72
|
+
|
|
73
|
+
if not self.context.current_status.is_terminal():
|
|
74
|
+
try:
|
|
75
|
+
asyncio.run(self._apply_event_and_derive_status(AgentTeamStoppedEvent()))
|
|
76
|
+
except Exception as run_e:
|
|
77
|
+
logger.critical(f"AgentTeamRuntime '{team_id}': Failed to emit derived shutdown complete: {run_e}")
|
|
55
78
|
|
|
56
79
|
def start(self):
|
|
57
80
|
if self._worker.is_alive:
|
|
@@ -59,9 +82,14 @@ class AgentTeamRuntime:
|
|
|
59
82
|
self._worker.start()
|
|
60
83
|
|
|
61
84
|
async def stop(self, timeout: float = 10.0):
|
|
62
|
-
|
|
85
|
+
if not self._worker.is_alive and not self._worker._is_active:
|
|
86
|
+
if not self.context.current_status.is_terminal():
|
|
87
|
+
await self._apply_event_and_derive_status(AgentTeamStoppedEvent())
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
await self._apply_event_and_derive_status(AgentTeamShutdownRequestedEvent())
|
|
63
91
|
await self._worker.stop(timeout=timeout)
|
|
64
|
-
await self.
|
|
92
|
+
await self._apply_event_and_derive_status(AgentTeamStoppedEvent())
|
|
65
93
|
|
|
66
94
|
async def submit_event(self, event: BaseAgentTeamEvent):
|
|
67
95
|
if not self._worker.is_alive:
|
|
@@ -77,6 +105,9 @@ class AgentTeamRuntime:
|
|
|
77
105
|
future = self._worker.schedule_coroutine(_coro_factory)
|
|
78
106
|
await asyncio.wrap_future(future)
|
|
79
107
|
|
|
108
|
+
async def _apply_event_and_derive_status(self, event: BaseAgentTeamEvent) -> None:
|
|
109
|
+
await apply_event_and_derive_status(event, self.context)
|
|
110
|
+
|
|
80
111
|
@property
|
|
81
112
|
def is_running(self) -> bool:
|
|
82
113
|
return self._worker.is_alive
|
|
@@ -5,8 +5,18 @@ import concurrent.futures
|
|
|
5
5
|
from typing import TYPE_CHECKING, Optional, Callable, Awaitable, Any
|
|
6
6
|
|
|
7
7
|
from autobyteus.agent_team.events.agent_team_event_dispatcher import AgentTeamEventDispatcher
|
|
8
|
+
from autobyteus.agent_team.events.agent_team_events import (
|
|
9
|
+
AgentTeamBootstrapStartedEvent,
|
|
10
|
+
AgentTeamReadyEvent,
|
|
11
|
+
AgentTeamErrorEvent,
|
|
12
|
+
AgentTeamStoppedEvent,
|
|
13
|
+
)
|
|
14
|
+
from autobyteus.agent_team.events.agent_team_input_event_queue_manager import AgentTeamInputEventQueueManager
|
|
15
|
+
from autobyteus.agent_team.events.event_store import AgentTeamEventStore
|
|
8
16
|
from autobyteus.agent_team.bootstrap_steps.agent_team_bootstrapper import AgentTeamBootstrapper
|
|
9
17
|
from autobyteus.agent_team.shutdown_steps.agent_team_shutdown_orchestrator import AgentTeamShutdownOrchestrator
|
|
18
|
+
from autobyteus.agent_team.status.status_deriver import AgentTeamStatusDeriver
|
|
19
|
+
from autobyteus.agent_team.status.status_update_utils import apply_event_and_derive_status
|
|
10
20
|
from autobyteus.agent.runtime.agent_thread_pool_manager import AgentThreadPoolManager
|
|
11
21
|
|
|
12
22
|
if TYPE_CHECKING:
|
|
@@ -19,8 +29,11 @@ class AgentTeamWorker:
|
|
|
19
29
|
"""Encapsulates the core event processing loop for an agent team."""
|
|
20
30
|
def __init__(self, context: 'AgentTeamContext', event_handler_registry: 'AgentTeamEventHandlerRegistry'):
|
|
21
31
|
self.context = context
|
|
22
|
-
self.
|
|
23
|
-
self.
|
|
32
|
+
self.status_manager = self.context.status_manager
|
|
33
|
+
if not self.status_manager: # pragma: no cover
|
|
34
|
+
raise ValueError(f"AgentTeamWorker for '{self.context.team_id}': AgentTeamStatusManager not found.")
|
|
35
|
+
|
|
36
|
+
self.event_dispatcher = AgentTeamEventDispatcher(event_handler_registry)
|
|
24
37
|
|
|
25
38
|
self._thread_pool_manager = AgentThreadPoolManager()
|
|
26
39
|
self._thread_future: Optional[concurrent.futures.Future] = None
|
|
@@ -31,6 +44,28 @@ class AgentTeamWorker:
|
|
|
31
44
|
self._done_callbacks: list[Callable[[concurrent.futures.Future], None]] = []
|
|
32
45
|
logger.info(f"AgentTeamWorker initialized for team '{self.context.team_id}'.")
|
|
33
46
|
|
|
47
|
+
async def _runtime_init(self) -> bool:
|
|
48
|
+
team_id = self.context.team_id
|
|
49
|
+
if self.context.state.event_store is None:
|
|
50
|
+
self.context.state.event_store = AgentTeamEventStore(team_id=team_id)
|
|
51
|
+
logger.info(f"Team '{team_id}': Runtime init completed (event store initialized).")
|
|
52
|
+
|
|
53
|
+
if self.context.state.status_deriver is None:
|
|
54
|
+
self.context.state.status_deriver = AgentTeamStatusDeriver()
|
|
55
|
+
logger.info(f"Team '{team_id}': Runtime init completed (status deriver initialized).")
|
|
56
|
+
|
|
57
|
+
if self.context.state.input_event_queues is not None:
|
|
58
|
+
logger.debug(f"Team '{team_id}': Runtime init skipped; input event queues already initialized.")
|
|
59
|
+
return True
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
self.context.state.input_event_queues = AgentTeamInputEventQueueManager()
|
|
63
|
+
logger.info(f"Team '{team_id}': Runtime init completed (input queues initialized).")
|
|
64
|
+
return True
|
|
65
|
+
except Exception as e:
|
|
66
|
+
logger.critical(f"Team '{team_id}': Runtime init failed while initializing input queues: {e}", exc_info=True)
|
|
67
|
+
return False
|
|
68
|
+
|
|
34
69
|
def get_worker_loop(self) -> Optional[asyncio.AbstractEventLoop]:
|
|
35
70
|
"""Returns the worker's event loop if it's running."""
|
|
36
71
|
return self._worker_loop if self._worker_loop and self._worker_loop.is_running() else None
|
|
@@ -69,11 +104,27 @@ class AgentTeamWorker:
|
|
|
69
104
|
self._is_active = False
|
|
70
105
|
|
|
71
106
|
async def async_run(self):
|
|
107
|
+
team_id = self.context.team_id
|
|
108
|
+
if not await self._runtime_init():
|
|
109
|
+
logger.critical(f"Team '{team_id}': Runtime init failed. Shutting down.")
|
|
110
|
+
await apply_event_and_derive_status(
|
|
111
|
+
AgentTeamErrorEvent(error_message="Runtime init failed.", exception_details="Failed to initialize event store or queues."),
|
|
112
|
+
self.context
|
|
113
|
+
)
|
|
114
|
+
return
|
|
115
|
+
|
|
72
116
|
bootstrapper = AgentTeamBootstrapper()
|
|
73
|
-
|
|
74
|
-
|
|
117
|
+
await self.event_dispatcher.dispatch(AgentTeamBootstrapStartedEvent(), self.context)
|
|
118
|
+
if not await bootstrapper.run(self.context):
|
|
119
|
+
logger.critical(f"Team '{team_id}' failed to initialize. Shutting down.")
|
|
120
|
+
await self.event_dispatcher.dispatch(
|
|
121
|
+
AgentTeamErrorEvent(error_message="Bootstrap failed.", exception_details="Bootstrapper returned failure."),
|
|
122
|
+
self.context
|
|
123
|
+
)
|
|
75
124
|
return
|
|
76
125
|
|
|
126
|
+
await self.event_dispatcher.dispatch(AgentTeamReadyEvent(), self.context)
|
|
127
|
+
|
|
77
128
|
logger.info(f"Team '{self.context.team_id}' entering main event loop.")
|
|
78
129
|
while not self._async_stop_event.is_set():
|
|
79
130
|
try:
|
|
@@ -103,7 +154,20 @@ class AgentTeamWorker:
|
|
|
103
154
|
return
|
|
104
155
|
self._stop_initiated = True
|
|
105
156
|
if self._worker_loop:
|
|
106
|
-
|
|
157
|
+
def _coro_factory():
|
|
158
|
+
async def _signal_coro():
|
|
159
|
+
if self._async_stop_event and not self._async_stop_event.is_set():
|
|
160
|
+
self._async_stop_event.set()
|
|
161
|
+
if self.context.state.input_event_queues:
|
|
162
|
+
await self.context.state.input_event_queues.enqueue_internal_system_event(
|
|
163
|
+
AgentTeamStoppedEvent()
|
|
164
|
+
)
|
|
165
|
+
return _signal_coro()
|
|
166
|
+
try:
|
|
167
|
+
future = self.schedule_coroutine(_coro_factory)
|
|
168
|
+
future.result(timeout=max(1.0, timeout - 1))
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.error(f"Team '{self.context.team_id}': Error signaling stop event: {e}", exc_info=True)
|
|
107
171
|
if self._thread_future:
|
|
108
172
|
try:
|
|
109
173
|
# FIX: Use asyncio.wait_for() to handle the timeout correctly.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This package contains components for defining and managing agent team operational status.
|
|
3
|
+
"""
|
|
4
|
+
from autobyteus.agent_team.status.agent_team_status import AgentTeamStatus
|
|
5
|
+
from autobyteus.agent_team.status.agent_team_status_manager import AgentTeamStatusManager
|
|
6
|
+
from autobyteus.agent_team.status.status_deriver import AgentTeamStatusDeriver
|
|
7
|
+
from autobyteus.agent_team.status.status_update_utils import apply_event_and_derive_status
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"AgentTeamStatus",
|
|
11
|
+
"AgentTeamStatusManager",
|
|
12
|
+
"AgentTeamStatusDeriver",
|
|
13
|
+
"apply_event_and_derive_status",
|
|
14
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
class AgentTeamStatus(str, Enum):
|
|
4
|
+
"""Defines the operational status of an AgentTeam."""
|
|
5
|
+
UNINITIALIZED = "uninitialized"
|
|
6
|
+
BOOTSTRAPPING = "bootstrapping"
|
|
7
|
+
IDLE = "idle"
|
|
8
|
+
PROCESSING = "processing"
|
|
9
|
+
SHUTTING_DOWN = "shutting_down"
|
|
10
|
+
SHUTDOWN_COMPLETE = "shutdown_complete"
|
|
11
|
+
ERROR = "error"
|
|
12
|
+
|
|
13
|
+
def is_terminal(self) -> bool:
|
|
14
|
+
"""Checks if the status is a terminal state."""
|
|
15
|
+
return self in [AgentTeamStatus.SHUTDOWN_COMPLETE, AgentTeamStatus.ERROR]
|
|
16
|
+
|
|
17
|
+
def __str__(self) -> str:
|
|
18
|
+
return self.value
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import TYPE_CHECKING, Optional
|
|
3
|
+
|
|
4
|
+
from autobyteus.agent_team.status.agent_team_status import AgentTeamStatus
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
8
|
+
from autobyteus.agent_team.streaming.agent_team_event_notifier import AgentTeamExternalEventNotifier
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
class AgentTeamStatusManager:
|
|
13
|
+
"""
|
|
14
|
+
Emits external notifications for status updates derived from events.
|
|
15
|
+
The status itself is owned by the event stream projection.
|
|
16
|
+
"""
|
|
17
|
+
def __init__(self, context: 'AgentTeamContext', notifier: 'AgentTeamExternalEventNotifier'):
|
|
18
|
+
if notifier is None:
|
|
19
|
+
raise ValueError("AgentTeamStatusManager requires a notifier.")
|
|
20
|
+
self.context = context
|
|
21
|
+
self.notifier = notifier
|
|
22
|
+
if not isinstance(self.context.state.current_status, AgentTeamStatus):
|
|
23
|
+
self.context.state.current_status = AgentTeamStatus.UNINITIALIZED
|
|
24
|
+
logger.debug(f"AgentTeamStatusManager initialized for team '{context.team_id}'.")
|
|
25
|
+
|
|
26
|
+
async def emit_status_update(self,
|
|
27
|
+
old_status: AgentTeamStatus,
|
|
28
|
+
new_status: AgentTeamStatus,
|
|
29
|
+
additional_data: Optional[dict] = None) -> None:
|
|
30
|
+
if old_status == new_status:
|
|
31
|
+
return
|
|
32
|
+
logger.info(f"Team '{self.context.team_id}' updating status from {old_status.value} to {new_status.value}.")
|
|
33
|
+
self.notifier.notify_status_updated(new_status, old_status, additional_data)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/status/status_deriver.py
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Optional, Tuple, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from autobyteus.agent_team.status.agent_team_status import AgentTeamStatus
|
|
6
|
+
from autobyteus.agent_team.events.agent_team_events import (
|
|
7
|
+
AgentTeamBootstrapStartedEvent,
|
|
8
|
+
AgentTeamReadyEvent,
|
|
9
|
+
AgentTeamIdleEvent,
|
|
10
|
+
AgentTeamShutdownRequestedEvent,
|
|
11
|
+
AgentTeamStoppedEvent,
|
|
12
|
+
AgentTeamErrorEvent,
|
|
13
|
+
OperationalAgentTeamEvent,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
18
|
+
from autobyteus.agent_team.events.agent_team_events import BaseAgentTeamEvent
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class AgentTeamStatusDeriver:
|
|
24
|
+
"""
|
|
25
|
+
Derives agent team status from an event stream.
|
|
26
|
+
"""
|
|
27
|
+
def __init__(self, initial_status: AgentTeamStatus = AgentTeamStatus.UNINITIALIZED):
|
|
28
|
+
self._current_status = initial_status
|
|
29
|
+
logger.debug(f"AgentTeamStatusDeriver initialized with status '{initial_status.value}'.")
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def current_status(self) -> AgentTeamStatus:
|
|
33
|
+
return self._current_status
|
|
34
|
+
|
|
35
|
+
def apply(self, event: 'BaseAgentTeamEvent', context: Optional['AgentTeamContext'] = None) -> Tuple[AgentTeamStatus, AgentTeamStatus]:
|
|
36
|
+
old_status = self._current_status
|
|
37
|
+
new_status = self._reduce(event, old_status, context)
|
|
38
|
+
self._current_status = new_status
|
|
39
|
+
return old_status, new_status
|
|
40
|
+
|
|
41
|
+
def _reduce(self, event: 'BaseAgentTeamEvent', current_status: AgentTeamStatus, context: Optional['AgentTeamContext']) -> AgentTeamStatus:
|
|
42
|
+
if isinstance(event, AgentTeamBootstrapStartedEvent):
|
|
43
|
+
return AgentTeamStatus.BOOTSTRAPPING
|
|
44
|
+
if isinstance(event, AgentTeamReadyEvent):
|
|
45
|
+
return AgentTeamStatus.IDLE
|
|
46
|
+
if isinstance(event, AgentTeamIdleEvent):
|
|
47
|
+
return AgentTeamStatus.IDLE
|
|
48
|
+
if isinstance(event, AgentTeamShutdownRequestedEvent):
|
|
49
|
+
if current_status == AgentTeamStatus.ERROR:
|
|
50
|
+
return current_status
|
|
51
|
+
return AgentTeamStatus.SHUTTING_DOWN
|
|
52
|
+
if isinstance(event, AgentTeamStoppedEvent):
|
|
53
|
+
if current_status == AgentTeamStatus.ERROR:
|
|
54
|
+
return current_status
|
|
55
|
+
return AgentTeamStatus.SHUTDOWN_COMPLETE
|
|
56
|
+
if isinstance(event, AgentTeamErrorEvent):
|
|
57
|
+
return AgentTeamStatus.ERROR
|
|
58
|
+
|
|
59
|
+
if isinstance(event, OperationalAgentTeamEvent):
|
|
60
|
+
return AgentTeamStatus.PROCESSING
|
|
61
|
+
|
|
62
|
+
return current_status
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/status/status_update_utils.py
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Optional, Tuple, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from autobyteus.agent_team.status.agent_team_status import AgentTeamStatus
|
|
6
|
+
from autobyteus.agent_team.events.agent_team_events import AgentTeamErrorEvent
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
10
|
+
from autobyteus.agent_team.events.agent_team_events import BaseAgentTeamEvent
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def build_status_update_data(event: 'BaseAgentTeamEvent',
|
|
16
|
+
new_status: AgentTeamStatus) -> Optional[dict]:
|
|
17
|
+
if new_status == AgentTeamStatus.ERROR and isinstance(event, AgentTeamErrorEvent):
|
|
18
|
+
return {"error_message": event.error_message}
|
|
19
|
+
return None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def apply_event_and_derive_status(event: 'BaseAgentTeamEvent',
|
|
23
|
+
context: 'AgentTeamContext') -> Tuple[AgentTeamStatus, AgentTeamStatus]:
|
|
24
|
+
if context.state.event_store:
|
|
25
|
+
try:
|
|
26
|
+
context.state.event_store.append(event)
|
|
27
|
+
except Exception as exc: # pragma: no cover
|
|
28
|
+
logger.error(f"Failed to append team event to store: {exc}", exc_info=True)
|
|
29
|
+
|
|
30
|
+
if not context.state.status_deriver:
|
|
31
|
+
return context.current_status, context.current_status
|
|
32
|
+
|
|
33
|
+
old_status, new_status = context.state.status_deriver.apply(event, context)
|
|
34
|
+
if old_status != new_status:
|
|
35
|
+
context.current_status = new_status
|
|
36
|
+
additional_data = build_status_update_data(event, new_status)
|
|
37
|
+
if context.status_manager:
|
|
38
|
+
await context.status_manager.emit_status_update(
|
|
39
|
+
old_status, new_status, additional_data=additional_data
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return old_status, new_status
|