@delali/narsil 0.2.4-next.51 → 0.2.4-next.52

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 (55) hide show
  1. package/README.md +27 -25
  2. package/dist/{capabilities-BWm4IITU.d.ts → capabilities-CuTSXvbN.d.ts} +2 -2
  3. package/dist/{chunk-BEIK3EOZ.mjs → chunk-2FO7KZ6K.mjs} +5468 -3837
  4. package/dist/{chunk-XE6XR2OE.mjs → chunk-3GWP2TO6.mjs} +1 -1
  5. package/dist/{chunk-KMMJMDUA.mjs → chunk-3L4U6EJQ.mjs} +15 -10
  6. package/dist/{chunk-MHE7YWAU.mjs → chunk-72AXTIBW.mjs} +2 -2
  7. package/dist/{chunk-CV5H7XL7.mjs → chunk-EY2ULUMT.mjs} +30 -7
  8. package/dist/chunk-IFBKLBGB.mjs +7 -0
  9. package/dist/{chunk-WYJXSLER.mjs → chunk-POWOTUKJ.mjs} +7 -1
  10. package/dist/chunk-T62YOSGS.mjs +4280 -0
  11. package/dist/chunk-U36IDJN7.mjs +366 -0
  12. package/dist/{chunk-ND34I3SV.mjs → chunk-ULJ36FK4.mjs} +3502 -2383
  13. package/dist/{chunk-RP23PWMV.mjs → chunk-WFKIGEBY.mjs} +3 -3
  14. package/dist/{chunk-CMVG2UEF.mjs → chunk-WM7IS45M.mjs} +55 -517
  15. package/dist/chunk-Y3L5MDRV.mjs +96 -0
  16. package/dist/{chunk-ZHUQKZBE.mjs → chunk-YPYULM5E.mjs} +20 -4
  17. package/dist/chunk-ZJ4CSAB2.mjs +13 -0
  18. package/dist/chunk-ZT5BRDFW.mjs +513 -0
  19. package/dist/{client-B_X6_AbT.d.ts → client-BMJWVxOP.d.ts} +3 -3
  20. package/dist/client.d.ts +8 -8
  21. package/dist/{config-OON7IJ_B.d.ts → config-BcYZkdMw.d.ts} +2 -2
  22. package/dist/{config-Czh2YNDi.d.ts → config-qMLpi5T4.d.ts} +2 -2
  23. package/dist/direct-executor-UJC36S2D.mjs +12 -0
  24. package/dist/distribution/coordinator/etcd.d.ts +2 -2
  25. package/dist/distribution/coordinator/in-memory.d.ts +2 -2
  26. package/dist/distribution.d.ts +8 -8
  27. package/dist/distribution.mjs +30 -15
  28. package/dist/{engine-9PtFY50q.d.ts → engine-zhms1qId.d.ts} +2 -2
  29. package/dist/index.browser.mjs +12845 -7766
  30. package/dist/index.d.ts +9 -21
  31. package/dist/index.mjs +13 -12
  32. package/dist/{memory-Bzd5xcEW.d.ts → memory-OmgkX_Z2.d.ts} +11 -1
  33. package/dist/persistence/durability/checkpoint-worker.d.ts +138 -3
  34. package/dist/persistence/durability/checkpoint-worker.mjs +31 -17
  35. package/dist/react.d.ts +6 -6
  36. package/dist/{schema-BqRx9t4E.d.ts → schema-OSWaaZzx.d.ts} +30 -6
  37. package/dist/serialization/crc32-worker.mjs +2 -1
  38. package/dist/server.d.ts +10 -10
  39. package/dist/server.mjs +75 -34
  40. package/dist/simd-DW5AtJ6B.d.ts +41 -0
  41. package/dist/{tasks-DT7L1p6w.d.ts → tasks-DiF1c9v2.d.ts} +1 -1
  42. package/dist/{thread-PZLEO6JL.mjs → thread-TLCX43WV.mjs} +129 -41
  43. package/dist/{types-DXPxaXPO.d.ts → types-LEzMyjVX.d.ts} +1 -1
  44. package/dist/vector/search-worker.d.ts +292 -128
  45. package/dist/vector/search-worker.mjs +70 -54
  46. package/dist/workers/entry.mjs +10 -7
  47. package/package.json +52 -31
  48. package/dist/brute-force-DbHYCTc3.d.ts +0 -8
  49. package/dist/chunk-CBLS46IE.mjs +0 -10
  50. package/dist/chunk-PIWKZPP7.mjs +0 -64
  51. package/dist/chunk-PMBHH44R.mjs +0 -492
  52. package/dist/chunk-X6YZO4MQ.mjs +0 -1572
  53. package/dist/direct-executor-OREXU72C.mjs +0 -12
  54. package/dist/vector/hnsw-build-worker.d.ts +0 -105
  55. package/dist/vector/hnsw-build-worker.mjs +0 -123
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Reports whether the runtime loaded the SIMD module that speeds up vector
3
+ * distance work.
4
+ *
5
+ * Vector search works either way, so read this to explain a difference in
6
+ * search latency between two hosts rather than to decide whether to search.
7
+ *
8
+ * @returns True once the SIMD module has loaded.
9
+ *
10
+ * @public
11
+ */
12
+ declare function isSimdAvailable(): boolean;
13
+ /**
14
+ * The distance kernels bound to one memory, which read their operands at byte
15
+ * offsets inside that memory so that a caller measures against a vector where
16
+ * it already lies.
17
+ *
18
+ * @internal
19
+ */
20
+ interface ArenaSimd {
21
+ /** The kernels read every operand out of this memory. */
22
+ memory: WebAssembly.Memory;
23
+ /** Returns the dot product of two float32 vectors at the given byte offsets. */
24
+ dot_product: (ptrA: number, ptrB: number, len: number) => number;
25
+ /** Returns the length of the float32 vector at the given byte offset. */
26
+ magnitude: (ptr: number, len: number) => number;
27
+ /** Returns the squared euclidean distance between two float32 vectors at the given byte offsets. */
28
+ squared_euclidean_distance: (ptrA: number, ptrB: number, len: number) => number;
29
+ /** Returns the integer dot product of two byte code vectors at the given byte offsets. */
30
+ dot_u8: (ptrA: number, ptrB: number, len: number) => number;
31
+ /** Returns the integer squared distance between two byte code vectors at the given byte offsets. */
32
+ sqdist_u8: (ptrA: number, ptrB: number, len: number) => number;
33
+ /** Returns the sum of level products of two 4-bit codes at the given byte offsets, each holding two levels per byte. */
34
+ osq_dot_nibbles_4x4: (ptrA: number, ptrB: number, bytes: number) => number;
35
+ /** Returns the sum of level products of a 1-bit or 2-bit code and a query staged as four bit planes. Each plane spans `planeBytes`, with one bit for each of the code's lowest level bits. */
36
+ osq_dot_bits: (ptrDoc: number, ptrPlanes: number, planeBytes: number, docBits: number) => number;
37
+ /** Returns the sum of level products of two 1-bit codes or two 2-bit codes at the given byte offsets. */
38
+ osq_dot_bits_pair: (ptrA: number, ptrB: number, bytes: number, bits: number) => number;
39
+ }
40
+
41
+ export { type ArenaSimd as A, isSimdAvailable as i };
@@ -1,4 +1,4 @@
1
- import { M as MemoryStats } from './memory-Bzd5xcEW.js';
1
+ import { M as MemoryStats } from './memory-OmgkX_Z2.js';
2
2
 
