autobyteus 1.1.4__py3-none-any.whl → 1.1.5__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/context/__init__.py +4 -2
- autobyteus/agent/context/agent_config.py +0 -4
- autobyteus/agent/context/agent_context_registry.py +73 -0
- autobyteus/agent/events/notifiers.py +4 -0
- autobyteus/agent/handlers/inter_agent_message_event_handler.py +7 -2
- autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +19 -19
- autobyteus/agent/handlers/user_input_message_event_handler.py +15 -0
- autobyteus/agent/message/send_message_to.py +29 -23
- autobyteus/agent/runtime/agent_runtime.py +10 -2
- autobyteus/agent/sender_type.py +15 -0
- autobyteus/agent/streaming/agent_event_stream.py +6 -0
- autobyteus/agent/streaming/stream_event_payloads.py +12 -0
- autobyteus/agent/streaming/stream_events.py +3 -0
- autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +7 -4
- autobyteus/agent_team/__init__.py +1 -0
- autobyteus/agent_team/agent_team.py +93 -0
- autobyteus/agent_team/agent_team_builder.py +184 -0
- autobyteus/agent_team/base_agent_team.py +86 -0
- autobyteus/agent_team/bootstrap_steps/__init__.py +24 -0
- autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +73 -0
- autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +54 -0
- autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +25 -0
- autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +23 -0
- autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +41 -0
- autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +85 -0
- autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +51 -0
- autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +45 -0
- autobyteus/agent_team/context/__init__.py +17 -0
- autobyteus/agent_team/context/agent_team_config.py +33 -0
- autobyteus/agent_team/context/agent_team_context.py +61 -0
- autobyteus/agent_team/context/agent_team_runtime_state.py +56 -0
- autobyteus/agent_team/context/team_manager.py +147 -0
- autobyteus/agent_team/context/team_node_config.py +76 -0
- autobyteus/agent_team/events/__init__.py +29 -0
- autobyteus/agent_team/events/agent_team_event_dispatcher.py +39 -0
- autobyteus/agent_team/events/agent_team_events.py +53 -0
- autobyteus/agent_team/events/agent_team_input_event_queue_manager.py +21 -0
- autobyteus/agent_team/exceptions.py +8 -0
- autobyteus/agent_team/factory/__init__.py +9 -0
- autobyteus/agent_team/factory/agent_team_factory.py +99 -0
- autobyteus/agent_team/handlers/__init__.py +19 -0
- autobyteus/agent_team/handlers/agent_team_event_handler_registry.py +23 -0
- autobyteus/agent_team/handlers/base_agent_team_event_handler.py +16 -0
- autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +61 -0
- autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +27 -0
- autobyteus/agent_team/handlers/process_user_message_event_handler.py +46 -0
- autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +48 -0
- autobyteus/agent_team/phases/__init__.py +11 -0
- autobyteus/agent_team/phases/agent_team_operational_phase.py +19 -0
- autobyteus/agent_team/phases/agent_team_phase_manager.py +48 -0
- autobyteus/agent_team/runtime/__init__.py +13 -0
- autobyteus/agent_team/runtime/agent_team_runtime.py +82 -0
- autobyteus/agent_team/runtime/agent_team_worker.py +117 -0
- autobyteus/agent_team/shutdown_steps/__init__.py +17 -0
- autobyteus/agent_team/shutdown_steps/agent_team_shutdown_orchestrator.py +35 -0
- autobyteus/agent_team/shutdown_steps/agent_team_shutdown_step.py +42 -0
- autobyteus/agent_team/shutdown_steps/base_agent_team_shutdown_step.py +16 -0
- autobyteus/agent_team/shutdown_steps/bridge_cleanup_step.py +28 -0
- autobyteus/agent_team/shutdown_steps/sub_team_shutdown_step.py +41 -0
- autobyteus/agent_team/streaming/__init__.py +26 -0
- autobyteus/agent_team/streaming/agent_event_bridge.py +48 -0
- autobyteus/agent_team/streaming/agent_event_multiplexer.py +70 -0
- autobyteus/agent_team/streaming/agent_team_event_notifier.py +64 -0
- autobyteus/agent_team/streaming/agent_team_event_stream.py +33 -0
- autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +32 -0
- autobyteus/agent_team/streaming/agent_team_stream_events.py +56 -0
- autobyteus/agent_team/streaming/team_event_bridge.py +50 -0
- autobyteus/agent_team/task_notification/__init__.py +11 -0
- autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +164 -0
- autobyteus/agent_team/task_notification/task_notification_mode.py +24 -0
- autobyteus/agent_team/utils/__init__.py +9 -0
- autobyteus/agent_team/utils/wait_for_idle.py +46 -0
- autobyteus/cli/agent_team_tui/__init__.py +4 -0
- autobyteus/cli/agent_team_tui/app.py +210 -0
- autobyteus/cli/agent_team_tui/state.py +180 -0
- autobyteus/cli/agent_team_tui/widgets/__init__.py +6 -0
- autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +149 -0
- autobyteus/cli/agent_team_tui/widgets/focus_pane.py +320 -0
- autobyteus/cli/agent_team_tui/widgets/logo.py +20 -0
- autobyteus/cli/agent_team_tui/widgets/renderables.py +77 -0
- autobyteus/cli/agent_team_tui/widgets/shared.py +60 -0
- autobyteus/cli/agent_team_tui/widgets/status_bar.py +14 -0
- autobyteus/cli/agent_team_tui/widgets/task_board_panel.py +82 -0
- autobyteus/events/event_types.py +7 -2
- autobyteus/llm/api/autobyteus_llm.py +11 -12
- autobyteus/llm/api/lmstudio_llm.py +10 -13
- autobyteus/llm/api/ollama_llm.py +8 -13
- autobyteus/llm/autobyteus_provider.py +73 -46
- autobyteus/llm/llm_factory.py +102 -140
- autobyteus/llm/lmstudio_provider.py +63 -48
- autobyteus/llm/models.py +83 -53
- autobyteus/llm/ollama_provider.py +69 -61
- autobyteus/llm/ollama_provider_resolver.py +1 -0
- autobyteus/llm/providers.py +13 -13
- autobyteus/llm/runtimes.py +11 -0
- autobyteus/task_management/__init__.py +43 -0
- autobyteus/task_management/base_task_board.py +68 -0
- autobyteus/task_management/converters/__init__.py +11 -0
- autobyteus/task_management/converters/task_board_converter.py +64 -0
- autobyteus/task_management/converters/task_plan_converter.py +48 -0
- autobyteus/task_management/deliverable.py +16 -0
- autobyteus/task_management/deliverables/__init__.py +8 -0
- autobyteus/task_management/deliverables/file_deliverable.py +15 -0
- autobyteus/task_management/events.py +27 -0
- autobyteus/task_management/in_memory_task_board.py +126 -0
- autobyteus/task_management/schemas/__init__.py +15 -0
- autobyteus/task_management/schemas/deliverable_schema.py +13 -0
- autobyteus/task_management/schemas/plan_definition.py +35 -0
- autobyteus/task_management/schemas/task_status_report.py +27 -0
- autobyteus/task_management/task_plan.py +110 -0
- autobyteus/task_management/tools/__init__.py +14 -0
- autobyteus/task_management/tools/get_task_board_status.py +68 -0
- autobyteus/task_management/tools/publish_task_plan.py +113 -0
- autobyteus/task_management/tools/update_task_status.py +135 -0
- autobyteus/tools/bash/bash_executor.py +59 -14
- autobyteus/tools/mcp/config_service.py +63 -58
- autobyteus/tools/mcp/server/http_managed_mcp_server.py +14 -2
- autobyteus/tools/mcp/server/stdio_managed_mcp_server.py +14 -2
- autobyteus/tools/mcp/server_instance_manager.py +30 -4
- autobyteus/tools/mcp/tool_registrar.py +103 -50
- autobyteus/tools/parameter_schema.py +17 -11
- autobyteus/tools/registry/tool_definition.py +24 -29
- autobyteus/tools/tool_category.py +1 -0
- autobyteus/tools/usage/formatters/default_json_example_formatter.py +78 -3
- autobyteus/tools/usage/formatters/default_xml_example_formatter.py +23 -3
- autobyteus/tools/usage/formatters/gemini_json_example_formatter.py +6 -0
- autobyteus/tools/usage/formatters/google_json_example_formatter.py +7 -0
- autobyteus/tools/usage/formatters/openai_json_example_formatter.py +6 -4
- autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +23 -7
- autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +14 -25
- autobyteus/tools/usage/providers/__init__.py +2 -12
- autobyteus/tools/usage/providers/tool_manifest_provider.py +36 -29
- autobyteus/tools/usage/registries/__init__.py +7 -12
- autobyteus/tools/usage/registries/tool_formatter_pair.py +15 -0
- autobyteus/tools/usage/registries/tool_formatting_registry.py +58 -0
- autobyteus/tools/usage/registries/tool_usage_parser_registry.py +55 -0
- {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/METADATA +3 -3
- {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/RECORD +146 -72
- examples/agent_team/__init__.py +1 -0
- examples/run_browser_agent.py +17 -15
- examples/run_google_slides_agent.py +17 -16
- examples/run_poem_writer.py +22 -12
- examples/run_sqlite_agent.py +17 -15
- autobyteus/tools/mcp/call_handlers/__init__.py +0 -16
- autobyteus/tools/mcp/call_handlers/base_handler.py +0 -40
- autobyteus/tools/mcp/call_handlers/stdio_handler.py +0 -76
- autobyteus/tools/mcp/call_handlers/streamable_http_handler.py +0 -55
- autobyteus/tools/usage/providers/json_example_provider.py +0 -32
- autobyteus/tools/usage/providers/json_schema_provider.py +0 -35
- autobyteus/tools/usage/providers/json_tool_usage_parser_provider.py +0 -28
- autobyteus/tools/usage/providers/xml_example_provider.py +0 -28
- autobyteus/tools/usage/providers/xml_schema_provider.py +0 -29
- autobyteus/tools/usage/providers/xml_tool_usage_parser_provider.py +0 -26
- autobyteus/tools/usage/registries/json_example_formatter_registry.py +0 -51
- autobyteus/tools/usage/registries/json_schema_formatter_registry.py +0 -51
- autobyteus/tools/usage/registries/json_tool_usage_parser_registry.py +0 -42
- autobyteus/tools/usage/registries/xml_example_formatter_registry.py +0 -30
- autobyteus/tools/usage/registries/xml_schema_formatter_registry.py +0 -33
- autobyteus/tools/usage/registries/xml_tool_usage_parser_registry.py +0 -30
- examples/workflow/__init__.py +0 -1
- examples/workflow/run_basic_research_workflow.py +0 -189
- examples/workflow/run_code_review_workflow.py +0 -269
- examples/workflow/run_debate_workflow.py +0 -212
- examples/workflow/run_workflow_with_tui.py +0 -153
- {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/WHEEL +0 -0
- {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/licenses/LICENSE +0 -0
- {autobyteus-1.1.4.dist-info → autobyteus-1.1.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py
|
|
2
|
+
import logging
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from autobyteus.agent_team.bootstrap_steps.base_agent_team_bootstrap_step import BaseAgentTeamBootstrapStep
|
|
6
|
+
from autobyteus.task_management import TaskBoard
|
|
7
|
+
from autobyteus.events.event_types import EventType
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
11
|
+
from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
class TeamContextInitializationStep(BaseAgentTeamBootstrapStep):
|
|
16
|
+
"""
|
|
17
|
+
Bootstrap step to initialize shared team context components, such as the
|
|
18
|
+
TaskBoard, and bridges its events to the team's notifier.
|
|
19
|
+
"""
|
|
20
|
+
async def execute(self, context: 'AgentTeamContext', phase_manager: 'AgentTeamPhaseManager') -> bool:
|
|
21
|
+
team_id = context.team_id
|
|
22
|
+
logger.info(f"Team '{team_id}': Executing TeamContextInitializationStep.")
|
|
23
|
+
try:
|
|
24
|
+
if context.state.task_board is None:
|
|
25
|
+
task_board = TaskBoard(team_id=team_id)
|
|
26
|
+
context.state.task_board = task_board
|
|
27
|
+
logger.info(f"Team '{team_id}': TaskBoard initialized and attached to team state.")
|
|
28
|
+
|
|
29
|
+
notifier = phase_manager.notifier
|
|
30
|
+
if notifier:
|
|
31
|
+
# The notifier, a long-lived component, subscribes to events
|
|
32
|
+
# from the task_board, another long-lived component.
|
|
33
|
+
notifier.subscribe_from(sender=task_board, event=EventType.TASK_BOARD_PLAN_PUBLISHED, listener=notifier.handle_and_publish_task_board_event)
|
|
34
|
+
notifier.subscribe_from(sender=task_board, event=EventType.TASK_BOARD_STATUS_UPDATED, listener=notifier.handle_and_publish_task_board_event)
|
|
35
|
+
logger.info(f"Team '{team_id}': Successfully bridged TaskBoard events to the team notifier.")
|
|
36
|
+
else:
|
|
37
|
+
logger.warning(f"Team '{team_id}': Notifier not found in PhaseManager. Cannot bridge TaskBoard events.")
|
|
38
|
+
|
|
39
|
+
else:
|
|
40
|
+
logger.warning(f"Team '{team_id}': TaskBoard already exists. Skipping initialization.")
|
|
41
|
+
|
|
42
|
+
return True
|
|
43
|
+
except Exception as e:
|
|
44
|
+
logger.error(f"Team '{team_id}': Critical failure during team context initialization: {e}", exc_info=True)
|
|
45
|
+
return False
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/context/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
Components related to the agent team's runtime context, state, and configuration.
|
|
4
|
+
"""
|
|
5
|
+
from autobyteus.agent_team.context.team_manager import TeamManager
|
|
6
|
+
from autobyteus.agent_team.context.agent_team_config import AgentTeamConfig
|
|
7
|
+
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
8
|
+
from autobyteus.agent_team.context.team_node_config import TeamNodeConfig
|
|
9
|
+
from autobyteus.agent_team.context.agent_team_runtime_state import AgentTeamRuntimeState
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"TeamManager",
|
|
13
|
+
"AgentTeamConfig",
|
|
14
|
+
"AgentTeamContext",
|
|
15
|
+
"TeamNodeConfig",
|
|
16
|
+
"AgentTeamRuntimeState",
|
|
17
|
+
]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/context/agent_team_config.py
|
|
2
|
+
import logging
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import List, Optional, Tuple
|
|
5
|
+
|
|
6
|
+
from autobyteus.agent_team.context.team_node_config import TeamNodeConfig
|
|
7
|
+
from autobyteus.agent_team.task_notification.task_notification_mode import TaskNotificationMode
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class AgentTeamConfig:
|
|
13
|
+
"""
|
|
14
|
+
Represents the complete, static configuration for an AgentTeam instance.
|
|
15
|
+
This is the user's primary input for defining an agent team.
|
|
16
|
+
"""
|
|
17
|
+
name: str
|
|
18
|
+
description: str
|
|
19
|
+
nodes: Tuple[TeamNodeConfig, ...]
|
|
20
|
+
coordinator_node: TeamNodeConfig
|
|
21
|
+
role: Optional[str] = None
|
|
22
|
+
task_notification_mode: TaskNotificationMode = TaskNotificationMode.AGENT_MANUAL_NOTIFICATION
|
|
23
|
+
|
|
24
|
+
def __post_init__(self):
|
|
25
|
+
if not self.name or not isinstance(self.name, str):
|
|
26
|
+
raise ValueError("The 'name' in AgentTeamConfig must be a non-empty string.")
|
|
27
|
+
if not self.nodes:
|
|
28
|
+
raise ValueError("The 'nodes' collection in AgentTeamConfig cannot be empty.")
|
|
29
|
+
if self.coordinator_node not in self.nodes:
|
|
30
|
+
raise ValueError("The 'coordinator_node' must be one of the nodes in the 'nodes' collection.")
|
|
31
|
+
if not isinstance(self.task_notification_mode, TaskNotificationMode):
|
|
32
|
+
raise TypeError("The 'task_notification_mode' must be an instance of TaskNotificationMode enum.")
|
|
33
|
+
logger.debug(f"AgentTeamConfig validated for team: '{self.name}'.")
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/context/agent_team_context.py
|
|
2
|
+
import logging
|
|
3
|
+
from typing import TYPE_CHECKING, List, Optional, Dict
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from autobyteus.agent_team.context.agent_team_config import AgentTeamConfig
|
|
7
|
+
from autobyteus.agent_team.context.agent_team_runtime_state import AgentTeamRuntimeState
|
|
8
|
+
from autobyteus.agent.agent import Agent
|
|
9
|
+
from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
|
|
10
|
+
from autobyteus.agent_team.context.team_manager import TeamManager
|
|
11
|
+
from autobyteus.agent_team.streaming.agent_event_multiplexer import AgentEventMultiplexer
|
|
12
|
+
from autobyteus.agent.context import AgentConfig
|
|
13
|
+
from autobyteus.agent_team.context.team_node_config import TeamNodeConfig
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
class AgentTeamContext:
|
|
18
|
+
"""Represents the complete operational context for a single agent team instance."""
|
|
19
|
+
def __init__(self, team_id: str, config: 'AgentTeamConfig', state: 'AgentTeamRuntimeState'):
|
|
20
|
+
if not team_id or not isinstance(team_id, str):
|
|
21
|
+
raise ValueError("AgentTeamContext requires a non-empty string 'team_id'.")
|
|
22
|
+
|
|
23
|
+
self.team_id: str = team_id
|
|
24
|
+
self.config: 'AgentTeamConfig' = config
|
|
25
|
+
self.state: 'AgentTeamRuntimeState' = state
|
|
26
|
+
self._node_config_map: Optional[Dict[str, 'TeamNodeConfig']] = None
|
|
27
|
+
|
|
28
|
+
logger.info(f"AgentTeamContext composed for team_id '{self.team_id}'.")
|
|
29
|
+
|
|
30
|
+
def get_node_config_by_name(self, name: str) -> Optional['TeamNodeConfig']:
|
|
31
|
+
"""Efficiently retrieves a node's config by its friendly name."""
|
|
32
|
+
if self._node_config_map is None:
|
|
33
|
+
# Build cache on first access
|
|
34
|
+
self._node_config_map = {node.name: node for node in self.config.nodes}
|
|
35
|
+
return self._node_config_map.get(name)
|
|
36
|
+
|
|
37
|
+
@property
|
|
38
|
+
def agents(self) -> List['Agent']:
|
|
39
|
+
"""Returns all agents managed by the TeamManager."""
|
|
40
|
+
if self.state.team_manager:
|
|
41
|
+
return self.state.team_manager.get_all_agents()
|
|
42
|
+
return []
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def coordinator_agent(self) -> Optional['Agent']:
|
|
46
|
+
"""Returns the coordinator agent from the TeamManager."""
|
|
47
|
+
if self.state.team_manager:
|
|
48
|
+
return self.state.team_manager.coordinator_agent
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
@property
|
|
52
|
+
def phase_manager(self) -> Optional['AgentTeamPhaseManager']:
|
|
53
|
+
return self.state.phase_manager_ref
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def team_manager(self) -> Optional['TeamManager']:
|
|
57
|
+
return self.state.team_manager
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def multiplexer(self) -> Optional['AgentEventMultiplexer']:
|
|
61
|
+
return self.state.multiplexer_ref
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/context/agent_team_runtime_state.py
|
|
2
|
+
import logging
|
|
3
|
+
from typing import List, Optional, TYPE_CHECKING, Dict
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
|
|
6
|
+
from autobyteus.agent_team.phases.agent_team_operational_phase import AgentTeamOperationalPhase
|
|
7
|
+
from autobyteus.agent.context import AgentConfig
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from autobyteus.agent.agent import Agent
|
|
11
|
+
from autobyteus.agent_team.events.agent_team_input_event_queue_manager import AgentTeamInputEventQueueManager
|
|
12
|
+
from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
|
|
13
|
+
from autobyteus.agent_team.context.team_node_config import TeamNodeConfig
|
|
14
|
+
from autobyteus.agent_team.context.team_manager import TeamManager
|
|
15
|
+
from autobyteus.agent_team.streaming.agent_event_multiplexer import AgentEventMultiplexer
|
|
16
|
+
from autobyteus.task_management.base_task_board import BaseTaskBoard
|
|
17
|
+
from autobyteus.task_management.artifacts.artifact_manifest import ArtifactManifest
|
|
18
|
+
from autobyteus.agent_team.task_notification.system_event_driven_agent_task_notifier import SystemEventDrivenAgentTaskNotifier
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class AgentTeamRuntimeState:
|
|
24
|
+
"""Encapsulates the dynamic, stateful data of a running agent team instance."""
|
|
25
|
+
team_id: str
|
|
26
|
+
current_phase: AgentTeamOperationalPhase = AgentTeamOperationalPhase.UNINITIALIZED
|
|
27
|
+
|
|
28
|
+
# State populated by bootstrap steps
|
|
29
|
+
prepared_coordinator_prompt: Optional[str] = None
|
|
30
|
+
final_agent_configs: Dict[str, 'AgentConfig'] = field(default_factory=dict)
|
|
31
|
+
|
|
32
|
+
# Core services
|
|
33
|
+
team_manager: Optional['TeamManager'] = None
|
|
34
|
+
task_notifier: Optional['SystemEventDrivenAgentTaskNotifier'] = None
|
|
35
|
+
|
|
36
|
+
# Runtime components and references
|
|
37
|
+
input_event_queues: Optional['AgentTeamInputEventQueueManager'] = None
|
|
38
|
+
phase_manager_ref: Optional['AgentTeamPhaseManager'] = None
|
|
39
|
+
multiplexer_ref: Optional['AgentEventMultiplexer'] = None
|
|
40
|
+
|
|
41
|
+
# Dynamic planning and artifact state
|
|
42
|
+
task_board: Optional['BaseTaskBoard'] = None
|
|
43
|
+
artifact_registry: Dict[str, 'ArtifactManifest'] = field(default_factory=dict)
|
|
44
|
+
|
|
45
|
+
def __post_init__(self):
|
|
46
|
+
if not self.team_id or not isinstance(self.team_id, str):
|
|
47
|
+
raise ValueError("AgentTeamRuntimeState requires a non-empty string 'team_id'.")
|
|
48
|
+
logger.info(f"AgentTeamRuntimeState initialized for team_id '{self.team_id}'.")
|
|
49
|
+
|
|
50
|
+
def __repr__(self) -> str:
|
|
51
|
+
agents_count = len(self.team_manager.get_all_agents()) if self.team_manager else 0
|
|
52
|
+
coordinator_set = self.team_manager.coordinator_agent is not None if self.team_manager else False
|
|
53
|
+
return (f"<AgentTeamRuntimeState id='{self.team_id}', phase='{self.current_phase.value}', "
|
|
54
|
+
f"agents_count={agents_count}, coordinator_set={coordinator_set}, "
|
|
55
|
+
f"final_configs_count={len(self.final_agent_configs)}, "
|
|
56
|
+
f"team_manager_set={self.team_manager is not None}>")
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/context/team_manager.py
|
|
2
|
+
import asyncio
|
|
3
|
+
import logging
|
|
4
|
+
from typing import List, Dict, Optional, TYPE_CHECKING, Union
|
|
5
|
+
|
|
6
|
+
from autobyteus.agent.factory import AgentFactory
|
|
7
|
+
from autobyteus.agent.utils.wait_for_idle import wait_for_agent_to_be_idle
|
|
8
|
+
from autobyteus.agent_team.utils.wait_for_idle import wait_for_team_to_be_idle
|
|
9
|
+
from autobyteus.agent_team.exceptions import TeamNodeNotFoundException
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from autobyteus.agent.agent import Agent
|
|
13
|
+
from autobyteus.agent_team.agent_team import AgentTeam
|
|
14
|
+
from autobyteus.agent_team.events.agent_team_events import InterAgentMessageRequestEvent, ProcessUserMessageEvent
|
|
15
|
+
from autobyteus.agent_team.runtime.agent_team_runtime import AgentTeamRuntime
|
|
16
|
+
from autobyteus.agent_team.streaming.agent_event_multiplexer import AgentEventMultiplexer
|
|
17
|
+
from autobyteus.agent_team.context.agent_team_config import AgentTeamConfig
|
|
18
|
+
|
|
19
|
+
ManagedNode = Union['Agent', 'AgentTeam']
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
class TeamManager:
|
|
24
|
+
"""
|
|
25
|
+
Manages all nodes (agents and sub-teams) within an agent team. It handles
|
|
26
|
+
lazy creation, on-demand startup, and provides access to managed instances.
|
|
27
|
+
It assumes all node names are unique within the team.
|
|
28
|
+
"""
|
|
29
|
+
def __init__(self, team_id: str, runtime: 'AgentTeamRuntime', multiplexer: 'AgentEventMultiplexer'):
|
|
30
|
+
self.team_id = team_id
|
|
31
|
+
self._runtime = runtime
|
|
32
|
+
self._multiplexer = multiplexer
|
|
33
|
+
self._agent_factory = AgentFactory()
|
|
34
|
+
self._nodes_cache: Dict[str, ManagedNode] = {}
|
|
35
|
+
self._agent_id_to_name_map: Dict[str, str] = {}
|
|
36
|
+
self._coordinator_agent: Optional['Agent'] = None
|
|
37
|
+
logger.info(f"TeamManager created for team '{self.team_id}'.")
|
|
38
|
+
|
|
39
|
+
async def dispatch_inter_agent_message_request(self, event: 'InterAgentMessageRequestEvent'):
|
|
40
|
+
await self._runtime.submit_event(event)
|
|
41
|
+
|
|
42
|
+
async def dispatch_user_message_to_agent(self, event: 'ProcessUserMessageEvent'):
|
|
43
|
+
"""Submits a user message event (potentially system-generated) to the team's runtime."""
|
|
44
|
+
await self._runtime.submit_event(event)
|
|
45
|
+
|
|
46
|
+
async def ensure_node_is_ready(self, name_or_agent_id: str) -> ManagedNode:
|
|
47
|
+
"""
|
|
48
|
+
Retrieves a node by its unique name or ID. If not yet created, it
|
|
49
|
+
instantiates and starts it on-demand.
|
|
50
|
+
"""
|
|
51
|
+
unique_name: str
|
|
52
|
+
if name_or_agent_id in self._agent_id_to_name_map:
|
|
53
|
+
unique_name = self._agent_id_to_name_map[name_or_agent_id]
|
|
54
|
+
else:
|
|
55
|
+
unique_name = name_or_agent_id
|
|
56
|
+
|
|
57
|
+
node_instance = self._nodes_cache.get(unique_name)
|
|
58
|
+
|
|
59
|
+
was_created = False
|
|
60
|
+
if not node_instance:
|
|
61
|
+
logger.debug(f"Node '{unique_name}' not in cache for team '{self.team_id}'. Attempting lazy creation.")
|
|
62
|
+
|
|
63
|
+
node_config_wrapper = self._runtime.context.get_node_config_by_name(unique_name)
|
|
64
|
+
if not node_config_wrapper:
|
|
65
|
+
raise TeamNodeNotFoundException(node_name=name_or_agent_id, team_id=self.team_id)
|
|
66
|
+
|
|
67
|
+
if node_config_wrapper.is_sub_team:
|
|
68
|
+
from autobyteus.agent_team.factory.agent_team_factory import AgentTeamFactory
|
|
69
|
+
from autobyteus.agent_team.context.agent_team_config import AgentTeamConfig
|
|
70
|
+
|
|
71
|
+
team_factory = AgentTeamFactory()
|
|
72
|
+
node_definition = node_config_wrapper.node_definition
|
|
73
|
+
if not isinstance(node_definition, AgentTeamConfig):
|
|
74
|
+
raise TypeError(f"Expected AgentTeamConfig for node '{unique_name}', but found {type(node_definition)}")
|
|
75
|
+
logger.info(f"Lazily creating sub-team node '{unique_name}' in team '{self.team_id}'.")
|
|
76
|
+
node_instance = team_factory.create_team(config=node_definition)
|
|
77
|
+
else:
|
|
78
|
+
# Agent creation is now simpler: just retrieve the pre-made config.
|
|
79
|
+
final_config = self._runtime.context.state.final_agent_configs.get(unique_name)
|
|
80
|
+
if not final_config:
|
|
81
|
+
raise RuntimeError(f"No pre-prepared agent configuration found for '{unique_name}'. "
|
|
82
|
+
"Bootstrap step may have failed or skipped this agent.")
|
|
83
|
+
|
|
84
|
+
logger.info(f"Lazily creating agent node '{unique_name}' using pre-prepared configuration.")
|
|
85
|
+
node_instance = self._agent_factory.create_agent(config=final_config)
|
|
86
|
+
|
|
87
|
+
self._nodes_cache[unique_name] = node_instance
|
|
88
|
+
was_created = True
|
|
89
|
+
|
|
90
|
+
from autobyteus.agent.agent import Agent
|
|
91
|
+
if isinstance(node_instance, Agent):
|
|
92
|
+
self._agent_id_to_name_map[node_instance.agent_id] = unique_name
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
if was_created and node_instance:
|
|
96
|
+
from autobyteus.agent_team.agent_team import AgentTeam
|
|
97
|
+
from autobyteus.agent.agent import Agent
|
|
98
|
+
if isinstance(node_instance, AgentTeam):
|
|
99
|
+
self._multiplexer.start_bridging_team_events(node_instance, unique_name)
|
|
100
|
+
elif isinstance(node_instance, Agent):
|
|
101
|
+
self._multiplexer.start_bridging_agent_events(node_instance, unique_name)
|
|
102
|
+
|
|
103
|
+
# On-Demand Startup Logic
|
|
104
|
+
if not node_instance.is_running:
|
|
105
|
+
from autobyteus.agent_team.agent_team import AgentTeam
|
|
106
|
+
logger.info(f"Team '{self.team_id}': Node '{unique_name}' is not running. Starting on-demand.")
|
|
107
|
+
await self._start_node(node_instance, unique_name)
|
|
108
|
+
|
|
109
|
+
return node_instance
|
|
110
|
+
|
|
111
|
+
async def _start_node(self, node: ManagedNode, name: str):
|
|
112
|
+
"""Starts a node and waits for it to be idle."""
|
|
113
|
+
try:
|
|
114
|
+
node.start()
|
|
115
|
+
from autobyteus.agent_team.agent_team import AgentTeam
|
|
116
|
+
if isinstance(node, AgentTeam):
|
|
117
|
+
await wait_for_team_to_be_idle(node, timeout=120.0)
|
|
118
|
+
else:
|
|
119
|
+
await wait_for_agent_to_be_idle(node, timeout=60.0)
|
|
120
|
+
except Exception as e:
|
|
121
|
+
logger.error(f"Team '{self.team_id}': Failed to start node '{name}' on-demand: {e}", exc_info=True)
|
|
122
|
+
raise RuntimeError(f"Failed to start node '{name}' on-demand.") from e
|
|
123
|
+
|
|
124
|
+
def get_all_agents(self) -> List['Agent']:
|
|
125
|
+
from autobyteus.agent.agent import Agent
|
|
126
|
+
return [node for node in self._nodes_cache.values() if isinstance(node, Agent)]
|
|
127
|
+
|
|
128
|
+
def get_all_sub_teams(self) -> List['AgentTeam']:
|
|
129
|
+
from autobyteus.agent_team.agent_team import AgentTeam
|
|
130
|
+
return [node for node in self._nodes_cache.values() if isinstance(node, AgentTeam)]
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def coordinator_agent(self) -> Optional['Agent']:
|
|
134
|
+
return self._coordinator_agent
|
|
135
|
+
|
|
136
|
+
async def ensure_coordinator_is_ready(self, coordinator_name: str) -> 'Agent':
|
|
137
|
+
"""
|
|
138
|
+
Ensures the coordinator agent is created, started, and ready, then
|
|
139
|
+
designates it as the coordinator.
|
|
140
|
+
"""
|
|
141
|
+
from autobyteus.agent.agent import Agent
|
|
142
|
+
node = await self.ensure_node_is_ready(name_or_agent_id=coordinator_name)
|
|
143
|
+
if not isinstance(node, Agent):
|
|
144
|
+
raise TypeError(f"Coordinator node '{coordinator_name}' resolved to a non-agent type: {type(node).__name__}")
|
|
145
|
+
|
|
146
|
+
self._coordinator_agent = node
|
|
147
|
+
return node
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/context/team_node_config.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import logging
|
|
4
|
+
import uuid
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import List, TYPE_CHECKING, Union, Tuple
|
|
7
|
+
|
|
8
|
+
# The import is moved into the TYPE_CHECKING block to break the circular dependency at module load time.
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from autobyteus.agent.context import AgentConfig
|
|
11
|
+
from autobyteus.agent_team.context.agent_team_config import AgentTeamConfig
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class TeamNodeConfig:
|
|
17
|
+
"""
|
|
18
|
+
Represents a node in an agent team graph.
|
|
19
|
+
|
|
20
|
+
This is the core building block for defining agent teams. A node can be either
|
|
21
|
+
a single agent (defined by an AgentConfig) or an entire sub-team
|
|
22
|
+
(defined by an AgentTeamConfig).
|
|
23
|
+
|
|
24
|
+
Attributes:
|
|
25
|
+
node_definition: The configuration for the agent or sub-team at this node.
|
|
26
|
+
dependencies: A tuple of other TeamNodeConfig objects that must be
|
|
27
|
+
successfully executed before this node can be executed.
|
|
28
|
+
node_id: A unique identifier for this node instance.
|
|
29
|
+
"""
|
|
30
|
+
node_definition: Union["AgentConfig", "AgentTeamConfig"]
|
|
31
|
+
dependencies: Tuple[TeamNodeConfig, ...] = field(default_factory=tuple)
|
|
32
|
+
node_id: str = field(default_factory=lambda: f"node_{uuid.uuid4().hex}", init=False, repr=False)
|
|
33
|
+
|
|
34
|
+
def __post_init__(self):
|
|
35
|
+
"""Validates the node configuration."""
|
|
36
|
+
from autobyteus.agent.context import AgentConfig
|
|
37
|
+
from autobyteus.agent_team.context.agent_team_config import AgentTeamConfig
|
|
38
|
+
|
|
39
|
+
if not isinstance(self.node_definition, (AgentConfig, AgentTeamConfig)):
|
|
40
|
+
raise TypeError("The 'node_definition' attribute must be an instance of AgentConfig or AgentTeamConfig.")
|
|
41
|
+
|
|
42
|
+
if not all(isinstance(dep, TeamNodeConfig) for dep in self.dependencies):
|
|
43
|
+
raise TypeError("All items in 'dependencies' must be instances of TeamNodeConfig.")
|
|
44
|
+
|
|
45
|
+
logger.debug(f"TeamNodeConfig created for: '{self.name}' (NodeID: {self.node_id}). Dependencies: {[dep.name for dep in self.dependencies]}")
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def name(self) -> str:
|
|
49
|
+
"""A convenience property to get the node's name from its definition."""
|
|
50
|
+
return self.node_definition.name
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def effective_config(self) -> Union["AgentConfig", "AgentTeamConfig"]:
|
|
54
|
+
"""Returns the underlying AgentConfig or AgentTeamConfig."""
|
|
55
|
+
return self.node_definition
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def is_sub_team(self) -> bool:
|
|
59
|
+
"""Returns True if this node represents a sub-team."""
|
|
60
|
+
from autobyteus.agent_team.context.agent_team_config import AgentTeamConfig
|
|
61
|
+
return isinstance(self.node_definition, AgentTeamConfig)
|
|
62
|
+
|
|
63
|
+
def __hash__(self):
|
|
64
|
+
"""
|
|
65
|
+
Makes the node hashable based on its unique node_id, allowing it to be
|
|
66
|
+
used in sets and as dictionary keys.
|
|
67
|
+
"""
|
|
68
|
+
return hash(self.node_id)
|
|
69
|
+
|
|
70
|
+
def __eq__(self, other):
|
|
71
|
+
"""
|
|
72
|
+
Compares two nodes based on their unique node_id.
|
|
73
|
+
"""
|
|
74
|
+
if isinstance(other, TeamNodeConfig):
|
|
75
|
+
return self.node_id == other.node_id
|
|
76
|
+
return False
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/events/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
This package contains event definitions and dispatchers for the agent team runtime.
|
|
4
|
+
"""
|
|
5
|
+
from autobyteus.agent_team.events.agent_team_events import (
|
|
6
|
+
BaseAgentTeamEvent,
|
|
7
|
+
LifecycleAgentTeamEvent,
|
|
8
|
+
OperationalAgentTeamEvent,
|
|
9
|
+
AgentTeamReadyEvent,
|
|
10
|
+
AgentTeamErrorEvent,
|
|
11
|
+
ProcessUserMessageEvent,
|
|
12
|
+
InterAgentMessageRequestEvent,
|
|
13
|
+
ToolApprovalTeamEvent,
|
|
14
|
+
)
|
|
15
|
+
from autobyteus.agent_team.events.agent_team_event_dispatcher import AgentTeamEventDispatcher
|
|
16
|
+
from autobyteus.agent_team.events.agent_team_input_event_queue_manager import AgentTeamInputEventQueueManager
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"BaseAgentTeamEvent",
|
|
20
|
+
"LifecycleAgentTeamEvent",
|
|
21
|
+
"OperationalAgentTeamEvent",
|
|
22
|
+
"AgentTeamReadyEvent",
|
|
23
|
+
"AgentTeamErrorEvent",
|
|
24
|
+
"ProcessUserMessageEvent",
|
|
25
|
+
"InterAgentMessageRequestEvent",
|
|
26
|
+
"ToolApprovalTeamEvent",
|
|
27
|
+
"AgentTeamEventDispatcher",
|
|
28
|
+
"AgentTeamInputEventQueueManager",
|
|
29
|
+
]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/events/agent_team_event_dispatcher.py
|
|
2
|
+
import logging
|
|
3
|
+
import traceback
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from autobyteus.agent_team.events.agent_team_events import BaseAgentTeamEvent, AgentTeamReadyEvent, ProcessUserMessageEvent
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
10
|
+
from autobyteus.agent_team.handlers.agent_team_event_handler_registry import AgentTeamEventHandlerRegistry
|
|
11
|
+
from autobyteus.agent_team.phases.agent_team_phase_manager import AgentTeamPhaseManager
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
class AgentTeamEventDispatcher:
|
|
16
|
+
"""Dispatches agent team events to their appropriate handlers."""
|
|
17
|
+
|
|
18
|
+
def __init__(self,
|
|
19
|
+
event_handler_registry: 'AgentTeamEventHandlerRegistry',
|
|
20
|
+
phase_manager: 'AgentTeamPhaseManager'):
|
|
21
|
+
self.registry = event_handler_registry
|
|
22
|
+
self.phase_manager = phase_manager
|
|
23
|
+
|
|
24
|
+
async def dispatch(self, event: BaseAgentTeamEvent, context: 'AgentTeamContext'):
|
|
25
|
+
handler = self.registry.get_handler(type(event))
|
|
26
|
+
team_id = context.team_id
|
|
27
|
+
|
|
28
|
+
if not handler:
|
|
29
|
+
logger.warning(f"Team '{team_id}': No handler for event '{type(event).__name__}'.")
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
await handler.handle(event, context)
|
|
34
|
+
if isinstance(event, AgentTeamReadyEvent):
|
|
35
|
+
await self.phase_manager.notify_initialization_complete()
|
|
36
|
+
except Exception as e:
|
|
37
|
+
error_msg = f"Error handling '{type(event).__name__}' in team '{team_id}': {e}"
|
|
38
|
+
logger.error(error_msg, exc_info=True)
|
|
39
|
+
await self.phase_manager.notify_error_occurred(error_msg, traceback.format_exc())
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/events/agent_team_events.py
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Dict, Any, Optional
|
|
4
|
+
|
|
5
|
+
from autobyteus.agent.message.agent_input_user_message import AgentInputUserMessage
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class BaseAgentTeamEvent:
|
|
9
|
+
"""Base class for all agent team events."""
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class LifecycleAgentTeamEvent(BaseAgentTeamEvent):
|
|
13
|
+
"""Base class for events related to the agent team's lifecycle."""
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class OperationalAgentTeamEvent(BaseAgentTeamEvent):
|
|
17
|
+
"""Base class for events related to the agent team's operational logic."""
|
|
18
|
+
|
|
19
|
+
# Specific Events
|
|
20
|
+
@dataclass
|
|
21
|
+
class AgentTeamReadyEvent(LifecycleAgentTeamEvent):
|
|
22
|
+
"""Indicates the agent team has completed bootstrapping and is ready for tasks."""
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class AgentTeamErrorEvent(LifecycleAgentTeamEvent):
|
|
26
|
+
"""Indicates a significant error occurred within the agent team."""
|
|
27
|
+
error_message: str
|
|
28
|
+
exception_details: Optional[str] = None
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class ProcessUserMessageEvent(OperationalAgentTeamEvent):
|
|
32
|
+
"""Carries a user's message to be processed by a specific agent in the team."""
|
|
33
|
+
user_message: AgentInputUserMessage
|
|
34
|
+
target_agent_name: str
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class InterAgentMessageRequestEvent(OperationalAgentTeamEvent):
|
|
38
|
+
"""
|
|
39
|
+
An internal request within the agent team to post a message from one agent to another.
|
|
40
|
+
This triggers on-demand startup logic if needed.
|
|
41
|
+
"""
|
|
42
|
+
sender_agent_id: str
|
|
43
|
+
recipient_name: str
|
|
44
|
+
content: str
|
|
45
|
+
message_type: str
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class ToolApprovalTeamEvent(OperationalAgentTeamEvent):
|
|
49
|
+
"""Carries a user's approval/denial for a tool execution to a specific agent."""
|
|
50
|
+
agent_name: str
|
|
51
|
+
tool_invocation_id: str
|
|
52
|
+
is_approved: bool
|
|
53
|
+
reason: Optional[str] = None
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/events/agent_team_input_event_queue_manager.py
|
|
2
|
+
import asyncio
|
|
3
|
+
import logging
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from autobyteus.agent_team.events.agent_team_events import ProcessUserMessageEvent
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
class AgentTeamInputEventQueueManager:
|
|
11
|
+
"""Manages asyncio.Queue instances for events consumed by the AgentTeamWorker."""
|
|
12
|
+
def __init__(self, queue_size: int = 0):
|
|
13
|
+
self.user_message_queue: asyncio.Queue[ProcessUserMessageEvent] = asyncio.Queue(maxsize=queue_size)
|
|
14
|
+
self.internal_system_event_queue: asyncio.Queue[Any] = asyncio.Queue(maxsize=queue_size)
|
|
15
|
+
logger.info("AgentTeamInputEventQueueManager initialized.")
|
|
16
|
+
|
|
17
|
+
async def enqueue_user_message(self, event: ProcessUserMessageEvent):
|
|
18
|
+
await self.user_message_queue.put(event)
|
|
19
|
+
|
|
20
|
+
async def enqueue_internal_system_event(self, event: Any):
|
|
21
|
+
await self.internal_system_event_queue.put(event)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent_team/exceptions.py
|
|
2
|
+
|
|
3
|
+
class TeamNodeNotFoundException(Exception):
|
|
4
|
+
"""Raised when a node (agent or sub-team) cannot be found in the agent team."""
|
|
5
|
+
def __init__(self, node_name: str, team_id: str):
|
|
6
|
+
super().__init__(f"Node '{node_name}' not found in agent team '{team_id}'.")
|
|
7
|
+
self.node_name = node_name
|
|
8
|
+
self.team_id = team_id
|