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,33 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/agent/input_processor/passthrough_input_processor.py
|
|
2
|
-
import logging
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
|
-
from .base_user_input_processor import BaseAgentUserInputMessageProcessor
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from autobyteus.agent.message.agent_input_user_message import AgentInputUserMessage
|
|
9
|
-
from autobyteus.agent.context import AgentContext # Composite AgentContext
|
|
10
|
-
from autobyteus.agent.events import UserMessageReceivedEvent
|
|
11
|
-
|
|
12
|
-
logger = logging.getLogger(__name__)
|
|
13
|
-
|
|
14
|
-
class PassthroughInputProcessor(BaseAgentUserInputMessageProcessor):
|
|
15
|
-
"""
|
|
16
|
-
A processor that returns the message unchanged.
|
|
17
|
-
Can be used as a default or for testing.
|
|
18
|
-
"""
|
|
19
|
-
@classmethod
|
|
20
|
-
def get_name(cls) -> str:
|
|
21
|
-
return "PassthroughInputProcessor"
|
|
22
|
-
|
|
23
|
-
async def process(self,
|
|
24
|
-
message: 'AgentInputUserMessage',
|
|
25
|
-
context: 'AgentContext',
|
|
26
|
-
triggering_event: 'UserMessageReceivedEvent') -> 'AgentInputUserMessage':
|
|
27
|
-
"""
|
|
28
|
-
Handles the message by returning it without modification.
|
|
29
|
-
The 'triggering_event' parameter is ignored by this processor.
|
|
30
|
-
"""
|
|
31
|
-
agent_id = context.agent_id # Convenience property
|
|
32
|
-
logger.debug(f"Agent '{agent_id}': PassthroughInputProcessor received message, returning as is.")
|
|
33
|
-
return message
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/agent/workflow/__init__.py
|
|
2
|
-
"""
|
|
3
|
-
Components for defining and running agentic workflows.
|
|
4
|
-
"""
|
|
5
|
-
from .agentic_workflow import AgenticWorkflow
|
|
6
|
-
from .base_agentic_workflow import BaseAgenticWorkflow
|
|
7
|
-
|
|
8
|
-
__all__ = [
|
|
9
|
-
"AgenticWorkflow",
|
|
10
|
-
"BaseAgenticWorkflow",
|
|
11
|
-
]
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/agent/workflow/agentic_workflow.py
|
|
2
|
-
import logging
|
|
3
|
-
import uuid
|
|
4
|
-
from typing import List, Dict, Optional, Any, cast
|
|
5
|
-
|
|
6
|
-
from autobyteus.agent.context.agent_config import AgentConfig
|
|
7
|
-
from autobyteus.agent.group.agent_group import AgentGroup
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger(__name__)
|
|
10
|
-
|
|
11
|
-
class AgenticWorkflow:
|
|
12
|
-
"""
|
|
13
|
-
A concrete class for defining and running multi-agent workflows declaratively.
|
|
14
|
-
It internally manages an AgentGroup and provides a user-friendly interface
|
|
15
|
-
to process tasks.
|
|
16
|
-
"""
|
|
17
|
-
def __init__(self,
|
|
18
|
-
agent_configs: List[AgentConfig],
|
|
19
|
-
coordinator_config_name: str,
|
|
20
|
-
workflow_id: Optional[str] = None,
|
|
21
|
-
input_param_name: str = "input",
|
|
22
|
-
):
|
|
23
|
-
"""
|
|
24
|
-
Initializes the AgenticWorkflow.
|
|
25
|
-
|
|
26
|
-
Args:
|
|
27
|
-
agent_configs: List of pre-made AgentConfig instances for the agents in this workflow.
|
|
28
|
-
coordinator_config_name: Name of the agent config to be used as coordinator.
|
|
29
|
-
workflow_id: Optional. A unique ID for this workflow instance. Auto-generated if None.
|
|
30
|
-
input_param_name: The key to use in `process(**kwargs)` to find the initial
|
|
31
|
-
input string for the coordinator. Defaults to "input".
|
|
32
|
-
"""
|
|
33
|
-
self.workflow_id: str = workflow_id or f"workflow_{uuid.uuid4()}"
|
|
34
|
-
self._input_param_name: str = input_param_name
|
|
35
|
-
|
|
36
|
-
logger.info(f"Initializing AgenticWorkflow '{self.workflow_id}'. "
|
|
37
|
-
f"Input parameter name for process(): '{self._input_param_name}'.")
|
|
38
|
-
|
|
39
|
-
# The AgentGroup is now initialized directly with the user-provided configs.
|
|
40
|
-
self.agent_group: AgentGroup = AgentGroup(
|
|
41
|
-
agent_configs=agent_configs,
|
|
42
|
-
coordinator_config_name=coordinator_config_name,
|
|
43
|
-
group_id=f"group_for_{self.workflow_id}",
|
|
44
|
-
)
|
|
45
|
-
logger.info(f"AgenticWorkflow '{self.workflow_id}' successfully instantiated internal AgentGroup '{self.agent_group.group_id}'.")
|
|
46
|
-
|
|
47
|
-
async def process(self, **kwargs: Any) -> Any:
|
|
48
|
-
logger.info(f"AgenticWorkflow '{self.workflow_id}' received process request with kwargs: {list(kwargs.keys())}")
|
|
49
|
-
|
|
50
|
-
initial_input_content = kwargs.get(self._input_param_name)
|
|
51
|
-
if initial_input_content is None:
|
|
52
|
-
raise ValueError(f"Required input parameter '{self._input_param_name}' not found in process() arguments.")
|
|
53
|
-
if not isinstance(initial_input_content, str):
|
|
54
|
-
raise ValueError(f"Input parameter '{self._input_param_name}' must be a string, "
|
|
55
|
-
f"got {type(initial_input_content).__name__}.")
|
|
56
|
-
|
|
57
|
-
user_id: Optional[str] = cast(Optional[str], kwargs.get("user_id")) if isinstance(kwargs.get("user_id"), str) else None
|
|
58
|
-
|
|
59
|
-
logger.debug(f"AgenticWorkflow '{self.workflow_id}': Extracted initial input for coordinator: '{initial_input_content[:100]}...'")
|
|
60
|
-
|
|
61
|
-
result = await self.agent_group.process_task_for_coordinator(
|
|
62
|
-
initial_input_content=initial_input_content,
|
|
63
|
-
user_id=user_id
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
return result
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
async def start(self) -> None:
|
|
70
|
-
logger.info(f"AgenticWorkflow '{self.workflow_id}' received start() request. Delegating to AgentGroup.")
|
|
71
|
-
await self.agent_group.start()
|
|
72
|
-
|
|
73
|
-
async def stop(self, timeout: float = 10.0) -> None:
|
|
74
|
-
logger.info(f"AgenticWorkflow '{self.workflow_id}' received stop() request. Delegating to AgentGroup.")
|
|
75
|
-
await self.agent_group.stop(timeout)
|
|
76
|
-
|
|
77
|
-
@property
|
|
78
|
-
def is_running(self) -> bool:
|
|
79
|
-
return self.agent_group.is_running
|
|
80
|
-
|
|
81
|
-
@property
|
|
82
|
-
def group_id(self) -> str:
|
|
83
|
-
return self.agent_group.group_id
|
|
84
|
-
|
|
85
|
-
def __repr__(self) -> str:
|
|
86
|
-
return (f"<AgenticWorkflow workflow_id='{self.workflow_id}', "
|
|
87
|
-
f"group_id='{self.agent_group.group_id}', "
|
|
88
|
-
f"coordinator='{self.agent_group.coordinator_config_name}', "
|
|
89
|
-
f"is_running={self.is_running}>")
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/tools/mcp/call_handlers/__init__.py
|
|
2
|
-
"""
|
|
3
|
-
This package contains the MCP Call Handlers.
|
|
4
|
-
Each handler is responsible for performing a complete, end-to-end tool call
|
|
5
|
-
for a specific transport protocol (e.g., STDIO, Streamable HTTP).
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from .base_handler import McpCallHandler
|
|
9
|
-
from .stdio_handler import StdioMcpCallHandler
|
|
10
|
-
from .streamable_http_handler import StreamableHttpMcpCallHandler
|
|
11
|
-
|
|
12
|
-
__all__ = [
|
|
13
|
-
"McpCallHandler",
|
|
14
|
-
"StdioMcpCallHandler",
|
|
15
|
-
"StreamableHttpMcpCallHandler",
|
|
16
|
-
]
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/tools/mcp/call_handlers/base_handler.py
|
|
2
|
-
import logging
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
from typing import Dict, Any, TYPE_CHECKING
|
|
5
|
-
|
|
6
|
-
if TYPE_CHECKING:
|
|
7
|
-
from ..types import BaseMcpConfig
|
|
8
|
-
|
|
9
|
-
logger = logging.getLogger(__name__)
|
|
10
|
-
|
|
11
|
-
class McpCallHandler(ABC):
|
|
12
|
-
"""
|
|
13
|
-
Abstract base class for a handler that performs a single, end-to-end
|
|
14
|
-
MCP tool call for a specific transport protocol.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
@abstractmethod
|
|
18
|
-
async def handle_call(
|
|
19
|
-
self,
|
|
20
|
-
config: 'BaseMcpConfig',
|
|
21
|
-
remote_tool_name: str,
|
|
22
|
-
arguments: Dict[str, Any]
|
|
23
|
-
) -> Any:
|
|
24
|
-
"""
|
|
25
|
-
Handles a complete MCP tool call, including connection, execution,
|
|
26
|
-
and disconnection if necessary.
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
config: The configuration object for the target MCP server.
|
|
30
|
-
remote_tool_name: The name of the tool to call on the remote server.
|
|
31
|
-
arguments: A dictionary of arguments for the tool call.
|
|
32
|
-
|
|
33
|
-
Returns:
|
|
34
|
-
The result returned by the remote tool.
|
|
35
|
-
|
|
36
|
-
Raises:
|
|
37
|
-
NotImplementedError: If the handler for a specific transport is not implemented.
|
|
38
|
-
RuntimeError: If the tool call fails for any reason.
|
|
39
|
-
"""
|
|
40
|
-
pass
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/tools/mcp/call_handlers/stdio_handler.py
|
|
2
|
-
import logging
|
|
3
|
-
import asyncio
|
|
4
|
-
from typing import Dict, Any, cast, TYPE_CHECKING
|
|
5
|
-
|
|
6
|
-
from .base_handler import McpCallHandler
|
|
7
|
-
from mcp import StdioServerParameters, ClientSession
|
|
8
|
-
from mcp.client.stdio import stdio_client
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from ..types import BaseMcpConfig, StdioMcpServerConfig
|
|
12
|
-
|
|
13
|
-
logger = logging.getLogger(__name__)
|
|
14
|
-
|
|
15
|
-
# A default timeout for STDIO subprocesses to prevent indefinite hangs.
|
|
16
|
-
DEFAULT_STDIO_TIMEOUT = 30 # seconds
|
|
17
|
-
|
|
18
|
-
class StdioMcpCallHandler(McpCallHandler):
|
|
19
|
-
"""Handles MCP tool calls over a stateless STDIO transport."""
|
|
20
|
-
|
|
21
|
-
async def handle_call(
|
|
22
|
-
self,
|
|
23
|
-
config: 'BaseMcpConfig',
|
|
24
|
-
remote_tool_name: str,
|
|
25
|
-
arguments: Dict[str, Any]
|
|
26
|
-
) -> Any:
|
|
27
|
-
"""
|
|
28
|
-
Creates a new subprocess, establishes a session, and executes the
|
|
29
|
-
requested tool call. It handles 'list_tools' as a special case.
|
|
30
|
-
Includes a timeout to prevent hanging on unresponsive subprocesses.
|
|
31
|
-
"""
|
|
32
|
-
logger.debug(f"Handling STDIO call to tool '{remote_tool_name}' on server '{config.server_id}'.")
|
|
33
|
-
|
|
34
|
-
from ..types import StdioMcpServerConfig
|
|
35
|
-
if not isinstance(config, StdioMcpServerConfig):
|
|
36
|
-
raise TypeError(f"StdioMcpCallHandler requires a StdioMcpServerConfig, but got {type(config).__name__}.")
|
|
37
|
-
|
|
38
|
-
stdio_config = cast(StdioMcpServerConfig, config)
|
|
39
|
-
|
|
40
|
-
mcp_lib_stdio_params = StdioServerParameters(
|
|
41
|
-
command=stdio_config.command,
|
|
42
|
-
args=stdio_config.args,
|
|
43
|
-
env=stdio_config.env,
|
|
44
|
-
cwd=stdio_config.cwd
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
async def _perform_call():
|
|
48
|
-
"""Inner function to be wrapped by the timeout."""
|
|
49
|
-
# The stdio_client context manager provides the read/write streams.
|
|
50
|
-
async with stdio_client(mcp_lib_stdio_params) as (read_stream, write_stream):
|
|
51
|
-
# The ClientSession is its own context manager that handles initialization.
|
|
52
|
-
async with ClientSession(read_stream, write_stream) as session:
|
|
53
|
-
logger.debug(f"STDIO session established for '{config.server_id}'. Calling tool '{remote_tool_name}'.")
|
|
54
|
-
|
|
55
|
-
# The 'list_tools' command is a special method on the session.
|
|
56
|
-
if remote_tool_name == "list_tools":
|
|
57
|
-
result = await session.list_tools()
|
|
58
|
-
else:
|
|
59
|
-
result = await session.call_tool(remote_tool_name, arguments)
|
|
60
|
-
|
|
61
|
-
logger.debug(f"STDIO call to tool '{remote_tool_name}' on server '{config.server_id}' completed.")
|
|
62
|
-
return result
|
|
63
|
-
|
|
64
|
-
try:
|
|
65
|
-
return await asyncio.wait_for(_perform_call(), timeout=DEFAULT_STDIO_TIMEOUT)
|
|
66
|
-
except asyncio.TimeoutError:
|
|
67
|
-
error_message = (f"MCP call to '{remote_tool_name}' on server '{config.server_id}' timed out "
|
|
68
|
-
f"after {DEFAULT_STDIO_TIMEOUT} seconds. The subprocess may have hung.")
|
|
69
|
-
logger.error(error_message)
|
|
70
|
-
raise RuntimeError(error_message) from None
|
|
71
|
-
except Exception as e:
|
|
72
|
-
logger.error(
|
|
73
|
-
f"An error occurred during STDIO tool call to '{remote_tool_name}' on server '{config.server_id}': {e}",
|
|
74
|
-
exc_info=True
|
|
75
|
-
)
|
|
76
|
-
raise RuntimeError(f"Failed to execute MCP tool '{remote_tool_name}' via STDIO on server '{config.server_id}': {e}") from e
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/tools/mcp/call_handlers/streamable_http_handler.py
|
|
2
|
-
import logging
|
|
3
|
-
from typing import Dict, Any, cast, TYPE_CHECKING
|
|
4
|
-
|
|
5
|
-
from .base_handler import McpCallHandler
|
|
6
|
-
from mcp import ClientSession
|
|
7
|
-
from mcp.client.streamable_http import streamablehttp_client
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from ..types import BaseMcpConfig, StreamableHttpMcpServerConfig
|
|
11
|
-
|
|
12
|
-
logger = logging.getLogger(__name__)
|
|
13
|
-
|
|
14
|
-
class StreamableHttpMcpCallHandler(McpCallHandler):
|
|
15
|
-
"""Handles MCP tool calls over a stateless Streamable HTTP transport."""
|
|
16
|
-
|
|
17
|
-
async def handle_call(
|
|
18
|
-
self,
|
|
19
|
-
config: 'BaseMcpConfig',
|
|
20
|
-
remote_tool_name: str,
|
|
21
|
-
arguments: Dict[str, Any]
|
|
22
|
-
) -> Any:
|
|
23
|
-
"""
|
|
24
|
-
Creates a new HTTP connection, establishes a session, and executes the
|
|
25
|
-
requested tool call. It handles 'list_tools' as a special case.
|
|
26
|
-
"""
|
|
27
|
-
logger.debug(f"Handling Streamable HTTP call to tool '{remote_tool_name}' on server '{config.server_id}'.")
|
|
28
|
-
|
|
29
|
-
from ..types import StreamableHttpMcpServerConfig
|
|
30
|
-
if not isinstance(config, StreamableHttpMcpServerConfig):
|
|
31
|
-
raise TypeError(f"StreamableHttpMcpCallHandler requires a StreamableHttpMcpServerConfig, got {type(config).__name__}.")
|
|
32
|
-
|
|
33
|
-
http_config = cast(StreamableHttpMcpServerConfig, config)
|
|
34
|
-
|
|
35
|
-
try:
|
|
36
|
-
# The streamablehttp_client context manager provides the read/write streams.
|
|
37
|
-
async with streamablehttp_client(http_config.url, headers=http_config.headers) as (read_stream, write_stream):
|
|
38
|
-
# The ClientSession is its own context manager that handles initialization.
|
|
39
|
-
async with ClientSession(read_stream, write_stream) as session:
|
|
40
|
-
logger.debug(f"Streamable HTTP session established for '{config.server_id}'. Calling tool '{remote_tool_name}'.")
|
|
41
|
-
|
|
42
|
-
# The 'list_tools' command is a special method on the session.
|
|
43
|
-
if remote_tool_name == "list_tools":
|
|
44
|
-
result = await session.list_tools()
|
|
45
|
-
else:
|
|
46
|
-
result = await session.call_tool(remote_tool_name, arguments)
|
|
47
|
-
|
|
48
|
-
logger.debug(f"Streamable HTTP call to tool '{remote_tool_name}' on server '{config.server_id}' completed.")
|
|
49
|
-
return result
|
|
50
|
-
except Exception as e:
|
|
51
|
-
logger.error(
|
|
52
|
-
f"An error occurred during Streamable HTTP tool call to '{remote_tool_name}' on server '{config.server_id}': {e}",
|
|
53
|
-
exc_info=True
|
|
54
|
-
)
|
|
55
|
-
raise RuntimeError(f"Failed to execute MCP tool '{remote_tool_name}' via Streamable HTTP on server '{config.server_id}': {e}") from e
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/tools/mcp/registrar.py
|
|
2
|
-
import logging
|
|
3
|
-
from typing import Any, Dict, List, Optional, Union
|
|
4
|
-
|
|
5
|
-
# Consolidated imports from the autobyteus.autobyteus.mcp package public API
|
|
6
|
-
from .config_service import McpConfigService
|
|
7
|
-
from .factory import McpToolFactory
|
|
8
|
-
from .schema_mapper import McpSchemaMapper
|
|
9
|
-
from .types import BaseMcpConfig, McpTransportType
|
|
10
|
-
from .server import StdioManagedMcpServer, HttpManagedMcpServer, BaseManagedMcpServer
|
|
11
|
-
|
|
12
|
-
from autobyteus.tools.registry import ToolRegistry, ToolDefinition
|
|
13
|
-
from autobyteus.tools.tool_category import ToolCategory
|
|
14
|
-
from autobyteus.utils.singleton import SingletonMeta
|
|
15
|
-
from mcp import types as mcp_types
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
logger = logging.getLogger(__name__)
|
|
19
|
-
|
|
20
|
-
class McpToolRegistrar(metaclass=SingletonMeta):
|
|
21
|
-
"""
|
|
22
|
-
Orchestrates the discovery of remote MCP tools and their registration
|
|
23
|
-
with the AutoByteUs ToolRegistry using a stateful, server-centric architecture.
|
|
24
|
-
"""
|
|
25
|
-
def __init__(self):
|
|
26
|
-
"""
|
|
27
|
-
Initializes the McpToolRegistrar singleton.
|
|
28
|
-
"""
|
|
29
|
-
self._config_service: McpConfigService = McpConfigService()
|
|
30
|
-
self._tool_registry: ToolRegistry = ToolRegistry()
|
|
31
|
-
self._registered_tools_by_server: Dict[str, List[ToolDefinition]] = {}
|
|
32
|
-
logger.info("McpToolRegistrar initialized.")
|
|
33
|
-
|
|
34
|
-
def _create_server_instance_for_discovery(self, server_config: BaseMcpConfig) -> BaseManagedMcpServer:
|
|
35
|
-
"""Creates a server instance based on transport type."""
|
|
36
|
-
if server_config.transport_type == McpTransportType.STDIO:
|
|
37
|
-
return StdioManagedMcpServer(server_config)
|
|
38
|
-
elif server_config.transport_type == McpTransportType.STREAMABLE_HTTP:
|
|
39
|
-
return HttpManagedMcpServer(server_config)
|
|
40
|
-
else:
|
|
41
|
-
raise NotImplementedError(f"Discovery not implemented for transport type: {server_config.transport_type}")
|
|
42
|
-
|
|
43
|
-
async def _fetch_tools_from_server(self, server_config: BaseMcpConfig) -> List[mcp_types.Tool]:
|
|
44
|
-
"""
|
|
45
|
-
Creates a temporary server instance to perform a single, one-shot
|
|
46
|
-
tool discovery, ensuring resources are properly closed.
|
|
47
|
-
"""
|
|
48
|
-
discovery_server = self._create_server_instance_for_discovery(server_config)
|
|
49
|
-
try:
|
|
50
|
-
# The list_remote_tools method implicitly handles the connection.
|
|
51
|
-
remote_tools = await discovery_server.list_remote_tools()
|
|
52
|
-
return remote_tools
|
|
53
|
-
finally:
|
|
54
|
-
# The finally block guarantees the temporary server connection is closed.
|
|
55
|
-
await discovery_server.close()
|
|
56
|
-
|
|
57
|
-
def _create_tool_definition_from_remote(
|
|
58
|
-
self,
|
|
59
|
-
remote_tool: mcp_types.Tool,
|
|
60
|
-
server_config: BaseMcpConfig,
|
|
61
|
-
schema_mapper: McpSchemaMapper
|
|
62
|
-
) -> ToolDefinition:
|
|
63
|
-
"""
|
|
64
|
-
Maps a single remote tool from an MCP server to an AutoByteUs ToolDefinition.
|
|
65
|
-
"""
|
|
66
|
-
if hasattr(remote_tool, 'model_dump_json'):
|
|
67
|
-
logger.debug(f"Processing remote tool from server '{server_config.server_id}':\n{remote_tool.model_dump_json(indent=2)}")
|
|
68
|
-
|
|
69
|
-
actual_arg_schema = schema_mapper.map_to_autobyteus_schema(remote_tool.inputSchema)
|
|
70
|
-
actual_desc = remote_tool.description
|
|
71
|
-
|
|
72
|
-
registered_name = remote_tool.name
|
|
73
|
-
if server_config.tool_name_prefix:
|
|
74
|
-
registered_name = f"{server_config.tool_name_prefix.rstrip('_')}_{remote_tool.name}"
|
|
75
|
-
|
|
76
|
-
# The factory now only needs key identifiers, not live objects.
|
|
77
|
-
tool_factory = McpToolFactory(
|
|
78
|
-
server_id=server_config.server_id,
|
|
79
|
-
remote_tool_name=remote_tool.name,
|
|
80
|
-
registered_tool_name=registered_name,
|
|
81
|
-
tool_description=actual_desc,
|
|
82
|
-
tool_argument_schema=actual_arg_schema
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
return ToolDefinition(
|
|
86
|
-
name=registered_name,
|
|
87
|
-
description=actual_desc,
|
|
88
|
-
argument_schema=actual_arg_schema,
|
|
89
|
-
category=ToolCategory.MCP,
|
|
90
|
-
custom_factory=tool_factory.create_tool,
|
|
91
|
-
config_schema=None,
|
|
92
|
-
tool_class=None
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
async def discover_and_register_tools(self, mcp_config: Optional[Union[BaseMcpConfig, Dict[str, Any]]] = None) -> List[ToolDefinition]:
|
|
96
|
-
"""
|
|
97
|
-
Discovers tools from MCP servers and registers them.
|
|
98
|
-
This process uses a helper to manage short-lived server instances for discovery.
|
|
99
|
-
"""
|
|
100
|
-
configs_to_process: List[BaseMcpConfig]
|
|
101
|
-
|
|
102
|
-
if mcp_config:
|
|
103
|
-
if isinstance(mcp_config, dict):
|
|
104
|
-
configs_to_process = [self._config_service.load_config(mcp_config)]
|
|
105
|
-
elif isinstance(mcp_config, BaseMcpConfig):
|
|
106
|
-
configs_to_process = [self._config_service.add_config(mcp_config)]
|
|
107
|
-
else:
|
|
108
|
-
raise TypeError(f"mcp_config must be a BaseMcpConfig object or a dictionary, not {type(mcp_config)}.")
|
|
109
|
-
logger.info(f"Starting targeted MCP tool discovery for server: {configs_to_process[0].server_id}")
|
|
110
|
-
self.unregister_tools_from_server(configs_to_process[0].server_id)
|
|
111
|
-
else:
|
|
112
|
-
logger.info("Starting full MCP tool discovery. Unregistering all existing MCP tools first.")
|
|
113
|
-
all_server_ids = list(self._registered_tools_by_server.keys())
|
|
114
|
-
for server_id in all_server_ids:
|
|
115
|
-
self.unregister_tools_from_server(server_id)
|
|
116
|
-
self._registered_tools_by_server.clear()
|
|
117
|
-
configs_to_process = self._config_service.get_all_configs()
|
|
118
|
-
|
|
119
|
-
if not configs_to_process:
|
|
120
|
-
logger.info("No MCP server configurations to process. Skipping discovery.")
|
|
121
|
-
return []
|
|
122
|
-
|
|
123
|
-
schema_mapper = McpSchemaMapper()
|
|
124
|
-
registered_tool_definitions: List[ToolDefinition] = []
|
|
125
|
-
for server_config in configs_to_process:
|
|
126
|
-
if not server_config.enabled:
|
|
127
|
-
logger.info(f"MCP server '{server_config.server_id}' is disabled. Skipping.")
|
|
128
|
-
continue
|
|
129
|
-
|
|
130
|
-
logger.info(f"Discovering tools from MCP server: '{server_config.server_id}' ({server_config.transport_type.value})")
|
|
131
|
-
|
|
132
|
-
try:
|
|
133
|
-
# The helper abstracts away the connect/close lifecycle for discovery.
|
|
134
|
-
remote_tools = await self._fetch_tools_from_server(server_config)
|
|
135
|
-
logger.info(f"Discovered {len(remote_tools)} tools from server '{server_config.server_id}'.")
|
|
136
|
-
|
|
137
|
-
for remote_tool in remote_tools:
|
|
138
|
-
try:
|
|
139
|
-
tool_def = self._create_tool_definition_from_remote(remote_tool, server_config, schema_mapper)
|
|
140
|
-
self._tool_registry.register_tool(tool_def)
|
|
141
|
-
self._registered_tools_by_server.setdefault(server_config.server_id, []).append(tool_def)
|
|
142
|
-
registered_tool_definitions.append(tool_def)
|
|
143
|
-
logger.info(f"Successfully registered MCP tool '{remote_tool.name}' from server '{server_config.server_id}' as '{tool_def.name}'.")
|
|
144
|
-
except Exception as e_tool:
|
|
145
|
-
logger.error(f"Failed to process or register remote tool '{remote_tool.name}': {e_tool}", exc_info=True)
|
|
146
|
-
|
|
147
|
-
except Exception as e_server:
|
|
148
|
-
logger.error(f"Failed to discover tools from MCP server '{server_config.server_id}': {e_server}", exc_info=True)
|
|
149
|
-
|
|
150
|
-
logger.info(f"MCP tool discovery and registration process completed. Total tools registered: {len(registered_tool_definitions)}.")
|
|
151
|
-
return registered_tool_definitions
|
|
152
|
-
|
|
153
|
-
async def list_remote_tools(self, mcp_config: Union[BaseMcpConfig, Dict[str, Any]]) -> List[ToolDefinition]:
|
|
154
|
-
"""
|
|
155
|
-
Previews tools from a remote MCP server without registering them.
|
|
156
|
-
This is a stateless "dry-run" or "preview" operation.
|
|
157
|
-
"""
|
|
158
|
-
validated_config: BaseMcpConfig
|
|
159
|
-
if isinstance(mcp_config, dict):
|
|
160
|
-
validated_config = McpConfigService.parse_mcp_config_dict(mcp_config)
|
|
161
|
-
elif isinstance(mcp_config, BaseMcpConfig):
|
|
162
|
-
validated_config = mcp_config
|
|
163
|
-
else:
|
|
164
|
-
raise TypeError(f"mcp_config must be a BaseMcpConfig object or a dictionary, not {type(mcp_config)}.")
|
|
165
|
-
|
|
166
|
-
logger.info(f"Previewing tools from MCP server: '{validated_config.server_id}' ({validated_config.transport_type.value})")
|
|
167
|
-
|
|
168
|
-
schema_mapper = McpSchemaMapper()
|
|
169
|
-
tool_definitions: List[ToolDefinition] = []
|
|
170
|
-
|
|
171
|
-
try:
|
|
172
|
-
# Use the same helper to fetch tools, abstracting away the connection lifecycle.
|
|
173
|
-
remote_tools = await self._fetch_tools_from_server(validated_config)
|
|
174
|
-
logger.info(f"Discovered {len(remote_tools)} tools from server '{validated_config.server_id}' for preview.")
|
|
175
|
-
|
|
176
|
-
for remote_tool in remote_tools:
|
|
177
|
-
try:
|
|
178
|
-
tool_def = self._create_tool_definition_from_remote(remote_tool, validated_config, schema_mapper)
|
|
179
|
-
tool_definitions.append(tool_def)
|
|
180
|
-
except Exception as e_tool:
|
|
181
|
-
logger.error(f"Failed to map remote tool '{remote_tool.name}' from server '{validated_config.server_id}' during preview: {e_tool}", exc_info=True)
|
|
182
|
-
|
|
183
|
-
except Exception as e_server:
|
|
184
|
-
logger.error(f"Failed to discover tools for preview from MCP server '{validated_config.server_id}': {e_server}", exc_info=True)
|
|
185
|
-
raise
|
|
186
|
-
|
|
187
|
-
logger.info(f"MCP tool preview completed. Found {len(tool_definitions)} tools.")
|
|
188
|
-
return tool_definitions
|
|
189
|
-
|
|
190
|
-
def unregister_tools_from_server(self, server_id: str) -> bool:
|
|
191
|
-
if not self.is_server_registered(server_id):
|
|
192
|
-
logger.info(f"No tools found for server ID '{server_id}'. Nothing to unregister.")
|
|
193
|
-
return False
|
|
194
|
-
tools_to_unregister = self._registered_tools_by_server.pop(server_id, [])
|
|
195
|
-
logger.info(f"Unregistering {len(tools_to_unregister)} tools from server ID: '{server_id}'...")
|
|
196
|
-
for tool_def in tools_to_unregister:
|
|
197
|
-
self._tool_registry.unregister_tool(tool_def.name)
|
|
198
|
-
logger.info(f"Successfully unregistered all tools and removed server '{server_id}' from registrar tracking.")
|
|
199
|
-
return True
|
|
200
|
-
|
|
201
|
-
def is_server_registered(self, server_id: str) -> bool:
|
|
202
|
-
return server_id in self._registered_tools_by_server
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/tools/usage/providers/json_example_provider.py
|
|
2
|
-
from typing import Optional, Any, TYPE_CHECKING
|
|
3
|
-
|
|
4
|
-
from autobyteus.llm.providers import LLMProvider
|
|
5
|
-
from autobyteus.tools.usage.registries.json_example_formatter_registry import JsonExampleFormatterRegistry
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from autobyteus.tools.registry import ToolDefinition
|
|
9
|
-
|
|
10
|
-
class JsonExampleProvider:
|
|
11
|
-
"""Provides a tool usage example as a JSON dictionary for a specific LLM provider."""
|
|
12
|
-
|
|
13
|
-
def __init__(self):
|
|
14
|
-
self._registry = JsonExampleFormatterRegistry()
|
|
15
|
-
|
|
16
|
-
def provide(self, tool_definition: 'ToolDefinition', llm_provider: Optional[LLMProvider] = None) -> Any:
|
|
17
|
-
"""
|
|
18
|
-
Generates a JSON dictionary or string for a single tool usage example.
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
tool_definition: A ToolDefinition object.
|
|
22
|
-
llm_provider: The LLMProvider for which to format the JSON.
|
|
23
|
-
|
|
24
|
-
Returns:
|
|
25
|
-
A dictionary or string representing the tool usage example.
|
|
26
|
-
"""
|
|
27
|
-
if llm_provider:
|
|
28
|
-
formatter = self._registry.get_formatter(llm_provider)
|
|
29
|
-
else:
|
|
30
|
-
formatter = self._registry.get_default_formatter()
|
|
31
|
-
|
|
32
|
-
return formatter.provide(tool_definition)
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/tools/usage/providers/json_schema_provider.py
|
|
2
|
-
from typing import Optional, Dict, TYPE_CHECKING
|
|
3
|
-
|
|
4
|
-
from autobyteus.llm.providers import LLMProvider
|
|
5
|
-
from autobyteus.tools.usage.registries.json_schema_formatter_registry import JsonSchemaFormatterRegistry
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from autobyteus.tools.registry import ToolDefinition
|
|
9
|
-
|
|
10
|
-
class JsonSchemaProvider:
|
|
11
|
-
"""
|
|
12
|
-
Provides the schema for a single tool formatted as a JSON dictionary,
|
|
13
|
-
tailored to the specific LLM provider's requirements.
|
|
14
|
-
"""
|
|
15
|
-
def __init__(self):
|
|
16
|
-
self._registry = JsonSchemaFormatterRegistry()
|
|
17
|
-
|
|
18
|
-
def provide(self, tool_definition: 'ToolDefinition', llm_provider: Optional[LLMProvider] = None) -> Dict:
|
|
19
|
-
"""
|
|
20
|
-
Generates a JSON dictionary for a single tool's schema.
|
|
21
|
-
|
|
22
|
-
Args:
|
|
23
|
-
tool_definition: A ToolDefinition object.
|
|
24
|
-
llm_provider: The LLMProvider for which to format the JSON. If None,
|
|
25
|
-
a default generic format is used.
|
|
26
|
-
|
|
27
|
-
Returns:
|
|
28
|
-
A dictionary representing the tool schema.
|
|
29
|
-
"""
|
|
30
|
-
if llm_provider:
|
|
31
|
-
formatter = self._registry.get_formatter(llm_provider)
|
|
32
|
-
else:
|
|
33
|
-
formatter = self._registry.get_default_formatter()
|
|
34
|
-
|
|
35
|
-
return formatter.provide(tool_definition)
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/tools/usage/providers/json_tool_usage_parser_provider.py
|
|
2
|
-
from typing import Optional, TYPE_CHECKING
|
|
3
|
-
|
|
4
|
-
from autobyteus.llm.providers import LLMProvider
|
|
5
|
-
from autobyteus.tools.usage.registries.json_tool_usage_parser_registry import JsonToolUsageParserRegistry
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from autobyteus.tools.usage.parsers.base_parser import BaseToolUsageParser
|
|
9
|
-
|
|
10
|
-
class JsonToolUsageParserProvider:
|
|
11
|
-
"""Provides a tool usage parser for JSON-based responses, specific to an LLM provider."""
|
|
12
|
-
|
|
13
|
-
def __init__(self):
|
|
14
|
-
self._registry = JsonToolUsageParserRegistry()
|
|
15
|
-
|
|
16
|
-
def provide(self, llm_provider: Optional[LLMProvider] = None) -> 'BaseToolUsageParser':
|
|
17
|
-
"""
|
|
18
|
-
Gets the appropriate parser from the registry.
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
llm_provider: The LLMProvider for which to get a parser.
|
|
22
|
-
|
|
23
|
-
Returns:
|
|
24
|
-
An instance of a class derived from BaseToolUsageParser.
|
|
25
|
-
"""
|
|
26
|
-
if llm_provider:
|
|
27
|
-
return self._registry.get_parser(llm_provider)
|
|
28
|
-
return self._registry.get_default_parser()
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# file: autobyteus/autobyteus/tools/usage/providers/xml_example_provider.py
|
|
2
|
-
from typing import Optional, TYPE_CHECKING
|
|
3
|
-
|
|
4
|
-
from autobyteus.llm.providers import LLMProvider
|
|
5
|
-
from autobyteus.tools.usage.registries.xml_example_formatter_registry import XmlExampleFormatterRegistry
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from autobyteus.tools.registry import ToolDefinition
|
|
9
|
-
|
|
10
|
-
class XmlExampleProvider:
|
|
11
|
-
"""Provides a tool usage example formatted as a single XML string."""
|
|
12
|
-
|
|
13
|
-
def __init__(self):
|
|
14
|
-
self._registry = XmlExampleFormatterRegistry()
|
|
15
|
-
|
|
16
|
-
def provide(self, tool_definition: 'ToolDefinition', llm_provider: Optional[LLMProvider] = None) -> str:
|
|
17
|
-
"""
|
|
18
|
-
Generates a single XML string for a tool usage example.
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
tool_definition: A ToolDefinition object.
|
|
22
|
-
llm_provider: Ignored, for API consistency.
|
|
23
|
-
|
|
24
|
-
Returns:
|
|
25
|
-
A string containing the XML tool usage example.
|
|
26
|
-
"""
|
|
27
|
-
formatter = self._registry.get_formatter(llm_provider)
|
|
28
|
-
return formatter.provide(tool_definition)
|