3
3
  /** Declarative index configuration accepted over HTTP. Function-valued engine
4
4
  * options (custom tokenizer, stopWords-as-function, group reducer, embedding
@@ -1,15 +1,56 @@
1
- import { loadUWebSockets, childAppOf, createRouteRunner, corsWriter, createSharedRequestGate, registerServerRoutes, sendRelayed, createDocumentReadHandlers, respondJson, SERVER_CAPABILITIES, sendError, serverRoutes, parseJson, validateSuggest, rejectInvalid, respondError, validateQuery } from './chunk-CV5H7XL7.mjs';
2
- import { executeListDocuments, executeSuggest, executePreflight, queryBindingOf, executeQuery } from './chunk-ZHUQKZBE.mjs';
3
- import './chunk-XE6XR2OE.mjs';
4
- import { extractVectorFieldsFromSchema } from './chunk-CMVG2UEF.mjs';
5
- import './chunk-CBLS46IE.mjs';
6
- import './chunk-RP23PWMV.mjs';
1
+ import { loadUWebSockets, childAppOf, createRouteRunner, corsWriter, createSharedRequestGate, registerServerRoutes, sendRelayed, createDocumentReadHandlers, respondJson, SERVER_CAPABILITIES, sendError, serverRoutes, parseJson, validateSuggest, rejectInvalid, respondError, validateQuery } from './chunk-EY2ULUMT.mjs';
2
+ import { executeListDocuments, executeSuggest, executePreflight, queryBindingOf, executeQuery } from './chunk-YPYULM5E.mjs';
3
+ import './chunk-3GWP2TO6.mjs';
4
+ import { resolveProjection, projectionKeepsField, setNestedValue } from './chunk-WM7IS45M.mjs';
5
+ import { extractVectorFieldsFromSchema } from './chunk-ZT5BRDFW.mjs';
6
+ import './chunk-ZJ4CSAB2.mjs';
7
+ import './chunk-WFKIGEBY.mjs';
7
8
  import './chunk-2GWVQWGA.mjs';
8
9
  import { ServerErrorCodes, NarsilError, ErrorCodes } from './chunk-P4ELXVJQ.mjs';
9
10
 
11
+ // src/server/request-threads/held-vectors.ts
12
+ function managerWithHeldVectors(manager, fieldPaths, vectorOf) {
13
+ function get(docId, projection) {
14
+ const document = manager.get(docId, projection);
15
+ if (document === void 0) return void 0;
16
+ for (const fieldPath of fieldPaths) {
17
+ if (projection !== void 0 && !projectionKeepsField(projection, fieldPath)) continue;
18
+ const vector = vectorOf(fieldPath, docId);
19
+ if (vector !== void 0)
20
+ setNestedValue(document, fieldPath, Float32Array.from(vector));
21
+ }
22
+ return document;
23
+ }
24
+ const reader = Object.create(manager);
25
+ reader.get = get;
26
+ return reader;
27
+ }
28
+
10
29
  // src/server/request-threads/read-engine.ts
11
30
  function createThreadReadEngine(options) {
12
31
  const { executor, relay, searchHooks } = options;
32
+ function vectorFieldsOf(context) {
33
+ return [...extractVectorFieldsFromSchema(context.config.schema).keys()];
34
+ }
35
+ function holdsEveryVectorField(indexName, context) {
36
+ return vectorFieldsOf(context).every((fieldPath) => executor.holdsVectorField(indexName, fieldPath));
37
+ }
38
+ function holdsEveryVectorFieldRead(indexName, context, params) {
39
+ if (params.document === false) return true;
40
+ const projection = resolveProjection(params.document === true ? void 0 : params.document);
41
+ return vectorFieldsOf(context).every(
42
+ (fieldPath) => !projectionKeepsField(projection, fieldPath) || executor.holdsVectorField(indexName, fieldPath)
43
+ );
44
+ }
45
+ function managerOf(indexName, context) {
46
+ const fieldPaths = vectorFieldsOf(context);
47
+ if (fieldPaths.length === 0) return context.manager;
48
+ return managerWithHeldVectors(
49
+ context.manager,
50
+ fieldPaths,
51
+ (fieldPath, docId) => executor.heldVectorOf(indexName, fieldPath, docId)
52
+ );
53
+ }
13
54
  function requireContext(indexName) {
14
55
  const context = executor.queryContextOf(indexName);
15
56
  if (context === void 0) {
@@ -20,29 +61,51 @@ function createThreadReadEngine(options) {
20
61
  relay.touch(indexName);
21
62
  return context;
22
63
  }
64
+ function requireWholeDocuments(indexName) {
65
+ const context = requireContext(indexName);
66
+ if (!holdsEveryVectorField(indexName, context)) {
67
+ throw new NarsilError(ErrorCodes.INDEX_NOT_FOUND, `This thread holds no vectors of index "${indexName}" yet`, {
68
+ indexName
69
+ });
70
+ }
71
+ return { context, manager: managerOf(indexName, context) };
72
+ }
23
73
  async function resolvedParams(indexName, params) {
24
74
  if (params.vector?.text === void 0) return params;
25
75
  const value = await relay.embed(indexName, params.vector);
26
76
  const { text: _text, ...vector } = params.vector;
27
77
  return { ...params, vector: { ...vector, value } };
28
78
  }
29
- function canAnswer(indexName, params) {
30
- if (searchHooks) return false;
79
+ function holdsDocumentsOf(indexName) {
31
80
  const context = executor.queryContextOf(indexName);
32
- if (context === void 0) return false;
81
+ return context !== void 0 && holdsEveryVectorField(indexName, context);
82
+ }
83
+ function searchableContext(indexName, params) {
84
+ if (searchHooks) return null;
85
+ const context = executor.queryContextOf(indexName);
86
+ if (context === void 0) return null;
33
87
  const field = params.vector?.field;
34
- if (field === void 0) return true;
88
+ if (field === void 0) return context;
35
89
  const vectorFields = extractVectorFieldsFromSchema(context.config.schema);
36
- if (!vectorFields.has(field)) return true;
37
- return context.vectorSearchers.has(field);
90
+ if (!vectorFields.has(field)) return context;
91
+ return context.vectorSearchers.has(field) ? context : null;
92
+ }
93
+ function canAnswer(indexName, params) {
94
+ const context = searchableContext(indexName, params);
95
+ return context !== null && holdsEveryVectorFieldRead(indexName, context, params);
96
+ }
97
+ function canCount(indexName, params) {
98
+ return searchableContext(indexName, params) !== null;
38
99
  }
39
100
  return {
40
101
  holdsCopyOf: (indexName) => executor.queryContextOf(indexName) !== void 0,
102
+ holdsDocumentsOf,
41
103
  canAnswer,
104
+ canCount,
42
105
  async query(indexName, params) {
43
- const context = requireContext(indexName);
106
+ const { context, manager } = requireWholeDocuments(indexName);
44
107
  const result = await executeQuery(await resolvedParams(indexName, params), {
45
- manager: context.manager,
108
+ manager,
46
109
  language: context.language,
47
110
  config: context.config,
48
111
  indexName,
@@ -72,10 +135,10 @@ function createThreadReadEngine(options) {
72
135
  return result;
73
136
  },
74
137
  async get(indexName, docId) {
75
- return requireContext(indexName).manager.get(docId);
138
+ return requireWholeDocuments(indexName).manager.get(docId);
76
139
  },
77
140
  async getMultiple(indexName, docIds) {
78
- const { manager } = requireContext(indexName);
141
+ const { manager } = requireWholeDocuments(indexName);
79
142
  const found = /* @__PURE__ */ new Map();
