clanka 0.2.69 → 0.2.70
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.
- package/dist/ChunkRepo.d.ts +1 -1
- package/dist/ChunkRepo.d.ts.map +1 -1
- package/dist/ChunkRepo.js +36 -21
- package/dist/ChunkRepo.js.map +1 -1
- package/dist/ChunkRepo.test.d.ts +2 -0
- package/dist/ChunkRepo.test.d.ts.map +1 -0
- package/dist/ChunkRepo.test.js +63 -0
- package/dist/ChunkRepo.test.js.map +1 -0
- package/dist/Sqlite.js +2 -2
- package/dist/Sqlite.js.map +1 -1
- package/package.json +2 -10
- package/src/ChunkRepo.test.ts +89 -0
- package/src/ChunkRepo.ts +37 -21
- package/src/Sqlite.ts +2 -2
- package/dist/internal/sqlite-vector.d.ts +0 -16
- package/dist/internal/sqlite-vector.d.ts.map +0 -1
- package/dist/internal/sqlite-vector.js +0 -181
- package/dist/internal/sqlite-vector.js.map +0 -1
- package/src/internal/sqlite-vector.ts +0 -214
package/dist/ChunkRepo.d.ts
CHANGED
|
@@ -167,6 +167,6 @@ export declare class ChunkRepoError extends ChunkRepoError_base {
|
|
|
167
167
|
* @since 1.0.0
|
|
168
168
|
* @category Layers
|
|
169
169
|
*/
|
|
170
|
-
export declare const layer: Layer.Layer<ChunkRepo,
|
|
170
|
+
export declare const layer: Layer.Layer<ChunkRepo, SqlError.SqlError, SqlClient.SqlClient | EmbeddingModel.Dimensions>;
|
|
171
171
|
export {};
|
|
172
172
|
//# sourceMappingURL=ChunkRepo.d.ts.map
|
package/dist/ChunkRepo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChunkRepo.d.ts","sourceRoot":"","sources":["../src/ChunkRepo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAEzC,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAC1D,OAAO,KAAK,QAAQ,MAAM,8BAA8B,CAAA;AAGxD,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,cAAc,MAAM,mCAAmC,CAAA;AAInE;;;GAGG;AACH,eAAO,MAAM,OAAO,kDAAwD,CAAA;AAC5E;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC;;;GAGG;AACH,eAAO,MAAM,MAAM,iDAAuD,CAAA;AAC1E;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAEvC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,6EAGhB,CAAA;AAEf;;;GAGG;AACH,eAAO,MAAM,qBAAqB,0IAQjC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;EAK5B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF;;;GAGG;AACH,qBAAa,KAAM,SAAQ,UAOzB;CAAG;;kBAUQ,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,GAC9B,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC;iBAGjC,OAAO,GACV,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,CAAC,kBAAkB,CAAC;iBAErD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;oBAE3D;QACd,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;QAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KACvB,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;cAErC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;uBAGlC,OAAO,UACR,MAAM,GACb,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;uBACnB,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;4BACvC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;;AA7BxE;;;GAGG;AACH,qBAAa,SAAU,SAAQ,cA2BR;CAAG;;;;AAE1B;;;GAGG;AACH,qBAAa,cAAe,SAAQ,mBAKnC;IACC,QAAQ,CAAC,KAAK,oBAAc;IAC5B,QAAQ,CAAC,OAAO,SAAsB;CACvC;AAED;;;GAGG;AACH,eAAO,MAAM,KAAK,
|
|
1
|
+
{"version":3,"file":"ChunkRepo.d.ts","sourceRoot":"","sources":["../src/ChunkRepo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AAEzC,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAC1D,OAAO,KAAK,QAAQ,MAAM,8BAA8B,CAAA;AAGxD,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,KAAK,MAAM,MAAM,eAAe,CAAA;AAC5C,OAAO,KAAK,cAAc,MAAM,mCAAmC,CAAA;AAInE;;;GAGG;AACH,eAAO,MAAM,OAAO,kDAAwD,CAAA;AAC5E;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC;;;GAGG;AACH,eAAO,MAAM,MAAM,iDAAuD,CAAA;AAC1E;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAEvC;;;GAGG;AACH,eAAO,MAAM,kBAAkB,6EAGhB,CAAA;AAEf;;;GAGG;AACH,eAAO,MAAM,qBAAqB,0IAQjC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;EAK5B,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF;;;GAGG;AACH,qBAAa,KAAM,SAAQ,UAOzB;CAAG;;kBAUQ,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,GAC9B,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC;iBAGjC,OAAO,GACV,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,CAAC,kBAAkB,CAAC;iBAErD,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;oBAE3D;QACd,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;QAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KACvB,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;cAErC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;uBAGlC,OAAO,UACR,MAAM,GACb,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;uBACnB,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;4BACvC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC;;AA7BxE;;;GAGG;AACH,qBAAa,SAAU,SAAQ,cA2BR;CAAG;;;;AAE1B;;;GAGG;AACH,qBAAa,cAAe,SAAQ,mBAKnC;IACC,QAAQ,CAAC,KAAK,oBAAc;IAC5B,QAAQ,CAAC,OAAO,SAAsB;CACvC;AAED;;;GAGG;AACH,eAAO,MAAM,KAAK,4FA0HjB,CAAA"}
|
package/dist/ChunkRepo.js
CHANGED
|
@@ -80,20 +80,37 @@ export class ChunkRepoError extends Schema.TaggedErrorClass()("ChunkRepoError",
|
|
|
80
80
|
export const layer = Layer.effect(ChunkRepo, Effect.gen(function* () {
|
|
81
81
|
const sql = yield* SqlClient.SqlClient;
|
|
82
82
|
const dimensions = yield* EmbeddingModel.Dimensions;
|
|
83
|
+
yield* Effect.gen(function* () {
|
|
84
|
+
yield* sql `CREATE VIRTUAL TABLE IF NOT EXISTS chunk_vectors USING vec0(
|
|
85
|
+
vector float[${sql.literal(String(dimensions))}]
|
|
86
|
+
)`;
|
|
87
|
+
yield* sql `CREATE TRIGGER IF NOT EXISTS chunks_vector_insert
|
|
88
|
+
AFTER INSERT ON chunks
|
|
89
|
+
BEGIN
|
|
90
|
+
INSERT INTO chunk_vectors(rowid, vector) VALUES (new.id, new.vector);
|
|
91
|
+
END`;
|
|
92
|
+
yield* sql `CREATE TRIGGER IF NOT EXISTS chunks_vector_update
|
|
93
|
+
AFTER UPDATE OF vector ON chunks
|
|
94
|
+
BEGIN
|
|
95
|
+
DELETE FROM chunk_vectors WHERE rowid = old.id;
|
|
96
|
+
INSERT INTO chunk_vectors(rowid, vector) VALUES (new.id, new.vector);
|
|
97
|
+
END`;
|
|
98
|
+
yield* sql `CREATE TRIGGER IF NOT EXISTS chunks_vector_delete
|
|
99
|
+
AFTER DELETE ON chunks
|
|
100
|
+
BEGIN
|
|
101
|
+
DELETE FROM chunk_vectors WHERE rowid = old.id;
|
|
102
|
+
END`;
|
|
103
|
+
yield* sql `DELETE FROM chunk_vectors
|
|
104
|
+
WHERE rowid NOT IN (SELECT id FROM chunks)`;
|
|
105
|
+
yield* sql `INSERT INTO chunk_vectors(rowid, vector)
|
|
106
|
+
SELECT id, vector FROM chunks
|
|
107
|
+
WHERE id NOT IN (SELECT rowid FROM chunk_vectors)`;
|
|
108
|
+
}).pipe(sql.withTransaction);
|
|
83
109
|
const loaders = yield* SqlModel.makeResolvers(Chunk, {
|
|
84
110
|
tableName: "chunks",
|
|
85
111
|
idColumn: "id",
|
|
86
112
|
spanPrefix: "ChunkRepo",
|
|
87
113
|
});
|
|
88
|
-
let needsQuantization = true;
|
|
89
|
-
const maybeQuantize = Effect.gen(function* () {
|
|
90
|
-
if (!needsQuantization)
|
|
91
|
-
return;
|
|
92
|
-
needsQuantization = false;
|
|
93
|
-
yield* sql `select vector_init('chunks', 'vector', 'type=FLOAT32,dimension=${sql.literal(String(dimensions))}')`;
|
|
94
|
-
yield* sql `select vector_quantize('chunks', 'vector')`;
|
|
95
|
-
}).pipe(Effect.mapError((reason) => new ChunkRepoError({ reason })));
|
|
96
|
-
yield* Effect.forkScoped(maybeQuantize);
|
|
97
114
|
const search = SqlSchema.findAll({
|
|
98
115
|
Request: Schema.Struct({
|
|
99
116
|
vector: Float32ArraySchema,
|
|
@@ -102,9 +119,11 @@ export const layer = Layer.effect(ChunkRepo, Effect.gen(function* () {
|
|
|
102
119
|
Result: Chunk,
|
|
103
120
|
execute: ({ vector, limit }) => sql `
|
|
104
121
|
select chunks.id, chunks.path, chunks.content, chunks.hash, chunks.syncId
|
|
105
|
-
from
|
|
106
|
-
JOIN
|
|
107
|
-
|
|
122
|
+
from chunk_vectors
|
|
123
|
+
JOIN chunks ON chunks.id = chunk_vectors.rowid
|
|
124
|
+
WHERE chunk_vectors.vector MATCH ${vector}
|
|
125
|
+
AND k = CAST(${limit} AS INTEGER)
|
|
126
|
+
ORDER BY chunk_vectors.distance
|
|
108
127
|
`,
|
|
109
128
|
});
|
|
110
129
|
const exists = SqlResolver.findById({
|
|
@@ -121,13 +140,10 @@ export const layer = Layer.effect(ChunkRepo, Effect.gen(function* () {
|
|
|
121
140
|
const insertResolver = loaders.insert.pipe(RequestResolver.setDelay(5));
|
|
122
141
|
const findByIdResolver = loaders.findById.pipe(RequestResolver.setDelay(5));
|
|
123
142
|
return ChunkRepo.of({
|
|
124
|
-
insert: (insert) => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
ResultLengthMismatch: Effect.die,
|
|
129
|
-
}, (reason) => Effect.fail(new ChunkRepoError({ reason }))));
|
|
130
|
-
},
|
|
143
|
+
insert: (insert) => SqlResolver.request(insert, insertResolver).pipe(Effect.catchTags({
|
|
144
|
+
SchemaError: Effect.die,
|
|
145
|
+
ResultLengthMismatch: Effect.die,
|
|
146
|
+
}, (reason) => Effect.fail(new ChunkRepoError({ reason })))),
|
|
131
147
|
findById: (id) => SqlResolver.request(id, findByIdResolver).pipe(Effect.catchTags({
|
|
132
148
|
SchemaError: Effect.die,
|
|
133
149
|
SqlError: (reason) => Effect.fail(new ChunkRepoError({ reason })),
|
|
@@ -137,13 +153,12 @@ export const layer = Layer.effect(ChunkRepo, Effect.gen(function* () {
|
|
|
137
153
|
SchemaError: Effect.die,
|
|
138
154
|
})),
|
|
139
155
|
search: Effect.fn("ChunkRepo.search")(function* (options) {
|
|
140
|
-
yield* maybeQuantize;
|
|
141
156
|
return yield* search(options).pipe(Effect.catchTags({
|
|
142
157
|
SqlError: (reason) => Effect.fail(new ChunkRepoError({ reason })),
|
|
143
158
|
SchemaError: Effect.die,
|
|
144
159
|
}));
|
|
145
160
|
}),
|
|
146
|
-
quantize:
|
|
161
|
+
quantize: Effect.void,
|
|
147
162
|
setSyncId: (chunkId, syncId) => sql `update chunks set syncId = ${syncId} where id = ${chunkId}`.pipe(Effect.mapError((reason) => new ChunkRepoError({ reason }))),
|
|
148
163
|
deleteByPath: (path) => sql `delete from chunks where path = ${path}`.pipe(Effect.mapError((reason) => new ChunkRepoError({ reason }))),
|
|
149
164
|
deleteForSyncId: (syncId) => sql `delete from chunks where syncId != ${syncId}`.pipe(Effect.mapError((reason) => new ChunkRepoError({ reason }))),
|
package/dist/ChunkRepo.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChunkRepo.js","sourceRoot":"","sources":["../src/ChunkRepo.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ChunkRepo.js","sourceRoot":"","sources":["../src/ChunkRepo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChunkRepo.test.d.ts","sourceRoot":"","sources":["../src/ChunkRepo.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import * as NodeServices from "@effect/platform-node/NodeServices";
|
|
5
|
+
import { assert, describe, it } from "@effect/vitest";
|
|
6
|
+
import * as Effect from "effect/Effect";
|
|
7
|
+
import * as Layer from "effect/Layer";
|
|
8
|
+
import * as EmbeddingModel from "effect/unstable/ai/EmbeddingModel";
|
|
9
|
+
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
10
|
+
import { Chunk, ChunkRepo, layer, SyncId } from "./ChunkRepo.js";
|
|
11
|
+
import { SqliteLayer } from "./Sqlite.js";
|
|
12
|
+
const withDatabase = Effect.acquireRelease(Effect.promise(() => mkdtemp(join(tmpdir(), "clanka-"))), (directory) => Effect.promise(() => rm(directory, { recursive: true })));
|
|
13
|
+
const sqliteLayer = (database) => SqliteLayer(database).pipe(Layer.provide(NodeServices.layer));
|
|
14
|
+
describe("ChunkRepo", () => {
|
|
15
|
+
it.live("backfills and synchronizes the vec0 index", () => Effect.gen(function* () {
|
|
16
|
+
const directory = yield* withDatabase;
|
|
17
|
+
const database = join(directory, "search.sqlite");
|
|
18
|
+
const existingVector = new Float32Array([0, 1, 0]);
|
|
19
|
+
yield* Effect.gen(function* () {
|
|
20
|
+
const sql = yield* SqlClient.SqlClient;
|
|
21
|
+
yield* sql `INSERT INTO chunks(path, content, hash, vector, syncId)
|
|
22
|
+
VALUES ('existing.ts', 'existing', 'existing', ${existingVector}, 'sync')`;
|
|
23
|
+
}).pipe(Effect.provide(sqliteLayer(database)), Effect.scoped);
|
|
24
|
+
const databaseLayer = sqliteLayer(database);
|
|
25
|
+
const repoLayer = Layer.merge(layer.pipe(Layer.provide(databaseLayer)), databaseLayer).pipe(Layer.provide(Layer.succeed(EmbeddingModel.Dimensions, 3)));
|
|
26
|
+
yield* Effect.gen(function* () {
|
|
27
|
+
const repo = yield* ChunkRepo;
|
|
28
|
+
const sql = yield* SqlClient.SqlClient;
|
|
29
|
+
const backfilled = yield* repo.search({
|
|
30
|
+
vector: existingVector,
|
|
31
|
+
limit: 1,
|
|
32
|
+
});
|
|
33
|
+
assert.strictEqual(backfilled[0]?.path, "existing.ts");
|
|
34
|
+
const inserted = yield* repo.insert(Chunk.insert.make({
|
|
35
|
+
path: "inserted.ts",
|
|
36
|
+
content: "inserted",
|
|
37
|
+
hash: "inserted",
|
|
38
|
+
vector: new Float32Array([1, 0, 0]),
|
|
39
|
+
syncId: SyncId.make("sync"),
|
|
40
|
+
}));
|
|
41
|
+
const insertedResult = yield* repo.search({
|
|
42
|
+
vector: new Float32Array([1, 0, 0]),
|
|
43
|
+
limit: 1,
|
|
44
|
+
});
|
|
45
|
+
assert.strictEqual(insertedResult[0]?.id, inserted.id);
|
|
46
|
+
yield* sql `UPDATE chunks
|
|
47
|
+
SET vector = ${new Float32Array([0, 0, 1])}
|
|
48
|
+
WHERE id = ${inserted.id}`;
|
|
49
|
+
const updatedResult = yield* repo.search({
|
|
50
|
+
vector: new Float32Array([0, 0, 1]),
|
|
51
|
+
limit: 1,
|
|
52
|
+
});
|
|
53
|
+
assert.strictEqual(updatedResult[0]?.id, inserted.id);
|
|
54
|
+
yield* repo.deleteByPath("inserted.ts");
|
|
55
|
+
const deletedResult = yield* repo.search({
|
|
56
|
+
vector: new Float32Array([0, 0, 1]),
|
|
57
|
+
limit: 2,
|
|
58
|
+
});
|
|
59
|
+
assert.deepStrictEqual(deletedResult.map((chunk) => chunk.path), ["existing.ts"]);
|
|
60
|
+
}).pipe(Effect.provide(repoLayer), Effect.scoped);
|
|
61
|
+
}));
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=ChunkRepo.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChunkRepo.test.js","sourceRoot":"","sources":["../src/ChunkRepo.test.ts"],"names":[],"mappings":"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"}
|
package/dist/Sqlite.js
CHANGED
|
@@ -8,7 +8,7 @@ import * as Layer from "effect/Layer";
|
|
|
8
8
|
import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
9
9
|
import * as FileSystem from "effect/FileSystem";
|
|
10
10
|
import * as Path from "effect/Path";
|
|
11
|
-
import {
|
|
11
|
+
import { getLoadablePath } from "sqlite-vec";
|
|
12
12
|
/**
|
|
13
13
|
* @since 1.0.0
|
|
14
14
|
* @category Layers
|
|
@@ -30,7 +30,7 @@ export const SqliteLayer = (database) => SqliteMigrator.layer({
|
|
|
30
30
|
}),
|
|
31
31
|
}).pipe(Layer.provide(Layer.effectDiscard(Effect.gen(function* () {
|
|
32
32
|
const client = yield* SqliteClient.SqliteClient;
|
|
33
|
-
yield* client.loadExtension(
|
|
33
|
+
yield* client.loadExtension(getLoadablePath());
|
|
34
34
|
}))), Layer.provideMerge(SqliteClient.layer({
|
|
35
35
|
filename: database,
|
|
36
36
|
})), Layer.provide(Layer.effectDiscard(Effect.gen(function* () {
|
package/dist/Sqlite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sqlite.js","sourceRoot":"","sources":["../src/Sqlite.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,YAAY,MAAM,sCAAsC,CAAA;AACpE,OAAO,KAAK,cAAc,MAAM,wCAAwC,CAAA;AACxE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAC1D,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"Sqlite.js","sourceRoot":"","sources":["../src/Sqlite.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,YAAY,MAAM,sCAAsC,CAAA;AACpE,OAAO,KAAK,cAAc,MAAM,wCAAwC,CAAA;AACxE,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,SAAS,MAAM,+BAA+B,CAAA;AAC1D,OAAO,KAAK,UAAU,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAE,EAAE,CAC9C,cAAc,CAAC,KAAK,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC;QAChC,oBAAoB,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACxC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC,SAAS,CAAA;YAEtC,KAAK,CAAC,CAAC,GAAG,CAAA;;;;;;;UAOR,CAAA;YAEF,KAAK,CAAC,CAAC,GAAG,CAAA,6DAA6D,CAAA;QACzE,CAAC,CAAC;KACH,CAAC;CACH,CAAC,CAAC,IAAI,CACL,KAAK,CAAC,OAAO,CACX,KAAK,CAAC,aAAa,CACjB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,YAAY,CAAC,YAAY,CAAA;IAC/C,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,eAAe,EAAE,CAAC,CAAA;AAChD,CAAC,CAAC,CACH,CACF,EACD,KAAK,CAAC,YAAY,CAChB,YAAY,CAAC,KAAK,CAAC;IACjB,QAAQ,EAAE,QAAQ;CACnB,CAAC,CACH,EACD,KAAK,CAAC,OAAO,CACX,KAAK,CAAC,aAAa,CACjB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAA;IACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACxC,IAAI,SAAS,KAAK,GAAG;QAAE,OAAM;IAC7B,KAAK,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;AACzD,CAAC,CAAC,CACH,CACF,CACF,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clanka",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.70",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -29,20 +29,12 @@
|
|
|
29
29
|
"@vscode/ripgrep": "^1.18.0",
|
|
30
30
|
"chalk": "^5.6.2",
|
|
31
31
|
"glob": "^13.0.6",
|
|
32
|
+
"sqlite-vec": "0.1.9",
|
|
32
33
|
"tree-sitter": "^0.21.1",
|
|
33
34
|
"tree-sitter-javascript": "^0.23.1",
|
|
34
35
|
"tree-sitter-typescript": "^0.23.2",
|
|
35
36
|
"turndown": "^7.2.4"
|
|
36
37
|
},
|
|
37
|
-
"optionalDependencies": {
|
|
38
|
-
"@sqliteai/sqlite-vector-darwin-arm64": "0.9.95",
|
|
39
|
-
"@sqliteai/sqlite-vector-darwin-x86_64": "0.9.95",
|
|
40
|
-
"@sqliteai/sqlite-vector-linux-arm64": "0.9.95",
|
|
41
|
-
"@sqliteai/sqlite-vector-linux-arm64-musl": "0.9.95",
|
|
42
|
-
"@sqliteai/sqlite-vector-linux-x86_64": "0.9.95",
|
|
43
|
-
"@sqliteai/sqlite-vector-linux-x86_64-musl": "0.9.95",
|
|
44
|
-
"@sqliteai/sqlite-vector-win32-x86_64": "0.9.95"
|
|
45
|
-
},
|
|
46
38
|
"peerDependencies": {
|
|
47
39
|
"@effect/ai-openai": ">=4.0.0-beta.94 <4.0.1",
|
|
48
40
|
"@effect/ai-openai-compat": ">=4.0.0-beta.94 <4.0.1",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises"
|
|
2
|
+
import { tmpdir } from "node:os"
|
|
3
|
+
import { join } from "node:path"
|
|
4
|
+
import * as NodeServices from "@effect/platform-node/NodeServices"
|
|
5
|
+
import { assert, describe, it } from "@effect/vitest"
|
|
6
|
+
import * as Effect from "effect/Effect"
|
|
7
|
+
import * as Layer from "effect/Layer"
|
|
8
|
+
import * as EmbeddingModel from "effect/unstable/ai/EmbeddingModel"
|
|
9
|
+
import * as SqlClient from "effect/unstable/sql/SqlClient"
|
|
10
|
+
import { Chunk, ChunkRepo, layer, SyncId } from "./ChunkRepo.ts"
|
|
11
|
+
import { SqliteLayer } from "./Sqlite.ts"
|
|
12
|
+
|
|
13
|
+
const withDatabase = Effect.acquireRelease(
|
|
14
|
+
Effect.promise(() => mkdtemp(join(tmpdir(), "clanka-"))),
|
|
15
|
+
(directory) => Effect.promise(() => rm(directory, { recursive: true })),
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
const sqliteLayer = (database: string) =>
|
|
19
|
+
SqliteLayer(database).pipe(Layer.provide(NodeServices.layer))
|
|
20
|
+
|
|
21
|
+
describe("ChunkRepo", () => {
|
|
22
|
+
it.live("backfills and synchronizes the vec0 index", () =>
|
|
23
|
+
Effect.gen(function* () {
|
|
24
|
+
const directory = yield* withDatabase
|
|
25
|
+
const database = join(directory, "search.sqlite")
|
|
26
|
+
const existingVector = new Float32Array([0, 1, 0])
|
|
27
|
+
|
|
28
|
+
yield* Effect.gen(function* () {
|
|
29
|
+
const sql = yield* SqlClient.SqlClient
|
|
30
|
+
yield* sql`INSERT INTO chunks(path, content, hash, vector, syncId)
|
|
31
|
+
VALUES ('existing.ts', 'existing', 'existing', ${existingVector}, 'sync')`
|
|
32
|
+
}).pipe(Effect.provide(sqliteLayer(database)), Effect.scoped)
|
|
33
|
+
|
|
34
|
+
const databaseLayer = sqliteLayer(database)
|
|
35
|
+
const repoLayer = Layer.merge(
|
|
36
|
+
layer.pipe(Layer.provide(databaseLayer)),
|
|
37
|
+
databaseLayer,
|
|
38
|
+
).pipe(Layer.provide(Layer.succeed(EmbeddingModel.Dimensions, 3)))
|
|
39
|
+
|
|
40
|
+
yield* Effect.gen(function* () {
|
|
41
|
+
const repo = yield* ChunkRepo
|
|
42
|
+
const sql = yield* SqlClient.SqlClient
|
|
43
|
+
|
|
44
|
+
const backfilled = yield* repo.search({
|
|
45
|
+
vector: existingVector,
|
|
46
|
+
limit: 1,
|
|
47
|
+
})
|
|
48
|
+
assert.strictEqual(backfilled[0]?.path, "existing.ts")
|
|
49
|
+
|
|
50
|
+
const inserted = yield* repo.insert(
|
|
51
|
+
Chunk.insert.make({
|
|
52
|
+
path: "inserted.ts",
|
|
53
|
+
content: "inserted",
|
|
54
|
+
hash: "inserted",
|
|
55
|
+
vector: new Float32Array([1, 0, 0]),
|
|
56
|
+
syncId: SyncId.make("sync"),
|
|
57
|
+
}),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
const insertedResult = yield* repo.search({
|
|
61
|
+
vector: new Float32Array([1, 0, 0]),
|
|
62
|
+
limit: 1,
|
|
63
|
+
})
|
|
64
|
+
assert.strictEqual(insertedResult[0]?.id, inserted.id)
|
|
65
|
+
|
|
66
|
+
yield* sql`UPDATE chunks
|
|
67
|
+
SET vector = ${new Float32Array([0, 0, 1])}
|
|
68
|
+
WHERE id = ${inserted.id}`
|
|
69
|
+
|
|
70
|
+
const updatedResult = yield* repo.search({
|
|
71
|
+
vector: new Float32Array([0, 0, 1]),
|
|
72
|
+
limit: 1,
|
|
73
|
+
})
|
|
74
|
+
assert.strictEqual(updatedResult[0]?.id, inserted.id)
|
|
75
|
+
|
|
76
|
+
yield* repo.deleteByPath("inserted.ts")
|
|
77
|
+
|
|
78
|
+
const deletedResult = yield* repo.search({
|
|
79
|
+
vector: new Float32Array([0, 0, 1]),
|
|
80
|
+
limit: 2,
|
|
81
|
+
})
|
|
82
|
+
assert.deepStrictEqual(
|
|
83
|
+
deletedResult.map((chunk) => chunk.path),
|
|
84
|
+
["existing.ts"],
|
|
85
|
+
)
|
|
86
|
+
}).pipe(Effect.provide(repoLayer), Effect.scoped)
|
|
87
|
+
}),
|
|
88
|
+
)
|
|
89
|
+
})
|
package/src/ChunkRepo.ts
CHANGED
|
@@ -139,23 +139,40 @@ export const layer = Layer.effect(
|
|
|
139
139
|
Effect.gen(function* () {
|
|
140
140
|
const sql = yield* SqlClient.SqlClient
|
|
141
141
|
const dimensions = yield* EmbeddingModel.Dimensions
|
|
142
|
+
|
|
143
|
+
yield* Effect.gen(function* () {
|
|
144
|
+
yield* sql`CREATE VIRTUAL TABLE IF NOT EXISTS chunk_vectors USING vec0(
|
|
145
|
+
vector float[${sql.literal(String(dimensions))}]
|
|
146
|
+
)`
|
|
147
|
+
yield* sql`CREATE TRIGGER IF NOT EXISTS chunks_vector_insert
|
|
148
|
+
AFTER INSERT ON chunks
|
|
149
|
+
BEGIN
|
|
150
|
+
INSERT INTO chunk_vectors(rowid, vector) VALUES (new.id, new.vector);
|
|
151
|
+
END`
|
|
152
|
+
yield* sql`CREATE TRIGGER IF NOT EXISTS chunks_vector_update
|
|
153
|
+
AFTER UPDATE OF vector ON chunks
|
|
154
|
+
BEGIN
|
|
155
|
+
DELETE FROM chunk_vectors WHERE rowid = old.id;
|
|
156
|
+
INSERT INTO chunk_vectors(rowid, vector) VALUES (new.id, new.vector);
|
|
157
|
+
END`
|
|
158
|
+
yield* sql`CREATE TRIGGER IF NOT EXISTS chunks_vector_delete
|
|
159
|
+
AFTER DELETE ON chunks
|
|
160
|
+
BEGIN
|
|
161
|
+
DELETE FROM chunk_vectors WHERE rowid = old.id;
|
|
162
|
+
END`
|
|
163
|
+
yield* sql`DELETE FROM chunk_vectors
|
|
164
|
+
WHERE rowid NOT IN (SELECT id FROM chunks)`
|
|
165
|
+
yield* sql`INSERT INTO chunk_vectors(rowid, vector)
|
|
166
|
+
SELECT id, vector FROM chunks
|
|
167
|
+
WHERE id NOT IN (SELECT rowid FROM chunk_vectors)`
|
|
168
|
+
}).pipe(sql.withTransaction)
|
|
169
|
+
|
|
142
170
|
const loaders = yield* SqlModel.makeResolvers(Chunk, {
|
|
143
171
|
tableName: "chunks",
|
|
144
172
|
idColumn: "id",
|
|
145
173
|
spanPrefix: "ChunkRepo",
|
|
146
174
|
})
|
|
147
175
|
|
|
148
|
-
let needsQuantization = true
|
|
149
|
-
|
|
150
|
-
const maybeQuantize = Effect.gen(function* () {
|
|
151
|
-
if (!needsQuantization) return
|
|
152
|
-
needsQuantization = false
|
|
153
|
-
yield* sql`select vector_init('chunks', 'vector', 'type=FLOAT32,dimension=${sql.literal(String(dimensions))}')`
|
|
154
|
-
yield* sql`select vector_quantize('chunks', 'vector')`
|
|
155
|
-
}).pipe(Effect.mapError((reason) => new ChunkRepoError({ reason })))
|
|
156
|
-
|
|
157
|
-
yield* Effect.forkScoped(maybeQuantize)
|
|
158
|
-
|
|
159
176
|
const search = SqlSchema.findAll({
|
|
160
177
|
Request: Schema.Struct({
|
|
161
178
|
vector: Float32ArraySchema,
|
|
@@ -165,9 +182,11 @@ export const layer = Layer.effect(
|
|
|
165
182
|
execute: ({ vector, limit }) =>
|
|
166
183
|
sql`
|
|
167
184
|
select chunks.id, chunks.path, chunks.content, chunks.hash, chunks.syncId
|
|
168
|
-
from
|
|
169
|
-
JOIN
|
|
170
|
-
|
|
185
|
+
from chunk_vectors
|
|
186
|
+
JOIN chunks ON chunks.id = chunk_vectors.rowid
|
|
187
|
+
WHERE chunk_vectors.vector MATCH ${vector}
|
|
188
|
+
AND k = CAST(${limit} AS INTEGER)
|
|
189
|
+
ORDER BY chunk_vectors.distance
|
|
171
190
|
`,
|
|
172
191
|
})
|
|
173
192
|
|
|
@@ -188,9 +207,8 @@ export const layer = Layer.effect(
|
|
|
188
207
|
const findByIdResolver = loaders.findById.pipe(RequestResolver.setDelay(5))
|
|
189
208
|
|
|
190
209
|
return ChunkRepo.of({
|
|
191
|
-
insert: (insert) =>
|
|
192
|
-
|
|
193
|
-
return SqlResolver.request(insert, insertResolver).pipe(
|
|
210
|
+
insert: (insert) =>
|
|
211
|
+
SqlResolver.request(insert, insertResolver).pipe(
|
|
194
212
|
Effect.catchTags(
|
|
195
213
|
{
|
|
196
214
|
SchemaError: Effect.die,
|
|
@@ -198,8 +216,7 @@ export const layer = Layer.effect(
|
|
|
198
216
|
},
|
|
199
217
|
(reason) => Effect.fail(new ChunkRepoError({ reason })),
|
|
200
218
|
),
|
|
201
|
-
)
|
|
202
|
-
},
|
|
219
|
+
),
|
|
203
220
|
findById: (id) =>
|
|
204
221
|
SqlResolver.request(id, findByIdResolver).pipe(
|
|
205
222
|
Effect.catchTags({
|
|
@@ -217,7 +234,6 @@ export const layer = Layer.effect(
|
|
|
217
234
|
}),
|
|
218
235
|
),
|
|
219
236
|
search: Effect.fn("ChunkRepo.search")(function* (options) {
|
|
220
|
-
yield* maybeQuantize
|
|
221
237
|
return yield* search(options as any).pipe(
|
|
222
238
|
Effect.catchTags({
|
|
223
239
|
SqlError: (reason) => Effect.fail(new ChunkRepoError({ reason })),
|
|
@@ -225,7 +241,7 @@ export const layer = Layer.effect(
|
|
|
225
241
|
}),
|
|
226
242
|
)
|
|
227
243
|
}),
|
|
228
|
-
quantize:
|
|
244
|
+
quantize: Effect.void,
|
|
229
245
|
setSyncId: (chunkId, syncId) =>
|
|
230
246
|
sql`update chunks set syncId = ${syncId} where id = ${chunkId}`.pipe(
|
|
231
247
|
Effect.mapError((reason) => new ChunkRepoError({ reason })),
|
package/src/Sqlite.ts
CHANGED
|
@@ -8,7 +8,7 @@ import * as Layer from "effect/Layer"
|
|
|
8
8
|
import * as SqlClient from "effect/unstable/sql/SqlClient"
|
|
9
9
|
import * as FileSystem from "effect/FileSystem"
|
|
10
10
|
import * as Path from "effect/Path"
|
|
11
|
-
import {
|
|
11
|
+
import { getLoadablePath } from "sqlite-vec"
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* @since 1.0.0
|
|
@@ -37,7 +37,7 @@ export const SqliteLayer = (database: string) =>
|
|
|
37
37
|
Layer.effectDiscard(
|
|
38
38
|
Effect.gen(function* () {
|
|
39
39
|
const client = yield* SqliteClient.SqliteClient
|
|
40
|
-
yield* client.loadExtension(
|
|
40
|
+
yield* client.loadExtension(getLoadablePath())
|
|
41
41
|
}),
|
|
42
42
|
),
|
|
43
43
|
),
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gets the absolute path to the SQLite Vector extension binary for the current platform
|
|
3
|
-
*
|
|
4
|
-
* @returns Absolute path to the extension binary (.so, .dylib, or .dll)
|
|
5
|
-
* @throws {ExtensionNotFoundError} If the extension binary cannot be found
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import { getExtensionPath } from '@sqliteai/sqlite-vector';
|
|
10
|
-
*
|
|
11
|
-
* const extensionPath = getExtensionPath();
|
|
12
|
-
* // On macOS ARM64: /path/to/node_modules/@sqliteai/sqlite-vector-darwin-arm64/vector.dylib
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
export declare function getExtensionPath(): string;
|
|
16
|
-
//# sourceMappingURL=sqlite-vector.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-vector.d.ts","sourceRoot":"","sources":["../../src/internal/sqlite-vector.ts"],"names":[],"mappings":"AAmLA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAoBzC"}
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
|
-
import { platform, arch } from "node:os";
|
|
3
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
-
import { execSync } from "node:child_process";
|
|
5
|
-
/**
|
|
6
|
-
* Binary extension for each platform
|
|
7
|
-
*/
|
|
8
|
-
const PLATFORM_EXTENSIONS = {
|
|
9
|
-
darwin: ".dylib",
|
|
10
|
-
linux: ".so",
|
|
11
|
-
win32: ".dll",
|
|
12
|
-
};
|
|
13
|
-
/**
|
|
14
|
-
* Detects if the system uses musl libc (Alpine Linux, etc.)
|
|
15
|
-
* Uses multiple detection strategies for reliability
|
|
16
|
-
*/
|
|
17
|
-
function isMusl() {
|
|
18
|
-
// Only relevant for Linux
|
|
19
|
-
if (platform() !== "linux") {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
// Strategy 1: Check for musl-specific files
|
|
23
|
-
const muslFiles = [
|
|
24
|
-
"/lib/ld-musl-x86_64.so.1",
|
|
25
|
-
"/lib/ld-musl-aarch64.so.1",
|
|
26
|
-
"/lib/ld-musl-armhf.so.1",
|
|
27
|
-
];
|
|
28
|
-
for (const file of muslFiles) {
|
|
29
|
-
if (existsSync(file)) {
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
// Strategy 2: Check ldd version output
|
|
34
|
-
try {
|
|
35
|
-
const lddVersion = execSync("ldd --version 2>&1", {
|
|
36
|
-
encoding: "utf-8",
|
|
37
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
38
|
-
});
|
|
39
|
-
if (lddVersion.includes("musl")) {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
// ldd command failed, continue to next strategy
|
|
45
|
-
}
|
|
46
|
-
// Strategy 3: Check /etc/os-release for Alpine
|
|
47
|
-
try {
|
|
48
|
-
if (existsSync("/etc/os-release")) {
|
|
49
|
-
const osRelease = readFileSync("/etc/os-release", "utf-8");
|
|
50
|
-
if (osRelease.includes("Alpine") || osRelease.includes("musl")) {
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
// File read failed, continue to next strategy
|
|
57
|
-
}
|
|
58
|
-
// Strategy 4: Check process.report.getReport() for musl
|
|
59
|
-
try {
|
|
60
|
-
const report = process.report?.getReport?.();
|
|
61
|
-
if (report?.header?.glibcVersionRuntime === "") {
|
|
62
|
-
// Empty glibc version often indicates musl
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
// Report not available
|
|
68
|
-
}
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Gets the current platform identifier
|
|
73
|
-
* @throws {Error} If the platform is unsupported
|
|
74
|
-
*/
|
|
75
|
-
function getCurrentPlatform() {
|
|
76
|
-
const platformName = platform();
|
|
77
|
-
const archName = arch();
|
|
78
|
-
// macOS
|
|
79
|
-
if (platformName === "darwin") {
|
|
80
|
-
if (archName === "arm64")
|
|
81
|
-
return "darwin-arm64";
|
|
82
|
-
if (archName === "x64" || archName === "ia32")
|
|
83
|
-
return "darwin-x86_64";
|
|
84
|
-
}
|
|
85
|
-
// Linux (with musl detection)
|
|
86
|
-
if (platformName === "linux") {
|
|
87
|
-
const muslSuffix = isMusl() ? "-musl" : "";
|
|
88
|
-
if (archName === "arm64") {
|
|
89
|
-
return `linux-arm64${muslSuffix}`;
|
|
90
|
-
}
|
|
91
|
-
if (archName === "x64" || archName === "ia32") {
|
|
92
|
-
return `linux-x86_64${muslSuffix}`;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
// Windows
|
|
96
|
-
if (platformName === "win32") {
|
|
97
|
-
if (archName === "x64" || archName === "ia32")
|
|
98
|
-
return "win32-x86_64";
|
|
99
|
-
}
|
|
100
|
-
// Unsupported platform
|
|
101
|
-
throw new Error(`Unsupported platform: ${platformName}-${archName}. ` +
|
|
102
|
-
`Supported platforms: darwin-arm64, darwin-x86_64, linux-arm64, linux-x86_64, win32-x86_64 ` +
|
|
103
|
-
`(with glibc or musl support for Linux)`);
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Gets the package name for the current platform
|
|
107
|
-
*/
|
|
108
|
-
function getPlatformPackageName() {
|
|
109
|
-
const currentPlatform = getCurrentPlatform();
|
|
110
|
-
return `@sqliteai/sqlite-vector-${currentPlatform}`;
|
|
111
|
-
}
|
|
112
|
-
/**
|
|
113
|
-
* Gets the binary filename for the current platform
|
|
114
|
-
*/
|
|
115
|
-
function getBinaryName() {
|
|
116
|
-
const platformName = platform();
|
|
117
|
-
const extension = PLATFORM_EXTENSIONS[platformName];
|
|
118
|
-
if (!extension) {
|
|
119
|
-
throw new Error(`Unknown platform: ${platformName}`);
|
|
120
|
-
}
|
|
121
|
-
return `vector${extension}`;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Error thrown when the SQLite Vector extension cannot be found
|
|
125
|
-
*/
|
|
126
|
-
class ExtensionNotFoundError extends Error {
|
|
127
|
-
constructor(message) {
|
|
128
|
-
super(message);
|
|
129
|
-
this.name = "ExtensionNotFoundError";
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Attempts to load the platform-specific package
|
|
134
|
-
* @returns The path to the extension binary, or null if not found
|
|
135
|
-
*/
|
|
136
|
-
function tryLoadPlatformPackage() {
|
|
137
|
-
try {
|
|
138
|
-
const packageName = getPlatformPackageName();
|
|
139
|
-
const platformPackage = import.meta.resolve(packageName);
|
|
140
|
-
return platformPackage
|
|
141
|
-
.replace(/\/index\.js$/, `/${getBinaryName()}`)
|
|
142
|
-
.replace("file://", "");
|
|
143
|
-
}
|
|
144
|
-
catch {
|
|
145
|
-
// Platform package not installed or failed to load
|
|
146
|
-
// This is expected when optionalDependencies fail
|
|
147
|
-
}
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Gets the absolute path to the SQLite Vector extension binary for the current platform
|
|
152
|
-
*
|
|
153
|
-
* @returns Absolute path to the extension binary (.so, .dylib, or .dll)
|
|
154
|
-
* @throws {ExtensionNotFoundError} If the extension binary cannot be found
|
|
155
|
-
*
|
|
156
|
-
* @example
|
|
157
|
-
* ```typescript
|
|
158
|
-
* import { getExtensionPath } from '@sqliteai/sqlite-vector';
|
|
159
|
-
*
|
|
160
|
-
* const extensionPath = getExtensionPath();
|
|
161
|
-
* // On macOS ARM64: /path/to/node_modules/@sqliteai/sqlite-vector-darwin-arm64/vector.dylib
|
|
162
|
-
* ```
|
|
163
|
-
*/
|
|
164
|
-
export function getExtensionPath() {
|
|
165
|
-
// Try to load from platform-specific package
|
|
166
|
-
const platformPath = tryLoadPlatformPackage();
|
|
167
|
-
if (platformPath) {
|
|
168
|
-
return resolve(platformPath);
|
|
169
|
-
}
|
|
170
|
-
// If we reach here, the platform package wasn't installed
|
|
171
|
-
const currentPlatform = getCurrentPlatform();
|
|
172
|
-
const packageName = getPlatformPackageName();
|
|
173
|
-
throw new ExtensionNotFoundError(`SQLite Vector extension not found for platform: ${currentPlatform}\n\n` +
|
|
174
|
-
`The platform-specific package "${packageName}" is not installed.\n` +
|
|
175
|
-
`This usually happens when:\n` +
|
|
176
|
-
` 1. Your platform is not supported\n` +
|
|
177
|
-
` 2. npm failed to install optional dependencies\n` +
|
|
178
|
-
` 3. You're installing with --no-optional flag\n\n` +
|
|
179
|
-
`Try running: npm install --force`);
|
|
180
|
-
}
|
|
181
|
-
//# sourceMappingURL=sqlite-vector.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-vector.js","sourceRoot":"","sources":["../../src/internal/sqlite-vector.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import { resolve } from "node:path"
|
|
2
|
-
import { platform, arch } from "node:os"
|
|
3
|
-
import { existsSync, readFileSync } from "node:fs"
|
|
4
|
-
import { execSync } from "node:child_process"
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Supported platform identifiers
|
|
8
|
-
*/
|
|
9
|
-
type Platform =
|
|
10
|
-
| "darwin-arm64"
|
|
11
|
-
| "darwin-x86_64"
|
|
12
|
-
| "linux-arm64"
|
|
13
|
-
| "linux-arm64-musl"
|
|
14
|
-
| "linux-x86_64"
|
|
15
|
-
| "linux-x86_64-musl"
|
|
16
|
-
| "win32-x86_64"
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Binary extension for each platform
|
|
20
|
-
*/
|
|
21
|
-
const PLATFORM_EXTENSIONS: Record<string, string> = {
|
|
22
|
-
darwin: ".dylib",
|
|
23
|
-
linux: ".so",
|
|
24
|
-
win32: ".dll",
|
|
25
|
-
} as const
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Detects if the system uses musl libc (Alpine Linux, etc.)
|
|
29
|
-
* Uses multiple detection strategies for reliability
|
|
30
|
-
*/
|
|
31
|
-
function isMusl(): boolean {
|
|
32
|
-
// Only relevant for Linux
|
|
33
|
-
if (platform() !== "linux") {
|
|
34
|
-
return false
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Strategy 1: Check for musl-specific files
|
|
38
|
-
const muslFiles = [
|
|
39
|
-
"/lib/ld-musl-x86_64.so.1",
|
|
40
|
-
"/lib/ld-musl-aarch64.so.1",
|
|
41
|
-
"/lib/ld-musl-armhf.so.1",
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
for (const file of muslFiles) {
|
|
45
|
-
if (existsSync(file)) {
|
|
46
|
-
return true
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Strategy 2: Check ldd version output
|
|
51
|
-
try {
|
|
52
|
-
const lddVersion = execSync("ldd --version 2>&1", {
|
|
53
|
-
encoding: "utf-8",
|
|
54
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
if (lddVersion.includes("musl")) {
|
|
58
|
-
return true
|
|
59
|
-
}
|
|
60
|
-
} catch {
|
|
61
|
-
// ldd command failed, continue to next strategy
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Strategy 3: Check /etc/os-release for Alpine
|
|
65
|
-
try {
|
|
66
|
-
if (existsSync("/etc/os-release")) {
|
|
67
|
-
const osRelease = readFileSync("/etc/os-release", "utf-8")
|
|
68
|
-
if (osRelease.includes("Alpine") || osRelease.includes("musl")) {
|
|
69
|
-
return true
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
} catch {
|
|
73
|
-
// File read failed, continue to next strategy
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Strategy 4: Check process.report.getReport() for musl
|
|
77
|
-
try {
|
|
78
|
-
const report = (process as any).report?.getReport?.()
|
|
79
|
-
if (report?.header?.glibcVersionRuntime === "") {
|
|
80
|
-
// Empty glibc version often indicates musl
|
|
81
|
-
return true
|
|
82
|
-
}
|
|
83
|
-
} catch {
|
|
84
|
-
// Report not available
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return false
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Gets the current platform identifier
|
|
92
|
-
* @throws {Error} If the platform is unsupported
|
|
93
|
-
*/
|
|
94
|
-
function getCurrentPlatform(): Platform {
|
|
95
|
-
const platformName = platform()
|
|
96
|
-
const archName = arch()
|
|
97
|
-
|
|
98
|
-
// macOS
|
|
99
|
-
if (platformName === "darwin") {
|
|
100
|
-
if (archName === "arm64") return "darwin-arm64"
|
|
101
|
-
if (archName === "x64" || archName === "ia32") return "darwin-x86_64"
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Linux (with musl detection)
|
|
105
|
-
if (platformName === "linux") {
|
|
106
|
-
const muslSuffix = isMusl() ? "-musl" : ""
|
|
107
|
-
|
|
108
|
-
if (archName === "arm64") {
|
|
109
|
-
return `linux-arm64${muslSuffix}` as Platform
|
|
110
|
-
}
|
|
111
|
-
if (archName === "x64" || archName === "ia32") {
|
|
112
|
-
return `linux-x86_64${muslSuffix}` as Platform
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Windows
|
|
117
|
-
if (platformName === "win32") {
|
|
118
|
-
if (archName === "x64" || archName === "ia32") return "win32-x86_64"
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Unsupported platform
|
|
122
|
-
throw new Error(
|
|
123
|
-
`Unsupported platform: ${platformName}-${archName}. ` +
|
|
124
|
-
`Supported platforms: darwin-arm64, darwin-x86_64, linux-arm64, linux-x86_64, win32-x86_64 ` +
|
|
125
|
-
`(with glibc or musl support for Linux)`,
|
|
126
|
-
)
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Gets the package name for the current platform
|
|
131
|
-
*/
|
|
132
|
-
function getPlatformPackageName(): string {
|
|
133
|
-
const currentPlatform = getCurrentPlatform()
|
|
134
|
-
return `@sqliteai/sqlite-vector-${currentPlatform}`
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Gets the binary filename for the current platform
|
|
139
|
-
*/
|
|
140
|
-
function getBinaryName(): string {
|
|
141
|
-
const platformName = platform()
|
|
142
|
-
const extension = PLATFORM_EXTENSIONS[platformName]
|
|
143
|
-
|
|
144
|
-
if (!extension) {
|
|
145
|
-
throw new Error(`Unknown platform: ${platformName}`)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return `vector${extension}`
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Error thrown when the SQLite Vector extension cannot be found
|
|
153
|
-
*/
|
|
154
|
-
class ExtensionNotFoundError extends Error {
|
|
155
|
-
constructor(message: string) {
|
|
156
|
-
super(message)
|
|
157
|
-
this.name = "ExtensionNotFoundError"
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Attempts to load the platform-specific package
|
|
163
|
-
* @returns The path to the extension binary, or null if not found
|
|
164
|
-
*/
|
|
165
|
-
function tryLoadPlatformPackage(): string | null {
|
|
166
|
-
try {
|
|
167
|
-
const packageName = getPlatformPackageName()
|
|
168
|
-
const platformPackage = import.meta.resolve(packageName)
|
|
169
|
-
return platformPackage
|
|
170
|
-
.replace(/\/index\.js$/, `/${getBinaryName()}`)
|
|
171
|
-
.replace("file://", "")
|
|
172
|
-
} catch {
|
|
173
|
-
// Platform package not installed or failed to load
|
|
174
|
-
// This is expected when optionalDependencies fail
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return null
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Gets the absolute path to the SQLite Vector extension binary for the current platform
|
|
182
|
-
*
|
|
183
|
-
* @returns Absolute path to the extension binary (.so, .dylib, or .dll)
|
|
184
|
-
* @throws {ExtensionNotFoundError} If the extension binary cannot be found
|
|
185
|
-
*
|
|
186
|
-
* @example
|
|
187
|
-
* ```typescript
|
|
188
|
-
* import { getExtensionPath } from '@sqliteai/sqlite-vector';
|
|
189
|
-
*
|
|
190
|
-
* const extensionPath = getExtensionPath();
|
|
191
|
-
* // On macOS ARM64: /path/to/node_modules/@sqliteai/sqlite-vector-darwin-arm64/vector.dylib
|
|
192
|
-
* ```
|
|
193
|
-
*/
|
|
194
|
-
export function getExtensionPath(): string {
|
|
195
|
-
// Try to load from platform-specific package
|
|
196
|
-
const platformPath = tryLoadPlatformPackage()
|
|
197
|
-
if (platformPath) {
|
|
198
|
-
return resolve(platformPath)
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// If we reach here, the platform package wasn't installed
|
|
202
|
-
const currentPlatform = getCurrentPlatform()
|
|
203
|
-
const packageName = getPlatformPackageName()
|
|
204
|
-
|
|
205
|
-
throw new ExtensionNotFoundError(
|
|
206
|
-
`SQLite Vector extension not found for platform: ${currentPlatform}\n\n` +
|
|
207
|
-
`The platform-specific package "${packageName}" is not installed.\n` +
|
|
208
|
-
`This usually happens when:\n` +
|
|
209
|
-
` 1. Your platform is not supported\n` +
|
|
210
|
-
` 2. npm failed to install optional dependencies\n` +
|
|
211
|
-
` 3. You're installing with --no-optional flag\n\n` +
|
|
212
|
-
`Try running: npm install --force`,
|
|
213
|
-
)
|
|
214
|
-
}
|