Skip to content

Commit 1ea5c11

Browse files
committed
Add docstrings
1 parent 137af18 commit 1ea5c11

File tree

14 files changed

+1289
-97
lines changed

14 files changed

+1289
-97
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,84 @@
1+
"""Abstract interface for UTCP client transport implementations.
2+
3+
This module defines the contract that all transport implementations must follow
4+
to integrate with the UTCP client. Transport implementations handle the actual
5+
communication with different types of tool providers (HTTP, CLI, WebSocket, etc.).
6+
"""
7+
18
from abc import ABC, abstractmethod
29
from typing import Dict, Any, List
310
from utcp.shared.provider import Provider
411
from utcp.shared.tool import Tool
512

613
class ClientTransportInterface(ABC):
14+
"""Abstract interface for UTCP client transport implementations.
15+
16+
Defines the contract that all transport implementations must follow to
17+
integrate with the UTCP client. Each transport handles communication
18+
with a specific type of provider (HTTP, CLI, WebSocket, etc.).
19+
20+
Transport implementations are responsible for:
21+
- Discovering available tools from providers
22+
- Managing provider lifecycle (registration/deregistration)
23+
- Executing tool calls through the appropriate protocol
24+
"""
25+
726
@abstractmethod
827
async def register_tool_provider(self, manual_provider: Provider) -> List[Tool]:
28+
"""Register a tool provider and discover its available tools.
29+
30+
Connects to the provider and retrieves the list of tools it offers.
31+
This may involve making discovery requests, parsing configuration files,
32+
or initializing connections depending on the provider type.
33+
34+
Args:
35+
manual_provider: The provider configuration to register.
36+
37+
Returns:
38+
List of Tool objects discovered from the provider.
39+
40+
Raises:
41+
ConnectionError: If unable to connect to the provider.
42+
ValueError: If the provider configuration is invalid.
43+
"""
944
pass
1045

1146
@abstractmethod
1247
async def deregister_tool_provider(self, manual_provider: Provider) -> None:
48+
"""Deregister a tool provider and clean up resources.
49+
50+
Cleanly disconnects from the provider and releases any associated
51+
resources such as connections, processes, or file handles.
52+
53+
Args:
54+
manual_provider: The provider configuration to deregister.
55+
56+
Note:
57+
Should handle cases where the provider is already disconnected
58+
or was never properly registered.
59+
"""
1360
pass
1461

1562
@abstractmethod
1663
async def call_tool(self, tool_name: str, arguments: Dict[str, Any], tool_provider: Provider) -> Any:
64+
"""Execute a tool call through this transport.
65+
66+
Sends a tool invocation request to the provider using the appropriate
67+
protocol and returns the result. Handles serialization of arguments
68+
and deserialization of responses according to the transport type.
69+
70+
Args:
71+
tool_name: Name of the tool to call (may include provider prefix).
72+
arguments: Dictionary of arguments to pass to the tool.
73+
tool_provider: Provider configuration for the tool.
74+
75+
Returns:
76+
The tool's response, with type depending on the tool's output schema.
77+
78+
Raises:
79+
ToolNotFoundError: If the specified tool doesn't exist.
80+
ValidationError: If the arguments don't match the tool's input schema.
81+
ConnectionError: If unable to communicate with the provider.
82+
TimeoutError: If the tool call exceeds the configured timeout.
83+
"""
1784
pass

src/utcp/client/openapi_converter.py

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
"""OpenAPI specification converter for UTCP tool generation.
2+
3+
This module provides functionality to convert OpenAPI specifications (both 2.0
4+
and 3.0) into UTCP tool definitions. It handles schema resolution, authentication
5+
mapping, and proper tool creation from REST API specifications.
6+
7+
Key Features:
8+
- OpenAPI 2.0 and 3.0 specification support
9+
- Automatic JSON reference ($ref) resolution
10+
- Authentication scheme mapping (API key, Basic, OAuth2)
11+
- Input/output schema extraction from OpenAPI schemas
12+
- URL path parameter handling
13+
- Request body and header field mapping
14+
- Provider name generation from specification metadata
15+
16+
The converter creates UTCP tools that can be used to interact with REST APIs
17+
defined by OpenAPI specifications, providing a bridge between OpenAPI and UTCP.
18+
"""
19+
120
import json
221
from typing import Any, Dict, List, Optional, Tuple
322
import sys
@@ -11,9 +30,45 @@
1130

