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

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 (50) hide show
  1. package/README.md +8 -4
  2. package/dist/adapters/filesystem.mjs +1 -1
  3. package/dist/adapters/indexeddb.mjs +1 -1
  4. package/dist/{capabilities-CuTSXvbN.d.ts → capabilities-DlYw0Ov0.d.ts} +13 -2
  5. package/dist/{chunk-U36IDJN7.mjs → chunk-4NVPQ6S5.mjs} +2 -2
  6. package/dist/{chunk-WM7IS45M.mjs → chunk-5T6AOR37.mjs} +2 -2
  7. package/dist/{chunk-ULJ36FK4.mjs → chunk-BH5SYB5W.mjs} +73 -46
  8. package/dist/{chunk-3GWP2TO6.mjs → chunk-D2S642IV.mjs} +4 -2
  9. package/dist/{chunk-P4ELXVJQ.mjs → chunk-FRQVMFY7.mjs} +7 -1
  10. package/dist/{chunk-ZT5BRDFW.mjs → chunk-L225SHNB.mjs} +2 -2
  11. package/dist/{chunk-72AXTIBW.mjs → chunk-NTZYA3SJ.mjs} +3 -3
  12. package/dist/{chunk-EY2ULUMT.mjs → chunk-RGS7FMCB.mjs} +25 -5
  13. package/dist/{chunk-YPYULM5E.mjs → chunk-TVT5V4E7.mjs} +84 -33
  14. package/dist/{chunk-T62YOSGS.mjs → chunk-U2AL3SON.mjs} +16 -98
  15. package/dist/chunk-UTOFOJOR.mjs +135 -0
  16. package/dist/{chunk-2FO7KZ6K.mjs → chunk-XNQAIO74.mjs} +53 -8
  17. package/dist/{client-BMJWVxOP.d.ts → client-CQUqt9Ir.d.ts} +13 -4
  18. package/dist/client.d.ts +8 -8
  19. package/dist/client.mjs +20 -14
  20. package/dist/{config-qMLpi5T4.d.ts → config-CNas6wJH.d.ts} +2 -2
  21. package/dist/{config-BcYZkdMw.d.ts → config-bXxnJrQc.d.ts} +80 -35
  22. package/dist/direct-executor-RBA5O7EN.mjs +12 -0
  23. package/dist/distribution/coordinator/etcd.d.ts +2 -2
  24. package/dist/distribution/coordinator/etcd.mjs +1 -1
  25. package/dist/distribution/coordinator/in-memory.d.ts +2 -2
  26. package/dist/distribution/transport/grpc.mjs +1 -1
  27. package/dist/distribution.d.ts +8 -8
  28. package/dist/distribution.mjs +12 -12
  29. package/dist/embeddings/openai.mjs +1 -1
  30. package/dist/{engine-zhms1qId.d.ts → engine-Dj4I91Jv.d.ts} +21 -8
  31. package/dist/index.browser.mjs +169 -72
  32. package/dist/index.d.ts +7 -7
  33. package/dist/index.mjs +10 -10
  34. package/dist/{memory-OmgkX_Z2.d.ts → memory-xrXOZMbw.d.ts} +58 -13
  35. package/dist/persistence/durability/checkpoint-worker.d.ts +1 -1
  36. package/dist/persistence/durability/checkpoint-worker.mjs +10 -10
  37. package/dist/react.d.ts +11 -11
  38. package/dist/react.mjs +16 -4
  39. package/dist/{schema-OSWaaZzx.d.ts → schema-mLpXZBEh.d.ts} +13 -6
  40. package/dist/server.d.ts +13 -10
  41. package/dist/server.mjs +68 -20
  42. package/dist/{tasks-DiF1c9v2.d.ts → tasks-Df73Tjgq.d.ts} +9 -5
  43. package/dist/{thread-TLCX43WV.mjs → thread-5UP6MGED.mjs} +8 -8
  44. package/dist/{types-LEzMyjVX.d.ts → types-BTIVO8DI.d.ts} +1 -1
  45. package/dist/vector/search-worker.d.ts +1 -1
  46. package/dist/vector/search-worker.mjs +3 -3
  47. package/dist/workers/entry.mjs +23 -10
  48. package/package.json +7 -7
  49. package/dist/chunk-WFKIGEBY.mjs +0 -11
  50. package/dist/direct-executor-UJC36S2D.mjs +0 -12
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ![Narsil, a distributed search engine](https://raw.githubusercontent.com/assetcorp/narsil/main/assets/banner.png)
1
+ ![Narsil, an open source search engine](https://raw.githubusercontent.com/assetcorp/narsil/main/assets/banner.png)
2
2
 
3
3
  # Narsil
4
4
 
@@ -8,11 +8,15 @@
8
8
  [![types](https://img.shields.io/badge/types-TypeScript-blue)](https://www.npmjs.com/package/@delali/narsil)
9
9
  [![license](https://img.shields.io/npm/l/@delali/narsil)](https://github.com/assetcorp/narsil/blob/main/LICENSE)
10
10
 
11
- Distributed search, reforged.
11
+ The search engine that scales with your data.
12
12
 
13
- Narsil is a distributed search engine with full-text, vector, hybrid, and geosearch. You can embed Narsil in your application process, where the engine searches without a network hop, or deploy it as a standalone search server with a REST API, a write-ahead log, and bulk NDJSON ingest. Both forms contain the same engine, which stores indexes in one cross-language binary format (`.nrsl`), so you can load an index from one form into the other.
13
+ Narsil is an open source search engine with full-text, vector, hybrid, and geosearch on one typed index. You can embed Narsil in your application process, where the engine searches without a network hop, or deploy it as a standalone search server with a REST API, a write-ahead log, and bulk NDJSON ingest. Both forms contain the same engine, which stores indexes in one cross-language binary format (`.nrsl`), so you can load an index from one form into the other.
14
14
 
15
- The engine partitions large indexes across workers and merges the results of the partitions into a single ranked list. Its BM25 nDCG@10 is within 0.006 of the Anserini reference on BEIR SciFact and NFCorpus. On SciFact, Narsil scores 0.681 nDCG@10, ahead of Elasticsearch and OpenSearch at 0.679. At its peak, it also serves 958 keyword queries per second on SciFact, while Elasticsearch serves 841 and OpenSearch serves 878 ([benchmarks](https://github.com/assetcorp/narsil/blob/main/BENCHMARKS.md)). This TypeScript package is the reference implementation of the `.nrsl` format, so a second implementation in Go or Rust is the headline item on the [roadmap](https://github.com/assetcorp/narsil/blob/main/ROADMAP.md).
15
+ The engine partitions large indexes across workers and merges the results of the partitions into a single ranked list. This TypeScript package is the reference implementation of the `.nrsl` format, so a second implementation in Go or Rust is the headline item on the [roadmap](https://github.com/assetcorp/narsil/blob/main/ROADMAP.md).
16
+
17
+ <!-- BENCH:headline START -->
18
+ On BEIR SciFact, Narsil's BM25 ranking scores 0.681 nDCG@10, which is within 0.002 of the Anserini reference of 0.679. Elasticsearch scores 0.679 and OpenSearch scores 0.679 on the same queries. On SciFact, Narsil answers 958 keyword queries a second at its peak, and OpenSearch follows with 878. On SciFact with every engine held at 0.99 recall, Narsil answers 259 vector queries a second at its peak, while OpenSearch leads with 730. Narsil has the highest peak throughput in 2 of the 6 keyword, vector, and hybrid comparisons in the newest recorded run, so read each figure beside its table. The harness recorded these figures in run `20260804T184221Z` on 2026-08-04, on GCP c3-standard-8, us-central1-a. You'll find every dataset, every engine's settings, and the full method in [`BENCHMARKS.md`](https://github.com/assetcorp/narsil/blob/main/BENCHMARKS.md).
19
+ <!-- BENCH:headline END -->
16
20
 
17
21
  Try it in your browser at [narsil.sondelali.com/demo](https://narsil.sondelali.com/demo). Read the full documentation at [narsil.sondelali.com/docs](https://narsil.sondelali.com/docs).
18
22
 
@@ -1,4 +1,4 @@
1
- import { NarsilError, ErrorCodes } from '../chunk-P4ELXVJQ.mjs';
1
+ import { NarsilError, ErrorCodes } from '../chunk-FRQVMFY7.mjs';
2
2
 
3
3
  // src/persistence/filesystem.ts
4
4
  var cachedFs = null;
@@ -1,4 +1,4 @@
1
- import { NarsilError, ErrorCodes } from '../chunk-P4ELXVJQ.mjs';
1
+ import { NarsilError, ErrorCodes } from '../chunk-FRQVMFY7.mjs';
2
2
 
3
3
  // src/persistence/constants.ts
4
4
  var DEFAULT_INDEXEDDB_NAME = "narsil";
@@ -1,6 +1,6 @@
1
1
  import { E as EmbeddingAdapter } from './adapters-79OIa4xm.js';
2
- import { C as ClusterNamespace } from './config-qMLpi5T4.js';
3
- import { h as TaskStore } from './tasks-DiF1c9v2.js';
2
+ import { C as ClusterNamespace } from './config-CNas6wJH.js';
3
+ import { h as TaskStore } from './tasks-Df73Tjgq.js';
4
4
 
5
5
  /**
6
6
  * Context handed to {@link OnRequestHook} for every inbound request, captured
@@ -181,6 +181,17 @@ interface NarsilServer {
181
181
  listen(): Promise<void>;
182
182
  /** Closes the socket and ends the server. The engine keeps running. */
183
183
  close(): Promise<void>;
184
+ /**
185
+ * Closes the server and then shuts the engine down, which is what a process
186
+ * whose work is this server calls on its way out.
187
+ *
188
+ * Shutting the engine down is what ends the request threads, so Node aborts
189
+ * a process that exits while one of those threads still holds a client
190
+ * connection. Call {@link NarsilServer.close} on its own where the engine
191
+ * keeps running after the server closes, as in a process that fronts one
192
+ * engine with two servers.
193
+ */
194
+ shutdown(): Promise<void>;
184
195
  /** The server bound to this port, which is what you read after binding to port 0. */
185
196
  readonly listeningPort: number;
186
197
  /**
@@ -1,5 +1,5 @@
1
- import { validateRequiredFields } from './chunk-ZT5BRDFW.mjs';
2
- import { ErrorCodes, NarsilError } from './chunk-P4ELXVJQ.mjs';
1
+ import { validateRequiredFields } from './chunk-L225SHNB.mjs';
2
+ import { ErrorCodes, NarsilError } from './chunk-FRQVMFY7.mjs';
3
3
 
4
4
  // src/narsil/internals.ts
5
5
  var engineCores = /* @__PURE__ */ new WeakMap();
@@ -1,6 +1,6 @@
1
- import { flattenSchema, SORTABLE_TEXT_FIELD_TYPE, MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, MAX_CURSOR_LENGTH, RESULT_WINDOW, DEFAULT_PAGE_SIZE, PROTOTYPE_POLLUTION_KEYS, isTextFieldType, PREFIX_MAX_EXPANSIONS, MAX_CURSOR_ANCHOR_CODE_POINTS } from './chunk-ZT5BRDFW.mjs';
1
+ import { flattenSchema, SORTABLE_TEXT_FIELD_TYPE, MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, MAX_CURSOR_LENGTH, RESULT_WINDOW, DEFAULT_PAGE_SIZE, PROTOTYPE_POLLUTION_KEYS, isTextFieldType, PREFIX_MAX_EXPANSIONS, MAX_CURSOR_ANCHOR_CODE_POINTS } from './chunk-L225SHNB.mjs';
2
2
  import { compareCodePoints, compareComparableKeys, toComparableSortValue, readSortField, SORT_VALUE_MAX_CODE_POINTS, compareSortValues } from './chunk-2GWVQWGA.mjs';
3
- import { createNarsilError, ErrorCodes, NarsilError } from './chunk-P4ELXVJQ.mjs';
3
+ import { createNarsilError, ErrorCodes, NarsilError } from './chunk-FRQVMFY7.mjs';
4
4
 
5
5
  // src/core/tokenizer/constants.ts
6
6
  var TOKEN_CACHE_SIZE_FLOOR = 5e4;
@@ -1,17 +1,17 @@
1
1
  import { ReplicationMessageTypes } from './chunk-GCM3JFVA.mjs';
2
- import { WIRE_BATCH_BUDGET, resolveVectorText, bindEngineCore, collectRequiredFieldFailures, embedChunkDocuments, providedDocId, admitInsert, asBatchInsertError, embedDocumentFields, assertDocumentCarriesMappedVectors } from './chunk-U36IDJN7.mjs';
3
- import { getNestedValue, generateId, getLanguage, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, createCompositePartition, deserializePayloadV2, createSharedFrozenSegment, createPartitionManager, buildSegmentPayload, resolvePartitionInsertOptions, readHeapStatistics, resolveIndexAnalysis, deserializePayloadV1, decodeVectorIndexParts, resolveRequestThreadCount, createPartitionIndex, VECTOR_FILE_MAX_VECTORS, deadBytesFor, mergeFrozenSegments, isCompositePartition, workerResourceLimits, deserializeMetadata, isNodeMainThread, spawnNodeWorker, freezeSegmentShared, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, serializeMetadata, SHUTDOWN_TIMEOUT_MS, encodeSegmentState, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, decodeVectorFilePayload, documentsOfPayloadV2, countDead, decodeVectorGraphPayload, deadBitsWhere, NO_LIVE_VECTOR_AT_POSITION, createFrozenSegment } from './chunk-2FO7KZ6K.mjs';
2
+ import { WIRE_BATCH_BUDGET, resolveVectorText, bindEngineCore, collectRequiredFieldFailures, embedChunkDocuments, providedDocId, admitInsert, asBatchInsertError, embedDocumentFields, assertDocumentCarriesMappedVectors } from './chunk-4NVPQ6S5.mjs';
3
+ import { getNestedValue, generateId, getLanguage, splitWorkerBudget, resolveWorkerCount, createDirectExecutor, createPartitionRouter, createCompositePartition, deserializePayloadV2, createSharedFrozenSegment, createPartitionManager, buildSegmentPayload, resolvePartitionInsertOptions, readHeapStatistics, resolveIndexAnalysis, deserializePayloadV1, decodeVectorIndexParts, resolveRequestThreadCount, createPartitionIndex, VECTOR_FILE_MAX_VECTORS, deadBytesFor, mergeFrozenSegments, isCompositePartition, workerResourceLimits, deserializeMetadata, isNodeMainThread, spawnNodeWorker, freezeSegmentShared, DEFAULT_BACKPRESSURE_LIMIT, DEFAULT_REQUEST_TIMEOUT_MS, serializeMetadata, SHUTDOWN_TIMEOUT_MS, encodeSegmentState, CONSECUTIVE_TIMEOUTS_BEFORE_DEATH, decodeVectorFilePayload, documentsOfPayloadV2, countDead, decodeVectorGraphPayload, deadBitsWhere, NO_LIVE_VECTOR_AT_POSITION, createFrozenSegment } from './chunk-XNQAIO74.mjs';
4
4
  import { detectRuntime } from './chunk-AV4IJKD2.mjs';
5
- import { validateWorkerConfig, validateIndexName, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-YPYULM5E.mjs';
6
- import { BATCH_CHUNK_SIZE, STATISTICS_BROADCAST_INTERVAL_MS, MAX_SWEEP_INTERVAL_MS, MIN_SWEEP_INTERVAL_MS, HEAP_PRESSURE_WARNING_FRACTION, FOREIGN_STATS_TTL_MS, MIN_DOCUMENTS_FOR_SEGMENTS, HEAP_PRESSURE_REARM_FRACTION } from './chunk-3GWP2TO6.mjs';
7
- import { collectQueryTermStats, mergePartitionStats, fnv1a, kWayMerge, mergeFacets } from './chunk-WM7IS45M.mjs';
8
- import { extractVectorFieldsFromSchema, validateSchema, validateVectorPromotion, validateVectorStorage, flattenSchema, isTextFieldType, validateRequiredFields, validateDocument, validateDocumentStrict } from './chunk-ZT5BRDFW.mjs';
9
- import { releaseLocksHeldBy } from './chunk-T62YOSGS.mjs';
5
+ import { validateWorkerConfig, validateIndexName, validateBM25Params, validatePartitionConfig, executeQuery, queryBindingOf, executePreflight, executeSuggest, executeListDocuments, validateDocId } from './chunk-TVT5V4E7.mjs';
6
+ import { BATCH_CHUNK_SIZE, STATISTICS_BROADCAST_INTERVAL_MS, MAX_SWEEP_INTERVAL_MS, MIN_SWEEP_INTERVAL_MS, HEAP_PRESSURE_WARNING_FRACTION, FOREIGN_STATS_TTL_MS, MIN_DOCUMENTS_FOR_SEGMENTS, HEAP_PRESSURE_REARM_FRACTION } from './chunk-D2S642IV.mjs';
7
+ import { collectQueryTermStats, mergePartitionStats, fnv1a, kWayMerge, mergeFacets } from './chunk-5T6AOR37.mjs';
8
+ import { extractVectorFieldsFromSchema, validateSchema, validateVectorPromotion, validateVectorStorage, flattenSchema, isTextFieldType, validateRequiredFields, validateDocument, validateDocumentStrict } from './chunk-L225SHNB.mjs';
9
+ import { releaseLocksHeldBy } from './chunk-U2AL3SON.mjs';
10
10
  import { crc32, nativeCrc32, crc32Final, crc32Init, crc32Update } from './chunk-3L4U6EJQ.mjs';
11
11
  import { CHECKSUM_TIMEOUT_MS, CHECKSUM_YIELD_CHUNK_BYTES } from './chunk-IFBKLBGB.mjs';
12
12
  import { compareCodePoints } from './chunk-2GWVQWGA.mjs';
13
13
  import { createRequestId, isValidWorkerResponse, threadSlotOfWorker } from './chunk-POWOTUKJ.mjs';
14
- import { NarsilError, ErrorCodes } from './chunk-P4ELXVJQ.mjs';
14
+ import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
15
15
  import { encode, decode } from '@msgpack/msgpack';
16
16
 
17
17
  // src/partitioning/constants.ts
@@ -1083,7 +1083,7 @@ async function unpackEnvelope(data, maxAcceptedVersion = CURRENT_ENVELOPE_VERSIO
1083
1083
  if (header.envelopeFormatVersion > maxAcceptedVersion) {
1084
1084
  throw new NarsilError(
1085
1085
  ErrorCodes.ENVELOPE_VERSION_MISMATCH,
1086
- `This data was written by Narsil envelope format v${header.envelopeFormatVersion} and requires a newer version of Narsil. You are running ${VERSION}.`
1086
+ `This data holds Narsil envelope format v${header.envelopeFormatVersion}, while this build of @delali/narsil reads up to v${maxAcceptedVersion}, so upgrade the package to read it.`
1087
1087
  );
1088
1088
  }
1089
1089
  if (header.flags.encryptionEnabled) {
@@ -3824,6 +3824,8 @@ async function spawnWorker2() {
3824
3824
  if (typeof worker.unref === "function") {
3825
3825
  worker.unref();
3826
3826
  }
3827
+ worker.on("error", () => discardWorker(worker));
3828
+ worker.on("exit", () => discardWorker(worker));
3827
3829
  spawnedWorkerCount += 1;
3828
3830
  return worker;
3829
3831
  } catch {
@@ -6008,12 +6010,20 @@ function createInvalidationIntegration(deps) {
6008
6010
  }
6009
6011
 
6010
6012
  // src/engine/heap-pressure.ts
6013
+ function spentHeapFraction(heap) {
6014
+ if (heap.configuredLimitBytes !== null) return heap.usedBytes / heap.configuredLimitBytes;
6015
+ if (heap.availableBytes === null) return heap.usedBytes / heap.limitBytes;
6016
+ return 1 - heap.availableBytes / heap.limitBytes;
6017
+ }
6018
+ function ceilingBytes(heap) {
6019
+ return heap.configuredLimitBytes ?? heap.limitBytes;
6020
+ }
6011
6021
  function createHeapPressureNotifier(deps) {
6012
6022
  let warned = false;
6013
6023
  function check(indexName) {
6014
6024
  const heap = deps.readHeap();
6015
6025
  if (heap === null) return;
6016
- const fraction = heap.usedBytes / heap.limitBytes;
6026
+ const fraction = spentHeapFraction(heap);
6017
6027
  if (warned) {
6018
6028
  if (fraction < HEAP_PRESSURE_REARM_FRACTION) warned = false;
6019
6029
  return;
@@ -6023,7 +6033,7 @@ function createHeapPressureNotifier(deps) {
6023
6033
  deps.emit({
6024
6034
  indexName,
6025
6035
  heapUsed: heap.usedBytes,
6026
- heapLimit: heap.limitBytes,
6036
+ heapLimit: ceilingBytes(heap),
6027
6037
  estimatedMemoryBytes: deps.estimateIndexBytes(indexName)
6028
6038
  });
6029
6039
  }
@@ -6751,7 +6761,7 @@ function createWorkerExecutor(worker, config) {
6751
6761
  clearTimeout(entry.timeoutId);
6752
6762
  pending.delete(response.requestId);
6753
6763
  if (response.type === "error") {
6754
- entry.reject(new NarsilError(response.code, response.message));
6764
+ entry.reject(new NarsilError(response.code, response.message, response.details));
6755
6765
  } else {
6756
6766
  entry.resolve(response.data);
6757
6767
  }
@@ -7312,6 +7322,7 @@ function scheduleRequestThreadPoolRestart(state) {
7312
7322
  if (typeof timer.unref === "function") timer.unref();
7313
7323
  }
7314
7324
  async function serveRequestsOnWorkers(state, listener) {
7325
+ if (!state.workersEnabled) return 0;
7315
7326
  state.requestThreads = listener;
7316
7327
  state.keywordWorkerCount = resolveRequestThreadCount(state.config?.workers?.count);
7317
7328
  if (state.vectorCopyPolicy !== void 0) {
@@ -7334,6 +7345,7 @@ async function serveRequestsOnWorkers(state, listener) {
7334
7345
  return pool.workerCount;
7335
7346
  }
7336
7347
  function requestThreadCountOf(state) {
7348
+ if (!state.workersEnabled) return 0;
7337
7349
  return resolveRequestThreadCount(state.config?.workers?.count);
7338
7350
  }
7339
7351
  function stopRequestThreads(state) {
@@ -8275,6 +8287,16 @@ function createEngineCore(config, hooks) {
8275
8287
  }
8276
8288
 
8277
8289
  // src/engine/index-lifecycle.ts
8290
+ async function runLifecycleHook(core, hookName, context) {
8291
+ try {
8292
+ await core.pluginRegistry.runHook(hookName, context);
8293
+ } catch (err) {
8294
+ console.warn(`${hookName} plugin hook error:`, err instanceof Error ? err.message : String(err));
8295
+ }
8296
+ }
8297
+ async function announceIndexCreated(core, name, config) {
8298
+ await runLifecycleHook(core, "onIndexCreate", { indexName: name, config });
8299
+ }
8278
8300
  async function createEngineIndex(core, config, name, indexConfig, indexUuid) {
8279
8301
  core.guardShutdown();
8280
8302
  validateIndexName(name);
@@ -8346,7 +8368,7 @@ async function createEngineIndex(core, config, name, indexConfig, indexUuid) {
8346
8368
  if (core.durability) {
8347
8369
  await core.durability.manager.persistMetadata(name);
8348
8370
  }
8349
- await core.pluginRegistry.runHook("onIndexCreate", { indexName: name, config: indexConfig });
8371
+ await runLifecycleHook(core, "onIndexCreate", { indexName: name, config: indexConfig });
8350
8372
  }
8351
8373
  async function dropEngineIndex(core, name) {
8352
8374
  core.guardShutdown();
@@ -8366,7 +8388,7 @@ async function dropEngineIndex(core, name) {
8366
8388
  core.watermarkNotifier.forget(name);
8367
8389
  core.analysisRebuild.clearStale(name);
8368
8390
  });
8369
- await core.pluginRegistry.runHook("onIndexDrop", { indexName: name, config: entry.config });
8391
+ await runLifecycleHook(core, "onIndexDrop", { indexName: name, config: entry.config });
8370
8392
  }
8371
8393
  function registerEngineEmbeddingAdapter(core, name, adapter) {
8372
8394
  core.guardShutdown();
@@ -8487,7 +8509,15 @@ async function awaitWriteVisibility(ctx, indexName) {
8487
8509
  async function insertDocument(ctx, indexName, document, docId, options) {
8488
8510
  ctx.guardShutdown();
8489
8511
  const entry = ctx.requireIndex(indexName);
8490
- const resolvedDocId = docId ?? providedDocId(document) ?? ctx.idGenerator();
8512
+ const embeddedDocId = providedDocId(document);
8513
+ if (docId !== void 0 && embeddedDocId !== void 0 && embeddedDocId !== docId) {
8514
+ throw new NarsilError(
8515
+ ErrorCodes.DOC_VALIDATION_FAILED,
8516
+ `The call names document id "${docId}" while the document's own id field is "${embeddedDocId}", so the stored document would contradict the key that it is stored under`,
8517
+ { docId, documentId: embeddedDocId }
8518
+ );
8519
+ }
8520
+ const resolvedDocId = docId ?? embeddedDocId ?? ctx.idGenerator();
8491
8521
  validateDocId(resolvedDocId);
8492
8522
  await ctx.pluginRegistry.runHook("beforeInsert", { indexName, docId: resolvedDocId, document });
8493
8523
  if (entry.config.required && entry.config.required.length > 0) {
@@ -8758,13 +8788,12 @@ async function admitBatchDocuments(ctx, indexName, documents, failed) {
8758
8788
  // src/engine/mutations/insert-batch-documents.ts
8759
8789
  async function applyAdmittedDocuments(ctx, indexName, admitted, options, failed) {
8760
8790
  const hasAfterHook = ctx.pluginRegistry.hasHooks("afterInsert");
8761
- const chunkSize = hasAfterHook ? 1 : BATCH_CHUNK_SIZE;
8762
8791
  const succeeded = [];
8763
8792
  const buffered = /* @__PURE__ */ new Set();
8764
8793
  const touchedVectorFields = /* @__PURE__ */ new Set();
8765
- for (let chunkStart = 0; chunkStart < admitted.length; chunkStart += chunkSize) {
8794
+ for (let chunkStart = 0; chunkStart < admitted.length; chunkStart += BATCH_CHUNK_SIZE) {
8766
8795
  if (ctx.abortController.signal.aborted) break;
8767
- const chunk = admitted.slice(chunkStart, chunkStart + chunkSize);
8796
+ const chunk = admitted.slice(chunkStart, chunkStart + BATCH_CHUNK_SIZE);
8768
8797
  const applications = await applyInsertChunk(ctx, indexName, chunk, options);
8769
8798
  for (let i = 0; i < chunk.length; i++) {
8770
8799
  const doc = chunk[i];
@@ -8791,8 +8820,8 @@ async function applyAdmittedDocuments(ctx, indexName, admitted, options, failed)
8791
8820
  }
8792
8821
  succeeded.push(doc.docId);
8793
8822
  }
8794
- const applied = chunkStart + chunkSize;
8795
- if (applied < admitted.length && applied % BATCH_CHUNK_SIZE === 0) {
8823
+ const applied = chunkStart + BATCH_CHUNK_SIZE;
8824
+ if (applied < admitted.length) {
8796
8825
  await new Promise((r) => setTimeout(r, 0));
8797
8826
  }
8798
8827
  }
@@ -9161,7 +9190,6 @@ async function insertDocumentBatch(ctx, indexName, documents, options) {
9161
9190
  const failed = [];
9162
9191
  const hasBeforeHook = ctx.pluginRegistry.hasHooks("beforeInsert");
9163
9192
  const hasAfterHook = ctx.pluginRegistry.hasHooks("afterInsert");
9164
- const documentByDocument = hasBeforeHook || hasAfterHook;
9165
9193
  const required = entry.config.required;
9166
9194
  const batchManager = ctx.requireManager(indexName);
9167
9195
  const batchVecIndexes = batchManager.getVectorIndexes();
@@ -9241,9 +9269,6 @@ async function insertDocumentBatch(ctx, indexName, documents, options) {
9241
9269
  } catch (err) {
9242
9270
  failed.push({ docId: batchDocId, error: asBatchInsertError(err) });
9243
9271
  }
9244
- if (documentByDocument && prepared.length > 0) {
9245
- await applyPrepared(prepared.splice(0, prepared.length));
9246
- }
9247
9272
  }
9248
9273
  if (prepared.length > 0) await applyPrepared(prepared);
9249
9274
  if (chunkEnd < documents.length) {
@@ -9358,12 +9383,10 @@ async function removeDocumentBatch(ctx, indexName, docIds, options) {
9358
9383
  const succeeded = [];
9359
9384
  const failed = [];
9360
9385
  const manager = ctx.requireManager(indexName);
9361
- const hooked = ctx.pluginRegistry.hasHooks("beforeRemove") || ctx.pluginRegistry.hasHooks("afterRemove");
9362
- const chunkSize = hooked ? 1 : BATCH_CHUNK_SIZE;
9363
9386
  manager.beginBatchRemove();
9364
9387
  try {
9365
- for (let chunkStart = 0; chunkStart < docIds.length; chunkStart += chunkSize) {
9366
- const chunkEnd = Math.min(chunkStart + chunkSize, docIds.length);
9388
+ for (let chunkStart = 0; chunkStart < docIds.length; chunkStart += BATCH_CHUNK_SIZE) {
9389
+ const chunkEnd = Math.min(chunkStart + BATCH_CHUNK_SIZE, docIds.length);
9367
9390
  const prepared = [];
9368
9391
  for (let i = chunkStart; i < chunkEnd; i++) {
9369
9392
  try {
@@ -9390,13 +9413,14 @@ async function removeDocumentBatch(ctx, indexName, docIds, options) {
9390
9413
  if (!removal.buffered) await settleRemoval(ctx, indexName, removal.docId);
9391
9414
  succeeded.push(removal.docId);
9392
9415
  }
9393
- if (chunkEnd < docIds.length && chunkEnd % BATCH_CHUNK_SIZE === 0) {
9416
+ if (chunkEnd < docIds.length) {
9394
9417
  await new Promise((r) => setTimeout(r, 0));
9395
9418
  }
9396
9419
  }
9397
9420
  } finally {
9398
9421
  manager.endBatchRemove();
9399
9422
  }
9423
+ ctx.checkHeapPressure(indexName);
9400
9424
  if (options?.wait === true) await awaitWriteVisibility(ctx, indexName);
9401
9425
  return { succeeded, failed };
9402
9426
  }
@@ -9557,10 +9581,8 @@ async function updateDocumentBatch(ctx, indexName, updates, options) {
9557
9581
  const updateBatchManager = ctx.requireManager(indexName);
9558
9582
  const updateBatchVecIndexes = updateBatchManager.getVectorIndexes();
9559
9583
  const touchedVectorFields = /* @__PURE__ */ new Set();
9560
- const hooked = ctx.pluginRegistry.hasHooks("beforeUpdate") || ctx.pluginRegistry.hasHooks("afterUpdate");
9561
- const chunkSize = hooked ? 1 : BATCH_CHUNK_SIZE;
9562
- for (let chunkStart = 0; chunkStart < updates.length; chunkStart += chunkSize) {
9563
- const chunkEnd = Math.min(chunkStart + chunkSize, updates.length);
9584
+ for (let chunkStart = 0; chunkStart < updates.length; chunkStart += BATCH_CHUNK_SIZE) {
9585
+ const chunkEnd = Math.min(chunkStart + BATCH_CHUNK_SIZE, updates.length);
9564
9586
  const prepared = [];
9565
9587
  for (let i = chunkStart; i < chunkEnd; i++) {
9566
9588
  try {
@@ -9590,7 +9612,7 @@ async function updateDocumentBatch(ctx, indexName, updates, options) {
9590
9612
  }
9591
9613
  succeeded.push(update.docId);
9592
9614
  }
9593
- if (chunkEnd < updates.length && chunkEnd % BATCH_CHUNK_SIZE === 0) {
9615
+ if (chunkEnd < updates.length) {
9594
9616
  await new Promise((r) => setTimeout(r, 0));
9595
9617
  }
9596
9618
  }
@@ -10225,6 +10247,7 @@ async function restoreFromSnapshot(indexName, data, deps) {
10225
10247
  await deps.durability.manager.persistMetadata(indexName);
10226
10248
  await deps.durability.manager.checkpoint(indexName);
10227
10249
  }
10250
+ await deps.announceIndexCreated(indexName, indexConfig);
10228
10251
  } catch (err) {
10229
10252
  try {
10230
10253
  deps.executor.dropIndex(indexName);
@@ -10296,13 +10319,14 @@ function readProcessMemory() {
10296
10319
  }
10297
10320
  try {
10298
10321
  const usage = proc.memoryUsage();
10322
+ const heap = readHeapStatistics();
10299
10323
  if (!Number.isFinite(usage.heapUsed) || !Number.isFinite(usage.heapTotal) || !Number.isFinite(usage.external) || !Number.isFinite(usage.rss)) {
10300
10324
  return null;
10301
10325
  }
10302
10326
  return {
10303
10327
  heapUsed: usage.heapUsed,
10304
10328
  heapTotal: usage.heapTotal,
10305
- heapLimit: readHeapStatistics()?.limitBytes ?? null,
10329
+ heapLimit: heap === null ? null : heap.configuredLimitBytes ?? heap.limitBytes,
10306
10330
  external: usage.external,
10307
10331
  rss: usage.rss
10308
10332
  };
@@ -10335,13 +10359,14 @@ async function runEngineQuery(core, indexName, params, options) {
10335
10359
  try {
10336
10360
  const entry = core.requireIndex(indexName);
10337
10361
  const manager = core.requireManager(indexName);
10362
+ const scoped = scopedParams(params, options);
10363
+ await core.pluginRegistry.runHook("beforeSearch", { indexName, params: scoped });
10338
10364
  const resolvedParams = await resolveVectorText(
10339
- scopedParams(params, options),
10365
+ scoped,
10340
10366
  entry.embeddingAdapter,
10341
10367
  core.abortController.signal,
10342
10368
  entry.embeddingAdapterName
10343
10369
  );
10344
- await core.pluginRegistry.runHook("beforeSearch", { indexName, params: resolvedParams });
10345
10370
  const workerSearch = core.orchestrator.hasWorkerPool() ? core.orchestrator.searchViaWorker.bind(core.orchestrator) : void 0;
10346
10371
  const result = await executeQuery(resolvedParams, {
10347
10372
  manager,
@@ -10353,14 +10378,13 @@ async function runEngineQuery(core, indexName, params, options) {
10353
10378
  partitionIds: options?.partitionIds,
10354
10379
  cursorBinding: queryBindingOf(params)
10355
10380
  });
10356
- try {
10357
- await core.pluginRegistry.runHook("afterSearch", {
10358
- indexName,
10359
- params: resolvedParams,
10360
- results: result
10361
- });
10362
- } catch (err) {
10363
- console.warn("afterSearch plugin hook error:", err);
10381
+ if (core.pluginRegistry.hasHooks("afterSearch")) {
10382
+ const observed = { ...result, hits: [...result.hits] };
10383
+ try {
10384
+ await core.pluginRegistry.runHook("afterSearch", { indexName, params: resolvedParams, results: observed });
10385
+ } catch (err) {
10386
+ console.warn("afterSearch plugin hook error:", err);
10387
+ }
10364
10388
  }
10365
10389
  if (core.analysisRebuild.isStale(indexName)) {
10366
10390
  result.analysisStale = true;
@@ -10376,8 +10400,10 @@ async function runEnginePreflight(core, indexName, params, options) {
10376
10400
  try {
10377
10401
  const entry = core.requireIndex(indexName);
10378
10402
  const manager = core.requireManager(indexName);
10403
+ const scoped = scopedParams(params, options);
10404
+ await core.pluginRegistry.runHook("beforeSearch", { indexName, params: scoped });
10379
10405
  const resolvedParams = await resolveVectorText(
10380
- scopedParams(params, options),
10406
+ scoped,
10381
10407
  entry.embeddingAdapter,
10382
10408
  core.abortController.signal,
10383
10409
  entry.embeddingAdapterName
@@ -10616,6 +10642,7 @@ function createNarsilFromCore(core, config) {
10616
10642
  indexRegistry,
10617
10643
  getVectorFieldPaths,
10618
10644
  dropIndex: narsil.dropIndex.bind(narsil),
10645
+ announceIndexCreated: (name, restoredConfig) => announceIndexCreated(core, name, restoredConfig),
10619
10646
  requireManager,
10620
10647
  durability,
10621
10648
  filesystemDurability: core.filesystemDurability,
@@ -1,4 +1,4 @@
1
- import { DEFAULT_PAGE_SIZE } from './chunk-ZT5BRDFW.mjs';
1
+ import { DEFAULT_PAGE_SIZE } from './chunk-L225SHNB.mjs';
2
2
 
3
3
  // src/engine/constants.ts
4
4
  var MIN_DOCUMENTS_FOR_SEGMENTS = 64;
@@ -6,6 +6,8 @@ var BATCH_CHUNK_SIZE = 1e3;
6
6
  var DEFAULT_LIMIT = DEFAULT_PAGE_SIZE;
7
7
  var DEFAULT_OFFSET = 0;
8
8
  var INDEX_NAME_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
9
+ var ABSOLUTE_WINDOWS_PATH_PATTERN = /^[a-zA-Z]:[\\/]/;
10
+ var MODULE_URL_SCHEME_PATTERN = /^(file|https?|data|node):/;
9
11
  var MAX_INDEX_NAME_LENGTH = 255;
10
12
  var MAX_DOC_ID_LENGTH = 512;
11
13
  var MIN_SWEEP_INTERVAL_MS = 100;
@@ -20,4 +22,4 @@ var SUGGEST_OVERSAMPLE_FACTOR = 1.5;
20
22
  var SUGGEST_OVERSAMPLE_PADDING = 10;
21
23
  var MAX_SUGGEST_SCATTER_LIMIT = Math.ceil(MAX_SUGGEST_LIMIT * SUGGEST_OVERSAMPLE_FACTOR) + SUGGEST_OVERSAMPLE_PADDING;
22
24
 
23
- export { BATCH_CHUNK_SIZE, DEFAULT_LIMIT, DEFAULT_OFFSET, DEFAULT_SUGGEST_LIMIT, FOREIGN_STATS_TTL_MS, HEAP_PRESSURE_REARM_FRACTION, HEAP_PRESSURE_WARNING_FRACTION, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, MAX_INDEX_NAME_LENGTH, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, MAX_SWEEP_INTERVAL_MS, MIN_DOCUMENTS_FOR_SEGMENTS, MIN_SWEEP_INTERVAL_MS, STATISTICS_BROADCAST_INTERVAL_MS, SUGGEST_OVERSAMPLE_FACTOR, SUGGEST_OVERSAMPLE_PADDING };
25
+ export { ABSOLUTE_WINDOWS_PATH_PATTERN, BATCH_CHUNK_SIZE, DEFAULT_LIMIT, DEFAULT_OFFSET, DEFAULT_SUGGEST_LIMIT, FOREIGN_STATS_TTL_MS, HEAP_PRESSURE_REARM_FRACTION, HEAP_PRESSURE_WARNING_FRACTION, INDEX_NAME_PATTERN, MAX_DOC_ID_LENGTH, MAX_INDEX_NAME_LENGTH, MAX_SUGGEST_LIMIT, MAX_SUGGEST_SCATTER_LIMIT, MAX_SWEEP_INTERVAL_MS, MIN_DOCUMENTS_FOR_SEGMENTS, MIN_SWEEP_INTERVAL_MS, MODULE_URL_SCHEME_PATTERN, STATISTICS_BROADCAST_INTERVAL_MS, SUGGEST_OVERSAMPLE_FACTOR, SUGGEST_OVERSAMPLE_PADDING };
@@ -1,4 +1,5 @@
1
1
  // src/errors.ts
2
+ var NARSIL_ERROR_MARKER = /* @__PURE__ */ Symbol.for("@delali/narsil.NarsilError");
2
3
  var ErrorCodes = {
3
4
  SCHEMA_INVALID_TYPE: "SCHEMA_INVALID_TYPE",
4
5
  SCHEMA_DEPTH_EXCEEDED: "SCHEMA_DEPTH_EXCEEDED",
@@ -16,6 +17,7 @@ var ErrorCodes = {
16
17
  WORKER_CRASHED: "WORKER_CRASHED",
17
18
  WORKER_BUSY: "WORKER_BUSY",
18
19
  WORKER_TIMEOUT: "WORKER_TIMEOUT",
20
+ WORKER_ACTION_FAILED: "WORKER_ACTION_FAILED",
19
21
  PERSISTENCE_SAVE_FAILED: "PERSISTENCE_SAVE_FAILED",
20
22
  PERSISTENCE_LOAD_FAILED: "PERSISTENCE_LOAD_FAILED",
21
23
  PERSISTENCE_DELETE_FAILED: "PERSISTENCE_DELETE_FAILED",
@@ -135,8 +137,12 @@ var NarsilError = class extends Error {
135
137
  this.name = "NarsilError";
136
138
  this.code = code;
137
139
  this.details = details ?? {};
140
+ Object.defineProperty(this, NARSIL_ERROR_MARKER, { value: true });
138
141
  }
139
142
  };
143
+ function isNarsilError(value) {
144
+ return typeof value === "object" && value !== null && NARSIL_ERROR_MARKER in value;
145
+ }
140
146
  function createNarsilError(code, message, details) {
141
147
  return new NarsilError(code, message, details);
142
148
  }
@@ -144,4 +150,4 @@ function describeError(error) {
144
150
  return error instanceof Error ? error.message : String(error);
145
151
  }
146
152
 
147
- export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, createNarsilError, describeError };
153
+ export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, createNarsilError, describeError, isNarsilError };
@@ -1,5 +1,5 @@
1
- import { MAX_M } from './chunk-WFKIGEBY.mjs';
2
- import { NarsilError, ErrorCodes } from './chunk-P4ELXVJQ.mjs';
1
+ import { MAX_M } from './chunk-UTOFOJOR.mjs';
2
+ import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
3
3
 
4
4
  // src/schema/constants.ts
5
5
  var MAX_NESTING_DEPTH = 4;
@@ -1,6 +1,6 @@
1
- import { MAX_PARTITION_COUNT, MAX_REPLICATION_FACTOR } from './chunk-U36IDJN7.mjs';
2
- import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN } from './chunk-3GWP2TO6.mjs';
3
- import { NarsilError, ErrorCodes } from './chunk-P4ELXVJQ.mjs';
1
+ import { MAX_PARTITION_COUNT, MAX_REPLICATION_FACTOR } from './chunk-4NVPQ6S5.mjs';
2
+ import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN } from './chunk-D2S642IV.mjs';
3
+ import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
4
4
  import { encode, decode } from '@msgpack/msgpack';
5
5
 
6
6
  var INDEX_CONFIG_PREFIX = "_narsil/index/";
@@ -1,5 +1,6 @@
1
- import { MAX_SORT_FIELDS } from './chunk-ZT5BRDFW.mjs';
2
- import { ServerErrorCodes, NarsilError, ErrorCodes } from './chunk-P4ELXVJQ.mjs';
1
+ import { MAX_SORT_FIELDS } from './chunk-L225SHNB.mjs';
2
+ import { nativeSearchCoreIsEnabled, loadNativeCore } from './chunk-UTOFOJOR.mjs';
3
+ import { NarsilError, ServerErrorCodes, ErrorCodes } from './chunk-FRQVMFY7.mjs';
3
4
 
4
5
  // src/server/capabilities.ts
5
6
  var ASYNC_IMPORT_CAPABILITY = "documents.import.async";
@@ -122,6 +123,7 @@ var STATUS_BY_CODE = {
122
123
  PARTITION_CORRUPTED: 503,
123
124
  WORKER_CRASHED: 503,
124
125
  WORKER_TIMEOUT: 503,
126
+ WORKER_ACTION_FAILED: 500,
125
127
  PERSISTENCE_SAVE_FAILED: 503,
126
128
  PERSISTENCE_LOAD_FAILED: 503,
127
129
  PERSISTENCE_DELETE_FAILED: 503,
@@ -224,6 +226,8 @@ var DEFAULT_MAX_FETCH_DOCUMENTS = 1e4;
224
226
  var DEFAULT_MAX_IMPORT_ERRORS = 100;
225
227
  var DEFAULT_MAX_TASK_PAGE_SIZE = 1e3;
226
228
  var DEFAULT_MAX_CONCURRENT_TASKS = 4;
229
+ var MIN_COUNTED_SERVER_LIMIT = 1;
230
+ var MIN_UNBOUNDED_SERVER_LIMIT = 0;
227
231
  var RESPONSE_STREAM_THRESHOLD_BYTES = 64 * 1024;
228
232
  var MAX_INDEX_TOUCH_INTERVAL_MS = 1e3;
229
233
  var INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT = 4;
@@ -484,7 +488,7 @@ function validateRebalance(body) {
484
488
  return null;
485
489
  }
486
490
  var TASK_TYPES = ["optimizeVectors", "rebalance", "restore", "import", "rebuildAnalysis"];
487
- var TASK_STATUSES = ["queued", "running", "succeeded", "failed", "cancelled"];
491
+ var TASK_STATUSES = ["running", "succeeded", "failed", "cancelled"];
488
492
  function parseCountParam(raw, field, minimum) {
489
493
  if (raw === null) return minimum;
490
494
  const value = Number(raw);
@@ -603,6 +607,22 @@ function indexDocNotFound(docId) {
603
607
  return new NarsilError(ErrorCodes.DOC_NOT_FOUND, `Document "${docId}" not found`, { docId });
604
608
  }
605
609
 
610
+ // src/vector/native/search-path.ts
611
+ function vectorSearchPath() {
612
+ return nativeSearchCoreIsEnabled() && loadNativeCore() !== null ? "native" : "wasm";
613
+ }
614
+
615
+ // src/server/handlers/version.ts
616
+ function versionReport(build) {
617
+ return { name: "narsil", ...build, vectorSearch: vectorSearchPath() };
618
+ }
619
+ function createVersionHandler(deps) {
620
+ function report(ctx) {
621
+ respondJson(ctx, versionReport(deps.build));
622
+ }
623
+ return { report };
624
+ }
625
+
606
626
  // src/server/request.ts
607
627
  function initAbortHandler(res) {
608
628
  const listeners = [];
@@ -790,7 +810,7 @@ function serverRoutes(limits) {
790
810
  return [
791
811
  { method: "get", path: "/livez", handler: "livez", options: probe },
792
812
  { method: "get", path: "/readyz", handler: "readyz", options: probe },
793
- { method: "get", path: "/health", handler: "livez", options: probe },
813
+ { method: "get", path: "/health", handler: "readyz", options: probe },
794
814
  { method: "get", path: "/version", handler: "version", options: probe },
795
815
  { method: "get", path: "/capabilities", handler: "capabilities", options: probe },
796
816
  { method: "get", path: "/cluster", handler: "clusterTopology", options: bare },
@@ -896,4 +916,4 @@ function childAppOf(app) {
896
916
  return candidate;
897
917
  }
898
918
 
899
- export { ASYNC_IMPORT_CAPABILITY, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_RETAINED_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_TASK_PAGE_SIZE, IMPORT_FLUSHES_IN_FLIGHT, INDEX_LIFECYCLE_CAPABILITY, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, MAIN_THREAD_GATE_SLOT, MAX_INDEX_TOUCH_INTERVAL_MS, REBUILD_ANALYSIS_CAPABILITY, RUNNING_TASK_TTL_MS, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, TASK_PROGRESS_WRITE_INTERVAL_MS, TERMINAL_TASK_TTL_MS, acceptorOf, authorizerFor, badRequest, childAppOf, clearGateSlot, corsWriter, createDocumentReadHandlers, createRouteRunner, createSharedGateBuffer, createSharedRequestGate, gateSlotOfWorker, httpStatusForNarsilError, loadUWebSockets, parseJson, parseJsonOptional, parseTaskListQuery, registerServerRoutes, rejectInvalid, resolveCors, respondError, respondJson, sendBinary, sendError, sendRelayed, serializeBatchResult, serializeNarsilError, serverRoutes, validateBatch, validateCreateIndex, validateDocumentBody, validateQuery, validateRebalance, validateSuggest };
919
+ export { ASYNC_IMPORT_CAPABILITY, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_RETAINED_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_TASK_PAGE_SIZE, IMPORT_FLUSHES_IN_FLIGHT, INDEX_LIFECYCLE_CAPABILITY, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, MAIN_THREAD_GATE_SLOT, MAX_INDEX_TOUCH_INTERVAL_MS, MIN_COUNTED_SERVER_LIMIT, MIN_UNBOUNDED_SERVER_LIMIT, REBUILD_ANALYSIS_CAPABILITY, RUNNING_TASK_TTL_MS, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, TASK_PROGRESS_WRITE_INTERVAL_MS, TERMINAL_TASK_TTL_MS, acceptorOf, authorizerFor, badRequest, childAppOf, clearGateSlot, corsWriter, createDocumentReadHandlers, createRouteRunner, createSharedGateBuffer, createSharedRequestGate, createVersionHandler, gateSlotOfWorker, httpStatusForNarsilError, loadUWebSockets, parseJson, parseJsonOptional, parseTaskListQuery, registerServerRoutes, rejectInvalid, resolveCors, respondError, respondJson, sendBinary, sendError, sendRelayed, serializeBatchResult, serializeNarsilError, serverRoutes, toHttpError, validateBatch, validateCreateIndex, validateDocumentBody, validateQuery, validateRebalance, validateSuggest, versionReport };