# ClawTex — Governed Agent with Genetic Memory
# Built by DeVere Cooley / AN2B LLC · an2b.com
# BB4C — Breath Before Code

"""
Tool registry — maps tool names to callable implementations.

Tools are registered with @registry.register("tool_name") and
retrieved by the agent at call time.  Each tool must declare its
action_type so the Warden can gate it.
"""

from __future__ import annotations

import logging
from dataclasses import dataclass, field
from typing import Any, Callable, Coroutine

logger = logging.getLogger(__name__)

ToolFn = Callable[..., Coroutine[Any, Any, Any]]


@dataclass
class ToolDefinition:
    name: str
    action_type: str  # used by Warden (e.g. "web.search", "exec", "file.read")
    description: str
    fn: ToolFn
    parameters: dict[str, Any] = field(default_factory=dict)


class ToolRegistry:
    """Central registry for all ClawTex tools."""

    def __init__(self) -> None:
        self._tools: dict[str, ToolDefinition] = {}

    def register(
        self,
        name: str,
        action_type: str,
        description: str,
        parameters: dict[str, Any] | None = None,
    ) -> Callable[[ToolFn], ToolFn]:
        """Decorator factory for registering a tool."""

        def decorator(fn: ToolFn) -> ToolFn:
            defn = ToolDefinition(
                name=name,
                action_type=action_type,
                description=description,
                fn=fn,
                parameters=parameters or {},
            )
            self._tools[name] = defn
            logger.debug("Tool registered: %s (action_type=%s)", name, action_type)
            return fn

        return decorator

    def get(self, name: str) -> ToolDefinition | None:
        return self._tools.get(name)

    def all(self) -> list[ToolDefinition]:
        return list(self._tools.values())

    def to_openai_schema(self) -> list[dict[str, Any]]:
        """Return tools in OpenAI function-calling schema format."""
        schema = []
        for t in self._tools.values():
            schema.append(
                {
                    "type": "function",
                    "function": {
                        "name": t.name,
                        "description": t.description,
                        "parameters": t.parameters
                        or {"type": "object", "properties": {}},
                    },
                }
            )
        return schema

    def to_anthropic_schema(self) -> list[dict[str, Any]]:
        """Return tools in Anthropic tool-use schema format."""
        schema = []
        for t in self._tools.values():
            schema.append(
                {
                    "name": t.name,
                    "description": t.description,
                    "input_schema": t.parameters
                    or {"type": "object", "properties": {}},
                }
            )
        return schema


# Module-level singleton registry
registry = ToolRegistry()
