autobyteus 1.1.3__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/agent.py +1 -1
- autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +4 -2
- autobyteus/agent/context/__init__.py +4 -2
- autobyteus/agent/context/agent_config.py +35 -8
- autobyteus/agent/context/agent_context_registry.py +73 -0
- autobyteus/agent/events/notifiers.py +4 -0
- autobyteus/agent/events/worker_event_dispatcher.py +1 -2
- autobyteus/agent/handlers/inter_agent_message_event_handler.py +8 -3
- autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +19 -19
- autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +2 -2
- autobyteus/agent/handlers/tool_result_event_handler.py +48 -20
- autobyteus/agent/handlers/user_input_message_event_handler.py +16 -1
- autobyteus/agent/input_processor/__init__.py +1 -7
- autobyteus/agent/message/context_file_type.py +6 -0
- autobyteus/agent/message/send_message_to.py +74 -99
- autobyteus/agent/phases/discover.py +2 -1
- autobyteus/agent/runtime/agent_runtime.py +10 -2
- autobyteus/agent/runtime/agent_worker.py +1 -0
- 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/tool_execution_result_processor/__init__.py +9 -0
- autobyteus/agent/tool_execution_result_processor/base_processor.py +46 -0
- autobyteus/agent/tool_execution_result_processor/processor_definition.py +36 -0
- autobyteus/agent/tool_execution_result_processor/processor_meta.py +36 -0
- autobyteus/agent/tool_execution_result_processor/processor_registry.py +70 -0
- autobyteus/agent/workspace/base_workspace.py +17 -2
- 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/__init__.py +1 -1
- 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/cli/cli_display.py +1 -1
- autobyteus/cli/workflow_tui/__init__.py +4 -0
- autobyteus/cli/workflow_tui/app.py +210 -0
- autobyteus/cli/workflow_tui/state.py +189 -0
- autobyteus/cli/workflow_tui/widgets/__init__.py +6 -0
- autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +149 -0
- autobyteus/cli/workflow_tui/widgets/focus_pane.py +335 -0
- autobyteus/cli/workflow_tui/widgets/logo.py +27 -0
- autobyteus/cli/workflow_tui/widgets/renderables.py +70 -0
- autobyteus/cli/workflow_tui/widgets/shared.py +51 -0
- autobyteus/cli/workflow_tui/widgets/status_bar.py +14 -0
- autobyteus/events/event_types.py +8 -0
- autobyteus/llm/api/autobyteus_llm.py +11 -12
- autobyteus/llm/api/lmstudio_llm.py +34 -0
- autobyteus/llm/api/ollama_llm.py +8 -13
- autobyteus/llm/api/openai_compatible_llm.py +20 -3
- autobyteus/llm/autobyteus_provider.py +73 -46
- autobyteus/llm/llm_factory.py +103 -139
- autobyteus/llm/lmstudio_provider.py +104 -0
- 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 -12
- autobyteus/llm/runtimes.py +11 -0
- autobyteus/llm/token_counter/token_counter_factory.py +2 -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/__init__.py +2 -0
- autobyteus/tools/ask_user_input.py +2 -1
- autobyteus/tools/bash/bash_executor.py +61 -15
- autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +2 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +3 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +3 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +3 -0
- autobyteus/tools/browser/standalone/google_search_ui.py +2 -0
- autobyteus/tools/browser/standalone/navigate_to.py +2 -0
- autobyteus/tools/browser/standalone/web_page_pdf_generator.py +3 -0
- autobyteus/tools/browser/standalone/webpage_image_downloader.py +3 -0
- autobyteus/tools/browser/standalone/webpage_reader.py +2 -0
- autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +3 -0
- autobyteus/tools/file/file_reader.py +36 -9
- autobyteus/tools/file/file_writer.py +37 -9
- autobyteus/tools/functional_tool.py +5 -4
- autobyteus/tools/image_downloader.py +2 -0
- 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 +106 -51
- autobyteus/tools/parameter_schema.py +17 -11
- autobyteus/tools/pdf_downloader.py +2 -1
- autobyteus/tools/registry/tool_definition.py +36 -37
- autobyteus/tools/registry/tool_registry.py +50 -2
- autobyteus/tools/timer.py +2 -0
- autobyteus/tools/tool_category.py +15 -4
- autobyteus/tools/tool_meta.py +6 -1
- autobyteus/tools/tool_origin.py +10 -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/workflow/agentic_workflow.py +93 -0
- autobyteus/{agent/workflow → workflow}/base_agentic_workflow.py +19 -27
- autobyteus/workflow/bootstrap_steps/__init__.py +20 -0
- autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +34 -0
- autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +23 -0
- autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +41 -0
- autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +108 -0
- autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +50 -0
- autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +25 -0
- autobyteus/workflow/context/__init__.py +17 -0
- autobyteus/workflow/context/team_manager.py +147 -0
- autobyteus/workflow/context/workflow_config.py +30 -0
- autobyteus/workflow/context/workflow_context.py +61 -0
- autobyteus/workflow/context/workflow_node_config.py +76 -0
- autobyteus/workflow/context/workflow_runtime_state.py +53 -0
- autobyteus/workflow/events/__init__.py +29 -0
- autobyteus/workflow/events/workflow_event_dispatcher.py +39 -0
- autobyteus/workflow/events/workflow_events.py +53 -0
- autobyteus/workflow/events/workflow_input_event_queue_manager.py +21 -0
- autobyteus/workflow/exceptions.py +8 -0
- autobyteus/workflow/factory/__init__.py +9 -0
- autobyteus/workflow/factory/workflow_factory.py +99 -0
- autobyteus/workflow/handlers/__init__.py +19 -0
- autobyteus/workflow/handlers/base_workflow_event_handler.py +16 -0
- autobyteus/workflow/handlers/inter_agent_message_request_event_handler.py +61 -0
- autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +27 -0
- autobyteus/workflow/handlers/process_user_message_event_handler.py +46 -0
- autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +39 -0
- autobyteus/workflow/handlers/workflow_event_handler_registry.py +23 -0
- autobyteus/workflow/phases/__init__.py +11 -0
- autobyteus/workflow/phases/workflow_operational_phase.py +19 -0
- autobyteus/workflow/phases/workflow_phase_manager.py +48 -0
- autobyteus/workflow/runtime/__init__.py +13 -0
- autobyteus/workflow/runtime/workflow_runtime.py +82 -0
- autobyteus/workflow/runtime/workflow_worker.py +117 -0
- autobyteus/workflow/shutdown_steps/__init__.py +17 -0
- autobyteus/workflow/shutdown_steps/agent_team_shutdown_step.py +42 -0
- autobyteus/workflow/shutdown_steps/base_workflow_shutdown_step.py +16 -0
- autobyteus/workflow/shutdown_steps/bridge_cleanup_step.py +28 -0
- autobyteus/workflow/shutdown_steps/sub_workflow_shutdown_step.py +41 -0
- autobyteus/workflow/shutdown_steps/workflow_shutdown_orchestrator.py +35 -0
- autobyteus/workflow/streaming/__init__.py +26 -0
- autobyteus/workflow/streaming/agent_event_bridge.py +48 -0
- autobyteus/workflow/streaming/agent_event_multiplexer.py +70 -0
- autobyteus/workflow/streaming/workflow_event_bridge.py +50 -0
- autobyteus/workflow/streaming/workflow_event_notifier.py +83 -0
- autobyteus/workflow/streaming/workflow_event_stream.py +33 -0
- autobyteus/workflow/streaming/workflow_stream_event_payloads.py +28 -0
- autobyteus/workflow/streaming/workflow_stream_events.py +45 -0
- autobyteus/workflow/utils/__init__.py +9 -0
- autobyteus/workflow/utils/wait_for_idle.py +46 -0
- autobyteus/workflow/workflow_builder.py +151 -0
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/METADATA +16 -14
- autobyteus-1.1.5.dist-info/RECORD +455 -0
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/top_level.txt +1 -0
- examples/__init__.py +1 -0
- examples/agent_team/__init__.py +1 -0
- examples/discover_phase_transitions.py +104 -0
- examples/run_browser_agent.py +262 -0
- examples/run_google_slides_agent.py +287 -0
- examples/run_mcp_browser_client.py +174 -0
- examples/run_mcp_google_slides_client.py +270 -0
- examples/run_mcp_list_tools.py +189 -0
- examples/run_poem_writer.py +284 -0
- examples/run_sqlite_agent.py +295 -0
- autobyteus/agent/context/agent_phase_manager.py +0 -264
- autobyteus/agent/context/phases.py +0 -49
- autobyteus/agent/group/__init__.py +0 -0
- autobyteus/agent/group/agent_group.py +0 -164
- autobyteus/agent/group/agent_group_context.py +0 -81
- autobyteus/agent/input_processor/content_prefixing_input_processor.py +0 -41
- autobyteus/agent/input_processor/metadata_appending_input_processor.py +0 -34
- autobyteus/agent/input_processor/passthrough_input_processor.py +0 -33
- autobyteus/agent/workflow/__init__.py +0 -11
- autobyteus/agent/workflow/agentic_workflow.py +0 -89
- 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/mcp/registrar.py +0 -202
- 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
- autobyteus/workflow/simple_task.py +0 -98
- autobyteus/workflow/task.py +0 -147
- autobyteus/workflow/workflow.py +0 -49
- autobyteus-1.1.3.dist-info/RECORD +0 -312
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/WHEEL +0 -0
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,150 +1,125 @@
|
|
|
1
|
-
# file: autobyteus/
|
|
1
|
+
# file: autobyteus/agent/message/send_message_to.py
|
|
2
2
|
import logging
|
|
3
3
|
from typing import TYPE_CHECKING, Any, Optional
|
|
4
4
|
|
|
5
|
-
from autobyteus.agent.message.inter_agent_message import InterAgentMessage
|
|
6
5
|
from autobyteus.tools.base_tool import BaseTool
|
|
7
|
-
from autobyteus.
|
|
8
|
-
# Updated imports for schema
|
|
6
|
+
from autobyteus.tools.tool_category import ToolCategory
|
|
9
7
|
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
10
|
-
|
|
8
|
+
from autobyteus.tools.tool_config import ToolConfig
|
|
9
|
+
# This import is for type hinting only and avoids circular dependencies at runtime
|
|
11
10
|
if TYPE_CHECKING:
|
|
12
11
|
from autobyteus.agent.context import AgentContext
|
|
13
|
-
from autobyteus.
|
|
12
|
+
from autobyteus.agent_team.context.agent_team_context import AgentTeamContext
|
|
13
|
+
from autobyteus.agent_team.context.team_manager import TeamManager
|
|
14
|
+
from autobyteus.agent_team.events.agent_team_events import InterAgentMessageRequestEvent
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
17
18
|
class SendMessageTo(BaseTool):
|
|
18
19
|
"""
|
|
19
|
-
A tool for sending messages to other agents within the same
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
A tool for sending messages to other agents within the same agent team.
|
|
21
|
+
This tool dynamically retrieves the team communication channel from the
|
|
22
|
+
agent's context at runtime.
|
|
22
23
|
"""
|
|
23
|
-
TOOL_NAME = "SendMessageTo"
|
|
24
|
+
TOOL_NAME = "SendMessageTo"
|
|
25
|
+
CATEGORY = ToolCategory.AGENT_COMMUNICATION
|
|
26
|
+
|
|
27
|
+
def __init__(self, config: Optional[ToolConfig] = None):
|
|
28
|
+
"""
|
|
29
|
+
Initializes the stateless SendMessageTo tool.
|
|
30
|
+
"""
|
|
31
|
+
super().__init__(config=config)
|
|
32
|
+
# The TeamManager is no longer stored as an instance variable.
|
|
33
|
+
logger.debug("SendMessageTo tool initialized (stateless).")
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
super().__init__()
|
|
27
|
-
logger.debug(f"{self.get_name()} tool initialized.") # Use get_name()
|
|
35
|
+
# The set_team_manager method has been removed.
|
|
28
36
|
|
|
29
37
|
@classmethod
|
|
30
|
-
def get_name(cls) -> str:
|
|
38
|
+
def get_name(cls) -> str:
|
|
31
39
|
return cls.TOOL_NAME
|
|
32
40
|
|
|
33
41
|
@classmethod
|
|
34
42
|
def get_description(cls) -> str:
|
|
35
|
-
return ("Sends a message to another agent within the same
|
|
36
|
-
"
|
|
43
|
+
return ("Sends a message to another agent within the same team, starting them if necessary. "
|
|
44
|
+
"You must specify the recipient by their unique name as provided in your team manifest.")
|
|
37
45
|
|
|
38
46
|
@classmethod
|
|
39
47
|
def get_argument_schema(cls) -> Optional[ParameterSchema]:
|
|
40
48
|
schema = ParameterSchema()
|
|
41
49
|
schema.add_parameter(ParameterDefinition(
|
|
42
|
-
name="
|
|
50
|
+
name="recipient_name",
|
|
43
51
|
param_type=ParameterType.STRING,
|
|
44
|
-
description=
|
|
52
|
+
description='The unique name of the recipient agent (e.g., "Researcher", "Writer_1"). This MUST match a name from your team manifest.',
|
|
45
53
|
required=True
|
|
46
54
|
))
|
|
47
55
|
schema.add_parameter(ParameterDefinition(
|
|
48
56
|
name="content",
|
|
49
57
|
param_type=ParameterType.STRING,
|
|
50
|
-
description="The actual message
|
|
58
|
+
description="The actual message content or task instruction.",
|
|
51
59
|
required=True
|
|
52
60
|
))
|
|
53
61
|
schema.add_parameter(ParameterDefinition(
|
|
54
62
|
name="message_type",
|
|
55
|
-
param_type=ParameterType.STRING,
|
|
63
|
+
param_type=ParameterType.STRING,
|
|
56
64
|
description="Type of the message (e.g., TASK_ASSIGNMENT, CLARIFICATION). Custom types allowed.",
|
|
57
65
|
required=True
|
|
58
66
|
))
|
|
59
|
-
schema.add_parameter(ParameterDefinition(
|
|
60
|
-
name="recipient_agent_id",
|
|
61
|
-
param_type=ParameterType.STRING,
|
|
62
|
-
description='Optional. Specific ID of the recipient agent. If "unknown" or omitted, resolves by role.',
|
|
63
|
-
required=False,
|
|
64
|
-
default_value=None # Explicitly no default, truly optional
|
|
65
|
-
))
|
|
66
67
|
return schema
|
|
67
68
|
|
|
68
|
-
# tool_usage_xml() and tool_usage_json() are inherited from BaseTool
|
|
69
|
-
# get_config_schema() for instantiation defaults to None
|
|
70
|
-
|
|
71
69
|
async def _execute(self,
|
|
72
70
|
context: 'AgentContext',
|
|
73
|
-
|
|
71
|
+
recipient_name: str,
|
|
74
72
|
content: str,
|
|
75
|
-
message_type: str
|
|
76
|
-
recipient_agent_id: Optional[str] = None) -> str: # Named parameters
|
|
73
|
+
message_type: str) -> str:
|
|
77
74
|
"""
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
Creates and dispatches an InterAgentMessageRequestEvent to the parent agent team
|
|
76
|
+
by retrieving the TeamManager from the agent's context.
|
|
80
77
|
"""
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
logger.error(error_msg)
|
|
78
|
+
# Local import to break circular dependency at module load time.
|
|
79
|
+
from autobyteus.agent_team.events.agent_team_events import InterAgentMessageRequestEvent
|
|
80
|
+
|
|
81
|
+
# --- NEW: Retrieve TeamManager dynamically from context ---
|
|
82
|
+
team_context: Optional['AgentTeamContext'] = context.custom_data.get("team_context")
|
|
83
|
+
if not team_context:
|
|
84
|
+
error_msg = "Critical error: SendMessageTo tool is not configured for team communication. It can only be used within a managed AgentTeam."
|
|
85
|
+
logger.error(f"Agent '{context.agent_id}': {error_msg}")
|
|
90
86
|
return f"Error: {error_msg}"
|
|
91
87
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if recipient_agent_id and recipient_agent_id.lower() != "unknown":
|
|
98
|
-
target_agent = group_context.get_agent(recipient_agent_id)
|
|
99
|
-
if not target_agent:
|
|
100
|
-
logger.warning(f"Tool '{self.get_name()}': Agent with ID '{recipient_agent_id}' not found in group '{group_context.group_id}'. "
|
|
101
|
-
f"Attempting to find by role '{recipient_role_name}'.")
|
|
102
|
-
|
|
103
|
-
if not target_agent:
|
|
104
|
-
agents_with_role = group_context.get_agents_by_role(recipient_role_name)
|
|
105
|
-
if not agents_with_role:
|
|
106
|
-
error_msg = f"No agent found with role '{recipient_role_name}' (and specific ID '{recipient_agent_id}' if provided was not found) in group '{group_context.group_id}'."
|
|
107
|
-
logger.error(f"Tool '{self.get_name()}': {error_msg}")
|
|
108
|
-
return f"Error: {error_msg}"
|
|
109
|
-
|
|
110
|
-
if len(agents_with_role) > 1:
|
|
111
|
-
logger.warning(f"Tool '{self.get_name()}': Multiple agents ({len(agents_with_role)}) found for role '{recipient_role_name}'. "
|
|
112
|
-
f"Sending to the first one: {agents_with_role[0].agent_id}. "
|
|
113
|
-
"Consider using specific recipient_agent_id for clarity.")
|
|
114
|
-
target_agent = agents_with_role[0]
|
|
115
|
-
# Update recipient_agent_id to the one resolved by role if it was initially None or "unknown"
|
|
116
|
-
recipient_agent_id = target_agent.agent_id
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
if not target_agent:
|
|
120
|
-
error_msg = f"Could not resolve recipient agent with role '{recipient_role_name}' or ID '{recipient_agent_id}'." # recipient_agent_id would be updated here
|
|
121
|
-
logger.error(f"Tool '{self.get_name()}': {error_msg}")
|
|
88
|
+
team_manager: Optional['TeamManager'] = team_context.team_manager
|
|
89
|
+
if not team_manager:
|
|
90
|
+
# This is an internal framework error and should not happen in a correctly configured team.
|
|
91
|
+
error_msg = "Internal Error: TeamManager not found in the provided team_context."
|
|
92
|
+
logger.error(f"Agent '{context.agent_id}': {error_msg}")
|
|
122
93
|
return f"Error: {error_msg}"
|
|
123
94
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
)
|
|
95
|
+
# --- Input Validation ---
|
|
96
|
+
if not isinstance(recipient_name, str) or not recipient_name.strip():
|
|
97
|
+
error_msg = "Error: `recipient_name` must be a non-empty string."
|
|
98
|
+
logger.error(f"Tool '{self.get_name()}' validation failed: {error_msg}")
|
|
99
|
+
return error_msg
|
|
100
|
+
if not isinstance(content, str) or not content.strip():
|
|
101
|
+
error_msg = "Error: `content` must be a non-empty string."
|
|
102
|
+
logger.error(f"Tool '{self.get_name()}' validation failed: {error_msg}")
|
|
103
|
+
return error_msg
|
|
104
|
+
if not isinstance(message_type, str) or not message_type.strip():
|
|
105
|
+
error_msg = "Error: `message_type` must be a non-empty string."
|
|
106
|
+
logger.error(f"Tool '{self.get_name()}' validation failed: {error_msg}")
|
|
107
|
+
return error_msg
|
|
132
108
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
109
|
+
sender_agent_id = context.agent_id
|
|
110
|
+
logger.info(f"Tool '{self.get_name()}': Agent '{sender_agent_id}' requesting to send message to '{recipient_name}'.")
|
|
111
|
+
|
|
112
|
+
# Create the event for the agent team to handle
|
|
113
|
+
event = InterAgentMessageRequestEvent(
|
|
114
|
+
sender_agent_id=sender_agent_id,
|
|
115
|
+
recipient_name=recipient_name,
|
|
116
|
+
content=content,
|
|
117
|
+
message_type=message_type
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Dispatch the event "up" to the team's event loop via the dynamically retrieved team manager
|
|
121
|
+
await team_manager.dispatch_inter_agent_message_request(event)
|
|
146
122
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
# then this method could be overridden. For now, assume auto-generated is fine.
|
|
123
|
+
success_msg = f"Message dispatch for recipient '{recipient_name}' has been successfully requested."
|
|
124
|
+
logger.info(f"Tool '{self.get_name()}': {success_msg}")
|
|
125
|
+
return success_msg
|
|
@@ -3,7 +3,8 @@ import inspect
|
|
|
3
3
|
import logging
|
|
4
4
|
from typing import List, Optional
|
|
5
5
|
|
|
6
|
-
from autobyteus.agent.
|
|
6
|
+
from autobyteus.agent.phases.manager import AgentPhaseManager
|
|
7
|
+
|
|
7
8
|
from .transition_info import PhaseTransitionInfo
|
|
8
9
|
|
|
9
10
|
logger = logging.getLogger(__name__)
|
|
@@ -5,7 +5,7 @@ import traceback
|
|
|
5
5
|
import concurrent.futures
|
|
6
6
|
from typing import Optional, Any, Callable, Awaitable, TYPE_CHECKING
|
|
7
7
|
|
|
8
|
-
from autobyteus.agent.context import AgentContext
|
|
8
|
+
from autobyteus.agent.context import AgentContext, AgentContextRegistry
|
|
9
9
|
from autobyteus.agent.phases import AgentOperationalPhase, AgentPhaseManager
|
|
10
10
|
from autobyteus.agent.events.notifiers import AgentExternalEventNotifier
|
|
11
11
|
from autobyteus.agent.events import BaseEvent
|
|
@@ -39,8 +39,12 @@ class AgentRuntime:
|
|
|
39
39
|
event_handler_registry=self.event_handler_registry,
|
|
40
40
|
)
|
|
41
41
|
self._worker.add_done_callback(self._handle_worker_completion)
|
|
42
|
+
|
|
43
|
+
# Register the context with the global registry
|
|
44
|
+
self._context_registry = AgentContextRegistry()
|
|
45
|
+
self._context_registry.register_context(self.context)
|
|
42
46
|
|
|
43
|
-
logger.info(f"AgentRuntime initialized for agent_id '{self.context.agent_id}'.")
|
|
47
|
+
logger.info(f"AgentRuntime initialized for agent_id '{self.context.agent_id}'. Context registered.")
|
|
44
48
|
|
|
45
49
|
def get_worker_loop(self) -> Optional[asyncio.AbstractEventLoop]:
|
|
46
50
|
return self._worker.get_worker_loop()
|
|
@@ -122,6 +126,10 @@ class AgentRuntime:
|
|
|
122
126
|
|
|
123
127
|
# LLM instance cleanup is now handled by the AgentWorker before its loop closes.
|
|
124
128
|
|
|
129
|
+
# Unregister the context from the global registry
|
|
130
|
+
self._context_registry.unregister_context(agent_id)
|
|
131
|
+
logger.info(f"AgentRuntime for '{agent_id}': Context unregistered.")
|
|
132
|
+
|
|
125
133
|
await self.phase_manager.notify_final_shutdown_complete()
|
|
126
134
|
logger.info(f"AgentRuntime for '{agent_id}' stop() method completed.")
|
|
127
135
|
|
|
@@ -221,6 +221,7 @@ class AgentWorker:
|
|
|
221
221
|
# Wait for the main thread future to complete.
|
|
222
222
|
if self._thread_future:
|
|
223
223
|
try:
|
|
224
|
+
# FIX: Use asyncio.wait_for() to handle the timeout correctly.
|
|
224
225
|
await asyncio.wait_for(asyncio.wrap_future(self._thread_future), timeout=timeout)
|
|
225
226
|
logger.info(f"AgentWorker '{agent_id}': Worker thread has terminated.")
|
|
226
227
|
except asyncio.TimeoutError:
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent/sender_type.py
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from typing import Set
|
|
4
|
+
|
|
5
|
+
class SenderType(str, Enum):
|
|
6
|
+
"""
|
|
7
|
+
Categorizes the origin of a message or event within the system.
|
|
8
|
+
"""
|
|
9
|
+
USER = "user" # A message originating from an external human user.
|
|
10
|
+
AGENT = "agent" # A message from another agent within the same team or a different team.
|
|
11
|
+
SYSTEM = "system" # An automated message from an internal system component.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# --- System Sender Identification ---
|
|
15
|
+
TASK_NOTIFIER_SENDER_ID = "system.task_notifier"
|
|
@@ -16,6 +16,7 @@ from autobyteus.agent.streaming.stream_event_payloads import (
|
|
|
16
16
|
create_error_event_data,
|
|
17
17
|
create_tool_invocation_approval_requested_data,
|
|
18
18
|
create_tool_invocation_auto_executing_data,
|
|
19
|
+
create_system_task_notification_data, # NEW
|
|
19
20
|
AssistantChunkData,
|
|
20
21
|
AssistantCompleteResponseData,
|
|
21
22
|
ToolInteractionLogEntryData,
|
|
@@ -23,6 +24,7 @@ from autobyteus.agent.streaming.stream_event_payloads import (
|
|
|
23
24
|
ToolInvocationApprovalRequestedData,
|
|
24
25
|
ToolInvocationAutoExecutingData,
|
|
25
26
|
ErrorEventData,
|
|
27
|
+
SystemTaskNotificationData, # NEW
|
|
26
28
|
EmptyData,
|
|
27
29
|
StreamDataPayload,
|
|
28
30
|
)
|
|
@@ -101,6 +103,10 @@ class AgentEventStream(EventEmitter):
|
|
|
101
103
|
elif event_type == EventType.AGENT_ERROR_OUTPUT_GENERATION:
|
|
102
104
|
typed_payload_for_stream_event = create_error_event_data(payload)
|
|
103
105
|
stream_event_type_for_generic_stream = StreamEventType.ERROR_EVENT
|
|
106
|
+
# NEW MAPPING
|
|
107
|
+
elif event_type == EventType.AGENT_DATA_SYSTEM_TASK_NOTIFICATION_RECEIVED:
|
|
108
|
+
typed_payload_for_stream_event = create_system_task_notification_data(payload)
|
|
109
|
+
stream_event_type_for_generic_stream = StreamEventType.SYSTEM_TASK_NOTIFICATION
|
|
104
110
|
|
|
105
111
|
elif event_type in [EventType.AGENT_DATA_ASSISTANT_CHUNK_STREAM_END, EventType.AGENT_DATA_TOOL_LOG_STREAM_END]:
|
|
106
112
|
pass
|
|
@@ -55,6 +55,11 @@ class ToolInvocationAutoExecutingData(BaseStreamPayload):
|
|
|
55
55
|
tool_name: str
|
|
56
56
|
arguments: Dict[str, Any]
|
|
57
57
|
|
|
58
|
+
# NEW PAYLOAD
|
|
59
|
+
class SystemTaskNotificationData(BaseStreamPayload):
|
|
60
|
+
sender_id: str
|
|
61
|
+
content: str
|
|
62
|
+
|
|
58
63
|
class EmptyData(BaseStreamPayload):
|
|
59
64
|
pass
|
|
60
65
|
|
|
@@ -67,6 +72,7 @@ StreamDataPayload = Union[
|
|
|
67
72
|
ErrorEventData,
|
|
68
73
|
ToolInvocationApprovalRequestedData,
|
|
69
74
|
ToolInvocationAutoExecutingData,
|
|
75
|
+
SystemTaskNotificationData, # NEW
|
|
70
76
|
EmptyData
|
|
71
77
|
]
|
|
72
78
|
|
|
@@ -165,3 +171,9 @@ def create_tool_invocation_auto_executing_data(auto_exec_data_dict: Any) -> Tool
|
|
|
165
171
|
if isinstance(auto_exec_data_dict, dict):
|
|
166
172
|
return ToolInvocationAutoExecutingData(**auto_exec_data_dict)
|
|
167
173
|
raise ValueError(f"Cannot create ToolInvocationAutoExecutingData from {type(auto_exec_data_dict)}")
|
|
174
|
+
|
|
175
|
+
# NEW FACTORY FUNCTION
|
|
176
|
+
def create_system_task_notification_data(notification_data_dict: Any) -> SystemTaskNotificationData:
|
|
177
|
+
if isinstance(notification_data_dict, dict):
|
|
178
|
+
return SystemTaskNotificationData(**notification_data_dict)
|
|
179
|
+
raise ValueError(f"Cannot create SystemTaskNotificationData from {type(notification_data_dict)}")
|
|
@@ -16,6 +16,7 @@ from .stream_event_payloads import (
|
|
|
16
16
|
ErrorEventData,
|
|
17
17
|
ToolInvocationApprovalRequestedData,
|
|
18
18
|
ToolInvocationAutoExecutingData,
|
|
19
|
+
SystemTaskNotificationData, # NEW
|
|
19
20
|
EmptyData
|
|
20
21
|
)
|
|
21
22
|
|
|
@@ -33,6 +34,7 @@ class StreamEventType(str, Enum):
|
|
|
33
34
|
ERROR_EVENT = "error_event"
|
|
34
35
|
TOOL_INVOCATION_APPROVAL_REQUESTED = "tool_invocation_approval_requested"
|
|
35
36
|
TOOL_INVOCATION_AUTO_EXECUTING = "tool_invocation_auto_executing"
|
|
37
|
+
SYSTEM_TASK_NOTIFICATION = "system_task_notification" # NEW
|
|
36
38
|
AGENT_IDLE = "agent_idle"
|
|
37
39
|
|
|
38
40
|
|
|
@@ -44,6 +46,7 @@ _STREAM_EVENT_TYPE_TO_PAYLOAD_CLASS: Dict[StreamEventType, Type[BaseModel]] = {
|
|
|
44
46
|
StreamEventType.ERROR_EVENT: ErrorEventData,
|
|
45
47
|
StreamEventType.TOOL_INVOCATION_APPROVAL_REQUESTED: ToolInvocationApprovalRequestedData,
|
|
46
48
|
StreamEventType.TOOL_INVOCATION_AUTO_EXECUTING: ToolInvocationAutoExecutingData,
|
|
49
|
+
StreamEventType.SYSTEM_TASK_NOTIFICATION: SystemTaskNotificationData, # NEW
|
|
47
50
|
StreamEventType.AGENT_IDLE: AgentOperationalPhaseTransitionData,
|
|
48
51
|
}
|
|
49
52
|
|
|
@@ -6,6 +6,7 @@ from .base_processor import BaseSystemPromptProcessor
|
|
|
6
6
|
from autobyteus.tools.registry import default_tool_registry, ToolDefinition
|
|
7
7
|
from autobyteus.tools.usage.providers import ToolManifestProvider
|
|
8
8
|
from autobyteus.prompt.prompt_template import PromptTemplate
|
|
9
|
+
from autobyteus.llm.providers import LLMProvider
|
|
9
10
|
|
|
10
11
|
if TYPE_CHECKING:
|
|
11
12
|
from autobyteus.tools.base_tool import BaseTool
|
|
@@ -18,6 +19,7 @@ class ToolManifestInjectorProcessor(BaseSystemPromptProcessor):
|
|
|
18
19
|
Injects a tool manifest into the system prompt using Jinja2-style placeholders.
|
|
19
20
|
It primarily targets the '{{tools}}' variable. It uses PromptTemplate for
|
|
20
21
|
rendering and delegates manifest generation to a ToolManifestProvider.
|
|
22
|
+
It automatically determines whether to use XML or JSON based on the LLM provider.
|
|
21
23
|
"""
|
|
22
24
|
# The '{{tools}}' placeholder is now handled by Jinja2 via PromptTemplate.
|
|
23
25
|
DEFAULT_PREFIX_FOR_TOOLS_ONLY_PROMPT = "You have access to a set of tools. Use them by outputting the appropriate tool call format. The user can only see the output of the tool, not the call itself. The available tools are:\n\n"
|
|
@@ -42,6 +44,10 @@ class ToolManifestInjectorProcessor(BaseSystemPromptProcessor):
|
|
|
42
44
|
if "tools" not in prompt_template.required_vars:
|
|
43
45
|
return system_prompt
|
|
44
46
|
|
|
47
|
+
llm_provider = None
|
|
48
|
+
if context.llm_instance and context.llm_instance.model:
|
|
49
|
+
llm_provider = context.llm_instance.model.provider
|
|
50
|
+
|
|
45
51
|
# Generate the manifest string for the 'tools' variable.
|
|
46
52
|
tools_manifest: str
|
|
47
53
|
if not tool_instances:
|
|
@@ -52,13 +58,10 @@ class ToolManifestInjectorProcessor(BaseSystemPromptProcessor):
|
|
|
52
58
|
td for name in tool_instances if (td := default_tool_registry.get_tool_definition(name))
|
|
53
59
|
]
|
|
54
60
|
|
|
55
|
-
llm_provider = context.llm_instance.model.provider if context.llm_instance and context.llm_instance.model else None
|
|
56
|
-
|
|
57
61
|
try:
|
|
58
|
-
# Delegate manifest generation to the provider
|
|
62
|
+
# Delegate manifest generation to the provider, which now handles all format logic.
|
|
59
63
|
tools_manifest = self._manifest_provider.provide(
|
|
60
64
|
tool_definitions=tool_definitions,
|
|
61
|
-
use_xml=context.config.use_xml_tool_format,
|
|
62
65
|
provider=llm_provider
|
|
63
66
|
)
|
|
64
67
|
except Exception as e:
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent/tool_execution_result_processor/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
Components for processing tool execution results before they are sent to the LLM.
|
|
4
|
+
"""
|
|
5
|
+
from .base_processor import BaseToolExecutionResultProcessor
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"BaseToolExecutionResultProcessor",
|
|
9
|
+
]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent/tool_execution_result_processor/base_processor.py
|
|
2
|
+
import logging
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
from .processor_meta import ToolExecutionResultProcessorMeta
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from autobyteus.agent.context import AgentContext
|
|
10
|
+
from autobyteus.agent.events import ToolResultEvent
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
|
|
14
|
+
class BaseToolExecutionResultProcessor(ABC, metaclass=ToolExecutionResultProcessorMeta):
|
|
15
|
+
"""
|
|
16
|
+
Abstract base class for processors that can modify a tool's execution result.
|
|
17
|
+
These processors are applied after a tool runs but before its result is formatted
|
|
18
|
+
for the LLM.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
@classmethod
|
|
22
|
+
def get_name(cls) -> str:
|
|
23
|
+
"""
|
|
24
|
+
Returns the unique registration name for this processor.
|
|
25
|
+
Defaults to the class name.
|
|
26
|
+
"""
|
|
27
|
+
return cls.__name__
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
async def process(self,
|
|
31
|
+
event: 'ToolResultEvent',
|
|
32
|
+
context: 'AgentContext') -> 'ToolResultEvent':
|
|
33
|
+
"""
|
|
34
|
+
Processes the given ToolResultEvent.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
event: The ToolResultEvent containing the tool's output or error.
|
|
38
|
+
context: The agent's context, providing access to config and state.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
The processed (potentially modified) ToolResultEvent.
|
|
42
|
+
"""
|
|
43
|
+
raise NotImplementedError("Subclasses must implement the 'process' method.")
|
|
44
|
+
|
|
45
|
+
def __repr__(self) -> str:
|
|
46
|
+
return f"<{self.__class__.__name__}>"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent/tool_execution_result_processor/processor_definition.py
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Type, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from .base_processor import BaseToolExecutionResultProcessor
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
class ToolExecutionResultProcessorDefinition:
|
|
11
|
+
"""
|
|
12
|
+
Represents the definition of a tool execution result processor.
|
|
13
|
+
Contains its registered name and the class itself.
|
|
14
|
+
"""
|
|
15
|
+
def __init__(self, name: str, processor_class: Type['BaseToolExecutionResultProcessor']):
|
|
16
|
+
"""
|
|
17
|
+
Initializes the ToolExecutionResultProcessorDefinition.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
name: The unique registered name of the processor.
|
|
21
|
+
processor_class: The class of the tool execution result processor.
|
|
22
|
+
|
|
23
|
+
Raises:
|
|
24
|
+
ValueError: If name is empty or processor_class is not a type.
|
|
25
|
+
"""
|
|
26
|
+
if not name or not isinstance(name, str):
|
|
27
|
+
raise ValueError("Tool Execution Result Processor name must be a non-empty string.")
|
|
28
|
+
if not isinstance(processor_class, type):
|
|
29
|
+
raise ValueError("processor_class must be a class type.")
|
|
30
|
+
|
|
31
|
+
self.name: str = name
|
|
32
|
+
self.processor_class: Type['BaseToolExecutionResultProcessor'] = processor_class
|
|
33
|
+
logger.debug(f"ToolExecutionResultProcessorDefinition created: name='{name}', class='{processor_class.__name__}'.")
|
|
34
|
+
|
|
35
|
+
def __repr__(self) -> str:
|
|
36
|
+
return f"<ToolExecutionResultProcessorDefinition name='{self.name}', class='{self.processor_class.__name__}'>"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent/tool_execution_result_processor/processor_meta.py
|
|
2
|
+
import logging
|
|
3
|
+
from abc import ABCMeta
|
|
4
|
+
|
|
5
|
+
from .processor_registry import default_tool_execution_result_processor_registry
|
|
6
|
+
from .processor_definition import ToolExecutionResultProcessorDefinition
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
class ToolExecutionResultProcessorMeta(ABCMeta):
|
|
11
|
+
"""
|
|
12
|
+
Metaclass for BaseToolExecutionResultProcessor that automatically registers
|
|
13
|
+
concrete processor subclasses with the default registry.
|
|
14
|
+
"""
|
|
15
|
+
def __init__(cls, name, bases, dct):
|
|
16
|
+
super().__init__(name, bases, dct)
|
|
17
|
+
|
|
18
|
+
if name == 'BaseToolExecutionResultProcessor' or getattr(cls, "__abstractmethods__", None):
|
|
19
|
+
logger.debug(f"Skipping registration for abstract tool execution result processor class: {name}")
|
|
20
|
+
return
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
processor_name = cls.get_name()
|
|
24
|
+
|
|
25
|
+
if not processor_name or not isinstance(processor_name, str):
|
|
26
|
+
logger.error(f"Tool execution result processor class {name} must return a valid string from get_name(). Skipping.")
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
definition = ToolExecutionResultProcessorDefinition(name=processor_name, processor_class=cls)
|
|
30
|
+
default_tool_execution_result_processor_registry.register_processor(definition)
|
|
31
|
+
logger.info(f"Auto-registered tool execution result processor: '{processor_name}' from class {name}.")
|
|
32
|
+
|
|
33
|
+
except AttributeError as e:
|
|
34
|
+
logger.error(f"Tool execution result processor class {name} is missing 'get_name' method ({e}). Skipping registration.")
|
|
35
|
+
except Exception as e:
|
|
36
|
+
logger.error(f"Failed to auto-register tool execution result processor class {name}: {e}", exc_info=True)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/agent/tool_execution_result_processor/processor_registry.py
|
|
2
|
+
import logging
|
|
3
|
+
from typing import TYPE_CHECKING, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from autobyteus.utils.singleton import SingletonMeta
|
|
6
|
+
from .processor_definition import ToolExecutionResultProcessorDefinition
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from .base_processor import BaseToolExecutionResultProcessor
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
class ToolExecutionResultProcessorRegistry(metaclass=SingletonMeta):
|
|
14
|
+
"""
|
|
15
|
+
A singleton registry for ToolExecutionResultProcessorDefinition objects.
|
|
16
|
+
Processors are typically auto-registered via ToolExecutionResultProcessorMeta.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
"""Initializes the registry with an empty store."""
|
|
21
|
+
self._definitions: Dict[str, ToolExecutionResultProcessorDefinition] = {}
|
|
22
|
+
logger.info("ToolExecutionResultProcessorRegistry initialized.")
|
|
23
|
+
|
|
24
|
+
def register_processor(self, definition: ToolExecutionResultProcessorDefinition) -> None:
|
|
25
|
+
"""
|
|
26
|
+
Registers a tool execution result processor definition.
|
|
27
|
+
"""
|
|
28
|
+
if not isinstance(definition, ToolExecutionResultProcessorDefinition):
|
|
29
|
+
raise TypeError(f"Expected ToolExecutionResultProcessorDefinition instance, got {type(definition).__name__}.")
|
|
30
|
+
|
|
31
|
+
processor_name = definition.name
|
|
32
|
+
if processor_name in self._definitions:
|
|
33
|
+
logger.warning(f"Overwriting existing tool execution result processor definition for name: '{processor_name}'.")
|
|
34
|
+
|
|
35
|
+
self._definitions[processor_name] = definition
|
|
36
|
+
logger.info(f"Tool execution result processor definition '{processor_name}' registered successfully.")
|
|
37
|
+
|
|
38
|
+
def get_processor_definition(self, name: str) -> Optional[ToolExecutionResultProcessorDefinition]:
|
|
39
|
+
"""
|
|
40
|
+
Retrieves a processor definition by its name.
|
|
41
|
+
"""
|
|
42
|
+
return self._definitions.get(name)
|
|
43
|
+
|
|
44
|
+
def get_processor(self, name: str) -> Optional['BaseToolExecutionResultProcessor']:
|
|
45
|
+
"""
|
|
46
|
+
Retrieves an instance of a processor by its name.
|
|
47
|
+
"""
|
|
48
|
+
definition = self.get_processor_definition(name)
|
|
49
|
+
if definition:
|
|
50
|
+
try:
|
|
51
|
+
return definition.processor_class()
|
|
52
|
+
except Exception as e:
|
|
53
|
+
logger.error(f"Failed to instantiate tool execution result processor '{name}': {e}", exc_info=True)
|
|
54
|
+
return None
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
def list_processor_names(self) -> List[str]:
|
|
58
|
+
"""
|
|
59
|
+
Returns a list of names of all registered processor definitions.
|
|
60
|
+
"""
|
|
61
|
+
return list(self._definitions.keys())
|
|
62
|
+
|
|
63
|
+
def get_all_definitions(self) -> Dict[str, ToolExecutionResultProcessorDefinition]:
|
|
64
|
+
"""
|
|
65
|
+
Returns a dictionary of all registered processor definitions.
|
|
66
|
+
"""
|
|
67
|
+
return dict(self._definitions)
|
|
68
|
+
|
|
69
|
+
# Default instance of the registry
|
|
70
|
+
default_tool_execution_result_processor_registry = ToolExecutionResultProcessorRegistry()
|