autobyteus 1.0.5__py3-none-any.whl → 1.1.0__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 +97 -222
- autobyteus/agent/bootstrap_steps/__init__.py +19 -0
- autobyteus/agent/bootstrap_steps/agent_bootstrapper.py +88 -0
- autobyteus/agent/bootstrap_steps/agent_runtime_queue_initialization_step.py +57 -0
- autobyteus/agent/bootstrap_steps/base_bootstrap_step.py +38 -0
- autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +93 -0
- autobyteus/agent/bootstrap_steps/workspace_context_initialization_step.py +47 -0
- autobyteus/agent/context/__init__.py +18 -0
- autobyteus/agent/context/agent_config.py +80 -0
- autobyteus/agent/context/agent_context.py +132 -0
- autobyteus/agent/context/agent_phase_manager.py +164 -0
- autobyteus/agent/context/agent_runtime_state.py +89 -0
- autobyteus/agent/context/phases.py +47 -0
- autobyteus/agent/events/__init__.py +63 -0
- autobyteus/agent/events/agent_events.py +147 -0
- autobyteus/agent/events/agent_input_event_queue_manager.py +174 -0
- autobyteus/agent/events/notifiers.py +104 -0
- autobyteus/agent/events/worker_event_dispatcher.py +118 -0
- autobyteus/agent/factory/__init__.py +9 -0
- autobyteus/agent/factory/agent_factory.py +126 -79
- autobyteus/agent/group/agent_group.py +155 -0
- autobyteus/agent/group/agent_group_context.py +81 -0
- autobyteus/agent/handlers/__init__.py +36 -0
- autobyteus/agent/handlers/approved_tool_invocation_event_handler.py +134 -0
- autobyteus/agent/handlers/base_event_handler.py +36 -0
- autobyteus/agent/handlers/event_handler_registry.py +76 -0
- autobyteus/agent/handlers/generic_event_handler.py +46 -0
- autobyteus/agent/handlers/inter_agent_message_event_handler.py +76 -0
- autobyteus/agent/handlers/lifecycle_event_logger.py +64 -0
- autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +136 -0
- autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +140 -0
- autobyteus/agent/handlers/tool_execution_approval_event_handler.py +85 -0
- autobyteus/agent/handlers/tool_invocation_request_event_handler.py +186 -0
- autobyteus/agent/handlers/tool_result_event_handler.py +96 -0
- autobyteus/agent/handlers/user_input_message_event_handler.py +77 -0
- autobyteus/agent/hooks/__init__.py +9 -0
- autobyteus/agent/hooks/base_phase_hook.py +52 -0
- autobyteus/agent/input_processor/__init__.py +18 -0
- autobyteus/agent/input_processor/base_user_input_processor.py +51 -0
- autobyteus/agent/input_processor/content_prefixing_input_processor.py +41 -0
- autobyteus/agent/input_processor/metadata_appending_input_processor.py +34 -0
- autobyteus/agent/input_processor/passthrough_input_processor.py +32 -0
- autobyteus/agent/input_processor/processor_definition.py +42 -0
- autobyteus/agent/input_processor/processor_meta.py +46 -0
- autobyteus/agent/input_processor/processor_registry.py +98 -0
- autobyteus/agent/llm_response_processor/__init__.py +16 -0
- autobyteus/agent/llm_response_processor/base_processor.py +50 -0
- autobyteus/agent/llm_response_processor/processor_definition.py +36 -0
- autobyteus/agent/llm_response_processor/processor_meta.py +37 -0
- autobyteus/agent/llm_response_processor/processor_registry.py +94 -0
- autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +53 -0
- autobyteus/agent/message/__init__.py +20 -0
- autobyteus/agent/message/agent_input_user_message.py +96 -0
- autobyteus/agent/message/context_file.py +82 -0
- autobyteus/agent/message/context_file_type.py +64 -0
- autobyteus/agent/message/{message.py → inter_agent_message.py} +12 -12
- autobyteus/agent/message/{message_types.py → inter_agent_message_type.py} +8 -6
- autobyteus/agent/message/send_message_to.py +142 -36
- autobyteus/agent/remote_agent.py +240 -5
- autobyteus/agent/runtime/__init__.py +15 -0
- autobyteus/agent/runtime/agent_runtime.py +139 -0
- autobyteus/agent/runtime/agent_thread_pool_manager.py +88 -0
- autobyteus/agent/runtime/agent_worker.py +200 -0
- autobyteus/agent/streaming/__init__.py +15 -0
- autobyteus/agent/streaming/agent_event_stream.py +120 -0
- autobyteus/agent/streaming/queue_streamer.py +58 -0
- autobyteus/agent/streaming/stream_event_payloads.py +156 -0
- autobyteus/agent/streaming/stream_events.py +123 -0
- autobyteus/agent/system_prompt_processor/__init__.py +14 -0
- autobyteus/agent/system_prompt_processor/base_processor.py +45 -0
- autobyteus/agent/system_prompt_processor/processor_definition.py +40 -0
- autobyteus/agent/system_prompt_processor/processor_meta.py +47 -0
- autobyteus/agent/system_prompt_processor/processor_registry.py +119 -0
- autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +65 -0
- autobyteus/agent/tool_invocation.py +28 -5
- autobyteus/agent/utils/__init__.py +9 -0
- autobyteus/agent/utils/wait_for_idle.py +59 -0
- autobyteus/agent/workflow/__init__.py +11 -0
- autobyteus/agent/workflow/agentic_workflow.py +89 -0
- autobyteus/agent/workflow/base_agentic_workflow.py +98 -0
- autobyteus/agent/workspace/__init__.py +9 -0
- autobyteus/agent/workspace/base_workspace.py +55 -0
- autobyteus/cli/__init__.py +10 -0
- autobyteus/cli/agent_cli.py +299 -0
- autobyteus/events/event_emitter.py +33 -56
- autobyteus/events/event_manager.py +133 -66
- autobyteus/events/event_types.py +41 -14
- autobyteus/llm/api/autobyteus_llm.py +13 -15
- autobyteus/llm/api/bedrock_llm.py +9 -3
- autobyteus/llm/api/claude_llm.py +10 -5
- autobyteus/llm/api/deepseek_llm.py +53 -91
- autobyteus/llm/api/gemini_llm.py +10 -4
- autobyteus/llm/api/grok_llm.py +53 -77
- autobyteus/llm/api/groq_llm.py +10 -5
- autobyteus/llm/api/mistral_llm.py +10 -5
- autobyteus/llm/api/nvidia_llm.py +9 -4
- autobyteus/llm/api/ollama_llm.py +56 -48
- autobyteus/llm/api/openai_llm.py +20 -14
- autobyteus/llm/base_llm.py +95 -34
- autobyteus/llm/extensions/base_extension.py +3 -4
- autobyteus/llm/extensions/token_usage_tracking_extension.py +2 -3
- autobyteus/llm/llm_factory.py +12 -13
- autobyteus/llm/models.py +87 -8
- autobyteus/llm/user_message.py +73 -0
- autobyteus/llm/utils/llm_config.py +124 -27
- autobyteus/llm/utils/response_types.py +3 -2
- autobyteus/llm/utils/token_usage.py +7 -4
- autobyteus/rpc/__init__.py +73 -0
- autobyteus/rpc/client/__init__.py +17 -0
- autobyteus/rpc/client/abstract_client_connection.py +124 -0
- autobyteus/rpc/client/client_connection_manager.py +153 -0
- autobyteus/rpc/client/sse_client_connection.py +306 -0
- autobyteus/rpc/client/stdio_client_connection.py +280 -0
- autobyteus/rpc/config/__init__.py +13 -0
- autobyteus/rpc/config/agent_server_config.py +153 -0
- autobyteus/rpc/config/agent_server_registry.py +152 -0
- autobyteus/rpc/hosting.py +244 -0
- autobyteus/rpc/protocol.py +244 -0
- autobyteus/rpc/server/__init__.py +20 -0
- autobyteus/rpc/server/agent_server_endpoint.py +181 -0
- autobyteus/rpc/server/base_method_handler.py +40 -0
- autobyteus/rpc/server/method_handlers.py +259 -0
- autobyteus/rpc/server/sse_server_handler.py +182 -0
- autobyteus/rpc/server/stdio_server_handler.py +151 -0
- autobyteus/rpc/server_main.py +198 -0
- autobyteus/rpc/transport_type.py +13 -0
- autobyteus/tools/__init__.py +75 -0
- autobyteus/tools/ask_user_input.py +34 -77
- autobyteus/tools/base_tool.py +66 -37
- autobyteus/tools/bash/__init__.py +2 -0
- autobyteus/tools/bash/bash_executor.py +42 -79
- autobyteus/tools/browser/__init__.py +2 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +50 -42
- autobyteus/tools/browser/session_aware/browser_session_aware_tool.py +7 -4
- autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +117 -125
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +75 -22
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +94 -28
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_web_element_trigger_factory.py +10 -2
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_reader_factory.py +18 -2
- autobyteus/tools/browser/session_aware/factory/browser_session_aware_webpage_screenshot_taker_factory.py +10 -2
- autobyteus/tools/browser/session_aware/shared_browser_session_manager.py +4 -3
- autobyteus/tools/browser/standalone/__init__.py +7 -0
- autobyteus/tools/browser/standalone/factory/google_search_factory.py +17 -2
- autobyteus/tools/browser/standalone/factory/webpage_reader_factory.py +17 -2
- autobyteus/tools/browser/standalone/factory/webpage_screenshot_taker_factory.py +10 -2
- autobyteus/tools/browser/standalone/google_search_ui.py +104 -67
- autobyteus/tools/browser/standalone/navigate_to.py +52 -28
- autobyteus/tools/browser/standalone/web_page_pdf_generator.py +94 -0
- autobyteus/tools/browser/standalone/webpage_image_downloader.py +146 -61
- autobyteus/tools/browser/standalone/webpage_reader.py +80 -61
- autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +91 -45
- autobyteus/tools/factory/__init__.py +9 -0
- autobyteus/tools/factory/tool_factory.py +25 -4
- autobyteus/tools/file/file_reader.py +22 -51
- autobyteus/tools/file/file_writer.py +25 -56
- autobyteus/tools/functional_tool.py +234 -0
- autobyteus/tools/image_downloader.py +49 -71
- autobyteus/tools/mcp/__init__.py +47 -0
- autobyteus/tools/mcp/call_handlers/__init__.py +18 -0
- autobyteus/tools/mcp/call_handlers/base_handler.py +40 -0
- autobyteus/tools/mcp/call_handlers/sse_handler.py +22 -0
- autobyteus/tools/mcp/call_handlers/stdio_handler.py +62 -0
- autobyteus/tools/mcp/call_handlers/streamable_http_handler.py +55 -0
- autobyteus/tools/mcp/config_service.py +258 -0
- autobyteus/tools/mcp/factory.py +70 -0
- autobyteus/tools/mcp/registrar.py +135 -0
- autobyteus/tools/mcp/schema_mapper.py +131 -0
- autobyteus/tools/mcp/tool.py +101 -0
- autobyteus/tools/mcp/types.py +96 -0
- autobyteus/tools/parameter_schema.py +268 -0
- autobyteus/tools/pdf_downloader.py +78 -79
- autobyteus/tools/registry/__init__.py +0 -2
- autobyteus/tools/registry/tool_definition.py +106 -34
- autobyteus/tools/registry/tool_registry.py +46 -22
- autobyteus/tools/timer.py +150 -102
- autobyteus/tools/tool_config.py +117 -0
- autobyteus/tools/tool_meta.py +48 -26
- autobyteus/tools/usage/__init__.py +6 -0
- autobyteus/tools/usage/formatters/__init__.py +31 -0
- autobyteus/tools/usage/formatters/anthropic_json_example_formatter.py +18 -0
- autobyteus/tools/usage/formatters/anthropic_json_schema_formatter.py +25 -0
- autobyteus/tools/usage/formatters/base_formatter.py +42 -0
- autobyteus/tools/usage/formatters/default_json_example_formatter.py +42 -0
- autobyteus/tools/usage/formatters/default_json_schema_formatter.py +28 -0
- autobyteus/tools/usage/formatters/default_xml_example_formatter.py +55 -0
- autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +46 -0
- autobyteus/tools/usage/formatters/gemini_json_example_formatter.py +34 -0
- autobyteus/tools/usage/formatters/gemini_json_schema_formatter.py +25 -0
- autobyteus/tools/usage/formatters/google_json_example_formatter.py +34 -0
- autobyteus/tools/usage/formatters/google_json_schema_formatter.py +25 -0
- autobyteus/tools/usage/formatters/openai_json_example_formatter.py +49 -0
- autobyteus/tools/usage/formatters/openai_json_schema_formatter.py +28 -0
- autobyteus/tools/usage/parsers/__init__.py +22 -0
- autobyteus/tools/usage/parsers/anthropic_xml_tool_usage_parser.py +10 -0
- autobyteus/tools/usage/parsers/base_parser.py +41 -0
- autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +106 -0
- autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +135 -0
- autobyteus/tools/usage/parsers/exceptions.py +13 -0
- autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +68 -0
- autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +147 -0
- autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +67 -0
- autobyteus/tools/usage/providers/__init__.py +22 -0
- autobyteus/tools/usage/providers/json_example_provider.py +32 -0
- autobyteus/tools/usage/providers/json_schema_provider.py +35 -0
- autobyteus/tools/usage/providers/json_tool_usage_parser_provider.py +28 -0
- autobyteus/tools/usage/providers/tool_manifest_provider.py +68 -0
- autobyteus/tools/usage/providers/xml_example_provider.py +28 -0
- autobyteus/tools/usage/providers/xml_schema_provider.py +29 -0
- autobyteus/tools/usage/providers/xml_tool_usage_parser_provider.py +26 -0
- autobyteus/tools/usage/registries/__init__.py +20 -0
- autobyteus/tools/usage/registries/json_example_formatter_registry.py +51 -0
- autobyteus/tools/usage/registries/json_schema_formatter_registry.py +51 -0
- autobyteus/tools/usage/registries/json_tool_usage_parser_registry.py +42 -0
- autobyteus/tools/usage/registries/xml_example_formatter_registry.py +30 -0
- autobyteus/tools/usage/registries/xml_schema_formatter_registry.py +33 -0
- autobyteus/tools/usage/registries/xml_tool_usage_parser_registry.py +30 -0
- {autobyteus-1.0.5.dist-info → autobyteus-1.1.0.dist-info}/METADATA +21 -3
- autobyteus-1.1.0.dist-info/RECORD +279 -0
- {autobyteus-1.0.5.dist-info → autobyteus-1.1.0.dist-info}/WHEEL +1 -1
- autobyteus/agent/async_agent.py +0 -175
- autobyteus/agent/async_group_aware_agent.py +0 -136
- autobyteus/agent/group/async_group_aware_agent.py +0 -122
- autobyteus/agent/group/coordinator_agent.py +0 -36
- autobyteus/agent/group/group_aware_agent.py +0 -121
- autobyteus/agent/orchestrator/__init__.py +0 -0
- autobyteus/agent/orchestrator/base_agent_orchestrator.py +0 -82
- autobyteus/agent/orchestrator/multi_replica_agent_orchestrator.py +0 -72
- autobyteus/agent/orchestrator/single_replica_agent_orchestrator.py +0 -43
- autobyteus/agent/registry/__init__.py +0 -11
- autobyteus/agent/registry/agent_definition.py +0 -94
- autobyteus/agent/registry/agent_registry.py +0 -114
- autobyteus/agent/response_parser/__init__.py +0 -0
- autobyteus/agent/response_parser/tool_usage_command_parser.py +0 -100
- autobyteus/agent/status.py +0 -12
- autobyteus/conversation/__init__.py +0 -0
- autobyteus/conversation/conversation.py +0 -54
- autobyteus/conversation/user_message.py +0 -59
- autobyteus/events/decorators.py +0 -29
- autobyteus/prompt/prompt_version_manager.py +0 -58
- autobyteus/prompt/storage/__init__.py +0 -0
- autobyteus/prompt/storage/prompt_version_model.py +0 -29
- autobyteus/prompt/storage/prompt_version_repository.py +0 -83
- autobyteus/tools/bash/factory/__init__.py +0 -0
- autobyteus/tools/bash/factory/bash_executor_factory.py +0 -6
- autobyteus/tools/factory/ask_user_input_factory.py +0 -6
- autobyteus/tools/factory/image_downloader_factory.py +0 -9
- autobyteus/tools/factory/pdf_downloader_factory.py +0 -9
- autobyteus/tools/factory/webpage_image_downloader_factory.py +0 -6
- autobyteus/tools/file/factory/__init__.py +0 -0
- autobyteus/tools/file/factory/file_reader_factory.py +0 -6
- autobyteus/tools/file/factory/file_writer_factory.py +0 -6
- autobyteus/tools/mcp_remote_tool.py +0 -82
- autobyteus/tools/web_page_pdf_generator.py +0 -90
- autobyteus-1.0.5.dist-info/RECORD +0 -163
- {autobyteus-1.0.5.dist-info → autobyteus-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {autobyteus-1.0.5.dist-info → autobyteus-1.1.0.dist-info}/top_level.txt +0 -0
autobyteus/tools/timer.py
CHANGED
|
@@ -1,121 +1,169 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
from typing import Optional
|
|
2
|
+
from typing import Optional, TYPE_CHECKING, Any
|
|
3
3
|
from autobyteus.tools.base_tool import BaseTool
|
|
4
|
-
from autobyteus.
|
|
4
|
+
from autobyteus.tools.tool_config import ToolConfig
|
|
5
|
+
from autobyteus.tools.parameter_schema import ParameterSchema, ParameterDefinition, ParameterType
|
|
6
|
+
from autobyteus.events.event_emitter import EventEmitter
|
|
5
7
|
from autobyteus.events.event_types import EventType
|
|
8
|
+
import logging
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
A tool that provides timer functionality with configurable duration and event emission.
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from autobyteus.agent.context import AgentContext
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
starting the timer, and emits events with the remaining time at configurable intervals.
|
|
13
|
-
The timer runs independently after being started.
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
_task (Optional[asyncio.Task]): The asyncio task for the running timer.
|
|
15
|
+
class Timer(BaseTool, EventEmitter):
|
|
16
|
+
"""
|
|
17
|
+
A tool that provides timer functionality with configurable duration and event emission.
|
|
18
|
+
The timer runs independently after being started and emits TIMER_UPDATE events.
|
|
20
19
|
"""
|
|
21
20
|
|
|
22
|
-
def __init__(self):
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
def __init__(self, config: Optional[ToolConfig] = None):
|
|
22
|
+
BaseTool.__init__(self, config=config)
|
|
23
|
+
EventEmitter.__init__(self)
|
|
24
|
+
|
|
25
|
+
self.duration: int = 300
|
|
26
|
+
self.interval: int = 60
|
|
27
|
+
|
|
28
|
+
if config:
|
|
29
|
+
try:
|
|
30
|
+
self.duration = int(config.get('duration', 300))
|
|
31
|
+
if not (1 <= self.duration <= 86400):
|
|
32
|
+
logger.warning(f"Timer duration {self.duration} out of bounds (1-86400). Clamping or using default.")
|
|
33
|
+
self.duration = max(1, min(self.duration, 86400))
|
|
34
|
+
except ValueError:
|
|
35
|
+
logger.warning(f"Invalid duration value in config, using default {self.duration}s.")
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
self.interval = int(config.get('interval', 60))
|
|
39
|
+
if not (1 <= self.interval <= 3600):
|
|
40
|
+
logger.warning(f"Timer interval {self.interval} out of bounds (1-3600). Clamping or using default.")
|
|
41
|
+
self.interval = max(1, min(self.interval, 3600))
|
|
42
|
+
except ValueError:
|
|
43
|
+
logger.warning(f"Invalid interval value in config, using default {self.interval}s.")
|
|
44
|
+
|
|
30
45
|
self._is_running: bool = False
|
|
31
46
|
self._task: Optional[asyncio.Task] = None
|
|
47
|
+
logger.debug(f"Timer initialized with duration: {self.duration}s, interval: {self.interval}s")
|
|
32
48
|
|
|
33
49
|
@classmethod
|
|
34
|
-
def
|
|
35
|
-
""
|
|
36
|
-
Return an XML string describing the usage of the Timer tool.
|
|
37
|
-
|
|
38
|
-
Returns:
|
|
39
|
-
str: An XML description of how to use the Timer tool.
|
|
40
|
-
"""
|
|
41
|
-
return '''Timer: Sets and runs a timer, emitting events with remaining time. Usage:
|
|
42
|
-
<command name="Timer">
|
|
43
|
-
<arg name="duration">300</arg>
|
|
44
|
-
<arg name="interval" optional="true">60</arg>
|
|
45
|
-
</command>
|
|
46
|
-
where duration and interval are in seconds. interval is optional and defaults to 60 seconds.
|
|
47
|
-
'''
|
|
48
|
-
|
|
49
|
-
def set_duration(self, duration: int):
|
|
50
|
-
"""
|
|
51
|
-
Set the duration of the timer.
|
|
52
|
-
|
|
53
|
-
Args:
|
|
54
|
-
duration (int): The duration of the timer in seconds.
|
|
55
|
-
"""
|
|
56
|
-
self.duration = duration
|
|
50
|
+
def get_description(cls) -> str:
|
|
51
|
+
return "Sets and runs a timer. Emits TIMER_UPDATE events with remaining time at specified intervals."
|
|
57
52
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
@classmethod
|
|
54
|
+
def get_argument_schema(cls) -> Optional[ParameterSchema]:
|
|
55
|
+
schema = ParameterSchema()
|
|
56
|
+
schema.add_parameter(ParameterDefinition(
|
|
57
|
+
name="duration",
|
|
58
|
+
param_type=ParameterType.INTEGER,
|
|
59
|
+
description="Duration to set for this timer run in seconds.",
|
|
60
|
+
required=True,
|
|
61
|
+
min_value=1,
|
|
62
|
+
max_value=86400
|
|
63
|
+
))
|
|
64
|
+
schema.add_parameter(ParameterDefinition(
|
|
65
|
+
name="interval",
|
|
66
|
+
param_type=ParameterType.INTEGER,
|
|
67
|
+
description="Interval for emitting timer events in seconds for this run. Overrides instance default.",
|
|
68
|
+
required=False,
|
|
69
|
+
default_value=None,
|
|
70
|
+
min_value=1,
|
|
71
|
+
max_value=3600
|
|
72
|
+
))
|
|
73
|
+
return schema
|
|
61
74
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
75
|
+
@classmethod
|
|
76
|
+
def get_config_schema(cls) -> Optional[ParameterSchema]:
|
|
77
|
+
schema = ParameterSchema()
|
|
78
|
+
schema.add_parameter(ParameterDefinition(
|
|
79
|
+
name="duration",
|
|
80
|
+
param_type=ParameterType.INTEGER,
|
|
81
|
+
description="Default duration of the timer in seconds if not overridden by execute.",
|
|
82
|
+
required=False,
|
|
83
|
+
default_value=300,
|
|
84
|
+
min_value=1,
|
|
85
|
+
max_value=86400
|
|
86
|
+
))
|
|
87
|
+
schema.add_parameter(ParameterDefinition(
|
|
88
|
+
name="interval",
|
|
89
|
+
param_type=ParameterType.INTEGER,
|
|
90
|
+
description="Default interval at which to emit timer events, in seconds, if not overridden by execute.",
|
|
91
|
+
required=False,
|
|
92
|
+
default_value=60,
|
|
93
|
+
min_value=1,
|
|
94
|
+
max_value=3600
|
|
95
|
+
))
|
|
96
|
+
return schema
|
|
97
|
+
|
|
98
|
+
def set_duration(self, duration: int) -> None:
|
|
99
|
+
if not (1 <= duration <= 86400):
|
|
100
|
+
raise ValueError("Duration must be between 1 and 86400 seconds.")
|
|
101
|
+
self.duration = duration
|
|
66
102
|
|
|
67
|
-
def
|
|
68
|
-
|
|
69
|
-
|
|
103
|
+
def set_interval(self, interval: int) -> None:
|
|
104
|
+
if not (1 <= interval <= 3600):
|
|
105
|
+
raise ValueError("Interval must be between 1 and 3600 seconds.")
|
|
106
|
+
self.interval = interval
|
|
70
107
|
|
|
71
|
-
|
|
72
|
-
RuntimeError: If the timer is already running or if no duration has been set.
|
|
73
|
-
"""
|
|
108
|
+
def start(self, run_duration: Optional[int] = None, run_interval: Optional[int] = None) -> None:
|
|
74
109
|
if self._is_running:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
async def _run_timer(self):
|
|
82
|
-
"""
|
|
83
|
-
Run the timer, emitting events at the specified interval.
|
|
84
|
-
"""
|
|
85
|
-
remaining_time = self.duration
|
|
86
|
-
while remaining_time > 0:
|
|
87
|
-
self.emit(EventType.TIMER_UPDATE, remaining_time=remaining_time)
|
|
88
|
-
await asyncio.sleep(min(self.interval, remaining_time))
|
|
89
|
-
remaining_time -= self.interval
|
|
90
|
-
self.emit(EventType.TIMER_UPDATE, remaining_time=0)
|
|
91
|
-
self._is_running = False
|
|
92
|
-
|
|
93
|
-
async def _execute(self, **kwargs):
|
|
94
|
-
"""
|
|
95
|
-
Execute the timer.
|
|
96
|
-
|
|
97
|
-
This method sets the duration and interval if provided, and starts the timer.
|
|
98
|
-
It returns immediately after starting the timer, allowing the timer to run independently.
|
|
99
|
-
|
|
100
|
-
Args:
|
|
101
|
-
**kwargs: Keyword arguments. Expected arguments:
|
|
102
|
-
- duration (int): The duration to set for the timer in seconds.
|
|
103
|
-
- interval (int, optional): The interval at which to emit timer events, in seconds.
|
|
104
|
-
Defaults to 60 seconds if not provided.
|
|
105
|
-
|
|
106
|
-
Returns:
|
|
107
|
-
str: A message indicating the timer has started.
|
|
108
|
-
|
|
109
|
-
Raises:
|
|
110
|
-
ValueError: If the duration is not provided.
|
|
111
|
-
"""
|
|
112
|
-
duration = kwargs.get('duration')
|
|
113
|
-
if duration is None:
|
|
114
|
-
raise ValueError("Timer duration must be provided")
|
|
115
|
-
self.set_duration(duration)
|
|
110
|
+
logger.warning("Timer start called but timer is already running.")
|
|
111
|
+
return
|
|
112
|
+
|
|
113
|
+
current_duration = run_duration if run_duration is not None else self.duration
|
|
114
|
+
current_interval = run_interval if run_interval is not None else self.interval
|
|
116
115
|
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
if current_duration <= 0:
|
|
117
|
+
raise RuntimeError("Timer duration must be positive and set before starting.")
|
|
118
|
+
if current_interval <=0:
|
|
119
|
+
raise RuntimeError("Timer interval must be positive and set.")
|
|
119
120
|
|
|
120
|
-
self.
|
|
121
|
-
|
|
121
|
+
self._is_running = True
|
|
122
|
+
self._task = asyncio.create_task(self._run_timer_task(current_duration, current_interval))
|
|
123
|
+
logger.info(f"Timer started for {current_duration}s, events every {current_interval}s.")
|
|
124
|
+
|
|
125
|
+
async def _run_timer_task(self, duration: int, interval: int) -> None:
|
|
126
|
+
remaining_time = duration
|
|
127
|
+
try:
|
|
128
|
+
while remaining_time > 0:
|
|
129
|
+
self.emit(EventType.TIMER_UPDATE, remaining_time=remaining_time)
|
|
130
|
+
await asyncio.sleep(min(interval, remaining_time))
|
|
131
|
+
remaining_time -= interval
|
|
132
|
+
self.emit(EventType.TIMER_UPDATE, remaining_time=0)
|
|
133
|
+
except asyncio.CancelledError:
|
|
134
|
+
logger.info("Timer task was cancelled.")
|
|
135
|
+
self.emit(EventType.TIMER_UPDATE, remaining_time=-1, status="cancelled")
|
|
136
|
+
raise
|
|
137
|
+
finally:
|
|
138
|
+
self._is_running = False
|
|
139
|
+
logger.info("Timer task finished.")
|
|
140
|
+
|
|
141
|
+
async def _execute(self, context: 'AgentContext', duration: int, interval: Optional[int] = None) -> str:
|
|
142
|
+
logger.debug(f"Timer execute called by agent {context.agent_id} with duration: {duration}, interval: {interval}")
|
|
143
|
+
|
|
144
|
+
effective_interval = interval if interval is not None else self.interval
|
|
145
|
+
|
|
146
|
+
if self._task and not self._task.done():
|
|
147
|
+
logger.info("Cancelling previous timer task before starting a new one.")
|
|
148
|
+
self._task.cancel()
|
|
149
|
+
try:
|
|
150
|
+
await self._task
|
|
151
|
+
except asyncio.CancelledError:
|
|
152
|
+
logger.debug("Previous timer task successfully cancelled.")
|
|
153
|
+
self._task = None
|
|
154
|
+
|
|
155
|
+
self.start(run_duration=duration, run_interval=effective_interval)
|
|
156
|
+
return f"Timer started for {duration} seconds, emitting events every {effective_interval} seconds."
|
|
157
|
+
|
|
158
|
+
async def stop(self) -> None:
|
|
159
|
+
if self._task and not self._task.done():
|
|
160
|
+
logger.info("Stopping timer task...")
|
|
161
|
+
self._task.cancel()
|
|
162
|
+
try:
|
|
163
|
+
await self._task
|
|
164
|
+
except asyncio.CancelledError:
|
|
165
|
+
logger.info("Timer task stopped successfully.")
|
|
166
|
+
self._task = None
|
|
167
|
+
self._is_running = False
|
|
168
|
+
else:
|
|
169
|
+
logger.info("Stop called, but no timer task is running or task already done.")
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/tools/tool_config.py
|
|
2
|
+
import logging
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
@dataclass
|
|
9
|
+
class ToolConfig:
|
|
10
|
+
"""
|
|
11
|
+
Configuration class for tools - a simple dictionary wrapper.
|
|
12
|
+
Tools define their own default configurations internally and use this
|
|
13
|
+
class to receive configuration overrides.
|
|
14
|
+
"""
|
|
15
|
+
params: Dict[str, Any] = field(default_factory=dict)
|
|
16
|
+
|
|
17
|
+
def __post_init__(self):
|
|
18
|
+
"""Validate configuration after initialization."""
|
|
19
|
+
if not isinstance(self.params, dict):
|
|
20
|
+
raise TypeError("params must be a dictionary")
|
|
21
|
+
|
|
22
|
+
logger.debug(f"ToolConfig initialized with params keys: {list(self.params.keys())}")
|
|
23
|
+
|
|
24
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
25
|
+
"""
|
|
26
|
+
Convert the ToolConfig to a dictionary representation.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Dict[str, Any]: Dictionary representation of the configuration.
|
|
30
|
+
"""
|
|
31
|
+
return self.params.copy()
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def from_dict(cls, config_data: Dict[str, Any]) -> 'ToolConfig':
|
|
35
|
+
"""
|
|
36
|
+
Create a ToolConfig instance from a dictionary.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
config_data: Dictionary containing configuration parameters.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
ToolConfig: New ToolConfig instance.
|
|
43
|
+
"""
|
|
44
|
+
if not isinstance(config_data, dict):
|
|
45
|
+
raise TypeError("config_data must be a dictionary")
|
|
46
|
+
|
|
47
|
+
return cls(params=config_data.copy())
|
|
48
|
+
|
|
49
|
+
def merge(self, other: 'ToolConfig') -> 'ToolConfig':
|
|
50
|
+
"""
|
|
51
|
+
Merge this ToolConfig with another, with the other taking precedence.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
other: ToolConfig to merge with this one.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
ToolConfig: New merged ToolConfig instance.
|
|
58
|
+
"""
|
|
59
|
+
if not isinstance(other, ToolConfig):
|
|
60
|
+
raise TypeError("Can only merge with another ToolConfig instance")
|
|
61
|
+
|
|
62
|
+
merged_params = self.params.copy()
|
|
63
|
+
merged_params.update(other.params)
|
|
64
|
+
|
|
65
|
+
return ToolConfig(params=merged_params)
|
|
66
|
+
|
|
67
|
+
def get_constructor_kwargs(self) -> Dict[str, Any]:
|
|
68
|
+
"""
|
|
69
|
+
Get keyword arguments suitable for tool constructor calls.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Dict[str, Any]: Dictionary of constructor arguments.
|
|
73
|
+
"""
|
|
74
|
+
return self.params.copy()
|
|
75
|
+
|
|
76
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
77
|
+
"""
|
|
78
|
+
Get a configuration parameter.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
key: The parameter key.
|
|
82
|
+
default: Default value if key doesn't exist.
|
|
83
|
+
|
|
84
|
+
Returns:
|
|
85
|
+
The parameter value or default.
|
|
86
|
+
"""
|
|
87
|
+
return self.params.get(key, default)
|
|
88
|
+
|
|
89
|
+
def set(self, key: str, value: Any) -> None:
|
|
90
|
+
"""
|
|
91
|
+
Set a configuration parameter.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
key: The parameter key.
|
|
95
|
+
value: The parameter value.
|
|
96
|
+
"""
|
|
97
|
+
self.params[key] = value
|
|
98
|
+
|
|
99
|
+
def update(self, params: Dict[str, Any]) -> None:
|
|
100
|
+
"""
|
|
101
|
+
Update multiple configuration parameters.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
params: Dictionary of parameters to update.
|
|
105
|
+
"""
|
|
106
|
+
if not isinstance(params, dict):
|
|
107
|
+
raise TypeError("params must be a dictionary")
|
|
108
|
+
self.params.update(params)
|
|
109
|
+
|
|
110
|
+
def __repr__(self) -> str:
|
|
111
|
+
return f"ToolConfig(params={self.params})"
|
|
112
|
+
|
|
113
|
+
def __len__(self) -> int:
|
|
114
|
+
return len(self.params)
|
|
115
|
+
|
|
116
|
+
def __bool__(self) -> bool:
|
|
117
|
+
return bool(self.params)
|
autobyteus/tools/tool_meta.py
CHANGED
|
@@ -1,52 +1,74 @@
|
|
|
1
|
-
# file: autobyteus/tools/tool_meta.py
|
|
1
|
+
# file: autobyteus/autobyteus/tools/tool_meta.py
|
|
2
2
|
import logging
|
|
3
3
|
from abc import ABCMeta
|
|
4
|
+
from typing import Dict, Any
|
|
4
5
|
|
|
5
|
-
# Import the global registry and definition class from the registry package
|
|
6
6
|
from autobyteus.tools.registry import default_tool_registry, ToolDefinition
|
|
7
|
+
from autobyteus.tools.parameter_schema import ParameterSchema
|
|
7
8
|
|
|
8
|
-
logger = logging.getLogger(__name__)
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
9
10
|
|
|
10
11
|
class ToolMeta(ABCMeta):
|
|
11
12
|
"""
|
|
12
|
-
Metaclass for BaseTool that automatically registers concrete tool subclasses
|
|
13
|
-
with the default_tool_registry using their static name and usage description
|
|
14
|
-
obtained from class method `tool_usage()`.
|
|
13
|
+
Metaclass for BaseTool that automatically registers concrete tool subclasses.
|
|
15
14
|
"""
|
|
16
15
|
def __init__(cls, name, bases, dct):
|
|
17
|
-
"""
|
|
18
|
-
Called when a class using this metaclass is defined.
|
|
19
|
-
"""
|
|
20
16
|
super().__init__(name, bases, dct)
|
|
21
17
|
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
# Skip registration for special classes that are not meant to be standalone tools.
|
|
19
|
+
# FunctionalTool is an explicit wrapper but shouldn't be registered itself.
|
|
20
|
+
if name in ['BaseTool', 'GenericMcpTool', 'FunctionalTool'] or getattr(cls, "__abstractmethods__", None):
|
|
21
|
+
logger.debug(f"Skipping registration for abstract or special tool class: {name}")
|
|
25
22
|
return
|
|
26
23
|
|
|
27
24
|
try:
|
|
28
|
-
#
|
|
25
|
+
# Use the class itself to get the metadata, not an instance.
|
|
29
26
|
tool_name = cls.get_name()
|
|
30
|
-
|
|
31
|
-
usage_description = cls.tool_usage()
|
|
32
|
-
|
|
33
|
-
# Basic validation of fetched static info
|
|
34
27
|
if not tool_name or not isinstance(tool_name, str):
|
|
35
28
|
logger.error(f"Tool class {name} must return a valid string from static get_name(). Skipping registration.")
|
|
36
29
|
return
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
|
|
31
|
+
general_description = cls.get_description()
|
|
32
|
+
if not general_description or not isinstance(general_description, str):
|
|
33
|
+
logger.error(f"Tool class {name} ({tool_name}) must return a valid string from get_description(). Skipping registration.")
|
|
40
34
|
return
|
|
41
35
|
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
argument_schema: ParameterSchema = None
|
|
37
|
+
try:
|
|
38
|
+
argument_schema = cls.get_argument_schema()
|
|
39
|
+
if argument_schema is not None and not isinstance(argument_schema, ParameterSchema):
|
|
40
|
+
logger.error(f"Tool class {name} ({tool_name}) get_argument_schema() must return a ParameterSchema or None. Got {type(argument_schema)}. Skipping registration.")
|
|
41
|
+
return
|
|
42
|
+
except Exception as e:
|
|
43
|
+
logger.error(f"Tool class {name} ({tool_name}) failed to provide argument_schema via get_argument_schema(): {e}. Skipping registration.", exc_info=True)
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
instantiation_config_schema: ParameterSchema = None
|
|
47
|
+
if hasattr(cls, 'get_config_schema'):
|
|
48
|
+
try:
|
|
49
|
+
instantiation_config_schema = cls.get_config_schema()
|
|
50
|
+
if instantiation_config_schema is not None and not isinstance(instantiation_config_schema, ParameterSchema):
|
|
51
|
+
logger.warning(f"Tool class {name} ({tool_name}) get_config_schema() returned non-ParameterSchema type: {type(instantiation_config_schema)}. Treating as no config schema.")
|
|
52
|
+
instantiation_config_schema = None
|
|
53
|
+
except Exception as e:
|
|
54
|
+
logger.warning(f"Tool class {name} ({tool_name}) has get_config_schema() but it failed: {e}. Assuming no instantiation config.")
|
|
55
|
+
|
|
56
|
+
# Create the definition without pre-generating usage strings
|
|
57
|
+
definition = ToolDefinition(
|
|
58
|
+
name=tool_name,
|
|
59
|
+
description=general_description,
|
|
60
|
+
tool_class=cls,
|
|
61
|
+
custom_factory=None,
|
|
62
|
+
argument_schema=argument_schema,
|
|
63
|
+
config_schema=instantiation_config_schema
|
|
64
|
+
)
|
|
44
65
|
default_tool_registry.register_tool(definition)
|
|
45
|
-
|
|
66
|
+
|
|
67
|
+
arg_schema_info = f"args: {len(argument_schema) if argument_schema else '0'}"
|
|
68
|
+
config_info = f"inst_config: {len(instantiation_config_schema) if instantiation_config_schema else '0'}"
|
|
69
|
+
logger.info(f"Auto-registered tool: '{tool_name}' from class {name} ({arg_schema_info}, {config_info})")
|
|
46
70
|
|
|
47
71
|
except AttributeError as e:
|
|
48
|
-
|
|
49
|
-
logger.error(f"Tool class {name} is missing required static/class method ({e}). Skipping registration.")
|
|
72
|
+
logger.error(f"Tool class {name} is missing a required method ({e}). Skipping registration.")
|
|
50
73
|
except Exception as e:
|
|
51
74
|
logger.error(f"Failed to auto-register tool class {name}: {e}", exc_info=True)
|
|
52
|
-
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/tools/usage/formatters/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
This package contains concrete formatter classes that translate a BaseTool's
|
|
4
|
+
metadata into a specific provider's format (e.g., OpenAI JSON, Anthropic JSON, XML).
|
|
5
|
+
"""
|
|
6
|
+
from .base_formatter import BaseSchemaFormatter, BaseExampleFormatter
|
|
7
|
+
from .default_xml_schema_formatter import DefaultXmlSchemaFormatter
|
|
8
|
+
from .default_json_schema_formatter import DefaultJsonSchemaFormatter
|
|
9
|
+
from .openai_json_schema_formatter import OpenAiJsonSchemaFormatter
|
|
10
|
+
from .anthropic_json_schema_formatter import AnthropicJsonSchemaFormatter
|
|
11
|
+
from .gemini_json_schema_formatter import GeminiJsonSchemaFormatter
|
|
12
|
+
from .default_xml_example_formatter import DefaultXmlExampleFormatter
|
|
13
|
+
from .default_json_example_formatter import DefaultJsonExampleFormatter
|
|
14
|
+
from .openai_json_example_formatter import OpenAiJsonExampleFormatter
|
|
15
|
+
from .anthropic_json_example_formatter import AnthropicJsonExampleFormatter
|
|
16
|
+
from .gemini_json_example_formatter import GeminiJsonExampleFormatter
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"BaseSchemaFormatter",
|
|
20
|
+
"BaseExampleFormatter",
|
|
21
|
+
"DefaultXmlSchemaFormatter",
|
|
22
|
+
"DefaultJsonSchemaFormatter",
|
|
23
|
+
"OpenAiJsonSchemaFormatter",
|
|
24
|
+
"AnthropicJsonSchemaFormatter",
|
|
25
|
+
"GeminiJsonSchemaFormatter",
|
|
26
|
+
"DefaultXmlExampleFormatter",
|
|
27
|
+
"DefaultJsonExampleFormatter",
|
|
28
|
+
"OpenAiJsonExampleFormatter",
|
|
29
|
+
"AnthropicJsonExampleFormatter",
|
|
30
|
+
"GeminiJsonExampleFormatter",
|
|
31
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/tools/usage/formatters/anthropic_json_example_formatter.py
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
from .base_formatter import BaseExampleFormatter
|
|
5
|
+
from .default_xml_example_formatter import DefaultXmlExampleFormatter
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from autobyteus.tools.registry import ToolDefinition
|
|
9
|
+
|
|
10
|
+
class AnthropicJsonExampleFormatter(BaseExampleFormatter):
|
|
11
|
+
"""
|
|
12
|
+
Formats a tool usage example for Anthropic models. Since Anthropic uses XML
|
|
13
|
+
for tool calls, this formatter returns a string representing the XML call.
|
|
14
|
+
"""
|
|
15
|
+
def provide(self, tool_definition: 'ToolDefinition') -> str:
|
|
16
|
+
# Anthropic expects XML tool call examples.
|
|
17
|
+
# We use the XML formatter's logic directly.
|
|
18
|
+
return DefaultXmlExampleFormatter().provide(tool_definition)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/tools/usage/formatters/anthropic_json_schema_formatter.py
|
|
2
|
+
from typing import Dict, TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
from .base_formatter import BaseSchemaFormatter
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from autobyteus.tools.registry import ToolDefinition
|
|
8
|
+
|
|
9
|
+
class AnthropicJsonSchemaFormatter(BaseSchemaFormatter):
|
|
10
|
+
"""Formats a tool's schema into the Anthropic JSON format."""
|
|
11
|
+
|
|
12
|
+
def provide(self, tool_definition: 'ToolDefinition') -> Dict:
|
|
13
|
+
name = tool_definition.name
|
|
14
|
+
description = tool_definition.description
|
|
15
|
+
arg_schema = tool_definition.argument_schema
|
|
16
|
+
|
|
17
|
+
input_schema = arg_schema.to_json_schema_dict() if arg_schema else {
|
|
18
|
+
"type": "object", "properties": {}, "required": []
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
"name": name,
|
|
23
|
+
"description": description,
|
|
24
|
+
"input_schema": input_schema,
|
|
25
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/tools/usage/formatters/base_formatter.py
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from typing import Union, Dict, TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from autobyteus.tools.registry import ToolDefinition
|
|
7
|
+
|
|
8
|
+
class BaseSchemaFormatter(ABC):
|
|
9
|
+
"""
|
|
10
|
+
Abstract base class for formatting the schema of a single tool
|
|
11
|
+
into a provider-specific format.
|
|
12
|
+
"""
|
|
13
|
+
@abstractmethod
|
|
14
|
+
def provide(self, tool_definition: 'ToolDefinition') -> Union[str, Dict]:
|
|
15
|
+
"""
|
|
16
|
+
Formats the schema of the given tool definition.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
tool_definition: The tool definition to format.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
An XML string or a dictionary representing the tool's schema.
|
|
23
|
+
"""
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
class BaseExampleFormatter(ABC):
|
|
27
|
+
"""
|
|
28
|
+
Abstract base class for formatting a usage example of a single tool
|
|
29
|
+
into a provider-specific format.
|
|
30
|
+
"""
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def provide(self, tool_definition: 'ToolDefinition') -> Union[str, Dict]:
|
|
33
|
+
"""
|
|
34
|
+
Formats a usage example for the given tool definition.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
tool_definition: The tool definition to format an example for.
|
|
38
|
+
|
|
39
|
+
Returns:
|
|
40
|
+
An XML string or a dictionary representing a tool usage example.
|
|
41
|
+
"""
|
|
42
|
+
pass
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# file: autobyteus/autobyteus/tools/usage/formatters/default_json_example_formatter.py
|
|
2
|
+
from typing import Dict, Any, TYPE_CHECKING
|
|
3
|
+
|
|
4
|
+
from autobyteus.tools.parameter_schema import ParameterType, ParameterDefinition
|
|
5
|
+
from .base_formatter import BaseExampleFormatter
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from autobyteus.tools.registry import ToolDefinition
|
|
9
|
+
|
|
10
|
+
class DefaultJsonExampleFormatter(BaseExampleFormatter):
|
|
11
|
+
"""
|
|
12
|
+
Formats a tool usage example into a generic JSON format, inspired by
|
|
13
|
+
the default XML format.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def provide(self, tool_definition: 'ToolDefinition') -> Dict:
|
|
17
|
+
tool_name = tool_definition.name
|
|
18
|
+
arg_schema = tool_definition.argument_schema
|
|
19
|
+
arguments = {}
|
|
20
|
+
|
|
21
|
+
if arg_schema and arg_schema.parameters:
|
|
22
|
+
for param_def in arg_schema.parameters:
|
|
23
|
+
if param_def.required or param_def.default_value is not None:
|
|
24
|
+
arguments[param_def.name] = self._generate_placeholder_value(param_def)
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
"tool": {
|
|
28
|
+
"function": tool_name,
|
|
29
|
+
"parameters": arguments,
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
def _generate_placeholder_value(self, param_def: ParameterDefinition) -> Any:
|
|
34
|
+
if param_def.default_value is not None: return param_def.default_value
|
|
35
|
+
if param_def.param_type == ParameterType.STRING: return f"example_{param_def.name}"
|
|
36
|
+
if param_def.param_type == ParameterType.INTEGER: return 123
|
|
37
|
+
if param_def.param_type == ParameterType.FLOAT: return 123.45
|
|
38
|
+
if param_def.param_type == ParameterType.BOOLEAN: return True
|
|
39
|
+
if param_def.param_type == ParameterType.ENUM: return param_def.enum_values[0] if param_def.enum_values else "enum_val"
|
|
40
|
+
if param_def.param_type == ParameterType.OBJECT: return {"key": "value"}
|
|
41
|
+
if param_def.param_type == ParameterType.ARRAY: return ["item1", "item2"]
|
|
42
|
+
return "placeholder"
|