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.
@@ -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, never, SqlClient.SqlClient | EmbeddingModel.Dimensions>;
170
+ export declare const layer: Layer.Layer<ChunkRepo, SqlError.SqlError, SqlClient.SqlClient | EmbeddingModel.Dimensions>;
171
171
  export {};
172
172
  //# sourceMappingURL=ChunkRepo.d.ts.map
@@ -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,gFA0GjB,CAAA"}
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 chunks
106
- JOIN vector_quantize_scan('chunks', 'vector', ${vector}, CAST(${limit} AS INTEGER)) AS v
107
- ON chunks.id = v.rowid
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
- needsQuantization = true;
126
- return SqlResolver.request(insert, insertResolver).pipe(Effect.catchTags({
127
- SchemaError: Effect.die,
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: maybeQuantize,
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 }))),
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ChunkRepo.test.d.ts.map
@@ -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 { getExtensionPath } from "./internal/sqlite-vector.js";
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(getExtensionPath());
33
+ yield* client.loadExtension(getLoadablePath());
34
34
  }))), Layer.provideMerge(SqliteClient.layer({
35
35
  filename: database,
36
36
  })), Layer.provide(Layer.effectDiscard(Effect.gen(function* () {
@@ -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,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AAE9D;;;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,gBAAgB,EAAE,CAAC,CAAA;AACjD,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"}
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.69",
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 chunks
169
- JOIN vector_quantize_scan('chunks', 'vector', ${vector}, CAST(${limit} AS INTEGER)) AS v
170
- ON chunks.id = v.rowid
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
- needsQuantization = true
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: maybeQuantize,
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 { getExtensionPath } from "./internal/sqlite-vector.ts"
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(getExtensionPath())
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
- }