80
143
  for (const docId of docIds) {
81
144
  const document = manager.get(docId);
@@ -90,8 +153,8 @@ function createThreadReadEngine(options) {
90
153
  return requireContext(indexName).manager.countDocuments();
91
154
  },
92
155
  async listDocuments(indexName, params) {
93
- const context = requireContext(indexName);
94
- return executeListDocuments(params ?? {}, { manager: context.manager, schema: context.config.schema });
156
+ const { context, manager } = requireWholeDocuments(indexName);
157
+ return executeListDocuments(params ?? {}, { manager, schema: context.config.schema });
95
158
  }
96
159
  };
97
160
  }
@@ -113,6 +176,13 @@ var SHUTTING_DOWN_DENIAL = {
113
176
  allowed: false,
114
177
  denial: { status: 503, code: ServerErrorCodes.INTERNAL_ERROR, message: "The server is shutting down" }
115
178
  };
179
+ function relayedBody(rawBody) {
180
+ if (rawBody === null) return { bytes: null, moved: [] };
181
+ const memory = rawBody.buffer;
182
+ const ownsItsMemory = memory instanceof ArrayBuffer && rawBody.byteOffset === 0 && rawBody.byteLength === memory.byteLength;
183
+ if (!ownsItsMemory) return { bytes: new Uint8Array(rawBody), moved: [] };
184
+ return { bytes: new Uint8Array(memory), moved: [memory] };
185
+ }
116
186
  function sendUnavailable(res) {
117
187
  sendError(res, 503, ServerErrorCodes.INTERNAL_ERROR, "The server is shutting down");
118
188
  }
