@delali/narsil 0.3.1-next.72 → 0.3.1-next.73

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 (59) hide show
  1. package/README.md +2 -2
  2. package/dist/adapters/filesystem.mjs +1 -1
  3. package/dist/adapters/indexeddb.mjs +1 -1
  4. package/dist/{capabilities-D6gjjQyA.d.ts → capabilities-CYeAWYxQ.d.ts} +19 -4
  5. package/dist/{chunk-Y52WZWAU.mjs → chunk-2WLD2NFW.mjs} +4 -4
  6. package/dist/{chunk-QR4OKRVY.mjs → chunk-3YKWSO54.mjs} +8 -3
  7. package/dist/{chunk-KZTI25D3.mjs → chunk-4MQ5F4IL.mjs} +1 -1
  8. package/dist/{chunk-CVPA5Q7R.mjs → chunk-AFKH4ZK3.mjs} +9 -6
  9. package/dist/{chunk-M6XF5HDE.mjs → chunk-AK3BLGCI.mjs} +141 -11
  10. package/dist/{chunk-7QMTA7AA.mjs → chunk-CVFAFZSN.mjs} +7771 -4271
  11. package/dist/{chunk-RV77FR2F.mjs → chunk-I64LXKO3.mjs} +0 -1
  12. package/dist/{chunk-EDMCZLSJ.mjs → chunk-LPBWCHBE.mjs} +193 -13
  13. package/dist/{chunk-P2ZZN32C.mjs → chunk-PU43WDY4.mjs} +4 -2
  14. package/dist/{chunk-HVJYTKK7.mjs → chunk-THMSFOJO.mjs} +365 -774
  15. package/dist/{chunk-LCCL6EEH.mjs → chunk-WVDFG45M.mjs} +92 -94
  16. package/dist/{chunk-3HQPUCCT.mjs → chunk-XW25X6AU.mjs} +66 -237
  17. package/dist/{chunk-2X2ZQOAB.mjs → chunk-ZULSEZCE.mjs} +3 -4
  18. package/dist/{client-C2TiW29y.d.ts → client-D698E5ge.d.ts} +76 -25
  19. package/dist/client.d.ts +7 -7
  20. package/dist/client.mjs +44 -22
  21. package/dist/{config-BLguB-om.d.ts → config-Bv8etwUZ.d.ts} +10 -3
  22. package/dist/{config-C7Ip8Ife.d.ts → config-QXU3HMpq.d.ts} +10 -1
  23. package/dist/direct-executor-5SRDFZAS.mjs +13 -0
  24. package/dist/distribution/coordinator/etcd.d.ts +27 -14
  25. package/dist/distribution/coordinator/etcd.mjs +162 -75
  26. package/dist/distribution/transport/grpc.d.ts +2 -2
  27. package/dist/distribution/transport/grpc.mjs +22 -2
  28. package/dist/distribution/transport/in-memory.d.ts +2 -2
  29. package/dist/distribution/transport/in-memory.mjs +6 -3
  30. package/dist/distribution/transport/tcp.d.ts +2 -2
  31. package/dist/distribution/transport/tcp.mjs +40 -16
  32. package/dist/distribution.d.ts +6 -6
  33. package/dist/distribution.mjs +637 -366
  34. package/dist/embeddings/openai.mjs +1 -1
  35. package/dist/{engine-Dm4446j1.d.ts → engine-D_OzKZ-6.d.ts} +96 -187
  36. package/dist/index.browser.mjs +7179 -4031
  37. package/dist/index.d.ts +5 -5
  38. package/dist/index.mjs +11 -14
  39. package/dist/{memory-CKHTU1CL.d.ts → memory-B4jMmygw.d.ts} +213 -2
  40. package/dist/pattern.mjs +1 -1
  41. package/dist/persistence/durability/checkpoint-worker.d.ts +24 -16
  42. package/dist/persistence/durability/checkpoint-worker.mjs +22 -16
  43. package/dist/react.d.ts +6 -6
  44. package/dist/react.mjs +0 -1
  45. package/dist/server.d.ts +9 -9
  46. package/dist/server.mjs +210 -32
  47. package/dist/{tasks-BECd0b__.d.ts → tasks-DpgCpW1x.d.ts} +3 -3
  48. package/dist/{thread-IBSIZZ6W.mjs → thread-3LNVA43V.mjs} +79 -21
  49. package/dist/{types-BQDlIvfS.d.ts → types-B3b68nfF.d.ts} +1 -1
  50. package/dist/{types-D5OwhtsQ.d.ts → types-Cb9kiY5P.d.ts} +1 -1
  51. package/dist/vector/search-worker.mjs +3 -3
  52. package/dist/workers/entry.mjs +4 -4
  53. package/package.json +7 -7
  54. package/dist/chunk-3L4U6EJQ.mjs +0 -49
  55. package/dist/chunk-IFBKLBGB.mjs +0 -7
  56. package/dist/chunk-XZ4PAREY.mjs +0 -25
  57. package/dist/direct-executor-SVCHXR74.mjs +0 -14
  58. package/dist/serialization/crc32-worker.d.ts +0 -20
  59. package/dist/serialization/crc32-worker.mjs +0 -62
@@ -1,16 +1,15 @@
1
- import { cloneProjected, everyValueFacetConfig, mergeFacets, computeFacets, tokenizeOptions, getNestedValue, visitTokens, joinPatternWorkMeter, countsWithoutScores, fanOutMatchCount, fanOutQuery, sanitizeGlobalStats, textFieldsChanged, projectionKeepsField, setNestedValue, fnv1a, kWayMerge, fuzzyPrefixOf, boundedLevenshtein, getFlatSchema, tokenize, getOrCreateFieldNameIndex, tokenizeIterator, getFieldValueByInternalId, undeclaredFilterField, requireValidOperands, polygonContainment, polygonBoxes, radiusBoxes, locationCode, coveringRanges, GEO_UNIT_METRES } from './chunk-QR4OKRVY.mjs';
2
- import { getLanguage, detectRuntime } from './chunk-KZTI25D3.mjs';
3
- import { schemaFieldsOf, isWordIndexedBase, validateDocument, validateDocumentStrict, isQuantizationMode, isStorageMode, requireValidFieldTypes, extractVectorFieldsFromSchema, VECTOR_PATTERN, parsedTypeOf, isListBase, VINCENTY_CONVERGENCE_THRESHOLD, EARTH_RADIUS_METERS, VINCENTY_MAX_ITERATIONS, DEG_TO_RAD } from './chunk-M6XF5HDE.mjs';
4
- import { SCRATCH_SLOTS_PER_THREAD_POOL, osqRecordBytes, openSharedVectorField, osqBitsOf, createVectorStore, DISK_STORAGE_BLOCK_BYTES, createOsqQuantizer, magnitude, createHNSWIndex, nativeStoreScratchBytes, createOrdinalFilter, isTombstoned, addToOrdinalFilter, ordinalFilterValues, nativeScoresOf, toScore, removeFromOrdinalFilter, euclideanDistance, dotProduct, cosineSimilarityWithMagnitudes, ordinalFilterHas, requireWholeNeighbourLists, STORE_CALIBRATION_GENERATION, entryForOrd, toDistance, sharedMemoryAvailable, GRAPH_BUILD_CHUNKS_IN_FLIGHT_PER_WORKER, GRAPH_BUILD_DISPATCH_CHUNK, releaseLocksHeldBy, VECTOR_SEARCH_TIMEOUT_MS, VECTOR_SEARCH_LOAD_TIMEOUT_MS, VECTOR_INSERT_TIMEOUT_MS, VECTOR_SCRATCH_SLOTS } from './chunk-LCCL6EEH.mjs';
5
- import { noteFallback } from './chunk-P2ZZN32C.mjs';
6
- import { VALID_HNSW_METRICS } from './chunk-IFBKLBGB.mjs';
7
- import { GrowableUint32, patternSearchModule } from './chunk-3HQPUCCT.mjs';
1
+ import { getLanguage, detectRuntime } from './chunk-4MQ5F4IL.mjs';
2
+ import { tokenizeOptions, getNestedValue, visitTokens, joinPatternWorkMeter, countsWithoutScores, fanOutMatchCount, fanOutQuery, sanitizeGlobalStats, computeFacets, cloneProjected, textFieldsChanged, projectionKeepsField, setNestedValue, fnv1a, fuzzyPrefixOf, boundedLevenshtein, getFlatSchema, tokenize, getOrCreateFieldNameIndex, tokenizeIterator, everyValueFacetConfig, mergeFacets, getFieldValueByInternalId, undeclaredFilterField, requireValidOperands, kWayMerge, polygonContainment, polygonBoxes, radiusBoxes, locationCode, coveringRanges, GEO_UNIT_METRES } from './chunk-3YKWSO54.mjs';
3
+ import { schemaFieldsOf, isWordIndexedBase, validateDocument, validateDocumentStrict, encodeDocument, extractVectorFieldsFromSchema, MAX_DOC_ID_LENGTH, parsedTypeOf, isListBase, VINCENTY_CONVERGENCE_THRESHOLD, EARTH_RADIUS_METERS, VINCENTY_MAX_ITERATIONS, DEG_TO_RAD } from './chunk-AK3BLGCI.mjs';
4
+ import { SCRATCH_SLOTS_PER_THREAD_POOL, osqRecordBytes, openSharedVectorField, osqBitsOf, createVectorStore, DISK_STORAGE_BLOCK_BYTES, createOsqQuantizer, magnitude, createHNSWIndex, nativeStoreScratchBytes, createOrdinalFilter, isTombstoned, addToOrdinalFilter, ordinalFilterValues, nativeScoresOf, toScore, removeFromOrdinalFilter, euclideanDistance, dotProduct, cosineSimilarityWithMagnitudes, ordinalFilterHas, STORE_CALIBRATION_GENERATION, entryForOrd, toDistance, sharedMemoryAvailable, requireWholeNeighbourLists, topLayerInParts, GRAPH_BUILD_CHUNKS_IN_FLIGHT_PER_WORKER, GRAPH_BUILD_DISPATCH_CHUNK, releaseLocksHeldBy, VECTOR_SEARCH_TIMEOUT_MS, VECTOR_SEARCH_LOAD_TIMEOUT_MS, VECTOR_INSERT_TIMEOUT_MS, VECTOR_SCRATCH_SLOTS } from './chunk-WVDFG45M.mjs';
5
+ import { MAX_M, noteFallback, EARLIER_RELEASE_MIN_M, MIN_M } from './chunk-PU43WDY4.mjs';
6
+ import { GrowableUint32, patternSearchModule } from './chunk-XW25X6AU.mjs';
8
7
  import { bitsetHas, createBitSet, bitsetSet, bitsetOrInto, bitsetAndNotInto, bitsetAndInto, PATTERN_RUN_CODE_POINTS, bitsetFromSet, bitsetIsEmpty, bitsetAnd, bitsetNot } from './chunk-ZKRV5M2P.mjs';
9
- import { compareCodePoints, appendFoldedCodePoint, toReducedSortValue, readSortField, compareComparableValues, defaultSortMode, truncateSortString, SORT_VALUE_MAX_CODE_POINTS } from './chunk-LJYTW7GT.mjs';
10
- import { NarsilError, ErrorCodes } from './chunk-RV77FR2F.mjs';
8
+ import { compareCodePoints, appendFoldedCodePoint, toReducedSortValue, readSortField, defaultSortMode, compareComparableValues, truncateSortString, SORT_VALUE_MAX_CODE_POINTS } from './chunk-LJYTW7GT.mjs';
9
+ import { NarsilError, ErrorCodes } from './chunk-I64LXKO3.mjs';
11
10
  import { totalmem } from 'os';
12
11
  import { getHeapStatistics } from 'v8';