1231

1332
class OpenApiConverter:
14-
"""Converts an OpenAPI JSON specification into a UtcpManual."""
33+
"""Converts OpenAPI specifications into UTCP tool definitions.
34+
35+
Processes OpenAPI 2.0 and 3.0 specifications to generate equivalent UTCP
36+
tools, handling schema resolution, authentication mapping, and proper
37+
HTTP provider configuration. Each operation in the OpenAPI spec becomes
38+
a UTCP tool with appropriate input/output schemas.
39+
40+
Features:
41+
- Complete OpenAPI specification parsing
42+
- Recursive JSON reference ($ref) resolution
43+
- Authentication scheme conversion (API key, Basic, OAuth2)
44+
- Input parameter and request body handling
45+
- Response schema extraction
46+
- URL template and path parameter support
47+
- Provider name normalization
48+
- Placeholder variable generation for configuration
49+
50+
Architecture:
51+
The converter works by iterating through all paths and operations
52+
in the OpenAPI spec, extracting relevant information for each
53+
operation, and creating corresponding UTCP tools with HTTP providers.
54+
55+
Attributes:
56+
spec: The parsed OpenAPI specification dictionary.
57+
spec_url: Optional URL where the specification was retrieved from.
58+
placeholder_counter: Counter for generating unique placeholder variables.
59+
provider_name: Normalized name for the provider derived from the spec.
60+
"""
1561

1662
def __init__(self, openapi_spec: Dict[str, Any], spec_url: Optional[str] = None, provider_name: Optional[str] = None):
63+
"""Initialize the OpenAPI converter.
64+
65+
Args:
66+
openapi_spec: Parsed OpenAPI specification as a dictionary.
67+
spec_url: Optional URL where the specification was retrieved from.
68+
Used for base URL determination if servers are not specified.
69+
provider_name: Optional custom name for the provider. If not
70+
provided, derives name from the specification title.
71+
"""
1772
self.spec = openapi_spec
1873
self.spec_url = spec_url
1974
# Single counter for all placeholder variables

src/utcp/client/tool_repository.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
1+
"""Abstract interface for tool and provider storage.
2+
3+
This module defines the contract for implementing tool repositories that store
4+
and manage UTCP tools and their associated providers. Different implementations
5+
can provide various storage backends such as in-memory, database, or file-based
6+
storage.
7+
"""
8+
19
from abc import ABC, abstractmethod
210
from typing import List, Dict, Any, Optional
311
from utcp.shared.provider import Provider
412
from utcp.shared.tool import Tool
513

