@delali/narsil 0.1.6 → 0.1.7

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.
@@ -1,4 +1,4 @@
1
- import { I as InvalidationAdapter } from '../adapters-XODT2F3h.js';
1
+ import { I as InvalidationAdapter } from '../adapters-BbRkoiu9.js';
2
2
 
3
3
  interface BroadcastChannelInvalidationConfig {
4
4
  channelName?: string;
@@ -1,4 +1,4 @@
1
- import { I as InvalidationAdapter } from '../adapters-XODT2F3h.js';
1
+ import { I as InvalidationAdapter } from '../adapters-BbRkoiu9.js';
2
2
 
3
3
  interface FilesystemInvalidationConfig {
4
4
  directory: string;
@@ -1,4 +1,4 @@
1
- import { I as InvalidationAdapter } from '../adapters-XODT2F3h.js';
1
+ import { I as InvalidationAdapter } from '../adapters-BbRkoiu9.js';
2
2
 
3
3
  declare function createNoopInvalidation(): InvalidationAdapter;
4
4
 
@@ -1 +1 @@
1
- export { english } from '../chunk-WYC635GI.mjs';
1
+ export { english } from '../chunk-I24SGLFS.mjs';
@@ -6,7 +6,7 @@ interface HNSWConfig {
6
6
  metric?: VectorMetric;
7
7
  }
8
8
  interface SerializedHNSWGraph {
9
- entryPoint: string;
9
+ entryPoint: string | null;
10
10
  maxLayer: number;
11
11
  m: number;
12
12
  efConstruction: number;
@@ -23,6 +23,13 @@ interface HNSWBuildRequest {
23
23
  dimension: number;
24
24
  config: HNSWConfig;
25
25
  }
26
+ interface HNSWBuildRequestBinary {
27
+ type: 'build-binary';
28
+ docIds: string[];
29
+ vectorData: Float32Array;
30
+ dimension: number;
31
+ config: HNSWConfig;
32
+ }
26
33
  interface HNSWBuildResponse {
27
34
  type: 'success';
28
35
  graph: SerializedHNSWGraph;
@@ -34,4 +41,4 @@ interface HNSWBuildError {
34
41
  type HNSWWorkerMessage = HNSWBuildResponse | HNSWBuildError;
35
42
  declare function handleBuildRequest(request: HNSWBuildRequest): SerializedHNSWGraph;
36
43
 
37
- export { type HNSWBuildError, type HNSWBuildRequest, type HNSWBuildResponse, type HNSWWorkerMessage, handleBuildRequest };
44
+ export { type HNSWBuildError, type HNSWBuildRequest, type HNSWBuildRequestBinary, type HNSWBuildResponse, type HNSWWorkerMessage, handleBuildRequest };
@@ -1,4 +1,4 @@
1
- import { createHNSWIndex } from '../chunk-GVN2W4VA.mjs';
1
+ import { createVectorStore, createHNSWIndex } from '../chunk-VVORJOXR.mjs';
2
2
 
3
3
  // src/vector/hnsw-build-worker.ts
4
4
  var MAX_WORKER_DIMENSION = 8192;
@@ -23,15 +23,63 @@ function validateBuildRequest(request) {
23
23
  }
24
24
  }
25
25
  }
26
+ function clampHNSWConfig(config) {
27
+ return {
28
+ ...config,
29
+ m: config.m != null ? Math.max(2, Math.min(64, config.m)) : void 0,
30
+ efConstruction: config.efConstruction != null ? Math.max(10, Math.min(1e3, config.efConstruction)) : void 0
31
+ };
32
+ }
26
33
  function handleBuildRequest(request) {
27
34
  validateBuildRequest(request);
28
- const hnsw = createHNSWIndex(request.dimension, request.config);
35
+ const safeConfig = clampHNSWConfig(request.config);
36
+ const store = createVectorStore();
37
+ for (const entry of request.vectors) {
38
+ store.insert(entry.docId, new Float32Array(entry.values));
39
+ }
40
+ const hnsw = createHNSWIndex(request.dimension, store, safeConfig);
29
41
  for (const entry of request.vectors) {
30
- const vec = new Float32Array(entry.values);
31
- hnsw.insert(entry.docId, vec);
42
+ hnsw.insertNode(entry.docId);
32
43
  }
33
44
  return hnsw.serialize();
34
45
  }
46
+ function handleBuildRequestBinary(request) {
47
+ const { docIds, vectorData, dimension, config } = request;
48
+ if (!Number.isInteger(dimension) || dimension <= 0 || dimension > MAX_WORKER_DIMENSION) {
49
+ throw new Error(`Invalid dimension: ${dimension} (must be 1..${MAX_WORKER_DIMENSION})`);
50
+ }
51
+ if (docIds.length > MAX_WORKER_VECTORS) {
52
+ throw new Error(`Too many vectors: ${docIds.length} (max ${MAX_WORKER_VECTORS})`);
53
+ }
54
+ const expectedLength = docIds.length * dimension;
55
+ if (vectorData.length !== expectedLength) {
56
+ throw new Error(
57
+ `vectorData length ${vectorData.length} does not match ${docIds.length} * ${dimension} = ${expectedLength}`
58
+ );
59
+ }
60
+ const safeConfig = clampHNSWConfig(config);
61
+ const store = createVectorStore();
62
+ for (let i = 0; i < docIds.length; i++) {
63
+ const offset = i * dimension;
64
+ const vec = vectorData.subarray(offset, offset + dimension);
65
+ store.insert(docIds[i], new Float32Array(vec));
66
+ }
67
+ const hnsw = createHNSWIndex(dimension, store, safeConfig);
68
+ for (const docId of docIds) {
69
+ hnsw.insertNode(docId);
70
+ }
71
+ return hnsw.serialize();
72
+ }
73
+ function handleAnyRequest(raw) {
74
+ const request = raw;
75
+ if (request.type === "build") {
76
+ return handleBuildRequest(raw);
77
+ }
78
+ if (request.type === "build-binary") {
79
+ return handleBuildRequestBinary(raw);
80
+ }
81
+ throw new Error(`Unknown request type: ${request.type}`);
82
+ }
35
83
  function setupWorker() {
36
84
  setupAsync().catch((err) => {
37
85
  console.error("HNSW build worker setup failed:", err);
@@ -48,10 +96,8 @@ async function setupAsync() {
48
96
  if (parentPort) {
49
97
  const port = parentPort;
50
98
  port.on("message", (raw) => {
51
- const request = raw;
52
- if (request.type !== "build") return;
53
99
  try {
54
- const graph = handleBuildRequest(request);
100
+ const graph = handleAnyRequest(raw);
55
101
  port.postMessage({ type: "success", graph });
56
102
  } catch (err) {
57
103
  const message = err instanceof Error ? err.message : String(err);
@@ -64,10 +110,8 @@ async function setupAsync() {
64
110
  if (globalSelf && typeof globalSelf.postMessage === "function") {
65
111
  const webSelf = globalSelf;
66
112
  webSelf.onmessage = (event) => {
67
- const request = event.data;
68
- if (request.type !== "build") return;
69
113
  try {
70
- const graph = handleBuildRequest(request);
114
+ const graph = handleAnyRequest(event.data);
71
115
  webSelf.postMessage({ type: "success", graph });
72
116
  } catch (err) {
73
117
  const message = err instanceof Error ? err.message : String(err);
@@ -15,7 +15,7 @@ async function setup() {
15
15
  } catch {
16
16
  parentPort = null;
17
17
  }
18
- const { createDirectExecutor } = await import('../direct-executor-6TSG7GWH.mjs');
18
+ const { createDirectExecutor } = await import('../direct-executor-LBJLGMJ2.mjs');
19
19
  const executor = createDirectExecutor();
20
20
  function buildErrorResponse(requestId, code, message) {
21
21
  return { type: "error", requestId, code, message };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@delali/narsil",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "description": "A distributed full-text search engine with cross-language portable binary format.",
6
6
  "author": "Delali (https://sondelali.com)",
@@ -74,6 +74,10 @@
74
74
  "import": "./dist/vector/hnsw-build-worker.mjs",
75
75
  "types": "./dist/vector/hnsw-build-worker.d.ts"
76
76
  },
77
+ "./embeddings/openai": {
78
+ "import": "./dist/embeddings/openai.mjs",
79
+ "types": "./dist/embeddings/openai.d.ts"
80
+ },
77
81
  "./languages/*": {
78
82
  "import": "./dist/languages/*.mjs",
79
83
  "types": "./dist/languages/*.d.ts"
@@ -93,13 +97,16 @@
93
97
  "tsup": "8.5.1",
94
98
  "typescript": "5.9.3",
95
99
  "vitest": "4.0.18",
96
- "wabt": "1.0.39"
100
+ "wabt": "1.0.39",
101
+ "@delali/narsil-embeddings-transformers": "0.1.6"
97
102
  },
98
103
  "scripts": {
99
104
  "build": "tsup",
100
- "test": "vitest run",
105
+ "test": "vitest run --exclude='**/vector/recall.test.ts'",
101
106
  "test:watch": "vitest",
102
107
  "test:coverage": "vitest run --coverage",
108
+ "test:recall": "vitest run src/__tests__/vector/recall.test.ts",
109
+ "test:embeddings": "NARSIL_TEST_EMBEDDINGS=1 vitest run embedding-e2e",
103
110
  "bench": "vitest bench",
104
111
  "lint": "biome check src/",
105
112
  "typecheck": "tsc --noEmit"
@@ -1,4 +0,0 @@
1
- export { createDirectExecutor } from './chunk-TFWBALU4.mjs';
2
- import './chunk-GVN2W4VA.mjs';
3
- import './chunk-WYC635GI.mjs';
4
- import './chunk-7GKPWGCN.mjs';