Spaces:
Running
Running
| """Agent tool registry. | |
| A deliberately small, trimmed tool set shared by the browser agent. Each tool has | |
| a name, a JSON-schema parameter spec, and a handler bound at runtime. The schema | |
| definitions are part of the cached prompt prefix, so keeping the set minimal is | |
| itself a token optimization (the reference docs note unused tool defs cost tokens | |
| on every call). | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| from typing import Any, Callable | |
| class Tool: | |
| name: str | |
| description: str | |
| parameters: dict # JSON-schema | |
| handler: Callable[..., Any] | None = None | |
| # Canonical browser tool definitions (the "contract" the agent reasons over). | |
| BROWSER_TOOLS: list[Tool] = [ | |
| Tool( | |
| name="navigate", | |
| description="Go to a URL.", | |
| parameters={"type": "object", "properties": {"url": {"type": "string"}}, | |
| "required": ["url"]}, | |
| ), | |
| Tool( | |
| name="click", | |
| description="Click an element by CSS selector or accessibility label.", | |
| parameters={"type": "object", "properties": {"selector": {"type": "string"}}, | |
| "required": ["selector"]}, | |
| ), | |
| Tool( | |
| name="fill", | |
| description="Type text into a form field identified by selector.", | |
| parameters={"type": "object", "properties": { | |
| "selector": {"type": "string"}, "text": {"type": "string"}}, | |
| "required": ["selector", "text"]}, | |
| ), | |
| Tool( | |
| name="extract", | |
| description="Extract the structured data visible on the page as JSON.", | |
| parameters={"type": "object", "properties": {}}, | |
| ), | |
| Tool( | |
| name="screenshot", | |
| description="Capture the current page for the audit trail.", | |
| parameters={"type": "object", "properties": {}}, | |
| ), | |
| Tool( | |
| name="done", | |
| description="Finish the task; args.result is the final JSON payload.", | |
| parameters={"type": "object", "properties": {"result": {}}, | |
| "required": ["result"]}, | |
| ), | |
| ] | |
| class ToolRegistry: | |
| def __init__(self, tools: list[Tool]) -> None: | |
| self._tools = {t.name: t for t in tools} | |
| def names(self) -> list[str]: | |
| return list(self._tools) | |
| def get(self, name: str) -> Tool | None: | |
| return self._tools.get(name) | |
| def bind(self, name: str, handler: Callable[..., Any]) -> None: | |
| if name in self._tools: | |
| self._tools[name].handler = handler | |
| def definitions(self) -> list[dict]: | |
| return [ | |
| {"name": t.name, "description": t.description, "parameters": t.parameters} | |
| for t in self._tools.values() | |
| ] | |
| def call(self, name: str, args: dict) -> Any: | |
| tool = self._tools.get(name) | |
| if tool is None or tool.handler is None: | |
| raise ValueError(f"unknown or unbound tool: {name}") | |
| return tool.handler(**(args or {})) | |
| def browser_registry() -> ToolRegistry: | |
| return ToolRegistry([Tool(t.name, t.description, t.parameters) for t in BROWSER_TOOLS]) | |