@@ -135,13 +205,18 @@ function createRelayClient(port, touchIntervalMs) {
135
205
  waiting.resolve(message);
136
206
  });
137
207
  port.on("close", failAll);
138
- function send(build) {
208
+ function send(build, moved = []) {
139
209
  if (closed) return Promise.reject(portClosedError());
140
210
  nextRequestId += 1;
141
211
  const requestId = nextRequestId;
142
212
  return new Promise((resolve, reject) => {
143
213
  pending.set(requestId, { resolve, reject });
144
- port.postMessage(build(requestId));
214
+ try {
215
+ port.postMessage(build(requestId), moved);
216
+ } catch (err) {
217
+ pending.delete(requestId);
218
+ reject(err instanceof Error ? err : new Error(String(err)));
219
+ }
145
220
  });
146
221
  }
147
222
  return {
@@ -159,17 +234,21 @@ function createRelayClient(port, touchIntervalMs) {
159
234
  },
160
235
  async request(route, ctx) {
161
236
  let reply;
237
+ const body = relayedBody(ctx.rawBody);
162
238
  try {
163
- reply = await send((requestId) => ({
164
- type: "request",
165
- requestId,
166
- route,
167
- params: ctx.params,
168
- query: ctx.query.toString(),
169
- contentType: ctx.contentType,
170
- rawBody: ctx.rawBody === null ? null : new Uint8Array(ctx.rawBody),
171
- hookContext: ctx.hookContext
172
- }));
239
+ reply = await send(
240
+ (requestId) => ({
241
+ type: "request",
242
+ requestId,
243
+ route,
244
+ params: ctx.params,
245
+ query: ctx.query.toString(),
246
+ contentType: ctx.contentType,
247
+ rawBody: body.bytes,
248
+ hookContext: ctx.hookContext
249
+ }),
250
+ body.moved
251
+ );
173
252
  } catch {
174
253
  if (!ctx.abort.aborted) sendUnavailable(ctx.res);
175
254
  return;
@@ -207,7 +286,11 @@ function relayed(relay, route) {
207
286
  function onHeldIndex(local, handler, fallback) {
208
287
  return (ctx) => local.holdsCopyOf(ctx.params[0]) ? handler(ctx) : fallback(ctx);
209
288
  }
210
- function searchHandler(local, fallback, maxResultWindow, answer) {
289
+ function onWholeDocuments(local, handler, fallback) {
290
+ return (ctx) => local.holdsDocumentsOf(ctx.params[0]) ? handler(ctx) : fallback(ctx);
291
+ }
292
+ function searchHandler(options) {
293
+ const { fallback, maxResultWindow, staysOnThread, answer } = options;
211
294
  return async (ctx) => {
212
295
  const params = parseJson(ctx);
213
296
  if (!params) return;
@@ -216,7 +299,7 @@ function searchHandler(local, fallback, maxResultWindow, answer) {
216
299
  rejectInvalid(ctx, failure);
217
300
  return;
218
301
  }
219
- if (!local.canAnswer(ctx.params[0], params)) {
302
+ if (!staysOnThread(ctx.params[0], params)) {
220
303
  await fallback(ctx);
221
304
  return;
222
305
  }
@@ -267,19 +350,24 @@ function threadHandlers(local, relay, settings) {
267
350
  livez: (ctx) => respondJson(ctx, { status: "ok" }),
268
351
  version: (ctx) => respondJson(ctx, { name: "narsil", ...settings.build }),
269
352
  capabilities: (ctx) => respondJson(ctx, { capabilities: [...SERVER_CAPABILITIES] }),
270
- search: searchHandler(local, forwarded.search, maxResultWindow, (name, params) => local.query(name, params)),
271
- preflight: searchHandler(
272
- local,
273
- forwarded.preflight,
353
+ search: searchHandler({
354
+ fallback: forwarded.search,
355
+ maxResultWindow,
356
+ staysOnThread: (name, params) => local.canAnswer(name, params),
357
+ answer: (name, params) => local.query(name, params)
358
+ }),
359
+ preflight: searchHandler({
360
+ fallback: forwarded.preflight,
274
361
  maxResultWindow,
275
- (name, params) => local.preflight(name, params)
276
- ),
362
+ staysOnThread: (name, params) => local.canCount(name, params),
363
+ answer: (name, params) => local.preflight(name, params)
364
+ }),
277
365
  suggest: suggestHandler(local, forwarded.suggest),
278
- get: onHeldIndex(local, reads.get, forwarded.get),
366
+ get: onWholeDocuments(local, reads.get, forwarded.get),
279
367
  exists: onHeldIndex(local, reads.exists, forwarded.exists),
280
368
  count: onHeldIndex(local, reads.count, forwarded.count),
281
- list: onHeldIndex(local, reads.list, forwarded.list),
282
- multiGet: onHeldIndex(local, reads.multiGet, forwarded.multiGet)
369
+ list: onWholeDocuments(local, reads.list, forwarded.list),
370
+ multiGet: onWholeDocuments(local, reads.multiGet, forwarded.multiGet)
283
371
  };
284
372
  }
285
373
  async function serveRequests(executor, settings) {
@@ -1,4 +1,4 @@
1
- import { S as SchemaDefinition } from './schema-BqRx9t4E.js';
1
+ import { S as SchemaDefinition } from './schema-OSWaaZzx.js';
2
2
 
3
3
  /**
4
4
  * What a node does in a cluster. A node may hold several roles at once.