@zauso-ai/capstan-db 0.1.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/dist/client.d.ts +31 -18
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +300 -24
  4. package/dist/client.js.map +1 -1
  5. package/dist/crud.d.ts +14 -0
  6. package/dist/crud.d.ts.map +1 -1
  7. package/dist/crud.js +49 -39
  8. package/dist/crud.js.map +1 -1
  9. package/dist/dialect.d.ts +25 -0
  10. package/dist/dialect.d.ts.map +1 -0
  11. package/dist/dialect.js +208 -0
  12. package/dist/dialect.js.map +1 -0
  13. package/dist/embedding.d.ts +63 -0
  14. package/dist/embedding.d.ts.map +1 -0
  15. package/dist/embedding.js +61 -0
  16. package/dist/embedding.js.map +1 -0
  17. package/dist/index.d.ts +14 -4
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +6 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/migrate.d.ts +44 -23
  22. package/dist/migrate.d.ts.map +1 -1
  23. package/dist/migrate.js +308 -125
  24. package/dist/migrate.js.map +1 -1
  25. package/dist/model.d.ts +9 -0
  26. package/dist/model.d.ts.map +1 -1
  27. package/dist/model.js +13 -0
  28. package/dist/model.js.map +1 -1
  29. package/dist/naming.d.ts +37 -0
  30. package/dist/naming.d.ts.map +1 -0
  31. package/dist/naming.js +196 -0
  32. package/dist/naming.js.map +1 -0
  33. package/dist/runtime.d.ts +51 -0
  34. package/dist/runtime.d.ts.map +1 -0
  35. package/dist/runtime.js +490 -0
  36. package/dist/runtime.js.map +1 -0
  37. package/dist/schema.d.ts +2 -12
  38. package/dist/schema.d.ts.map +1 -1
  39. package/dist/schema.js +199 -105
  40. package/dist/schema.js.map +1 -1
  41. package/dist/search.d.ts +52 -0
  42. package/dist/search.d.ts.map +1 -0
  43. package/dist/search.js +110 -0
  44. package/dist/search.js.map +1 -0
  45. package/dist/types.d.ts +5 -2
  46. package/dist/types.d.ts.map +1 -1
  47. package/dist/vector-store-memory.d.ts +31 -0
  48. package/dist/vector-store-memory.d.ts.map +1 -0
  49. package/dist/vector-store-memory.js +125 -0
  50. package/dist/vector-store-memory.js.map +1 -0
  51. package/dist/vector-store-pgvector.d.ts +46 -0
  52. package/dist/vector-store-pgvector.d.ts.map +1 -0
  53. package/dist/vector-store-pgvector.js +215 -0
  54. package/dist/vector-store-pgvector.js.map +1 -0
  55. package/dist/vector-store-sqlite.d.ts +51 -0
  56. package/dist/vector-store-sqlite.d.ts.map +1 -0
  57. package/dist/vector-store-sqlite.js +203 -0
  58. package/dist/vector-store-sqlite.js.map +1 -0
  59. package/dist/vector-store.d.ts +79 -0
  60. package/dist/vector-store.d.ts.map +1 -0
  61. package/dist/vector-store.js +5 -0
  62. package/dist/vector-store.js.map +1 -0
  63. package/dist/write.d.ts +15 -0
  64. package/dist/write.d.ts.map +1 -0
  65. package/dist/write.js +156 -0
  66. package/dist/write.js.map +1 -0
  67. package/package.json +17 -4
