import type { ToolSpec } from "../core/types.js"; export interface SqlToolOptions { /** * Execute a query that has already passed read-only validation, returning rows. * IMPORTANT: back this with **read-only database credentials** — the validation here is * defense-in-depth, not the primary guarantee. */ query: (sql: string) => Promise; /** * If set, the query may only reference these tables (case-insensitive). **Best-effort, NOT a hard * isolation boundary.** Table extraction is regex-based; to stay sound it FAILS CLOSED — comma-joins * (`FROM a, b`), sub-queries in FROM/JOIN, and set operations (UNION/INTERSECT/EXCEPT) are REJECTED * (their full table set can't be reliably enumerated). Even so, do **NOT** rely on this alone for * multi-tenant / cross-tenant isolation: back it with **read-only DB credentials scoped to the tenant + * DB-level GRANTs**. The allowlist is a usability guardrail and defense-in-depth, not the security * boundary. (Full AST-parser coverage is deferred to preserve the zero-extra-dependency posture.) */ allowTables?: string[]; /** Maximum rows returned to the model. Default 100. */ maxRows?: number; /** Tool name exposed to the model. Default "query_sql". */ name?: string; /** Description override. */ description?: string; } /** Validate that `sql` is a single, read-only SELECT/CTE query within the allowlist. */ export declare function validateReadOnlySql(sql: string, allowTables?: string[]): void; /** * Build a safe, read-only `query_sql` tool. * * Layers of defense: (1) read-only DB credentials supplied by the caller's `query`, * (2) static validation (single SELECT/WITH only, no DML/DDL, no comments/multi-statement), * (3) optional table allowlist, (4) a row cap on what is returned to the model. */ export declare function createSqlTool(opts: SqlToolOptions): ToolSpec; //# sourceMappingURL=sql.d.ts.map