import { VectorStore } from "./vector-store.contract.mjs"; //#region ../ai/src/rag/store/pg-vector-store.d.ts /** * Minimal `pg`-compatible client surface the Postgres {@link VectorStore} * depends on. Both `pg.Pool` and `pg.Client` satisfy it — the store only * ever calls `query`. * * `@warlock.js/ai` takes **no** hard dependency on `pg`; the dev installs * it (an optional peer) and passes the client in. Structurally identical * to the snapshot / human-interrupt stores' `PgClientLike`, so a single * pool can back the orchestrator checkpoint/snapshot tables, the * interrupt table, and this vectors table alike. */ interface PgClientLike { query(text: string, params?: unknown[]): Promise<{ rows: unknown[]; }>; } /** * Options for the Postgres {@link VectorStore}. * * Two mutually-supportive ways to supply the connection (mirroring * `ai.human.interrupt.pg`): * - **`client`** — pass an already-built `pg.Pool` / `pg.Client` (anything * satisfying {@link PgClientLike}). The store only ever calls `query` * and never opens or closes it; one pool can back several stores. * - **`connectionString`** — let the store lazily `import("pg")` and build * its own `Pool`. `@warlock.js/ai` takes **no** hard dependency on * `pg` (an optional peer); when it is absent the store throws a curated * install string at first use, never a raw module-resolution stack trace * at import. * * Exactly one of the two must be present. */ interface PgVectorStoreOptions { /** An already-built `pg.Pool` / `pg.Client` — anything matching {@link PgClientLike}. */ client?: PgClientLike; /** Connection string the store passes to a lazily-imported `pg.Pool`. */ connectionString?: string; /** * Backing table name. Defaults to `warlock_ai_rag_vectors`. Must be a * safe SQL identifier — it is interpolated into DDL/DML. */ table?: string; /** * Embedding dimensionality used in the `CREATE TABLE` DDL emitted by * {@link VectorStore.schema | ensureSchema}. Defaults to `1536` * (OpenAI `text-embedding-3-small`). The column is declared * `vector(N)`; queries and upserts never re-state it, so an existing * table provisioned at a different size is unaffected — only the DDL * helper reads this. */ dimensions?: number; /** * Approximate-nearest-neighbour index strategy baked into the DDL * emitted by {@link VectorStore.schema | ensureSchema}. Defaults to * `"hnsw"` (better recall/latency on modern pgvector). Use `"ivfflat"` * for the classic list-partitioned index, or `"none"` to emit no ANN * index (exact scan — correct, but linear in row count). */ index?: "hnsw" | "ivfflat" | "none"; /** * `lists` parameter for an `ivfflat` index (ignored for `hnsw` / `none`). * Defaults to `100`. Tune toward `rows / 1000` for large tables. */ ivfflatLists?: number; } /** * Serialize a JS `number[]` to the pgvector text literal: `[1,2,3]`. * pgvector accepts a vector either as this bracketed literal or via a * typed parameter; passing the literal string + an explicit `::vector` * cast keeps the store driver-agnostic (no dependency on a registered * `pg` type parser). * * Non-finite components (`NaN` / `±Infinity`) are rejected — pgvector * stores only finite floats, and silently coercing them would corrupt the * index. The check is cheap relative to the embed call that produced the * vector. * * @example * vectorLiteral([1, 0.5, -2]); // "[1,0.5,-2]" */ declare function vectorLiteral(vector: number[]): string; /** * The {@link VectorStore} surface plus the pg store's extra DDL helpers. * `schema()` / `ensureSchema()` are not part of the base contract (the * cache store has no backing table), so the factory's return type widens * it for callers that want the migration SQL. */ interface PgVectorStoreInstance extends VectorStore { /** Reference migration DDL (extension + table + indexes). Never executed. */ schema(): string; /** Alias for {@link PgVectorStoreInstance.schema} — reads better in a migration script. */ ensureSchema(): string; } /** * Create a Postgres + pgvector-backed {@link VectorStore} for the RAG * pipeline. Either pass a live `pg.Pool` / `pg.Client` (`{ client }`) — * `@warlock.js/ai` never imports `pg` in that case — or a * `{ connectionString }` and let the store lazily `import("pg")` to build * its own pool. When `pg` is not installed, a curated install string * surfaces on first use, never at import. * * Run {@link PgVectorStoreInstance.ensureSchema} through your migration * tool once before use (it enables the `vector` extension, creates the * table, and builds the tag + ANN indexes); the store never auto-migrates. * * Index and query MUST use the same embedding model — the `vector(N)` * column width is fixed at table-creation time from `dimensions`. * * @example * import { Pool } from "pg"; * import { ai } from "@warlock.js/ai"; * * const pool = new Pool({ connectionString: process.env.DATABASE_URL }); * const store = ai.rag.pgVectorStore({ client: pool, dimensions: 1536 }); * * // Once, via your migration tooling: * // await pool.query(store.ensureSchema()); * * const kb = ai.rag({ * name: "docs", * embedder: openai.embedder({ name: "text-embedding-3-small" }), * store, * }); * * @example * // Let the store build its own pool from a connection string: * const store = ai.rag.pgVectorStore({ * connectionString: process.env.DATABASE_URL, * index: "ivfflat", * ivfflatLists: 200, * }); */ declare function pgVectorStore(options: PgVectorStoreOptions): PgVectorStoreInstance; //#endregion export { PgClientLike, PgVectorStoreInstance, PgVectorStoreOptions, pgVectorStore, vectorLiteral }; //# sourceMappingURL=pg-vector-store.d.mts.map