614
class ToolRepository(ABC):
15+
"""Abstract interface for tool and provider storage implementations.
16+
17+
Defines the contract for repositories that manage the lifecycle and storage
18+
of UTCP tools and providers. Repositories are responsible for:
19+
- Persisting provider configurations and their associated tools
20+
- Providing efficient lookup and retrieval operations
21+
- Managing relationships between providers and tools
22+
- Ensuring data consistency during operations
23+
24+
The repository interface supports both individual and bulk operations,
25+
allowing for flexible implementation strategies ranging from simple
26+
in-memory storage to sophisticated database backends.
27+
28+
Note:
29+
All methods are async to support both synchronous and asynchronous
30+
storage implementations.
31+
"""
732
@abstractmethod
833
async def save_provider_with_tools(self, provider: Provider, tools: List[Tool]) -> None:
934
"""

src/utcp/client/tool_search_strategies/tag_search.py

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
"""Tag-based tool search strategy implementation.
2+
3+
This module provides a search strategy that ranks tools based on tag matches
4+
and description keyword matches. It implements a weighted scoring system where
5+
explicit tag matches receive higher scores than description word matches.
6+
"""
7+
18
from utcp.client.tool_search_strategy import ToolSearchStrategy
29
from typing import List, Dict, Tuple
310
from utcp.shared.tool import Tool
@@ -6,25 +13,73 @@
613
import asyncio
714

815
class TagSearchStrategy(ToolSearchStrategy):
16+
"""Tag-based search strategy for UTCP tools.
17+
18+
Implements a weighted scoring algorithm that matches search queries against
19+
tool tags and descriptions. Explicit tag matches receive full weight while
20+
description word matches receive reduced weight.
21+
22+
Scoring Algorithm:
23+
- Exact tag matches: Weight 1.0
24+
- Tag word matches: Weight equal to description_weight
25+
- Description word matches: Weight equal to description_weight
26+
- Only considers description words longer than 2 characters
27+
28+
Examples:
29+
>>> strategy = TagSearchStrategy(repository, description_weight=0.3)
30+
>>> tools = await strategy.search_tools("weather api", limit=5)
31+
>>> # Returns tools with "weather" or "api" tags/descriptions
32+
33+
Attributes:
34+
tool_repository: Repository to search for tools.
35+
description_weight: Weight multiplier for description matches (0.0-1.0).
36+
"""
937

1038
def __init__(self, tool_repository: ToolRepository, description_weight: float = 0.3):
39+
"""Initialize the tag search strategy.
40+
41+
Args:
42+
tool_repository: Repository containing tools to search.
43+
description_weight: Weight for description word matches relative to
44+
tag matches. Should be between 0.0 and 1.0, where 1.0 gives
45+
equal weight to tags and descriptions.
46+
47+
Raises:
48+
ValueError: If description_weight is not between 0.0 and 1.0.
49+
"""
50+
if not 0.0 <= description_weight <= 1.0:
51+
raise ValueError("description_weight must be between 0.0 and 1.0")
52+
1153
self.tool_repository = tool_repository
1254
# Weight for description words vs explicit tags (explicit tags have weight of 1.0)
1355
self.description_weight = description_weight
1456

1557
async def search_tools(self, query: str, limit: int = 10) -> List[Tool]:
16-
"""
17-
Return tools ordered by tag occurrences in the query.
18-
19-
Uses both explicit tags and words from tool descriptions (with less weight).
20-
58+
"""Search tools using tag and description matching.
59+
60+
Implements a weighted scoring system that ranks tools based on how well
61+
their tags and descriptions match the search query. Normalizes the query
62+
and uses word-based matching with configurable weights.
63+
64+
Scoring Details:
65+
- Exact tag matches in query: +1.0 points
66+
- Individual tag words matching query words: +description_weight points
67+
- Description words matching query words: +description_weight points
68+
- Only description words > 2 characters are considered
69+
2170
Args:
22-
query: The search query string
23-
limit: Maximum number of tools to return
24-
71+
query: Search query string. Case-insensitive, word-based matching.
72+
limit: Maximum number of tools to return. Must be >= 0.
73+
2574
Returns:
26-
List of tools ordered by relevance to the query
75+
List of Tool objects ranked by relevance score (highest first).
76+
Empty list if no tools match or repository is empty.
77+
78+
Raises:
79+
ValueError: If limit is negative.
2780
"""
81+
if limit < 0:
82+
raise ValueError("limit must be non-negative")
2883
# Normalize query to lowercase and split into words
2984
query_lower = query.lower()
3085
# Extract words from the query, filtering out non-word characters
Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,48 @@
1+
"""Abstract interface for tool search strategies.
2+
3+
This module defines the contract for implementing tool search and ranking
4+
algorithms. Different strategies can implement various approaches such as
5+
tag-based search, semantic search, or hybrid approaches.
6+
"""
7+
18
from abc import ABC, abstractmethod
29
from typing import List
310
from utcp.shared.tool import Tool
411