@@ -0,0 +1,125 @@
1
+ // ---------------------------------------------------------------------------
2
+ // InMemoryVectorStore — brute-force in-memory vector search
3
+ // ---------------------------------------------------------------------------
4
+ //
5
+ // Suitable for development and small datasets (<10K vectors). All data lives
6
+ // in a plain Map and is lost when the process exits. Search is O(n) per
7
+ // query — acceptable for prototyping but not for production workloads.
8
+ // ---------------------------------------------------------------------------
9
+ import { cosineDistance } from "./search.js";
10
+ /** Simple whitespace tokeniser with lower-casing and deduplication. */
11
+ function tokenize(text) {
12
+ return [
13
+ ...new Set(text
14
+ .toLowerCase()
15
+ .split(/\W+/)
16
+ .filter((t) => t.length > 0)),
17
+ ];
18
+ }
19
+ /** Normalised keyword overlap score in [0, 1]. */
20
+ function keywordOverlap(queryTerms, text) {
21
+ if (queryTerms.length === 0)
22
+ return 0;
23
+ const docTokens = new Set(tokenize(text));
24
+ let hits = 0;
25
+ for (const term of queryTerms) {
26
+ if (docTokens.has(term))
27
+ hits++;
28
+ }
29
+ return hits / queryTerms.length;
30
+ }
31
+ function matchesFilter(metadata, filter) {
32
+ for (const [key, value] of Object.entries(filter)) {
33
+ const actual = metadata[key];
34
+ if (Array.isArray(value)) {
35
+ if (!value.includes(actual))
36
+ return false;
37
+ }
38
+ else if (actual !== value) {
39
+ return false;
40
+ }
41
+ }
42
+ return true;
43
+ }
44
+ /**
45
+ * In-memory vector store backed by a `Map`.
46
+ *
47
+ * This implementation wraps the same cosine-distance utilities that power the
48
+ * existing `findNearest` and `hybridSearch` exports so that behaviour is
49
+ * identical when running without a database.
50
+ */
51
+ export class InMemoryVectorStore {
52
+ /** @internal */
53
+ _store = new Map();
54
+ _dimensions;
55
+ constructor(config) {
56
+ this._dimensions = config?.dimensions;
57
+ }
58
+ _validateDimensions(vector) {
59
+ if (vector.length === 0) {
60
+ throw new Error("Cannot store a zero-length vector.");
61
+ }
62
+ if (this._dimensions !== undefined && vector.length !== this._dimensions) {
63
+ throw new Error(`Dimension mismatch: expected ${this._dimensions}, got ${vector.length}.`);
64
+ }
65
+ }
66
+ async upsert(id, vector, metadata) {
67
+ this._validateDimensions(vector);
68
+ this._store.set(id, { vector, metadata: metadata ?? {} });
69
+ }
70
+ async upsertBatch(items) {
71
+ for (const item of items) {
72
+ this._validateDimensions(item.vector);
73
+ }
74
+ for (const item of items) {
75
+ this._store.set(item.id, { vector: item.vector, metadata: item.metadata ?? {} });
76
+ }
77
+ }
78
+ async search(query, k, filter) {
79
+ if (query.length === 0)
80
+ return [];
81
+ const results = [];
82
+ for (const [id, entry] of this._store) {
83
+ if (filter && !matchesFilter(entry.metadata, filter))
84
+ continue;
85
+ if (entry.vector.length !== query.length)
86
+ continue;
87
+ const score = 1 - cosineDistance(query, entry.vector);
88
+ results.push({ id, score, metadata: entry.metadata });
89
+ }
90
+ results.sort((a, b) => b.score - a.score);
91
+ return results.slice(0, Math.max(0, k));
92
+ }
93
+ async hybridSearch(query, queryVector, k, opts) {
94
+ const keywordWeight = opts?.keywordWeight ?? 0.3;
95
+ const vectorWeight = opts?.vectorWeight ?? 0.7;
96
+ const queryTerms = tokenize(query);
97
+ if (queryTerms.length === 0 && queryVector.length === 0)
98
+ return [];
99
+ const results = [];
100
+ for (const [id, entry] of this._store) {
101
+ if (opts?.filter && !matchesFilter(entry.metadata, opts.filter))
102
+ continue;
103
+ const vectorScore = queryVector.length > 0 && entry.vector.length === queryVector.length
104
+ ? 1 - cosineDistance(queryVector, entry.vector)
105
+ : 0;
106
+ // Use the "text" metadata field for keyword matching when available.
107
+ const text = typeof entry.metadata["text"] === "string" ? entry.metadata["text"] : "";
108
+ const kwScore = keywordOverlap(queryTerms, text);
109
+ results.push({
110
+ id,
111
+ score: vectorWeight * vectorScore + keywordWeight * kwScore,
112
+ metadata: entry.metadata,
113
+ });
114
+ }
115
+ results.sort((a, b) => b.score - a.score);
116
+ return results.slice(0, Math.max(0, k));
117
+ }
118
+ async remove(id) {
119
+ return this._store.delete(id);
120
+ }
121
+ async count() {
122
+ return this._store.size;
123
+ }
124
+ }
125
+ //# sourceMappingURL=vector-store-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-store-memory.js","sourceRoot":"","sources":["../../../.claude/worktrees/agent-a1ae6f0b/packages/db/src/vector-store-memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { VectorFilter, VectorHybridSearchOptions, VectorSearchResult, VectorStore, VectorStoreConfig } from "./vector-store.js";
2
+ /** Minimal query interface accepted by the pgvector store. */
3
+ export interface PgQueryFn {
4
+ /** Execute a parameterised SQL statement and return rows. */
5
+ (sql: string, params?: unknown[]): Promise<Record<string, unknown>[]>;
6
+ }
7
+ /**
8
+ * PostgreSQL vector store powered by the pgvector extension.
9
+ *
10
+ * The store creates a `capstan_vectors` table (configurable via
11
+ * `config.tableName`) and uses the `<=>` cosine distance operator for
12
+ * similarity search. The pgvector extension is created automatically on
13
+ * first use if the connected role has the required permissions.
14
+ *
15
+ * No pgvector npm package is required — all interaction happens through raw
16
+ * parameterised SQL.
17
+ */
18
+ export declare class PgVectorStore implements VectorStore {
19
+ private readonly _query;
20
+ private readonly _table;
21
+ private readonly _dimensions;
22
+ private _initialised;
23
+ constructor(config: VectorStoreConfig & {
24
+ connection: PgQueryFn;
25
+ });
26
+ /** @internal */
27
+ _ensureSchema(): Promise<void>;
28
+ upsert(id: string, vector: number[], metadata?: Record<string, unknown>): Promise<void>;
29
+ upsertBatch(items: ReadonlyArray<{
30
+ id: string;
31
+ vector: number[];
32
+ metadata?: Record<string, unknown>;
33
+ }>): Promise<void>;
34
+ search(query: number[], k: number, filter?: VectorFilter): Promise<VectorSearchResult[]>;
35
+ hybridSearch(query: string, queryVector: number[], k: number, opts?: VectorHybridSearchOptions): Promise<VectorSearchResult[]>;
36
+ remove(id: string): Promise<boolean>;
37
+ count(): Promise<number>;
38
+ private _validateDimensions;
39
+ /** Format a number array as a pgvector literal `[1,2,3]`. */
40
+ private _vec;
41
+ /** Quote a SQL identifier to prevent injection. */
42
+ private _qi;
43
+ /** Build a WHERE clause from a VectorFilter, starting param indices at `startIdx`. */
44
+ private _buildFilterClause;
45
+ }
46
+ //# sourceMappingURL=vector-store-pgvector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-store-pgvector.d.ts","sourceRoot":"","sources":["../../../.claude/worktrees/agent-a1ae6f0b/packages/db/src/vector-store-pgvector.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAE3B,8DAA8D;AAC9D,MAAM,WAAW,SAAS;IACxB,6DAA6D;IAC7D,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;CACvE;AAED;;;;;;;;;;GAUG;AACH,qBAAa,aAAc,YAAW,WAAW;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,iBAAiB,GAAG;QAAE,UAAU,EAAE,SAAS,CAAA;KAAE;IAgBjE,gBAAgB;IACV,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IA6C9B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBvF,WAAW,CACf,KAAK,EAAE,aAAa,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,GACzF,OAAO,CAAC,IAAI,CAAC;IA6BV,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IA0BxF,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EAAE,EACrB,CAAC,EAAE,MAAM,EACT,IAAI,CAAC,EAAE,yBAAyB,GAC/B,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAkC1B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IASpC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAY9B,OAAO,CAAC,mBAAmB;IAW3B,6DAA6D;IAC7D,OAAO,CAAC,IAAI;IAIZ,mDAAmD;IACnD,OAAO,CAAC,GAAG;IAIX,sFAAsF;IACtF,OAAO,CAAC,kBAAkB;CA0B3B"}
@@ -0,0 +1,215 @@
1
+ // ---------------------------------------------------------------------------
2
+ // PgVectorStore — PostgreSQL pgvector-backed vector search
3
+ // ---------------------------------------------------------------------------
4
+ //
5
+ // Uses raw SQL over a caller-supplied query function so there is no hard
6
+ // dependency on any specific PostgreSQL client library. The pgvector
7
+ // extension must be installed in the target database.
8
+ // ---------------------------------------------------------------------------
9
+ /**
10
+ * PostgreSQL vector store powered by the pgvector extension.
11
+ *
12
+ * The store creates a `capstan_vectors` table (configurable via
13
+ * `config.tableName`) and uses the `<=>` cosine distance operator for
14
+ * similarity search. The pgvector extension is created automatically on
15
+ * first use if the connected role has the required permissions.
16
+ *
17
+ * No pgvector npm package is required — all interaction happens through raw
18
+ * parameterised SQL.
19
+ */
20
+ export class PgVectorStore {
21
+ _query;
22
+ _table;
23
+ _dimensions;
24
+ _initialised = false;
25
+ constructor(config) {
26
+ if (!config.connection) {
27
+ throw new Error("PgVectorStore requires a `connection` query function.");
28
+ }
29
+ if (!config.dimensions) {
30
+ throw new Error("PgVectorStore requires `dimensions` to be specified.");
31
+ }
32
+ this._query = config.connection;
33
+ this._table = config.tableName ?? "capstan_vectors";
34
+ this._dimensions = config.dimensions;
35
+ }
36
+ // -------------------------------------------------------------------------
37
+ // Schema bootstrap
38
+ // -------------------------------------------------------------------------
39
+ /** @internal */
40
+ async _ensureSchema() {
41
+ if (this._initialised)
42
+ return;
43
+ try {
44
+ await this._query("CREATE EXTENSION IF NOT EXISTS vector");
45
+ }
46
+ catch (err) {
47
+ const message = err instanceof Error ? err.message : String(err);
48
+ throw new Error(`pgvector extension not found. Run: CREATE EXTENSION vector;\n` +
49
+ `Underlying error: ${message}`);
50
+ }
51
+ const table = this._table;
52
+ const dim = this._dimensions;
53
+ await this._query(`
54
+ CREATE TABLE IF NOT EXISTS ${this._qi(table)} (
55
+ id TEXT PRIMARY KEY,
56
+ embedding vector(${dim}) NOT NULL,
57
+ content TEXT NOT NULL DEFAULT '',
58
+ metadata JSONB NOT NULL DEFAULT '{}'::jsonb
59
+ )
60
+ `);
61
+ // Create an IVFFlat index if it does not already exist. The index
62
+ // requires at least one row so we wrap in a DO block that is safe to
63
+ // re-run.
64
+ await this._query(`
65
+ CREATE INDEX IF NOT EXISTS ${this._qi(table + "_embedding_idx")}
66
+ ON ${this._qi(table)}
67
+ USING ivfflat (embedding vector_cosine_ops)
68
+ WITH (lists = 100)
69
+ `).catch(() => {
70
+ // Index creation can fail on an empty table — that is fine, it will
71
+ // be retried lazily on the next search.
72
+ });
73
+ this._initialised = true;
74
+ }
75
+ // -------------------------------------------------------------------------
76
+ // VectorStore implementation
77
+ // -------------------------------------------------------------------------
78
+ async upsert(id, vector, metadata) {
79
+ this._validateDimensions(vector);
80
+ await this._ensureSchema();
81
+ const text = typeof metadata?.["text"] === "string" ? metadata["text"] : "";
82
+ const metaJson = JSON.stringify(metadata ?? {});
83
+ await this._query(`INSERT INTO ${this._qi(this._table)} (id, embedding, content, metadata)
84
+ VALUES ($1, $2::vector, $3, $4::jsonb)
85
+ ON CONFLICT (id) DO UPDATE
86
+ SET embedding = EXCLUDED.embedding,
87
+ content = EXCLUDED.content,
88
+ metadata = EXCLUDED.metadata`, [id, this._vec(vector), text, metaJson]);
89
+ }
90
+ async upsertBatch(items) {
91
+ if (items.length === 0)
92
+ return;
93
+ for (const item of items)
94
+ this._validateDimensions(item.vector);
95
+ await this._ensureSchema();
96
+ // Batch upserts using a single multi-row INSERT .. ON CONFLICT.
97
+ const valueClauses = [];
98
+ const params = [];
99
+ let idx = 1;
100
+ for (const item of items) {
101
+ const text = typeof item.metadata?.["text"] === "string" ? item.metadata["text"] : "";
102
+ const metaJson = JSON.stringify(item.metadata ?? {});
103
+ valueClauses.push(`($${idx}, $${idx + 1}::vector, $${idx + 2}, $${idx + 3}::jsonb)`);
104
+ params.push(item.id, this._vec(item.vector), text, metaJson);
105
+ idx += 4;
106
+ }
107
+ await this._query(`INSERT INTO ${this._qi(this._table)} (id, embedding, content, metadata)
108
+ VALUES ${valueClauses.join(", ")}
109
+ ON CONFLICT (id) DO UPDATE
110
+ SET embedding = EXCLUDED.embedding,
111
+ content = EXCLUDED.content,
112
+ metadata = EXCLUDED.metadata`, params);
113
+ }
114
+ async search(query, k, filter) {
115
+ if (query.length === 0)
116
+ return [];
117
+ this._validateDimensions(query);
118
+ await this._ensureSchema();
119
+ const { clause, params, nextIndex } = this._buildFilterClause(filter, 2);
120
+ const rows = await this._query(`SELECT id, metadata, 1 - (embedding <=> $1::vector) AS score
121
+ FROM ${this._qi(this._table)}
122
+ ${clause}
123
+ ORDER BY embedding <=> $1::vector
124
+ LIMIT $${nextIndex}`, [this._vec(query), ...params, Math.max(1, k)]);
125
+ return rows.map((row) => {
126
+ const meta = typeof row["metadata"] === "string"
127
+ ? JSON.parse(row["metadata"])
128
+ : row["metadata"];
129
+ const result = { id: String(row["id"]), score: Number(row["score"]) };
130
+ if (meta !== undefined)
131
+ result.metadata = meta;
132
+ return result;
133
+ });
134
+ }
135
+ async hybridSearch(query, queryVector, k, opts) {
136
+ if (query.length === 0 && queryVector.length === 0)
137
+ return [];
138
+ if (queryVector.length > 0)
139
+ this._validateDimensions(queryVector);
140
+ await this._ensureSchema();
141
+ const vectorWeight = opts?.vectorWeight ?? 0.7;
142
+ const keywordWeight = opts?.keywordWeight ?? 0.3;
143
+ const { clause, params, nextIndex } = this._buildFilterClause(opts?.filter, 3);
144
+ let idx = nextIndex;
145
+ // Use ts_rank for text relevance combined with cosine similarity.
146
+ const rows = await this._query(`SELECT id, metadata,
147
+ ${vectorWeight} * (1 - (embedding <=> $1::vector))
148
+ + ${keywordWeight} * COALESCE(ts_rank(to_tsvector('simple', content), plainto_tsquery('simple', $2)), 0)
149
+ AS score
150
+ FROM ${this._qi(this._table)}
151
+ ${clause}
152
+ ORDER BY score DESC
153
+ LIMIT $${idx}`, [this._vec(queryVector), query, ...params, Math.max(1, k)]);
154
+ return rows.map((row) => {
155
+ const meta = typeof row["metadata"] === "string"
156
+ ? JSON.parse(row["metadata"])
157
+ : row["metadata"];
158
+ const result = { id: String(row["id"]), score: Number(row["score"]) };
159
+ if (meta !== undefined)
160
+ result.metadata = meta;
161
+ return result;
162
+ });
163
+ }
164
+ async remove(id) {
165
+ await this._ensureSchema();
166
+ const rows = await this._query(`DELETE FROM ${this._qi(this._table)} WHERE id = $1 RETURNING id`, [id]);
167
+ return rows.length > 0;
168
+ }
169
+ async count() {
170
+ await this._ensureSchema();
171
+ const rows = await this._query(`SELECT COUNT(*)::int AS count FROM ${this._qi(this._table)}`);
172
+ return Number(rows[0]?.["count"] ?? 0);
173
+ }
174
+ // -------------------------------------------------------------------------
175
+ // Internal helpers
176
+ // -------------------------------------------------------------------------
177
+ _validateDimensions(vector) {
178
+ if (vector.length === 0) {
179
+ throw new Error("Cannot store a zero-length vector.");
180
+ }
181
+ if (vector.length !== this._dimensions) {
182
+ throw new Error(`Dimension mismatch: expected ${this._dimensions}, got ${vector.length}.`);
183
+ }
184
+ }
185
+ /** Format a number array as a pgvector literal `[1,2,3]`. */
186
+ _vec(v) {
187
+ return `[${v.join(",")}]`;
188
+ }
189
+ /** Quote a SQL identifier to prevent injection. */
190
+ _qi(identifier) {
191
+ return `"${identifier.replace(/"/g, '""')}"`;
192
+ }
193
+ /** Build a WHERE clause from a VectorFilter, starting param indices at `startIdx`. */
194
+ _buildFilterClause(filter, startIdx) {
195
+ if (!filter || Object.keys(filter).length === 0) {
196
+ return { clause: "", params: [], nextIndex: startIdx };
197
+ }
198
+ const parts = [];
199
+ const params = [];
200
+ let idx = startIdx;
201
+ for (const [key, value] of Object.entries(filter)) {
202
+ // Use JSONB containment for metadata filtering.
203
+ const fragment = JSON.stringify({ [key]: value });
204
+ parts.push(`metadata @> $${idx}::jsonb`);
205
+ params.push(fragment);
206
+ idx++;
207
+ }
208
+ return {
209
+ clause: `WHERE ${parts.join(" AND ")}`,
210
+ params,
211
+ nextIndex: idx,
212
+ };
213
+ }
214
+ }
215
+ //# sourceMappingURL=vector-store-pgvector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-store-pgvector.js","sourceRoot":"","sources":["../../../.claude/worktrees/agent-a1ae6f0b/packages/db/src/vector-store-pgvector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import type { VectorFilter, VectorHybridSearchOptions, VectorSearchResult, VectorStore, VectorStoreConfig } from "./vector-store.js";
2
+ /**
3
+ * Minimal interface for a `better-sqlite3` Database instance.
4
+ *
5
+ * We only declare the subset of the API we actually use so that callers are
6
+ * not forced to depend on `@types/better-sqlite3`.
7
+ */
8
+ export interface SqliteConnection {
9
+ prepare(sql: string): {
10
+ run(...params: unknown[]): {
11
+ changes: number;
12
+ };
13
+ all(...params: unknown[]): Record<string, unknown>[];
14
+ get(...params: unknown[]): Record<string, unknown> | undefined;
15
+ };
16
+ exec(sql: string): void;
17
+ }
18
+ /**
19
+ * SQLite vector store.
20
+ *
21
+ * Stores vectors as JSON text columns and loads them into memory for
22
+ * brute-force cosine search. The trade-off is durability with a simple
23
+ * dependency chain — no native extensions beyond `better-sqlite3`.
24
+ */
25
+ export declare class SqliteVectorStore implements VectorStore {
26
+ private readonly _db;
27
+ private readonly _table;
28
+ private readonly _dimensions;
29
+ private _initialised;
30
+ constructor(config: VectorStoreConfig & {
31
+ connection: SqliteConnection;
32
+ });
33
+ /** @internal */
34
+ _ensureSchema(): void;
35
+ upsert(id: string, vector: number[], metadata?: Record<string, unknown>): Promise<void>;
36
+ upsertBatch(items: ReadonlyArray<{
37
+ id: string;
38
+ vector: number[];
39
+ metadata?: Record<string, unknown>;
40
+ }>): Promise<void>;
41
+ search(query: number[], k: number, filter?: VectorFilter): Promise<VectorSearchResult[]>;
42
+ hybridSearch(query: string, queryVector: number[], k: number, opts?: VectorHybridSearchOptions): Promise<VectorSearchResult[]>;
43
+ remove(id: string): Promise<boolean>;
44
+ count(): Promise<number>;
45
+ private _validateDimensions;
46
+ /** Load all stored rows, parsing JSON columns. */
47
+ private _loadAll;
48
+ /** Escape a SQL identifier (double-quote style). */
49
+ private _esc;
50
+ }
51
+ //# sourceMappingURL=vector-store-sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-store-sqlite.d.ts","sourceRoot":"","sources":["../../../.claude/worktrees/agent-a1ae6f0b/packages/db/src/vector-store-sqlite.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;QACpB,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;KAChE,CAAC;IACF,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AA2CD;;;;;;GAMG;AACH,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAmB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,iBAAiB,GAAG;QAAE,UAAU,EAAE,gBAAgB,CAAA;KAAE;IAaxE,gBAAgB;IAChB,aAAa,IAAI,IAAI;IAiBf,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBvF,WAAW,CACf,KAAK,EAAE,aAAa,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,GACzF,OAAO,CAAC,IAAI,CAAC;IAqBV,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAkBxF,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EAAE,EACrB,CAAC,EAAE,MAAM,EACT,IAAI,CAAC,EAAE,yBAAyB,GAC/B,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAgC1B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQpC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAY9B,OAAO,CAAC,mBAAmB;IAW3B,kDAAkD;IAClD,OAAO,CAAC,QAAQ;IAahB,oDAAoD;IACpD,OAAO,CAAC,IAAI;CAGb"}