13
- import { encode, decode } from '@msgpack/msgpack';
12
+ import { decode } from '@msgpack/msgpack';
14
13
 
15
14
  var MEGABYTE_BYTES = 1048576;
16
15
  var IN_MEGABYTES = /^--max-old-space-size=(\d+)$/;
@@ -118,518 +117,6 @@ function resolveIndexAnalysis(config) {
118
117
  customTokenizer: typeof config.tokenizer === "string" ? getTokenizer(config.tokenizer) : config.tokenizer
119
118
  };
120
119
  }
121
- function metadataToWire(meta) {
122
- const wire = {
123
- index_name: meta.indexName,
124
- schema: meta.schema,
125
- language: meta.language,
126
- partition_count: meta.partitionCount,
127
- bm25_params: meta.bm25Params,
128
- created_at: meta.createdAt,
129
- engine_version: meta.engineVersion
130
- };
131
- if (meta.vectorFields) {
132
- wire.vector_fields = meta.vectorFields;
133
- }
134
- if (isNonNegativeInteger(meta.documentCount) && Number.isSafeInteger(meta.documentCount)) {
135
- wire.document_count = meta.documentCount;
136
- }
137
- if (meta.embedding) {
138
- wire.embedding = meta.embedding.adapter !== void 0 ? { adapter: meta.embedding.adapter, fields: meta.embedding.fields } : { fields: meta.embedding.fields };
139
- }
140
- if (meta.surfaceForms !== void 0) {
141
- wire.surface_forms_enabled = meta.surfaceForms;
142
- }
143
- if (meta.analysisRevision !== void 0) {
144
- wire.analysis_revision = meta.analysisRevision;
145
- }
146
- if (meta.tokenizer !== void 0) {
147
- wire.tokenizer = meta.tokenizer;
148
- }
149
- if (meta.stopWords !== void 0) {
150
- wire.stop_words = meta.stopWords;
151
- }
152
- if (meta.stopWordList !== void 0) {
153
- wire.stop_word_list = meta.stopWordList;
154
- }
155
- if (meta.partitionLimits !== void 0) {
156
- wire.partition_limits = {
157
- ...meta.partitionLimits.maxDocsPerPartition !== void 0 ? { max_docs_per_partition: meta.partitionLimits.maxDocsPerPartition } : {},
158
- ...meta.partitionLimits.maxPartitions !== void 0 ? { max_partitions: meta.partitionLimits.maxPartitions } : {},
159
- ...meta.partitionLimits.watermark !== void 0 ? { watermark: meta.partitionLimits.watermark } : {}
160
- };
161
- }
162
- if (meta.defaultScoring !== void 0) {
163
- wire.default_scoring = meta.defaultScoring;
164
- }
165
- if (meta.trackPositions !== void 0) {
166
- wire.track_positions = meta.trackPositions;
167
- }
168
- if (meta.strict !== void 0) {
169
- wire.strict = meta.strict;
170
- }
171
- if (meta.required !== void 0) {
172
- wire.required = meta.required;
173
- }
174
- if (meta.vectorPromotion !== void 0) {
175
- const promotion = meta.vectorPromotion;
176
- wire.vector_promotion = {
177
- ...promotion.threshold !== void 0 ? { threshold: promotion.threshold } : {},
178
- ...promotion.filterThreshold !== void 0 ? { filter_threshold: promotion.filterThreshold } : {},
179
- ...promotion.hnswConfig !== void 0 ? {
180
- hnsw_config: {
181
- ...promotion.hnswConfig.m !== void 0 ? { m: promotion.hnswConfig.m } : {},
182
- ...promotion.hnswConfig.efConstruction !== void 0 ? { ef_construction: promotion.hnswConfig.efConstruction } : {},
183
- ...promotion.hnswConfig.metric !== void 0 ? { metric: promotion.hnswConfig.metric } : {}
184
- }
185
- } : {},
186
- ...promotion.quantization !== void 0 ? { quantization: promotion.quantization } : {},
187
- ...promotion.storage !== void 0 ? { storage: promotion.storage } : {}
188
- };
189
- }
190
- if (meta.patternValueLimit !== void 0) {
191
- wire.pattern_value_limit = meta.patternValueLimit;
192
- }
193
- if (meta.indexUuid !== void 0) {
194
- wire.index_uuid = meta.indexUuid;
195
- }
196
- if (meta.heldPartitions !== void 0) {
197
- wire.held_partitions = meta.heldPartitions;
198
- }
199
- return wire;
200
- }
201
- function wireToMetadata(raw) {
202
- const meta = {
203
- indexName: raw.index_name,
204
- schema: raw.schema ?? {},
205
- language: raw.language ?? "english",
206
- partitionCount: raw.partition_count ?? 1,
207
- bm25Params: raw.bm25_params ?? { k1: 1.2, b: 0.75 },
208
- createdAt: raw.created_at ?? 0,
209
- engineVersion: raw.engine_version ?? "0.0.0"
210
- };
211
- if (raw.vector_fields) {
212
- for (const [fieldPath, field] of Object.entries(raw.vector_fields)) {
213
- if (!isQuantizationMode(field.quantization)) {
214
- throw new NarsilError(
215
- ErrorCodes.CONFIG_INVALID,
216
- `Index metadata names a vector quantization "${String(field.quantization)}" for "${fieldPath}" this engine does not read`,
217
- { fieldPath, quantization: field.quantization }
218
- );
219
- }
220
- }
221
- meta.vectorFields = raw.vector_fields;
222
- }
223
- if (isNonNegativeInteger(raw.document_count) && Number.isSafeInteger(raw.document_count)) {
224
- meta.documentCount = raw.document_count;
225
- }
226
- if (raw.embedding && typeof raw.embedding === "object" && typeof raw.embedding.fields === "object") {
227
- meta.embedding = typeof raw.embedding.adapter === "string" ? { adapter: raw.embedding.adapter, fields: raw.embedding.fields } : { fields: raw.embedding.fields };
228
- }
229
- if (typeof raw.surface_forms_enabled === "boolean") {
230
- meta.surfaceForms = raw.surface_forms_enabled;
231
- }
232
- if (typeof raw.analysis_revision === "string") {
233
- meta.analysisRevision = raw.analysis_revision;
234
- }
235
- if (typeof raw.tokenizer === "string") {
236
- meta.tokenizer = raw.tokenizer;
237
- }
238
- if (typeof raw.stop_words === "string") {
239
- meta.stopWords = raw.stop_words;
240
- }
241
- if (Array.isArray(raw.stop_word_list) && raw.stop_word_list.every((word) => typeof word === "string")) {
242
- meta.stopWordList = raw.stop_word_list;
243
- }
244
- if (raw.partition_limits && typeof raw.partition_limits === "object") {
245
- const limits = {
246
- ...isPositiveInteger(raw.partition_limits.max_docs_per_partition) ? { maxDocsPerPartition: raw.partition_limits.max_docs_per_partition } : {},
247
- ...isPositiveInteger(raw.partition_limits.max_partitions) ? { maxPartitions: raw.partition_limits.max_partitions } : {},
248
- ...isWatermarkFraction(raw.partition_limits.watermark) ? { watermark: raw.partition_limits.watermark } : {}
249
- };
250
- if (Object.keys(limits).length > 0) {
251
- meta.partitionLimits = limits;
252
- }
253
- }
254
- if (raw.default_scoring === "local" || raw.default_scoring === "dfs" || raw.default_scoring === "broadcast") {
255
- meta.defaultScoring = raw.default_scoring;
256
- }
257
- if (typeof raw.track_positions === "boolean") {
258
- meta.trackPositions = raw.track_positions;
259
- }
260
- if (typeof raw.strict === "boolean") {
261
- meta.strict = raw.strict;
262
- }
263
- if (Array.isArray(raw.required) && raw.required.every((field) => typeof field === "string")) {
264
- meta.required = raw.required;
265
- }
266
- if (raw.vector_promotion && typeof raw.vector_promotion === "object") {
267
- const promotion = raw.vector_promotion;
268
- const hnsw = promotion.hnsw_config && typeof promotion.hnsw_config === "object" ? promotion.hnsw_config : void 0;
269
- const metric = hnsw?.metric;
270
- const restored = {};
271
- const hnswConfig = {};
272
- if (isPositiveInteger(hnsw?.m)) {
273
- hnswConfig.m = hnsw?.m;
274
- }
275
- if (isPositiveInteger(hnsw?.ef_construction)) {
276
- hnswConfig.efConstruction = hnsw?.ef_construction;
277
- }
278
- if (metric === "cosine" || metric === "dotProduct" || metric === "euclidean") {
279
- hnswConfig.metric = metric;
280
- }
281
- if (isPositiveInteger(promotion.threshold)) {
282
- restored.threshold = promotion.threshold;
283
- }
284
- if (isSelectivityRatio(promotion.filter_threshold)) {
285
- restored.filterThreshold = promotion.filter_threshold;
286
- }
287
- if (Object.keys(hnswConfig).length > 0) {
288
- restored.hnswConfig = hnswConfig;
289
- }
290
- if (promotion.quantization !== void 0) {
291
- if (!isQuantizationMode(promotion.quantization)) {
292
- throw new NarsilError(
293
- ErrorCodes.CONFIG_INVALID,
294
- `Index metadata names a vector quantization "${String(promotion.quantization)}" this engine does not read`,
295
- { quantization: promotion.quantization }
296
- );
297
- }
298
- restored.quantization = promotion.quantization;
299
- }
300
- if (promotion.storage !== void 0) {
301
- if (!isStorageMode(promotion.storage)) {
302
- throw new NarsilError(
303
- ErrorCodes.CONFIG_INVALID,
304
- `Index metadata names a vector storage "${String(promotion.storage)}" this engine does not read`,
305
- { storage: promotion.storage }
306
- );
307
- }
308
- restored.storage = promotion.storage;
309
- }
310
- if (Object.keys(restored).length > 0) {
311
- meta.vectorPromotion = restored;
312
- }
313
- }
314
- if (raw.pattern_value_limit !== void 0) {
315
- if (!isPositiveInteger(raw.pattern_value_limit)) {
316
- throw new NarsilError(
317
- ErrorCodes.CONFIG_INVALID,
318
- `The pattern value limit in the index metadata is ${String(raw.pattern_value_limit)}, but the limit must be a whole number of code points`,
319
- { patternValueLimit: String(raw.pattern_value_limit) }
320
- );
321
- }
322
- meta.patternValueLimit = raw.pattern_value_limit;
323
- }
324
- if (typeof raw.index_uuid === "string" && raw.index_uuid.length > 0) {
325
- meta.indexUuid = raw.index_uuid;
326
- }
327
- if (Array.isArray(raw.held_partitions) && raw.held_partitions.every(isNonNegativeInteger)) {
328
- meta.heldPartitions = raw.held_partitions;
329
- }
330
- return meta;
331
- }
332
- function isNonNegativeInteger(value) {
333
- return typeof value === "number" && Number.isInteger(value) && value >= 0;
334
- }
335
- function isPositiveInteger(value) {
336
- return typeof value === "number" && Number.isInteger(value) && value >= 1;
337
- }
338
- function isSelectivityRatio(value) {
339
- return typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= 1;
340
- }
341
- function isWatermarkFraction(value) {
342
- return typeof value === "number" && value > 0 && value <= 1;
343
- }
344
- function serializeMetadata(meta) {
345
- const wire = metadataToWire(meta);
346
- return encode(wire);
347
- }
348
- function deserializeMetadata(data) {
349
- const raw = decode(data);
350
- return wireToMetadata(raw);
351
- }
352
-
353
- // src/serialization/stored-vector-values.ts
354
- function dropStoredVectorValues(documents, schema) {
355
- const vectorFieldPaths = [];
356
- for (const [fieldPath, fieldType] of Object.entries(schema)) {
357
- if (typeof fieldType === "string" && VECTOR_PATTERN.test(fieldType)) {
358
- vectorFieldPaths.push(fieldPath);
359
- }
360
- }
361
- if (vectorFieldPaths.length === 0) {
362
- return;
363
- }
364
- for (const document of Object.values(documents)) {
365
- for (const fieldPath of vectorFieldPaths) {
366
- removeFieldAtPath(document.fields, fieldPath);
367
- }
368
- }
369
- }
370
- function removeFieldAtPath(fields, fieldPath) {
371
- if (!fieldPath.includes(".")) {
372
- delete fields[fieldPath];
373
- return;
374
- }
375
- const segments = fieldPath.split(".");
376
- let current = fields;
377
- for (let i = 0; i < segments.length - 1; i += 1) {
378
- const next = current[segments[i]];
379
- if (next === null || typeof next !== "object") {
380
- return;
381
- }
382
- current = next;
383
- }
384
- delete current[segments[segments.length - 1]];
385
- }
386
-
387
- // src/serialization/payload-v1/partition.ts
388
- function sanitizeSurfaceForms(raw) {
389
- if (raw === void 0 || raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
390
- const result = /* @__PURE__ */ Object.create(null);
391
- let count = 0;
392
- for (const [surface, value] of Object.entries(raw)) {
393
- if (typeof value === "number") {
394
- result[surface] = value;
395
- count++;
396
- } else if (Array.isArray(value) && typeof value[0] === "number" && typeof value[1] === "string") {
397
- result[surface] = [value[0], value[1]];
398
- count++;
399
- }
400
- }
401
- return count > 0 ? result : void 0;
402
- }
403
- function patternIndexesToWire(pattern) {
404
- if (pattern === void 0) return {};
405
- const wire = /* @__PURE__ */ Object.create(null);
406
- for (const [field, index] of Object.entries(pattern)) wire[field] = { doc_ids: index.docIds, runs: index.runs };
407
- return { pattern: wire };
408
- }
409
- function isWireRecord(value) {
410
- return value !== null && typeof value === "object" && !Array.isArray(value);
411
- }
412
- function corruptPatternEntry(field) {
413
- return new NarsilError(
414
- ErrorCodes.PERSISTENCE_LOAD_FAILED,
415
- `The pattern entry of field "${field}" in this partition must hold a list of document IDs and a map of runs`,
416
- { field }
417
- );
418
- }
419
- function patternIndexesFromWire(raw) {
420
- if (raw === void 0 || raw === null) return {};
421
- if (!isWireRecord(raw)) {
422
- throw new NarsilError(
423
- ErrorCodes.PERSISTENCE_LOAD_FAILED,
424
- "The pattern entry of this partition must be a map of fields"
425
- );
426
- }
427
- const pattern = /* @__PURE__ */ Object.create(null);
428
- for (const [field, index] of Object.entries(raw)) {
429
- if (!isWireRecord(index) || !isWireRecord(index.runs) || !Array.isArray(index.doc_ids)) {
430
- throw corruptPatternEntry(field);
431
- }
432
- const docIds = [];
433
- for (const docId of index.doc_ids) {
434
- if (typeof docId !== "string") throw corruptPatternEntry(field);
435
- docIds.push(docId);
436
- }
437
- pattern[field] = { docIds, runs: index.runs };
438
- }
439
- return { pattern };
440
- }
441
- function validateHnswMetric(value) {
442
- if (value === void 0 || value === null) return void 0;
443
- if (typeof value === "string" && VALID_HNSW_METRICS.has(value)) {
444
- return value;
445
- }
446
- return void 0;
447
- }
448
- function wireToPartition(raw) {
449
- const documents = {};
450
- for (const [docId, doc] of Object.entries(raw.documents ?? {})) {
451
- documents[docId] = {
452
- fields: doc.fields,
453
- fieldLengths: doc.field_lengths ?? {}
454
- };
455
- }
456
- requireValidFieldTypes(raw.schema ?? {});
457
- dropStoredVectorValues(documents, raw.schema ?? {});
458
- const invertedIndex = {};
459
- for (const [token, list] of Object.entries(raw.inverted_index ?? {})) {
460
- invertedIndex[token] = {
461
- docFrequency: list.doc_freq,
462
- postings: (list.postings ?? []).map((p) => ({
463
- docId: p.doc_id,
464
- termFrequency: p.term_freq,
465
- field: p.field,
466
- positions: p.positions ?? []
467
- }))
468
- };
469
- }
470
- const numeric = {};
471
- for (const [field, entries] of Object.entries(raw.field_indexes?.numeric ?? {})) {
472
- numeric[field] = entries.map((e) => ({ value: e.value, docId: e.doc_id }));
473
- }
474
- const boolean = {};
475
- for (const [field, idx] of Object.entries(raw.field_indexes?.boolean ?? {})) {
476
- boolean[field] = { trueDocs: idx.true_docs ?? [], falseDocs: idx.false_docs ?? [] };
477
- }
478
- const geopoint = {};
479
- for (const [field, entries] of Object.entries(raw.field_indexes?.geopoint ?? {})) {
480
- geopoint[field] = entries.map((e) => ({ lat: e.lat, lon: e.lon, docId: e.doc_id }));
481
- }
482
- const vectorData = {};
483
- for (const [field, data] of Object.entries(raw.vector_data ?? {})) {
484
- vectorData[field] = {
485
- dimension: data.dimension,
486
- vectors: (data.vectors ?? []).map((v) => ({ docId: v.doc_id, vector: v.vector })),
487
- hnswGraph: data.hnsw_graph ? {
488
- entryPoint: data.hnsw_graph.entry_point,
489
- maxLayer: data.hnsw_graph.max_layer,
490
- m: data.hnsw_graph.m,
491
- efConstruction: data.hnsw_graph.ef_construction,
492
- metric: validateHnswMetric(data.hnsw_graph.metric),
493
- nodes: data.hnsw_graph.nodes
494
- } : null,
495
- codes: data.codes ? { bits: data.codes.bits, centroid: data.codes.centroid, records: data.codes.records } : null
496
- };
497
- }
498
- return {
499
- indexName: raw.index_name,
500
- partitionId: raw.partition_id,
501
- totalPartitions: raw.total_partitions,
502
- language: raw.language ?? "english",
503
- schema: raw.schema ?? {},
504
- docCount: raw.doc_count ?? 0,
505
- avgDocLength: raw.avg_doc_length ?? 0,
506
- documents,
507
- invertedIndex,
508
- fieldIndexes: {
509
- numeric,
510
- boolean,
511
- enum: raw.field_indexes?.enum ?? {},
512
- geopoint,
513
- ...patternIndexesFromWire(raw.field_indexes?.pattern)
514
- },
515
- surfaceForms: sanitizeSurfaceForms(raw.surface_forms),
516
- vectorData,
517
- statistics: {
518
- totalDocuments: raw.statistics?.total_documents ?? 0,
519
- totalFieldLengths: raw.statistics?.total_field_lengths ?? {},
520
- averageFieldLengths: raw.statistics?.average_field_lengths ?? {},
521
- docFrequencies: raw.statistics?.doc_frequencies ?? {}
522
- }
523
- };
524
- }
525
- function deserializePayloadV1(data) {
526
- const raw = decode(data);
527
- return wireToPartition(raw);
528
- }
529
-
530
- // src/serialization/payload-v2.ts
531
- function encodeRawPayloadV2(wire) {
532
- return encode(wire);
533
- }
534
- function validateHnswMetric2(value) {
535
- if (value === void 0 || value === null) return void 0;
536
- if (typeof value === "string" && VALID_HNSW_METRICS.has(value)) {
537
- return value;
538
- }
539
- return void 0;
540
- }
541
- function storedDocumentsOf(raw) {
542
- requireValidFieldTypes(raw.schema ?? {});
543
- const documents = {};
544
- for (const [docId, doc] of Object.entries(raw.documents ?? {})) {
545
- documents[docId] = {
546
- fields: doc.fields,
547
- fieldLengths: doc.field_lengths ?? {}
548
- };
549
- }
550
- dropStoredVectorValues(documents, raw.schema ?? {});
551
- return documents;
552
- }
553
- function documentsOfPayloadV2(data) {
554
- const raw = decode(data);
555
- return { documents: storedDocumentsOf(raw), schema: raw.schema ?? {} };
556
- }
557
- function deserializePayloadV2(data) {
558
- const raw = decode(data);
559
- const documents = storedDocumentsOf(raw);
560
- const fieldNames = raw.inverted_index?.field_names ?? [];
561
- const invertedIndex = {};
562
- for (const [token, list] of Object.entries(raw.inverted_index?.entries ?? {})) {
563
- const count = list.ids.length;
564
- const postings = new Array(count);
565
- for (let i = 0; i < count; i++) {
566
- postings[i] = {
567
- docId: list.ids[i],
568
- termFrequency: list.tf[i],
569
- field: fieldNames[list.fi[i]] ?? "",
570
- positions: list.pos ? list.pos[i] : []
571
- };
572
- }
573
- invertedIndex[token] = {
574
- docFrequency: list.df,
575
- postings
576
- };
577
- }
578
- const numeric = {};
579
- for (const [field, entries] of Object.entries(raw.field_indexes?.numeric ?? {})) {
580
- numeric[field] = entries.map((e) => ({ value: e.value, docId: e.doc_id }));
581
- }
582
- const boolean = {};
583
- for (const [field, idx] of Object.entries(raw.field_indexes?.boolean ?? {})) {
584
- boolean[field] = { trueDocs: idx.true_docs ?? [], falseDocs: idx.false_docs ?? [] };
585
- }
586
- const geopoint = {};
587
- for (const [field, entries] of Object.entries(raw.field_indexes?.geopoint ?? {})) {
588
- geopoint[field] = entries.map((e) => ({ lat: e.lat, lon: e.lon, docId: e.doc_id }));
589
- }
590
- const vectorData = {};
591
- for (const [field, data2] of Object.entries(raw.vector_data ?? {})) {
592
- vectorData[field] = {
593
- dimension: data2.dimension,
594
- vectors: (data2.vectors ?? []).map((v) => ({ docId: v.doc_id, vector: v.vector })),
595
- hnswGraph: data2.hnsw_graph ? {
596
- entryPoint: data2.hnsw_graph.entry_point,
597
- maxLayer: data2.hnsw_graph.max_layer,
598
- m: data2.hnsw_graph.m,
599
- efConstruction: data2.hnsw_graph.ef_construction,
600
- metric: validateHnswMetric2(data2.hnsw_graph.metric),
601
- nodes: data2.hnsw_graph.nodes
602
- } : null,
603
- codes: data2.codes ? { bits: data2.codes.bits, centroid: data2.codes.centroid, records: data2.codes.records } : null
604
- };
605
- }
606
- return {
607
- indexName: raw.index_name,
608
- partitionId: raw.partition_id,
609
- totalPartitions: raw.total_partitions,
610
- language: raw.language ?? "english",
611
- schema: raw.schema ?? {},
612
- docCount: raw.doc_count ?? 0,
613
- avgDocLength: raw.avg_doc_length ?? 0,
614
- documents,
615
- invertedIndex,
616
- fieldIndexes: {
617
- numeric,
618
- boolean,
619
- enum: raw.field_indexes?.enum ?? {},
620
- geopoint,
621
- ...patternIndexesFromWire(raw.field_indexes?.pattern)
622
- },
623
- surfaceForms: sanitizeSurfaceForms(raw.surface_forms),
624
- vectorData,
625
- statistics: {
626
- totalDocuments: raw.statistics?.total_documents ?? 0,
627
- totalFieldLengths: raw.statistics?.total_field_lengths ?? {},
628
- averageFieldLengths: raw.statistics?.average_field_lengths ?? {},
629
- docFrequencies: raw.statistics?.doc_frequencies ?? {}
630
- }
631
- };
632
- }
633
120
 
634
121
  // src/core/document-store.ts
635
122
  function detachedView(view) {
@@ -889,7 +376,7 @@ function createPostingList() {
889
376
  length: 0,
890
377
  docIds: [],
891
378
  termFrequencies: new Uint16Array(POSTING_LIST_INITIAL_CAPACITY),
892
- fieldNameIndices: new Uint8Array(POSTING_LIST_INITIAL_CAPACITY),
379
+ fieldNameIndices: new Uint16Array(POSTING_LIST_INITIAL_CAPACITY),
893
380
  positions: null,
894
381
  docIdSet: /* @__PURE__ */ new Set(),
895
382
  deletedDocs: /* @__PURE__ */ new Set(),
@@ -903,7 +390,7 @@ function growTypedArrays(list) {
903
390
  const newTF = new Uint16Array(newCap);
904
391
  newTF.set(list.termFrequencies);
905
392
  list.termFrequencies = newTF;
906
- const newFNI = new Uint8Array(newCap);
393
+ const newFNI = new Uint16Array(newCap);
907
394
  newFNI.set(list.fieldNameIndices);
908
395
  list.fieldNameIndices = newFNI;
909
396
  }
@@ -1148,7 +635,7 @@ function createInvertedIndex(fieldNameTable) {
1148
635
  const docIdSet = /* @__PURE__ */ new Set();
1149
636
  const docIds = new Array(count);
1150
637
  const termFrequencies = new Uint16Array(count);
1151
- const fieldNameIndices = new Uint8Array(count);
638
+ const fieldNameIndices = new Uint16Array(count);
1152
639
  let hasPositions = false;
1153
640
  let validCount = 0;
1154
641
  let totalTermFrequency = 0;
@@ -4931,7 +4418,7 @@ function encodeSegmentState(state) {
4931
4418
  const postingOffsets = new Uint32Array(state.invertedIdx.size() + 1);
4932
4419
  const postingDocIds = new Uint32Array(postings);
4933
4420
  const postingFrequencies = new Uint16Array(postings);
4934
- const postingFieldIndices = new Uint8Array(postings);
4421
+ const postingFieldIndices = new Uint16Array(postings);
4935
4422
  const positionOffsets = hasPositions ? new Uint32Array(postings + 1) : null;
4936
4423
  const positionValues = hasPositions ? new Uint32Array(positions) : null;
4937
4424
  let postingCursor = 0;
@@ -5465,113 +4952,6 @@ function expandTermPrefix(state, surfacePrefix, stemmedToken, maxExpansions) {
5465
4952
  return entries.map((e) => e[0]);
5466
4953
  }
5467
4954
 
5468
- // src/core/partition/wire-payload.ts
5469
- function serializePartitionToWirePayloadV2(state, partitionId, indexName, totalPartitions, language, schema) {
5470
- const flatSchema = getFlatSchema(state, schema);
5471
- const flatSchemaStrings = {};
5472
- for (const [k, v] of Object.entries(flatSchema)) {
5473
- flatSchemaStrings[k] = v;
5474
- }
5475
- const wireDocs = /* @__PURE__ */ Object.create(null);
5476
- for (const [docId, stored] of state.docStore.all()) {
5477
- wireDocs[docId] = {
5478
- fields: stored.fields,
5479
- field_lengths: { ...stored.fieldLengths }
5480
- };
5481
- }
5482
- const resolver = state.docStore.resolver();
5483
- const fieldNames = [...state.fieldNameTable.names];
5484
- const wireEntries = /* @__PURE__ */ Object.create(null);
5485
- for (const token of state.invertedIdx.tokens()) {
5486
- const list = state.invertedIdx.lookup(token);
5487
- if (!list) continue;
5488
- const hasDeleted = list.deletedDocs.size > 0;
5489
- const ids = [];
5490
- const tf = [];
5491
- const fi = new Uint8Array(list.length);
5492
- const pos = list.positions ? [] : null;
5493
- let writeIdx = 0;
5494
- for (let i = 0; i < list.length; i++) {
5495
- if (hasDeleted && list.deletedDocs.has(list.docIds[i])) continue;
5496
- const externalId = resolver.toExternal(list.docIds[i]);
5497
- if (externalId === void 0) continue;
5498
- ids.push(externalId);
5499
- tf.push(list.termFrequencies[i]);
5500
- fi[writeIdx] = list.fieldNameIndices[i];
5501
- writeIdx++;
5502
- if (pos && list.positions) {
5503
- pos.push(list.positions[i]);
5504
- }
5505
- }
5506
- if (ids.length > 0) {
5507
- const finalFi = writeIdx < list.length ? fi.subarray(0, writeIdx) : fi;
5508
- wireEntries[token] = { df: list.docIdSet.size, ids, tf, fi: finalFi, pos };
5509
- }
5510
- }
5511
- const wireNumeric = {};
5512
- for (const [path, idx] of state.numericIndexes) {
5513
- wireNumeric[path] = idx.serialize().map((e) => ({
5514
- value: e.value,
5515
- doc_id: resolver.toExternal(e.docId) ?? ""
5516
- }));
5517
- }
5518
- const wireBoolean = {};
5519
- for (const [path, idx] of state.booleanIndexes) {
5520
- const s = idx.serialize();
5521
- wireBoolean[path] = {
5522
- true_docs: s.trueDocs.map((id) => resolver.toExternal(id) ?? "").filter((id) => id !== ""),
5523
- false_docs: s.falseDocs.map((id) => resolver.toExternal(id) ?? "").filter((id) => id !== "")
5524
- };
5525
- }
5526
- const wireEnum = {};
5527
- for (const [path, idx] of state.enumIndexes) {
5528
- const raw = idx.serialize();
5529
- const converted = /* @__PURE__ */ Object.create(null);
5530
- for (const [value, internalIds] of Object.entries(raw)) {
5531
- converted[value] = internalIds.map((id) => resolver.toExternal(id) ?? "").filter((id) => id !== "");
5532
- }
5533
- wireEnum[path] = converted;
5534
- }
5535
- const wireGeo = {};
5536
- for (const [path, idx] of state.geoIndexes) {
5537
- wireGeo[path] = idx.serialize().map((e) => ({
5538
- lat: e.lat,
5539
- lon: e.lon,
5540
- doc_id: resolver.toExternal(e.docId) ?? ""
5541
- }));
5542
- }
5543
- const serializedStats = state.stats.serialize();
5544
- return {
5545
- v: 2,
5546
- index_name: indexName,
5547
- partition_id: partitionId,
5548
- total_partitions: totalPartitions,
5549
- language,
5550
- schema: flatSchemaStrings,
5551
- doc_count: state.docStore.count(),
5552
- avg_doc_length: Object.values(serializedStats.averageFieldLengths).reduce((sum, v) => sum + v, 0),
5553
- documents: wireDocs,
5554
- inverted_index: {
5555
- field_names: fieldNames,
5556
- entries: wireEntries
5557
- },
5558
- field_indexes: {
5559
- numeric: wireNumeric,
5560
- boolean: wireBoolean,
5561
- enum: wireEnum,
5562
- geopoint: wireGeo,
5563
- ...patternIndexesToWire(serializePatternIndexes(state, schema))
5564
- },
5565
- surface_forms: state.surfaceRegistry.serialize(),
5566
- statistics: {
5567
- total_documents: serializedStats.totalDocuments,
5568
- total_field_lengths: serializedStats.totalFieldLengths,
5569
- average_field_lengths: serializedStats.averageFieldLengths,
5570
- doc_frequencies: serializedStats.docFrequencies
5571
- }
5572
- };
5573
- }
5574
-
5575
4955
  // src/core/partition/index.ts
5576
4956
  var statesByPartition = /* @__PURE__ */ new WeakMap();
5577
4957
  function readSegmentState(segment) {
@@ -5814,10 +5194,6 @@ function createPartitionIndex(partitionId, trackPositions = true) {
5814
5194
  serialize(indexName, totalPartitions, language, schema) {
5815
5195
  return serializePartition(state, partitionId, indexName, totalPartitions, language, schema);
5816
5196
  },
5817
- serializeToBytes(indexName, totalPartitions, language, schema) {
5818
- const wire = serializePartitionToWirePayloadV2(state, partitionId, indexName, totalPartitions, language, schema);
5819
- return encodeRawPayloadV2(wire);
5820
- },
5821
5197
  deserialize(data, schema) {
5822
5198
  deserializePartition(state, data, clearAll, schema);
5823
5199
  }
@@ -6340,10 +5716,6 @@ function createCompositePartition(partitionId, trackPositions = true, existingLi
6340
5716
  if (frozen.length === 0) return live.serialize(indexName, totalPartitions, language, schema);
6341
5717
  return composedScratch().serialize(indexName, totalPartitions, language, schema);
6342
5718
  },
6343
- serializeToBytes(indexName, totalPartitions, language, schema) {
6344
- if (frozen.length === 0) return live.serializeToBytes(indexName, totalPartitions, language, schema);
6345
- return composedScratch().serializeToBytes(indexName, totalPartitions, language, schema);
6346
- },
6347
5719
  deserialize(data, schema) {
6348
5720
  frozen.length = 0;
6349
5721
  invalidateDocFrequencies();
@@ -6774,10 +6146,6 @@ function createPartitionManager(indexName, config, language, router, initialPart
6774
6146
  validatePartitionId(partitionId);
6775
6147
  return partitions[partitionId].serialize(indexName, partitions.length, language.name, config.schema);
6776
6148
  },
6777
- serializePartitionToBytes(partitionId) {
6778
- validatePartitionId(partitionId);
6779
- return partitions[partitionId].serializeToBytes(indexName, partitions.length, language.name, config.schema);
6780
- },
6781
6149
  mergeSegment(partitionId, payload, documents) {
6782
6150
  validatePartitionId(partitionId);
6783
6151
  const partition = partitions[partitionId];
@@ -6903,6 +6271,9 @@ var WORKER_COPY_MIN_VECTORS = 1024;
6903
6271
  var BUILD_CHUNK_SIZE = 100;
6904
6272
  var REBUILD_REMOVED_RATIO = 0.2;
6905
6273
  var VECTOR_FILE_REPLACED_ABOVE_DEAD_SHARE = 0.2;
6274
+ var VECTOR_FILE_FIXED_OVERHEAD_BYTES = 65536;
6275
+ var VECTOR_FILE_STRING_HEADER_BYTES = 5;
6276
+ var VECTOR_FILE_CENTROID_BYTES_PER_COMPONENT = 9;
6906
6277
  var OSQ4_MIN_DIMENSION = 384;
6907
6278
  var DISK_ADOPTION_YIELD_INTERVAL = 4096;
6908
6279
 
@@ -6962,7 +6333,7 @@ function yieldToEventLoop() {
6962
6333
  return new Promise((resolve) => setTimeout(resolve, 0));
6963
6334
  }
6964
6335
  function* allLiveDocIds(state) {
6965
- for (const [docId] of state.store.entries()) {
6336
+ for (const docId of state.store.docIds()) {
6966
6337
  if (state.tombstones.has(docId)) continue;
6967
6338
  yield docId;
6968
6339
  }
@@ -7083,14 +6454,6 @@ async function nodeThreadId() {
7083
6454
  return 0;
7084
6455
  }
7085
6456
  }
7086
- async function isNodeMainThread() {
7087
- try {
7088
- const workerThreads = await import('worker_threads');
7089
- return workerThreads.isMainThread;
7090
- } catch {
7091
- return true;
7092
- }
7093
- }
7094
6457
 
7095
6458
  // src/workers/entry-point.ts
7096
6459
  var DIST_SEGMENT = "/dist/";
@@ -7855,6 +7218,12 @@ function scheduleBuild(state) {
7855
7218
  }, 0);
7856
7219
  }
7857
7220
 
7221
+ // src/serialization/constants.ts
7222
+ var CHECKSUM_YIELD_CHUNK_BYTES = 4 * 1024 * 1024;
7223
+ var NATIVE_CRC32_MIN_BYTES = 16;
7224
+ var MAX_FILE_BYTES = 2147483647;
7225
+ var VALID_HNSW_METRICS = /* @__PURE__ */ new Set(["cosine", "dotProduct", "euclidean"]);
7226
+
7858
7227
  // src/vector/vector-index/payload.ts
7859
7228
  var VECTOR_INDEX_PAYLOAD_VERSION = 3;
7860
7229
  var VECTOR_INDEX_PART_VECTORS = 65536;
@@ -7881,7 +7250,7 @@ function invalid(message, details) {
7881
7250
  function isRecord(value) {
7882
7251
  return typeof value === "object" && value !== null && !Array.isArray(value);
7883
7252
  }
7884
- function isNonNegativeInteger2(value) {
7253
+ function isNonNegativeInteger(value) {
7885
7254
  return typeof value === "number" && Number.isInteger(value) && value >= 0;
7886
7255
  }
7887
7256
  function isSerializedGraph(value) {
@@ -7911,9 +7280,9 @@ function decodeVectorIndexPart(raw) {
7911
7280
  );
7912
7281
  }
7913
7282
  if (typeof raw.fieldName !== "string") invalid("fieldName must be a string");
7914
- if (!isNonNegativeInteger2(raw.dimension) || raw.dimension === 0) invalid("dimension must be a positive integer");
7915
- if (!isNonNegativeInteger2(raw.part)) invalid("part must be a non-negative integer");
7916
- if (!isNonNegativeInteger2(raw.parts) || raw.parts === 0 || raw.part >= raw.parts) {
7283
+ if (!isNonNegativeInteger(raw.dimension) || raw.dimension === 0) invalid("dimension must be a positive integer");
7284
+ if (!isNonNegativeInteger(raw.part)) invalid("part must be a non-negative integer");
7285
+ if (!isNonNegativeInteger(raw.parts) || raw.parts === 0 || raw.part >= raw.parts) {
7917
7286
  invalid("parts must exceed part", { part: raw.part, parts: raw.parts });
7918
7287
  }
7919
7288
  if (!Array.isArray(raw.docIds) || !raw.docIds.every((docId) => typeof docId === "string")) {
@@ -7952,6 +7321,8 @@ function decodeVectorIndexParts(raw) {
7952
7321
  // src/vector/vector-index/checkpoint-payload.ts
7953
7322
  var VECTOR_FILE_PAYLOAD_VERSION = 1;
7954
7323
  var VECTOR_GRAPH_PAYLOAD_VERSION = 1;
7324
+ var VECTOR_GRAPH_PART_PAYLOAD_VERSION = 2;
7325
+ var VECTOR_GRAPH_PART_VECTORS = 16384;
7955
7326
  var VECTOR_FILE_MAX_VECTORS = VECTOR_INDEX_PART_VECTORS;
7956
7327
  var METRICS = ["cosine", "dotProduct", "euclidean"];
7957
7328
  function invalid2(payload, message, details) {
@@ -8002,14 +7373,16 @@ function decodeVectorFilePayload(raw) {
8002
7373
  function isMetric(value) {
8003
7374
  return METRICS.some((metric) => metric === value);
8004
7375
  }
8005
- function decodeNumberedGraph(raw) {
7376
+ function decodeNumberedGraph(raw, minimumM) {
8006
7377
  const name = "vector graph";
8007
7378
  if (!isRecord2(raw)) invalid2(name, "each graph must be a map");
8008
7379
  const entryPoint = raw.entryPoint ?? null;
8009
7380
  if (entryPoint !== null && !isIntegerUpTo(entryPoint, 4294967295))
8010
7381
  invalid2(name, "entryPoint must be a uint32 or nil");
8011
7382
  if (!isIntegerUpTo(raw.maxLayer, 255)) invalid2(name, "maxLayer must be a uint8");
8012
- if (!isIntegerUpTo(raw.m, 65535) || raw.m === 0) invalid2(name, "m must be a positive uint16");
7383
+ if (!isIntegerUpTo(raw.m, MAX_M) || raw.m < minimumM) {
7384
+ invalid2(name, `m must be a whole number from ${minimumM} to ${MAX_M}`);
7385
+ }
8013
7386
  if (!isIntegerUpTo(raw.efConstruction, 65535)) invalid2(name, "efConstruction must be a uint16");
8014
7387
  if (!isMetric(raw.metric)) invalid2(name, "metric must name a supported metric", { metric: raw.metric });
8015
7388
  if (!(raw.levels instanceof Uint8Array)) invalid2(name, "levels must be bytes");
@@ -8030,7 +7403,56 @@ function decodeVectorGraphPayload(raw) {
8030
7403
  requireVersion(name, raw.v, VECTOR_GRAPH_PAYLOAD_VERSION);
8031
7404
  if (typeof raw.fieldName !== "string") invalid2(name, "fieldName must be a string");
8032
7405
  if (!Array.isArray(raw.graphs)) invalid2(name, "graphs must be a list");
8033
- return { v: VECTOR_GRAPH_PAYLOAD_VERSION, fieldName: raw.fieldName, graphs: raw.graphs.map(decodeNumberedGraph) };
7406
+ return {
7407
+ v: VECTOR_GRAPH_PAYLOAD_VERSION,
7408
+ fieldName: raw.fieldName,
7409
+ graphs: raw.graphs.map((graph) => decodeNumberedGraph(graph, EARLIER_RELEASE_MIN_M))
7410
+ };
7411
+ }
7412
+ function decodeVectorGraphPartPayload(raw) {
7413
+ const name = "vector graph part";
7414
+ if (!isRecord2(raw)) invalid2(name, "payload must be a map");
7415
+ requireVersion(name, raw.v, VECTOR_GRAPH_PART_PAYLOAD_VERSION);
7416
+ if (typeof raw.fieldName !== "string") invalid2(name, "fieldName must be a string");
7417
+ if (!Array.isArray(raw.graphs)) invalid2(name, "graphs must be a list");
7418
+ return {
7419
+ v: VECTOR_GRAPH_PART_PAYLOAD_VERSION,
7420
+ fieldName: raw.fieldName,
7421
+ graphs: raw.graphs.map((graph) => decodeNumberedGraph(graph, MIN_M))
7422
+ };
7423
+ }
7424
+ function sameGraphHeader(a, b) {
7425
+ return a.entryPoint === b.entryPoint && a.maxLayer === b.maxLayer && a.m === b.m && a.efConstruction === b.efConstruction && a.metric === b.metric;
7426
+ }
7427
+ function assembleGraphParts(parts) {
7428
+ const name = "vector graph part";
7429
+ const first = parts[0];
7430
+ if (first === void 0) invalid2(name, "a field that holds a graph must have at least one part");
7431
+ const partLists = first.graphs.map(() => []);
7432
+ for (let p = 0; p < parts.length; p++) {
7433
+ const part = parts[p];
7434
+ const isLast = p === parts.length - 1;
7435
+ if (part.fieldName !== first.fieldName || part.graphs.length !== first.graphs.length) {
7436
+ invalid2(name, `part ${p} lists other graphs than part 0`, { part: p });
7437
+ }
7438
+ for (let g = 0; g < part.graphs.length; g++) {
7439
+ const graph = part.graphs[g];
7440
+ if (!sameGraphHeader(graph, first.graphs[g]))
7441
+ invalid2(name, `part ${p} gives graph ${g} other headers`, { part: p });
7442
+ const levels = graph.levels.length;
7443
+ const fits = isLast ? levels >= 1 && levels <= VECTOR_GRAPH_PART_VECTORS : levels === VECTOR_GRAPH_PART_VECTORS;
7444
+ if (!fits) invalid2(name, `part ${p} gives graph ${g} ${levels} bytes of levels`, { part: p, levels });
7445
+ partLists[g].push(graph);
7446
+ }
7447
+ }
7448
+ const graphs = partLists.map((list) => ({ partSize: VECTOR_GRAPH_PART_VECTORS, parts: list }));
7449
+ return { fieldName: first.fieldName, graphs };
7450
+ }
7451
+ function graphPartsOfEarlierPayload(payload) {
7452
+ return {
7453
+ fieldName: payload.fieldName,
7454
+ graphs: payload.graphs.map((graph) => ({ partSize: Math.max(graph.levels.length, 1), parts: [graph] }))
7455
+ };
8034
7456
  }
8035
7457
 
8036
7458
  // src/vector/vector-index/dead-bits.ts
@@ -8060,36 +7482,6 @@ function deadBitsWhere(count, isDeadAt) {
8060
7482
  }
8061
7483
 
8062
7484
  // src/vector/vector-index/persistence.ts
8063
- function liveDocIds(state) {
8064
- const docIds = [];
8065
- for (let ordinal = 0; ordinal < state.store.slots; ordinal++) {
8066
- const docId = state.store.docIdForOrdinal(ordinal);
8067
- if (docId === void 0 || state.tombstones.has(docId)) continue;
8068
- docIds.push(docId);
8069
- }
8070
- return docIds;
8071
- }
8072
- function partVectors(state, docIds) {
8073
- const dimension = state.dimension;
8074
- const vectors = new Float32Array(docIds.length * dimension);
8075
- for (let i = 0; i < docIds.length; i++) {
8076
- const entry = state.store.get(docIds[i]);
8077
- if (entry !== void 0) vectors.set(entry.vector, i * dimension);
8078
- }
8079
- return vectors;
8080
- }
8081
- function graphsPerPart(state, partOf, parts) {
8082
- const sliced = Array.from({ length: parts }, () => []);
8083
- if (state.hnsw === null || partOf.size === 0) return sliced;
8084
- const graph = state.hnsw.serialize();
8085
- const nodesPerPart = Array.from({ length: parts }, () => []);
8086
- for (const node of graph.nodes) {
8087
- const part = partOf.get(node[0]);
8088
- if (part !== void 0) nodesPerPart[part].push(node);
8089
- }
8090
- for (let part = 0; part < parts; part++) sliced[part].push({ ...graph, nodes: nodesPerPart[part] });
8091
- return sliced;
8092
- }
8093
7485
  function recordFor(state, quantizer, docId) {
8094
7486
  const record = quantizer.recordOf(docId);
8095
7487
  if (record !== void 0) return record;
@@ -8128,36 +7520,6 @@ function partCodes(state, docIds, centroid) {
8128
7520
  }
8129
7521
  return { bits: quantizer.bits, centroid, records };
8130
7522
  }
8131
- function planParts(state) {
8132
- const docIds = liveDocIds(state);
8133
- const parts = Math.max(1, Math.ceil(docIds.length / VECTOR_INDEX_PART_VECTORS));
8134
- const partOf = /* @__PURE__ */ new Map();
8135
- for (let i = 0; i < docIds.length; i++) partOf.set(docIds[i], Math.floor(i / VECTOR_INDEX_PART_VECTORS));
8136
- const graphs = graphsPerPart(state, partOf, parts);
8137
- const centroid = codedCentroid(state);
8138
- return {
8139
- parts,
8140
- readPart(part) {
8141
- const start = part * VECTOR_INDEX_PART_VECTORS;
8142
- const slice = docIds.slice(start, start + VECTOR_INDEX_PART_VECTORS);
8143
- return {
8144
- v: VECTOR_INDEX_PAYLOAD_VERSION,
8145
- fieldName: state.fieldName,
8146
- dimension: state.dimension,
8147
- part,
8148
- parts,
8149
- docIds: slice,
8150
- graphs: graphs[part],
8151
- codes: partCodes(state, slice, centroid),
8152
- vectors: vectorsToBytes(partVectors(state, slice))
8153
- };
8154
- }
8155
- };
8156
- }
8157
- function serialize(state) {
8158
- const plan = planParts(state);
8159
- return Array.from({ length: plan.parts }, (_, part) => plan.readPart(part));
8160
- }
8161
7523
  function splitSequences(parts) {
8162
7524
  const sequences = [];
8163
7525
  let current = null;
@@ -8210,7 +7572,7 @@ function restoreCodes(state, sequences) {
8210
7572
  }
8211
7573
  function restoreGraphs(state, graphs) {
8212
7574
  if (graphs.length === 0) {
8213
- for (const [docId] of state.store.entries()) {
7575
+ for (const docId of state.store.docIds()) {
8214
7576
  if (!state.tombstones.has(docId)) state.buffer.add(docId);
8215
7577
  }
8216
7578
  return;
@@ -8233,14 +7595,14 @@ function restoreGraphs(state, graphs) {
8233
7595
  if (!restoredHnsw.has(nodeDocId) && state.store.has(nodeDocId)) restoredHnsw.insertNode(nodeDocId);
8234
7596
  }
8235
7597
  }
8236
- for (const [docId] of state.store.entries()) {
7598
+ for (const docId of state.store.docIds()) {
8237
7599
  if (state.tombstones.has(docId)) continue;
8238
7600
  if (!restoredHnsw.has(docId)) state.buffer.add(docId);
8239
7601
  }
8240
7602
  if (state.buffer.size > restoredHnsw.size) {
8241
7603
  adoptGraph(state, null);
8242
7604
  state.buffer.clear();
8243
- for (const [docId] of state.store.entries()) {
7605
+ for (const docId of state.store.docIds()) {
8244
7606
  if (!state.tombstones.has(docId)) state.buffer.add(docId);
8245
7607
  }
8246
7608
  }
@@ -8279,6 +7641,17 @@ function deserialize(state, parts) {
8279
7641
 
8280
7642
  // src/vector/vector-index/checkpoint-plan.ts
8281
7643
  var ORDINAL_HOLDS_NO_NUMBER = -1;
7644
+ function vectorsPerFile(dimension, codeBits) {
7645
+ const recordBytes = codeBits === 1 || codeBits === 2 || codeBits === 4 || codeBits === 8 ? osqRecordBytes(dimension, codeBits) : 0;
7646
+ const docIdBytes = VECTOR_FILE_STRING_HEADER_BYTES + MAX_DOC_ID_LENGTH * 3;
7647
+ const perVector = dimension * 4 + recordBytes + docIdBytes;
7648
+ const overhead = VECTOR_FILE_FIXED_OVERHEAD_BYTES + dimension * VECTOR_FILE_CENTROID_BYTES_PER_COMPONENT;
7649
+ const fitting = Math.floor((MAX_FILE_BYTES - overhead) / perVector);
7650
+ return Math.max(1, Math.min(VECTOR_FILE_MAX_VECTORS, fitting));
7651
+ }
7652
+ function fileCapacityOf(state) {
7653
+ return vectorsPerFile(state.dimension, osqBitsOf(state.quantizationMode));
7654
+ }
8282
7655
  function calibrationOf(state) {
8283
7656
  if (codedCentroid(state) === null) return null;
8284
7657
  return Atomics.load(state.store.handles.header, STORE_CALIBRATION_GENERATION);
@@ -8318,10 +7691,10 @@ function filesWorthKeeping(state, listed, calibration, liveCounts) {
8318
7691
  }
8319
7692
  return kept;
8320
7693
  }
8321
- function absorbSmallerPartialFiles(kept, liveCounts, vectorsToWrite) {
7694
+ function absorbSmallerPartialFiles(kept, liveCounts, vectorsToWrite, capacity) {
8322
7695
  let pending = vectorsToWrite;
8323
7696
  for (let index = kept.length - 1; index >= 0 && pending > 0; index--) {
8324
- if (kept[index].ordinals.length >= VECTOR_FILE_MAX_VECTORS) continue;
7697
+ if (kept[index].ordinals.length >= capacity) continue;
8325
7698
  if (liveCounts[index] > pending) return;
8326
7699
  pending += liveCounts[index];
8327
7700
  kept.splice(index, 1);
@@ -8369,13 +7742,14 @@ function numberEveryVector(state, kept, written) {
8369
7742
  }
8370
7743
  return { numberOfOrdinal, ordinalOfNumber };
8371
7744
  }
8372
- function graphOf(state, numbers) {
8373
- if (state.hnsw === null) return null;
8374
- return {
8375
- v: VECTOR_GRAPH_PAYLOAD_VERSION,
8376
- fieldName: state.fieldName,
8377
- graphs: [state.hnsw.serializeNumbered(numbers.numberOfOrdinal, numbers.ordinalOfNumber)]
8378
- };
7745
+ function graphPartsOf(state, numbers) {
7746
+ if (state.hnsw === null || numbers.ordinalOfNumber.length === 0) return null;
7747
+ const parts = state.hnsw.serializeNumbered(
7748
+ numbers.numberOfOrdinal,
7749
+ numbers.ordinalOfNumber,
7750
+ VECTOR_GRAPH_PART_VECTORS
7751
+ );
7752
+ return parts.map((graph) => ({ v: VECTOR_GRAPH_PART_PAYLOAD_VERSION, fieldName: state.fieldName, graphs: [graph] }));
8379
7753
  }
8380
7754
  function readFile(state, planned, docIds, centroid) {
8381
7755
  const dimension = state.dimension;
@@ -8400,18 +7774,19 @@ function readFile(state, planned, docIds, centroid) {
8400
7774
  ordinals
8401
7775
  };
8402
7776
  }
8403
- function planCheckpoint(state, listedKeys) {
7777
+ function planCheckpoint(state, listedKeys, rewritesGraph = false) {
8404
7778
  const signature = signatureOf(state);
8405
7779
  const calibration = signature.calibration;
8406
7780
  const trusted = registryMatches(state, listedKeys);
7781
+ const capacity = fileCapacityOf(state);
8407
7782
  const liveCounts = [];
8408
7783
  const keptFiles = filesWorthKeeping(state, trusted ? state.savedFiles : [], calibration, liveCounts);
8409
- absorbSmallerPartialFiles(keptFiles, liveCounts, countOutside(state, liveCounts));
7784
+ absorbSmallerPartialFiles(keptFiles, liveCounts, countOutside(state, liveCounts), capacity);
8410
7785
  const written = ordinalsOutsideOf(state, keptFiles);
8411
7786
  const writtenDocIds = written.map((ordinal) => state.store.docIdForOrdinal(ordinal) ?? "");
8412
7787
  const centroid = codedCentroid(state);
8413
7788
  const listedBefore = trusted && listedKeys !== null;
8414
- const unchanged = listedBefore && sameSignature(state.savedSignature, signature) && written.length === 0;
7789
+ const unchanged = !rewritesGraph && listedBefore && sameSignature(state.savedSignature, signature) && written.length === 0;
8415
7790
  return {
8416
7791
  unchanged,
8417
7792
  keptFiles,
@@ -8421,12 +7796,12 @@ function planCheckpoint(state, listedKeys) {
8421
7796
  count: file.ordinals.length,
8422
7797
  dead: deadBitsOf(state, file)
8423
7798
  })),
8424
- newFiles: Math.ceil(written.length / VECTOR_FILE_MAX_VECTORS),
8425
- graph: unchanged ? null : graphOf(state, numberEveryVector(state, keptFiles, written)),
7799
+ newFiles: Math.ceil(written.length / capacity),
7800
+ graphParts: unchanged ? null : graphPartsOf(state, numberEveryVector(state, keptFiles, written)),
8426
7801
  signature,
8427
7802
  readNewFile(index) {
8428
- const start = index * VECTOR_FILE_MAX_VECTORS;
8429
- const end = start + VECTOR_FILE_MAX_VECTORS;
7803
+ const start = index * capacity;
7804
+ const end = start + capacity;
8430
7805
  return readFile(state, written.slice(start, end), writtenDocIds.slice(start, end), centroid);
8431
7806
  }
8432
7807
  };
@@ -8446,13 +7821,22 @@ function sameCentroid2(a, b) {
8446
7821
  return true;
8447
7822
  }
8448
7823
  function bufferEveryVectorOutsideTheGraph(state) {
8449
- for (const [docId] of state.store.entries()) {
7824
+ for (const docId of state.store.docIds()) {
8450
7825
  if (state.tombstones.has(docId)) continue;
8451
7826
  if (state.hnsw === null || !state.hnsw.has(docId)) state.buffer.add(docId);
8452
7827
  }
8453
7828
  }
7829
+ function insertNodesOfLaterGraph(state, graph, later, ordinals) {
7830
+ for (const part of later.parts) requireWholeNeighbourLists(part);
7831
+ for (let number = 0; number < ordinals.length; number++) {
7832
+ const ordinal = ordinals[number];
7833
+ if (ordinal === NO_LIVE_VECTOR_AT_POSITION || topLayerInParts(later, number) < 0) continue;
7834
+ const docId = state.store.docIdForOrdinal(ordinal);
7835
+ if (docId !== void 0 && !graph.has(docId)) graph.insertOrdinal(ordinal);
7836
+ }
7837
+ }
8454
7838
  function restoreGraph(state, payload, ordinalOfNumber) {
8455
- const first = payload?.graphs[0];
7839
+ const first = payload?.graphs[0]?.parts[0];
8456
7840
  if (payload === null || first === void 0) {
8457
7841
  bufferEveryVectorOutsideTheGraph(state);
8458
7842
  return;
@@ -8463,17 +7847,9 @@ function restoreGraph(state, payload, ordinalOfNumber) {
8463
7847
  { m: first.m, efConstruction: first.efConstruction, metric: first.metric },
8464
7848
  state.osq ?? void 0
8465
7849
  );
8466
- graph.deserializeNumbered(first, ordinalOfNumber);
7850
+ graph.deserializeNumbered(payload.graphs[0], ordinalOfNumber);
8467
7851
  adoptGraph(state, graph);
8468
- for (const later of payload.graphs.slice(1)) {
8469
- requireWholeNeighbourLists(later);
8470
- for (let number = 0; number < later.levels.length && number < ordinalOfNumber.length; number++) {
8471
- const ordinal = ordinalOfNumber[number];
8472
- if (later.levels[number] === 0 || ordinal === NO_LIVE_VECTOR_AT_POSITION) continue;
8473
- const docId = state.store.docIdForOrdinal(ordinal);
8474
- if (docId !== void 0 && !graph.has(docId)) graph.insertOrdinal(ordinal);
8475
- }
8476
- }
7852
+ for (const later of payload.graphs.slice(1)) insertNodesOfLaterGraph(state, graph, later, ordinalOfNumber);
8477
7853
  bufferEveryVectorOutsideTheGraph(state);
8478
7854
  if (state.buffer.size <= graph.size) return;
8479
7855
  adoptGraph(state, null);
@@ -9154,12 +8530,11 @@ function createVectorIndex(fieldName, dimension, config, workerCopies = VECTOR_W
9154
8530
  },
9155
8531
  maintenanceStatus: () => maintenanceStatus(state),
9156
8532
  estimateMemoryBytes: () => estimateMemoryBytes(state),
9157
- serialize: () => serialize(state),
9158
8533
  deserialize: (parts) => {
9159
8534
  invalidateWorkerCopies(state);
9160
8535
  deserialize(state, parts);
9161
8536
  },
9162
- planCheckpoint: (listedKeys) => planCheckpoint(state, listedKeys),
8537
+ planCheckpoint: (listedKeys, rewritesGraph) => planCheckpoint(state, listedKeys, rewritesGraph),
9163
8538
  recordCheckpoint: (plan, written) => recordCheckpoint(state, plan, written),
9164
8539
  restoreCheckpoint: (shape) => {
9165
8540
  invalidateWorkerCopies(state);
@@ -9277,11 +8652,46 @@ function createFrozenDocTable(idTable, lengthColumns, documents, tombstones) {
9277
8652
  }
9278
8653
  };
9279
8654
  }
8655
+ function removeFieldAtPath(document, fieldPath) {
8656
+ const segments = fieldPath.split(".");
8657
+ let current = document;
8658
+ for (let i = 0; i < segments.length - 1; i += 1) {
8659
+ const next = current[segments[i]];
8660
+ if (next === null || typeof next !== "object" || Array.isArray(next)) return;
8661
+ current = next;
8662
+ }
8663
+ delete current[segments[segments.length - 1]];
8664
+ }
8665
+ function decodeStoredDocument(bytes, discardedFields) {
8666
+ let decoded;
8667
+ try {
8668
+ decoded = decode(bytes);
8669
+ } catch (error) {
8670
+ throw new NarsilError(
8671
+ ErrorCodes.PERSISTENCE_LOAD_FAILED,
8672
+ `A stored document is not MessagePack: ${error instanceof Error ? error.message : String(error)}`
8673
+ );
8674
+ }
8675
+ if (decoded === null || typeof decoded !== "object" || Array.isArray(decoded) || decoded instanceof Uint8Array) {
8676
+ throw new NarsilError(ErrorCodes.PERSISTENCE_LOAD_FAILED, "A stored document decodes to something other than a map");
8677
+ }
8678
+ const document = decoded;
8679
+ if (discardedFields !== void 0) {
8680
+ for (const fieldPath of discardedFields) removeFieldAtPath(document, fieldPath);
8681
+ }
8682
+ return document;
8683
+ }
8684
+ function decodeEveryStoredDocument(data) {
8685
+ const count = data.offsets.length - 1;
8686
+ for (let ordinal = 0; ordinal < count; ordinal++) {
8687
+ decodeStoredDocument(data.blob.subarray(data.offsets[ordinal], data.offsets[ordinal + 1]), data.discardedFields);
8688
+ }
8689
+ }
9280
8690
  function encodeDocumentTableData(documents) {
9281
8691
  const encoded = new Array(documents.length);
9282
8692
  let blobLength = 0;
9283
8693
  for (let ordinal = 0; ordinal < documents.length; ordinal++) {
9284
- const bytes = encode(documents[ordinal]);
8694
+ const bytes = encodeDocument(documents[ordinal]);
9285
8695
  encoded[ordinal] = bytes;
9286
8696
  blobLength += bytes.length;
9287
8697
  }
@@ -9309,7 +8719,7 @@ function wrapEncodedDocumentTable(data) {
9309
8719
  docAt(ordinal) {
9310
8720
  let document = decoded[ordinal];
9311
8721
  if (document === void 0) {
9312
- document = decode(blob.slice(offsets[ordinal], offsets[ordinal + 1]));
8722
+ document = decodeStoredDocument(blob.slice(offsets[ordinal], offsets[ordinal + 1]), data.discardedFields);
9313
8723
  decoded[ordinal] = document;
9314
8724
  decodedBytes += documentValueBytes(document);
9315
8725
  }
@@ -9944,6 +9354,9 @@ function wrapFrozenTokenTable(data) {
9944
9354
  }
9945
9355
  return token;
9946
9356
  },
9357
+ byteLengthAt(sortedIndex) {
9358
+ return offsets[sortedIndex + 1] - offsets[sortedIndex];
9359
+ },
9947
9360
  payloadSlot(sortedIndex) {
9948
9361
  return payloadSlots[sortedIndex];
9949
9362
  },
@@ -10032,6 +9445,34 @@ function sharedSurfaceTable(payload) {
10032
9445
  if (table.counts.length === 0) return null;
10033
9446
  return { blob: sharedUint8(table.blob), offsets: sharedUint32(table.offsets), counts: sharedUint32(table.counts) };
10034
9447
  }
9448
+ function segmentArraysOf(payload, documentData) {
9449
+ const tokenTable = encodeFrozenTokenTableData(payload.tokens, payload.docFrequencies);
9450
+ const idTable = encodeExternalIdTableData(payload.docIds);
9451
+ const surfaceTable = payload.surfaceForms === null ? null : encodeSurfaceTable(payload.surfaceForms);
9452
+ return {
9453
+ documentCount: payload.documentCount,
9454
+ fieldNames: payload.fieldNames,
9455
+ fieldLengthNames: payload.fieldLengthNames,
9456
+ fieldLengthColumns: payload.fieldLengthColumns,
9457
+ totalFieldLengths: payload.totalFieldLengths,
9458
+ tokenTable,
9459
+ idTable,
9460
+ documentTable: documentData,
9461
+ postingOffsets: payload.postingOffsets,
9462
+ postingDocIds: payload.postingDocIds,
9463
+ postingFrequencies: payload.postingFrequencies,
9464
+ postingFieldIndices: payload.postingFieldIndices,
9465
+ positionOffsets: payload.positionOffsets,
9466
+ positionValues: payload.positionValues,
9467
+ numeric: payload.numeric,
9468
+ sizes: payload.sizes,
9469
+ boolean: payload.boolean,
9470
+ enums: payload.enums,
9471
+ geo: payload.geo,
9472
+ pattern: payload.pattern,
9473
+ surfaceTable: surfaceTable === null || surfaceTable.counts.length === 0 ? null : surfaceTable
9474
+ };
9475
+ }
10035
9476
  function freezeSegmentShared(payload, documents, segmentId) {
10036
9477
  if (typeof SharedArrayBuffer !== "function") return null;
10037
9478
  return freezeEncodedSegmentShared(payload, encodeDocumentTableData(documents), segmentId);
@@ -10060,12 +9501,13 @@ function freezeEncodedSegmentShared(payload, documentData, segmentId) {
10060
9501
  },
10061
9502
  documentTable: {
10062
9503
  blob: sharedUint8(documentData.blob),
10063
- offsets: sharedUint32(documentData.offsets)
9504
+ offsets: sharedUint32(documentData.offsets),
9505
+ ...documentData.discardedFields === void 0 ? {} : { discardedFields: documentData.discardedFields }
10064
9506
  },
10065
9507
  postingOffsets: sharedUint32(payload.postingOffsets),
10066
9508
  postingDocIds: sharedUint32(payload.postingDocIds),
10067
9509
  postingFrequencies: sharedUint16(payload.postingFrequencies),
10068
- postingFieldIndices: sharedUint8(payload.postingFieldIndices),
9510
+ postingFieldIndices: sharedUint16(payload.postingFieldIndices),
10069
9511
  positionOffsets: payload.positionOffsets === null ? null : sharedUint32(payload.positionOffsets),
10070
9512
  positionValues: payload.positionValues === null ? null : sharedUint32(payload.positionValues),
10071
9513
  numeric: payload.numeric.map((entry) => ({
@@ -10248,6 +9690,133 @@ function createSharedFrozenSegment(snapshot) {
10248
9690
  snapshot
10249
9691
  );
10250
9692
  }
9693
+ var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
9694
+ var keyDecoder = new TextDecoder("utf-8", { fatal: true });
9695
+ function headerAt(view, offset) {
9696
+ if (offset >= view.byteLength) return null;
9697
+ const tag = view.getUint8(offset);
9698
+ if (tag <= 127 || tag >= 224) return { headerBytes: 1, bodyBytes: 0, children: 0 };
9699
+ if (tag <= 143) return { headerBytes: 1, bodyBytes: 0, children: (tag & 15) * 2 };
9700
+ if (tag <= 159) return { headerBytes: 1, bodyBytes: 0, children: tag & 15 };
9701
+ if (tag <= 191) return { headerBytes: 1, bodyBytes: tag & 31, children: 0 };
9702
+ const lengthBytes = LENGTH_BYTES_BY_TAG.get(tag);
9703
+ if (lengthBytes !== void 0) {
9704
+ if (offset + 1 + lengthBytes > view.byteLength) return null;
9705
+ const length = lengthBytes === 1 ? view.getUint8(offset + 1) : lengthBytes === 2 ? view.getUint16(offset + 1, false) : view.getUint32(offset + 1, false);
9706
+ const headerBytes = 1 + lengthBytes;
9707
+ if (ARRAY_TAGS.has(tag)) return { headerBytes, bodyBytes: 0, children: length };
9708
+ if (MAP_TAGS.has(tag)) return { headerBytes, bodyBytes: 0, children: length * 2 };
9709
+ return { headerBytes, bodyBytes: length + (EXT_TAGS.has(tag) ? 1 : 0), children: 0 };
9710
+ }
9711
+ const fixedBytes = FIXED_BODY_BYTES_BY_TAG.get(tag);
9712
+ return fixedBytes === void 0 ? null : { headerBytes: 1, bodyBytes: fixedBytes, children: 0 };
9713
+ }
9714
+ var LENGTH_BYTES_BY_TAG = /* @__PURE__ */ new Map([
9715
+ [196, 1],
9716
+ [197, 2],
9717
+ [198, 4],
9718
+ [199, 1],
9719
+ [200, 2],
9720
+ [201, 4],
9721
+ [217, 1],
9722
+ [218, 2],
9723
+ [219, 4],
9724
+ [220, 2],
9725
+ [221, 4],
9726
+ [222, 2],
9727
+ [223, 4]
9728
+ ]);
9729
+ var ARRAY_TAGS = /* @__PURE__ */ new Set([220, 221]);
9730
+ var MAP_TAGS = /* @__PURE__ */ new Set([222, 223]);
9731
+ var EXT_TAGS = /* @__PURE__ */ new Set([199, 200, 201]);
9732
+ var FIXED_BODY_BYTES_BY_TAG = /* @__PURE__ */ new Map([
9733
+ [192, 0],
9734
+ [194, 0],
9735
+ [195, 0],
9736
+ [202, 4],
9737
+ [203, 8],
9738
+ [204, 1],
9739
+ [205, 2],
9740
+ [206, 4],
9741
+ [207, 8],
9742
+ [208, 1],
9743
+ [209, 2],
9744
+ [210, 4],
9745
+ [211, 8],
9746
+ [212, 2],
9747
+ [213, 3],
9748
+ [214, 5],
9749
+ [215, 9],
9750
+ [216, 17]
9751
+ ]);
9752
+ function endOfValue(view, start) {
9753
+ let offset = start;
9754
+ let pending = 1;
9755
+ while (pending > 0) {
9756
+ const header = headerAt(view, offset);
9757
+ if (header === null) return null;
9758
+ offset += header.headerBytes + header.bodyBytes;
9759
+ if (offset > view.byteLength) return null;
9760
+ pending += header.children - 1;
9761
+ }
9762
+ return offset;
9763
+ }
9764
+ function stringKeyAt(bytes, view, offset) {
9765
+ const header = headerAt(view, offset);
9766
+ if (header === null || header.children !== 0) return null;
9767
+ const tag = view.getUint8(offset);
9768
+ const isString = tag >= 160 && tag <= 191 || tag === 217 || tag === 218 || tag === 219;
9769
+ const end = offset + header.headerBytes + header.bodyBytes;
9770
+ if (!isString || end > bytes.length) return null;
9771
+ try {
9772
+ return { key: keyDecoder.decode(bytes.subarray(offset + header.headerBytes, end)), end };
9773
+ } catch {
9774
+ return null;
9775
+ }
9776
+ }
9777
+ function topLevelMapKeys(bytes) {
9778
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
9779
+ const top = headerAt(view, 0);
9780
+ if (top === null || top.bodyBytes !== 0) return null;
9781
+ const tag = view.getUint8(0);
9782
+ if (!(tag >= 128 && tag <= 143 || MAP_TAGS.has(tag))) return null;
9783
+ const keys = /* @__PURE__ */ new Set();
9784
+ let offset = top.headerBytes;
9785
+ for (let pair = 0; pair < top.children / 2; pair += 1) {
9786
+ const key = stringKeyAt(bytes, view, offset);
9787
+ if (key === null) return null;
9788
+ const valueEnd = endOfValue(view, key.end);
9789
+ if (valueEnd === null) return null;
9790
+ keys.add(key.key);
9791
+ offset = valueEnd;
9792
+ }
9793
+ return keys;
9794
+ }
9795
+ function decodeMapWithoutFields(bytes, skippedFields) {
9796
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
9797
+ const top = headerAt(view, 0);
9798
+ if (top === null || top.children === 0 || top.bodyBytes !== 0) return null;
9799
+ const tag = view.getUint8(0);
9800
+ const isMap = tag >= 128 && tag <= 143 || MAP_TAGS.has(tag);
9801
+ if (!isMap) return null;
9802
+ const document = {};
9803
+ let offset = top.headerBytes;
9804
+ for (let pair = 0; pair < top.children / 2; pair += 1) {
9805
+ const key = stringKeyAt(bytes, view, offset);
9806
+ if (key === null || FORBIDDEN_KEYS.has(key.key)) return null;
9807
+ const valueEnd = endOfValue(view, key.end);
9808
+ if (valueEnd === null) return null;
9809
+ if (!skippedFields.has(key.key)) {
9810
+ try {
9811
+ document[key.key] = decode(bytes.subarray(key.end, valueEnd));
9812
+ } catch {
9813
+ return null;
9814
+ }
9815
+ }
9816
+ offset = valueEnd;
9817
+ }
9818
+ return offset === bytes.length ? document : null;
9819
+ }
10251
9820
 
10252
9821
  // src/core/partition/frozen/merge-fields.ts
10253
9822
  function indexByFieldPath(entries) {
@@ -10510,7 +10079,7 @@ function mergePostings2(inputs) {
10510
10079
  const postingOffsets = new Uint32Array(tokenCount + 1);
10511
10080
  const postingDocIds = new Uint32Array(totalPostings);
10512
10081
  const postingFrequencies = new Uint16Array(totalPostings);
10513
- const postingFieldIndices = new Uint8Array(totalPostings);
10082
+ const postingFieldIndices = new Uint16Array(totalPostings);
10514
10083
  const positionOffsets = hasPositions ? new Uint32Array(totalPostings + 1) : null;
10515
10084
  const positionValues = hasPositions ? new Uint32Array(totalPositions) : null;
10516
10085
  let postingCursor = 0;
@@ -10584,11 +10153,15 @@ function mergePostings2(inputs) {
10584
10153
  }
10585
10154
 
10586
10155
  // src/core/partition/frozen/merge.ts
10587
- function remapOf(segment, docIds) {
10156
+ function selectionKeeps(selection, ordinal) {
10157
+ return selection.keep === void 0 ? !selection.segment.isTombstoned(ordinal) : selection.keep(ordinal);
10158
+ }
10159
+ function remapOf(selection, docIds) {
10160
+ const { segment } = selection;
10588
10161
  const count = segment.arrays.documentCount;
10589
10162
  const remap = new Int32Array(count).fill(-1);
10590
10163
  for (let ordinal = 0; ordinal < count; ordinal++) {
10591
- if (segment.isTombstoned(ordinal)) continue;
10164
+ if (!selectionKeeps(selection, ordinal)) continue;
10592
10165
  remap[ordinal] = docIds.length;
10593
10166
  docIds.push(segment.arrays.idTable.idAt(ordinal));
10594
10167
  }
@@ -10601,7 +10174,7 @@ function fieldNameIndex(fieldNames, name) {
10601
10174
  return fieldNames.length - 1;
10602
10175
  }
10603
10176
  function fieldIndexRemapOf(segment, fieldNames) {
10604
- const remap = new Uint8Array(segment.arrays.fieldNames.length);
10177
+ const remap = new Uint16Array(segment.arrays.fieldNames.length);
10605
10178
  for (let i = 0; i < segment.arrays.fieldNames.length; i++) {
10606
10179
  remap[i] = fieldNameIndex(fieldNames, segment.arrays.fieldNames[i]);
10607
10180
  }
@@ -10647,20 +10220,34 @@ function mergeSurfaceForms2(inputs) {
10647
10220
  }
10648
10221
  return registry.size() === 0 ? null : registry.serialize();
10649
10222
  }
10223
+ function holdsADiscardedField(bytes, discardedFields) {
10224
+ const keys = topLevelMapKeys(bytes);
10225
+ if (keys === null) return true;
10226
+ for (const fieldPath of discardedFields) {
10227
+ const dot = fieldPath.indexOf(".");
10228
+ if (keys.has(dot < 0 ? fieldPath : fieldPath.slice(0, dot))) return true;
10229
+ }
10230
+ return false;
10231
+ }
10650
10232
  function encodedDocumentsOf(input) {
10651
10233
  const table = input.segment.arrays.documentTable;
10652
- if (table !== null) {
10653
- return (ordinal) => table.blob.subarray(table.offsets[ordinal], table.offsets[ordinal + 1]);
10654
- }
10655
10234
  const encoded = new Array(input.remap.length);
10656
- return (ordinal) => {
10235
+ const encodeOrdinal = (ordinal) => {
10657
10236
  let bytes = encoded[ordinal];
10658
10237
  if (bytes === void 0) {
10659
- bytes = encode(input.segment.documentSource.docAt(ordinal));
10238
+ bytes = encodeDocument(input.segment.documentSource.docAt(ordinal));
10660
10239
  encoded[ordinal] = bytes;
10661
10240
  }
10662
10241
  return bytes;
10663
10242
  };
10243
+ if (table === null) return encodeOrdinal;
10244
+ const discardedFields = table.discardedFields;
10245
+ return (ordinal) => {
10246
+ if (encoded[ordinal] !== void 0) return encodeOrdinal(ordinal);
10247
+ const stored = table.blob.subarray(table.offsets[ordinal], table.offsets[ordinal + 1]);
10248
+ if (discardedFields === void 0 || !holdsADiscardedField(stored, discardedFields)) return stored;
10249
+ return encodeOrdinal(ordinal);
10250
+ };
10664
10251
  }
10665
10252
  function mergeDocuments2(inputs, documentCount) {
10666
10253
  const readers = inputs.map(encodedDocumentsOf);
@@ -10684,12 +10271,16 @@ function mergeDocuments2(inputs, documentCount) {
10684
10271
  }
10685
10272
  function mergeFrozenSegments(segments) {
10686
10273
  if (typeof SharedArrayBuffer !== "function") return null;
10274
+ const merged = mergeSegmentContents(segments.map((segment) => ({ segment })));
10275
+ return freezeEncodedSegmentShared(merged.payload, merged.documents);
10276
+ }
10277
+ function mergeSegmentContents(selections) {
10687
10278
  const docIds = [];
10688
10279
  const fieldNames = [];
10689
- const inputs = segments.map((segment) => ({
10690
- segment,
10691
- remap: remapOf(segment, docIds),
10692
- fieldIndexRemap: fieldIndexRemapOf(segment, fieldNames)
10280
+ const inputs = selections.map((selection) => ({
10281
+ segment: selection.segment,
10282
+ remap: remapOf(selection, docIds),
10283
+ fieldIndexRemap: fieldIndexRemapOf(selection.segment, fieldNames)
10693
10284
  }));
10694
10285
  const documentCount = docIds.length;
10695
10286
  const postings = mergePostings2(inputs);
@@ -10712,7 +10303,7 @@ function mergeFrozenSegments(segments) {
10712
10303
  surfaceForms: mergeSurfaceForms2(inputs),
10713
10304
  ...mergeFieldIndexes2(inputs)
10714
10305
  };
10715
- return freezeEncodedSegmentShared(payload, mergeDocuments2(inputs, documentCount));
10306
+ return { payload, documents: mergeDocuments2(inputs, documentCount) };
10716
10307
  }
10717
10308
 
10718
10309
  // src/core/partition/segment-postings.ts
@@ -10826,7 +10417,7 @@ var TextPostings = class {
10826
10417
  const writeCursor = postingOffsets.slice(0, tokenCount);
10827
10418
  const postingDocIds = new Uint32Array(postings);
10828
10419
  const postingFrequencies = new Uint16Array(postings);
10829
- const postingFieldIndices = new Uint8Array(postings);
10420
+ const postingFieldIndices = new Uint16Array(postings);
10830
10421
  const logRowOfPosting = new Uint32Array(postings);
10831
10422
  for (let row = 0; row < postings; row++) {
10832
10423
  const target = writeCursor[this.logToken.values[row]]++;
@@ -11559,4 +11150,4 @@ function createDirectExecutor(options) {
11559
11150
  };
11560
11151
  }
11561
11152
 
11562
- export { CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, FIELD_FILTER_OPERATORS, FILTER_EXPRESSION_KEYS, NO_LIVE_VECTOR_AT_POSITION, SHUTDOWN_TIMEOUT_MS, VECTOR_FILE_MAX_VECTORS, buildSegmentPayload, countDead, createCompositePartition, createDirectExecutor, createFrozenSegment, createPartitionIndex, createPartitionManager, createPartitionRouter, createSharedFrozenSegment, deadBitsWhere, deadBytesFor, decodeVectorFilePayload, decodeVectorGraphPayload, decodeVectorIndexParts, deserializeMetadata, deserializePayloadV1, deserializePayloadV2, documentsOfPayloadV2, encodeSegmentState, freezeSegmentShared, generateId, getStopWords, getTokenizer, hasStopWords, hasTokenizer, isCompositePartition, isNodeMainThread, mergeFrozenSegments, missingWorkerEntry, nodeThreadId, readHeapStatistics, registerPatternSearch, registerStopWords, registerTokenizer, requirePatternSearchFor, resolveIndexAnalysis, resolvePartitionInsertOptions, resolveRequestThreadCount, resolveWorkerCount, resolveWorkerEntry, serializeMetadata, spawnNodeWorker, splitWorkerBudget, workerResourceLimits };
11153
+ export { CHECKSUM_YIELD_CHUNK_BYTES, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, FIELD_FILTER_OPERATORS, FILTER_EXPRESSION_KEYS, MAX_FILE_BYTES, NATIVE_CRC32_MIN_BYTES, NO_LIVE_VECTOR_AT_POSITION, SHUTDOWN_TIMEOUT_MS, VALID_HNSW_METRICS, VECTOR_FILE_MAX_VECTORS, VECTOR_FILE_PAYLOAD_VERSION, assembleGraphParts, buildSegmentPayload, bytesToVectors, countDead, createDirectExecutor, createFrozenSegment, createPartitionIndex, createPartitionManager, createPartitionRouter, createSharedFrozenSegment, deadBitsWhere, deadBytesFor, decodeEveryStoredDocument, decodeMapWithoutFields, decodeStoredDocument, decodeVectorFilePayload, decodeVectorGraphPartPayload, decodeVectorGraphPayload, decodeVectorIndexParts, encodeSegmentState, freezeSegmentShared, generateId, getStopWords, getTokenizer, graphPartsOfEarlierPayload, hasStopWords, hasTokenizer, isCompositePartition, isDead, mergeFrozenSegments, mergeSegmentContents, missingWorkerEntry, nodeThreadId, partitionStateOf, readHeapStatistics, registerPatternSearch, registerStopWords, registerTokenizer, requirePatternSearchFor, resolveIndexAnalysis, resolvePartitionInsertOptions, resolveRequestThreadCount, resolveWorkerCount, resolveWorkerEntry, segmentArraysOf, selectionKeeps, spawnNodeWorker, splitWorkerBudget, survivorDocumentsOf, vectorsPerFile, vectorsToBytes, workerResourceLimits };