512
class ToolSearchStrategy(ABC):
13+
"""Abstract interface for tool search implementations.
14+
15+
Defines the contract for tool search strategies that can be plugged into
16+
the UTCP client. Different implementations can provide various search
17+
algorithms such as tag-based matching, semantic similarity, or keyword
18+
search.
19+
20+
Search strategies are responsible for:
21+
- Interpreting search queries
22+
- Ranking tools by relevance
23+
- Limiting results appropriately
24+
- Providing consistent search behavior
25+
"""
26+
627
@abstractmethod
728
async def search_tools(self, query: str, limit: int = 10) -> List[Tool]:
8-
"""
9-
Search for tools relevant to the query.
29+
"""Search for tools relevant to the query.
30+
31+
Executes a search against the available tools and returns the most
32+
relevant matches ranked by the strategy's scoring algorithm.
1033
1134
Args:
12-
query: The search query.
13-
limit: The maximum number of tools to return. 0 for no limit.
35+
query: The search query string. Format depends on the strategy
36+
(e.g., keywords, tags, natural language).
37+
limit: Maximum number of tools to return. Use 0 for no limit.
38+
Strategies should respect this limit for performance.
1439
1540
Returns:
16-
A list of tools that match the search query.
41+
List of Tool objects ranked by relevance, limited to the
42+
specified count. Empty list if no matches found.
43+
44+
Raises:
45+
ValueError: If the query format is invalid for this strategy.
46+
RuntimeError: If the search operation fails unexpectedly.
1747
"""
1848
pass

src/utcp/client/transport_interfaces/cli_transport.py

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
1-
"""
2-
Command Line Interface (CLI) transport for UTCP client.
1+
"""Command Line Interface (CLI) transport for UTCP client.
2+
3+
This module provides the CLI transport implementation that enables UTCP clients
4+
to interact with command-line tools and processes. It handles tool discovery
5+
through startup commands, tool execution with proper argument formatting,
6+
and output processing with JSON parsing capabilities.
37
4-
This transport executes command-line tools and processes.
8+
Key Features:
9+
- Asynchronous command execution with timeout handling
10+
- Tool discovery via startup commands that output UTCP manuals
11+
- Flexible argument formatting for command-line flags
12+
- Environment variable support for authentication and configuration
13+
- JSON output parsing with fallback to raw text
14+
- Cross-platform command parsing (Windows/Unix)
15+
- Working directory control for command execution
16+
17+
Security:
18+
- Command execution is isolated through subprocess
19+
- Environment variables can be controlled per provider
20+
- Working directory can be restricted
521
"""
622
import asyncio
723
import json
@@ -20,11 +36,28 @@
2036

2137
class CliTransport(ClientTransportInterface):
2238
"""Transport implementation for CLI-based tool providers.
23-
24-
This transport executes command-line tools and processes. It supports:
25-
- Tool discovery via startup commands that output tool definitions
26-
- Tool execution by running commands with arguments
27-
- Basic authentication via environment variables or command-line flags
39+
40+
Handles communication with command-line tools by executing processes
41+
and managing their input/output. Supports both tool discovery and
42+
execution phases with comprehensive error handling and timeout management.
43+
44+
Features:
45+
- Asynchronous subprocess execution with proper cleanup
46+
- Tool discovery through startup commands returning UTCP manuals
47+
- Flexible argument formatting for various CLI conventions
48+
- Environment variable injection for authentication
49+
- JSON output parsing with graceful fallback to text
50+
- Cross-platform command parsing and execution
51+
- Configurable working directories and timeouts
52+
- Process lifecycle management with proper termination
53+
54+
Architecture:
55+
CLI tools are discovered by executing the provider's command_name
56+
and parsing the output for UTCP manual JSON. Tool calls execute
57+
the same command with formatted arguments and return processed output.
58+
59+
Attributes:
60+
_log: Logger function for debugging and error reporting.
2861
"""
2962

3063
def __init__(self, logger: Optional[Callable[[str], None]] = None):

0 commit comments

Comments
 (0)