""" Thin Supabase wrapper. Every tool that needs a credential pulls it from the `tool_keys` table in the `gate` Supabase project via get_tool_keys(tool_name). Table shape (public.tool_keys): tool text -- matches TOOLS[i]["name"] in registry.py label text key_type text api_key text -- primary credential slot secondary_key text -- e.g. client_secret, cookie value, etc. is_active bool notes text """ import os from functools import lru_cache from supabase import create_client, Client @lru_cache(maxsize=1) def get_client() -> Client: url = os.environ["SUPABASE_URL"] key = os.environ["SUPABASE_SERVICE_KEY"] return create_client(url, key) def get_tool_keys(tool_name: str) -> dict | None: """Return the active credential row for a tool, or None if missing/inactive.""" client = get_client() resp = ( client.table("tool_keys") .select("*") .eq("tool", tool_name) .eq("is_active", True) .limit(1) .execute() ) return resp.data[0] if resp.data else None def require_tool_keys(tool_name: str) -> dict: row = get_tool_keys(tool_name) if not row: raise ValueError( f"No active credentials for '{tool_name}' in tool_keys. " f"Add a row and set is_active = true." ) return row