Source code for pctx_client._convert

from collections.abc import Callable
from typing import Any, overload

from pctx_client._tool import AsyncTool, Tool


@overload
def tool(
    name_or_callable: str,
    *args: Any,
    namespace: str = "tools",
    description: str | None = None,
) -> Callable[[Callable], Tool | AsyncTool]: ...
@overload
def tool(
    name_or_callable: Callable,
    *args: Any,
    namespace: str = "tools",
    description: str | None = None,
) -> Tool | AsyncTool: ...


[docs] def tool( name_or_callable: str | Callable, *args: Any, namespace: str = "tools", description: str | None = None, ) -> Tool | AsyncTool | Callable[[Callable], Tool | AsyncTool]: """ Decorator that converts a function into a Tool or AsyncTool instance. Can be used with or without parameters: - @tool - Uses function name as tool name - @tool("custom_name") - Uses custom name for the tool - @tool(namespace="custom", description="...") - With additional options Args: name_or_callable: Either a custom tool name (str) or the function to wrap (Callable) namespace: The namespace the tool belongs to (default: "tools") description: Optional description override (default: uses function docstring) Returns: Either a Tool/AsyncTool instance or a decorator function that creates one Examples: >>> @tool ... def my_function(x: int) -> int: ... '''Adds one to x''' ... return x + 1 >>> @tool("custom_name", namespace="math") ... def add_two(x: int) -> int: ... return x + 2 """ def _crate_tool_factory(tool_name: str) -> Callable[[Callable], Tool | AsyncTool]: """ Creates a decorator which takes the callable & returns the tool Args: tool_name: the unique name of the tool Returns: A function that takes a callable & returns a base tool """ def _tool_factory(fn: Callable) -> Tool | AsyncTool: tool_desc = description return Tool.from_func( func=fn, name=tool_name, namespace=namespace, description=tool_desc, ) return _tool_factory if len(args) != 0: raise ValueError("Too many arguments for @tool decorator") if isinstance(name_or_callable, str): # decorator used with params # @tool("other_tool") # def some_tool(): # pass return _crate_tool_factory(name_or_callable) elif callable(name_or_callable) and hasattr(name_or_callable, "__name__"): # decorator used without params # @tool # def some_tool(): # pass return _crate_tool_factory(name_or_callable.__name__)(name_or_callable) else: raise ValueError( f"The first arg of the tool decorator must be a string or a callable with a __name__ attribute. Got {type(name_or_callable)}" )