@delali/narsil 0.2.4-next.51 → 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 (64) hide show
  1. package/README.md +33 -27
  2. package/dist/adapters/filesystem.mjs +1 -1
  3. package/dist/adapters/indexeddb.mjs +1 -1
  4. package/dist/{capabilities-BWm4IITU.d.ts → capabilities-DlYw0Ov0.d.ts} +13 -2
  5. package/dist/{chunk-KMMJMDUA.mjs → chunk-3L4U6EJQ.mjs} +15 -10
  6. package/dist/chunk-4NVPQ6S5.mjs +366 -0
  7. package/dist/{chunk-CMVG2UEF.mjs → chunk-5T6AOR37.mjs} +56 -518
  8. package/dist/{chunk-ND34I3SV.mjs → chunk-BH5SYB5W.mjs} +3295 -2149
  9. package/dist/{chunk-XE6XR2OE.mjs → chunk-D2S642IV.mjs} +4 -2
  10. package/dist/{chunk-P4ELXVJQ.mjs → chunk-FRQVMFY7.mjs} +7 -1
  11. package/dist/chunk-IFBKLBGB.mjs +7 -0
  12. package/dist/chunk-L225SHNB.mjs +513 -0
  13. package/dist/{chunk-MHE7YWAU.mjs → chunk-NTZYA3SJ.mjs} +3 -3
  14. package/dist/{chunk-WYJXSLER.mjs → chunk-POWOTUKJ.mjs} +7 -1
  15. package/dist/{chunk-CV5H7XL7.mjs → chunk-RGS7FMCB.mjs} +53 -10
  16. package/dist/{chunk-ZHUQKZBE.mjs → chunk-TVT5V4E7.mjs} +101 -34
  17. package/dist/chunk-U2AL3SON.mjs +4198 -0
  18. package/dist/chunk-UTOFOJOR.mjs +135 -0
  19. package/dist/{chunk-BEIK3EOZ.mjs → chunk-XNQAIO74.mjs} +5523 -3847
  20. package/dist/chunk-Y3L5MDRV.mjs +96 -0
  21. package/dist/chunk-ZJ4CSAB2.mjs +13 -0
  22. package/dist/{client-B_X6_AbT.d.ts → client-CQUqt9Ir.d.ts} +13 -4
  23. package/dist/client.d.ts +8 -8
  24. package/dist/client.mjs +20 -14
  25. package/dist/{config-Czh2YNDi.d.ts → config-CNas6wJH.d.ts} +2 -2
  26. package/dist/{config-OON7IJ_B.d.ts → config-bXxnJrQc.d.ts} +80 -35
  27. package/dist/direct-executor-RBA5O7EN.mjs +12 -0
  28. package/dist/distribution/coordinator/etcd.d.ts +2 -2
  29. package/dist/distribution/coordinator/etcd.mjs +1 -1
  30. package/dist/distribution/coordinator/in-memory.d.ts +2 -2
  31. package/dist/distribution/transport/grpc.mjs +1 -1
  32. package/dist/distribution.d.ts +8 -8
  33. package/dist/distribution.mjs +32 -17
  34. package/dist/embeddings/openai.mjs +1 -1
  35. package/dist/{engine-9PtFY50q.d.ts → engine-Dj4I91Jv.d.ts} +21 -8
  36. package/dist/index.browser.mjs +12962 -7786
  37. package/dist/index.d.ts +9 -21
  38. package/dist/index.mjs +14 -13
  39. package/dist/{memory-Bzd5xcEW.d.ts → memory-xrXOZMbw.d.ts} +68 -13
  40. package/dist/persistence/durability/checkpoint-worker.d.ts +138 -3
  41. package/dist/persistence/durability/checkpoint-worker.mjs +32 -18
  42. package/dist/react.d.ts +11 -11
  43. package/dist/react.mjs +16 -4
  44. package/dist/{schema-BqRx9t4E.d.ts → schema-mLpXZBEh.d.ts} +43 -12
  45. package/dist/serialization/crc32-worker.mjs +2 -1
  46. package/dist/server.d.ts +13 -10
  47. package/dist/server.mjs +136 -47
  48. package/dist/simd-DW5AtJ6B.d.ts +41 -0
  49. package/dist/{tasks-DT7L1p6w.d.ts → tasks-Df73Tjgq.d.ts} +9 -5
  50. package/dist/{thread-PZLEO6JL.mjs → thread-5UP6MGED.mjs} +131 -43
  51. package/dist/{types-DXPxaXPO.d.ts → types-BTIVO8DI.d.ts} +1 -1
  52. package/dist/vector/search-worker.d.ts +292 -128
  53. package/dist/vector/search-worker.mjs +70 -54
  54. package/dist/workers/entry.mjs +30 -14
  55. package/package.json +52 -31
  56. package/dist/brute-force-DbHYCTc3.d.ts +0 -8
  57. package/dist/chunk-CBLS46IE.mjs +0 -10
  58. package/dist/chunk-PIWKZPP7.mjs +0 -64
  59. package/dist/chunk-PMBHH44R.mjs +0 -492
  60. package/dist/chunk-RP23PWMV.mjs +0 -11
  61. package/dist/chunk-X6YZO4MQ.mjs +0 -1572
  62. package/dist/direct-executor-OREXU72C.mjs +0 -12
  63. package/dist/vector/hnsw-build-worker.d.ts +0 -105
  64. package/dist/vector/hnsw-build-worker.mjs +0 -123
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
- import { c as StopWordOverride, C as CustomTokenizer } from './schema-BqRx9t4E.js';
2
- export { A as AnyDocument, B as BM25Params, E as EmbeddingFieldConfig, F as FieldType, I as IndexConfig, b as InsertOptions, P as PartitionConfig, S as SchemaDefinition, a as ScoringMode, V as VectorIndexConfig, d as VectorQuantizationMode, W as WriteOptions } from './schema-BqRx9t4E.js';
1
+ import { b as StopWordOverride, C as CustomTokenizer } from './schema-mLpXZBEh.js';
2
+ export { A as AnyDocument, B as BM25Params, E as EmbeddingFieldConfig, F as FieldType, I as IndexConfig, a as InsertOptions, P as PartitionConfig, S as SchemaDefinition, c as ScoringMode, V as VectorIndexConfig, d as VectorQuantizationMode, e as VectorStorageMode, W as WriteOptions } from './schema-mLpXZBEh.js';
3
3
  import { L as LanguageModule } from './language-DB8KG1z5.js';
4
4
  export { T as TokenizerConfig } from './language-DB8KG1z5.js';
5
- export { A as ArrayFilter, B as BatchResult, C as ClientErrorCode, a as ClientErrorCodes, k as ComparisonFilter, D as DocumentProjection, E as ErrorCode, b as ErrorCodes, F as FacetConfig, l as FacetResult, m as FieldFilter, n as FilterExpression, G as GeoFilter, o as GeoPolygonFilter, p as GeoRadiusFilter, q as GroupConfig, r as GroupReducer, s as GroupResult, H as HighlightConfig, t as HighlightMatch, u as Hit, v as HybridConfig, I as IndexInfo, f as IndexStats, L as ListParams, g as ListResult, w as ListedDocument, M as MemoryStats, N as NarsilError, c as NarsilErrorCode, P as PartitionStatsResult, h as PreflightResult, x as PresenceFilter, y as ProcessMemoryReport, z as QueryCoverage, Q as QueryParams, e as QueryResult, J as ScoreComponents, K as SearchMode, S as ServerErrorCode, d as ServerErrorCodes, O as SortField, R as SortSpec, T as StringFilter, i as SuggestParams, j as SuggestResult, U as TermMatchPolicy, V as VectorMaintenanceResult, W as VectorQueryConfig, X as WorkerCopyReport } from './memory-Bzd5xcEW.js';
6
- import { N as NarsilConfig } from './config-OON7IJ_B.js';
7
- export { A as AnalysisConfig, D as DurabilityConfig, I as IndexContext, a as IndexLifecycleConfig, b as InsertContext, M as MainCopyQueries, c as NarsilPlugin, P as PartitionContext, R as RemoveContext, S as SearchContext, d as StaleAnalysis, U as UpdateContext, W as WorkerConfig, e as WorkerContext } from './config-OON7IJ_B.js';
8
- import { a as Narsil } from './engine-9PtFY50q.js';
9
- export { D as DocumentWriteOperations, I as IndexLifecycleOperations, N as NarsilEventMap } from './engine-9PtFY50q.js';
5
+ export { A as ArrayFilter, B as BatchResult, C as ClientErrorCode, a as ClientErrorCodes, l as ComparisonFilter, D as DocumentProjection, E as ErrorCode, b as ErrorCodes, F as FacetConfig, m as FacetResult, n as FieldFilter, o as FilterExpression, G as GeoFilter, p as GeoPolygonFilter, q as GeoRadiusFilter, r as GroupConfig, s as GroupReducer, t as GroupResult, H as HighlightConfig, u as HighlightMatch, v as Hit, w as HybridConfig, I as IndexInfo, f as IndexStats, L as ListParams, g as ListResult, x as ListedDocument, M as MemoryStats, N as NarsilError, c as NarsilErrorCode, P as PartitionStatsResult, h as PreflightResult, y as PresenceFilter, z as ProcessMemoryReport, J as QueryCoverage, Q as QueryParams, e as QueryResult, K as ScoreComponents, O as SearchMode, S as ServerErrorCode, d as ServerErrorCodes, R as SortField, T as SortSpec, U as StringFilter, j as SuggestParams, k as SuggestResult, W as TermMatchPolicy, V as VectorMaintenanceResult, X as VectorQueryConfig, Y as WorkerCopyReport, i as isNarsilError } from './memory-xrXOZMbw.js';
6
+ import { N as NarsilConfig } from './config-bXxnJrQc.js';
7
+ export { A as AnalysisConfig, D as DurabilityConfig, I as IndexContext, a as IndexLifecycleConfig, b as InsertContext, M as MainCopyQueries, c as NarsilPlugin, P as PartitionContext, R as RemoveContext, S as SearchContext, d as StaleAnalysis, U as UpdateContext, W as WorkerConfig, e as WorkerContext } from './config-bXxnJrQc.js';
8
+ import { a as Narsil } from './engine-Dj4I91Jv.js';
9
+ export { D as DocumentWriteOperations, I as IndexLifecycleOperations, N as NarsilEventMap } from './engine-Dj4I91Jv.js';
10
10
  export { E as EmbeddingAdapter, I as InvalidationAdapter, a as InvalidationEvent, b as PartitionStatistics, P as PersistenceAdapter } from './adapters-79OIa4xm.js';
11
+ export { i as isSimdAvailable } from './simd-DW5AtJ6B.js';
11
12
 
12
13
  /**
13
14
  * Registers a tokeniser under a name that an index config can then reference.
@@ -165,19 +166,6 @@ declare function getLanguage(name: string): LanguageModule;
165
166
  */
166
167
  declare function createNarsil(config?: NarsilConfig): Promise<Narsil>;
167
168
 
168
- /**
169
- * Reports whether the runtime loaded the SIMD module that speeds up vector
170
- * distance work.
171
- *
172
- * Vector search works either way, so read this to explain a difference in
173
- * search latency between two hosts rather than to decide whether to search.
174
- *
175
- * @returns True once the SIMD module has loaded.
176
- *
177
- * @public
178
- */
179
- declare function isSimdAvailable(): boolean;
180
-
181
169
  /**
182
170
  * Engine version written into the engine-version bytes of every `.nrsl` file,
183
171
  * for diagnostics.
@@ -190,4 +178,4 @@ declare function isSimdAvailable(): boolean;
190
178
  */
191
179
  declare const VERSION = "0.1.0";
192
180
 
193
- export { CustomTokenizer, LanguageModule, Narsil, NarsilConfig, StopWordOverride, VERSION, clearNormalizationCache, configureNormalizationCache, createNarsil, getLanguage, getNormalizationCacheSize, getStopWords, getTokenizer, hasStopWords, hasTokenizer, isSimdAvailable, registerLanguage, registerStopWords, registerTokenizer, resetNormalizationCache };
181
+ export { CustomTokenizer, LanguageModule, Narsil, NarsilConfig, StopWordOverride, VERSION, clearNormalizationCache, configureNormalizationCache, createNarsil, getLanguage, getNormalizationCacheSize, getStopWords, getTokenizer, hasStopWords, hasTokenizer, registerLanguage, registerStopWords, registerTokenizer, resetNormalizationCache };
package/dist/index.mjs CHANGED
@@ -1,18 +1,19 @@
1
- export { VERSION, createNarsil } from './chunk-ND34I3SV.mjs';
2
- import './chunk-ZHUQKZBE.mjs';
1
+ export { VERSION, createNarsil } from './chunk-BH5SYB5W.mjs';
3
2
  import './chunk-GCM3JFVA.mjs';
4
- import './chunk-PIWKZPP7.mjs';
5
- import './chunk-XE6XR2OE.mjs';
6
- export { getLanguage, getStopWords, getTokenizer, hasStopWords, hasTokenizer, registerLanguage, registerStopWords, registerTokenizer } from './chunk-BEIK3EOZ.mjs';
7
- export { clearNormalizationCache, configureNormalizationCache, getNormalizationCacheSize, resetNormalizationCache } from './chunk-CMVG2UEF.mjs';
3
+ import './chunk-4NVPQ6S5.mjs';
4
+ export { getLanguage, getStopWords, getTokenizer, hasStopWords, hasTokenizer, registerLanguage, registerStopWords, registerTokenizer } from './chunk-XNQAIO74.mjs';
8
5
  import './chunk-AV4IJKD2.mjs';
9
- import './chunk-CBLS46IE.mjs';
6
+ import './chunk-TVT5V4E7.mjs';
7
+ import './chunk-D2S642IV.mjs';
8
+ export { clearNormalizationCache, configureNormalizationCache, getNormalizationCacheSize, resetNormalizationCache } from './chunk-5T6AOR37.mjs';
9
+ import './chunk-L225SHNB.mjs';
10
10
  import './chunk-TGP5M5R7.mjs';
11
- import './chunk-PMBHH44R.mjs';
12
- export { isSimdAvailable } from './chunk-X6YZO4MQ.mjs';
13
- import './chunk-RP23PWMV.mjs';
14
- import './chunk-KMMJMDUA.mjs';
11
+ export { isSimdAvailable } from './chunk-U2AL3SON.mjs';
12
+ import './chunk-ZJ4CSAB2.mjs';
13
+ import './chunk-UTOFOJOR.mjs';
14
+ import './chunk-3L4U6EJQ.mjs';
15
+ import './chunk-IFBKLBGB.mjs';
15
16
  import './chunk-U2BKYEC7.mjs';
16
17
  import './chunk-2GWVQWGA.mjs';
17
- import './chunk-WYJXSLER.mjs';
18
- export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes } from './chunk-P4ELXVJQ.mjs';
18
+ import './chunk-POWOTUKJ.mjs';
19
+ export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, isNarsilError } from './chunk-FRQVMFY7.mjs';
@@ -1,4 +1,4 @@
1
- import { A as AnyDocument, S as SchemaDefinition, a as ScoringMode } from './schema-BqRx9t4E.js';
1
+ import { A as AnyDocument, S as SchemaDefinition, c as ScoringMode } from './schema-mLpXZBEh.js';
2
2
 
3
3
  /**
4
4
  * Every code a {@link NarsilError} carries, grouped by the part of the engine
@@ -27,6 +27,7 @@ declare const ErrorCodes: {
27
27
  readonly WORKER_CRASHED: "WORKER_CRASHED";
28
28
  readonly WORKER_BUSY: "WORKER_BUSY";
29
29
  readonly WORKER_TIMEOUT: "WORKER_TIMEOUT";
30
+ readonly WORKER_ACTION_FAILED: "WORKER_ACTION_FAILED";
30
31
  readonly PERSISTENCE_SAVE_FAILED: "PERSISTENCE_SAVE_FAILED";
31
32
  readonly PERSISTENCE_LOAD_FAILED: "PERSISTENCE_LOAD_FAILED";
32
33
  readonly PERSISTENCE_DELETE_FAILED: "PERSISTENCE_DELETE_FAILED";
@@ -140,13 +141,15 @@ declare const ServerErrorCodes: {
140
141
  */
141
142
  type ServerErrorCode = (typeof ServerErrorCodes)[keyof typeof ServerErrorCodes];
142
143
  /**
143
- * Every code the HTTP client raises when a request never reaches a server, or
144
- * when the client cannot read the answer.
144
+ * Every code that the caller's own side raises, where a request never reaches
145
+ * a server, or where the caller cannot read the answer.
145
146
  *
146
- * No server sends one of these, so a failure under one of them means the
147
- * exchange broke before the operation ran. `STATUS_BY_CODE` in
148
- * `src/server/errors.ts` therefore maps none of them, because no request can
149
- * arrive under one and no HTTP status belongs to one.
147
+ * The HTTP client raises the first five. The React bindings raise
148
+ * `CLIENT_UNEXPECTED_ERROR` alone, which reports a fault inside a hook. No
149
+ * server sends any of them, so a failure under one means the exchange broke
150
+ * before the operation ran. `STATUS_BY_CODE` in `src/server/errors.ts`
151
+ * therefore maps none of them, because no request can arrive under one and no
152
+ * HTTP status belongs to one.
150
153
  *
151
154
  * @public
152
155
  */
@@ -204,6 +207,22 @@ declare class NarsilError extends Error {
204
207
  */
205
208
  constructor(code: NarsilErrorCode, message: string, details?: Record<string, unknown>);
206
209
  }
210
+ /**
211
+ * Reports whether a caught value is a {@link NarsilError}, including one that
212
+ * another entry point of this package raises.
213
+ *
214
+ * Each browser bundle holds its own copy of the class, so an `instanceof` test
215
+ * inside the React bindings returns false for an error that the client raises,
216
+ * although that error still holds its code. This function tests for the marker
217
+ * that the constructor writes, so it returns true for an error from any entry
218
+ * point.
219
+ *
220
+ * @param value - The value that a `catch` block receives.
221
+ * @returns True where the value holds a code in {@link NarsilError.code}.
222
+ *
223
+ * @public
224
+ */
225
+ declare function isNarsilError(value: unknown): value is NarsilError;
207
226
 
208
227
  /**
209
228
  * What {@link Narsil.query} returns: the ranked hits and everything the query
@@ -283,7 +302,12 @@ interface Hit<T = AnyDocument> {
283
302
  * @public
284
303
  */
285
304
  interface ScoreComponents {
286
- /** Each query term appears in this document this often, keyed by term. */
305
+ /**
306
+ * Each query term appears in one field of this document this many times,
307
+ * under a key of `field:term`. A term that appears in two fields therefore
308
+ * has two entries here, while the keys of {@link ScoreComponents.idf} hold
309
+ * the bare term.
310
+ */
287
311
  termFrequencies: Record<string, number>;
288
312
  /** Each field the query searched holds this many tokens, keyed by field. */
289
313
  fieldLengths: Record<string, number>;
@@ -298,7 +322,13 @@ interface ScoreComponents {
298
322
  interface HighlightMatch {
299
323
  /** This is the field's text around the match, wrapped in the query's tags. */
300
324
  snippet: string;
301
- /** The match covers these character ranges in the original field, for rendering the highlight yourself. */
325
+ /**
326
+ * Each range gives the start and the end of one match in the original field,
327
+ * so you can render the highlight yourself. Where the snippet covers part of
328
+ * the field alone, the engine lists only the matches that the snippet
329
+ * displays. Every offset is a character count from the start of the original
330
+ * field, whatever the snippet contains.
331
+ */
302
332
  positions: Array<{
303
333
  start: number;
304
334
  end: number;
@@ -462,7 +492,12 @@ interface SuggestResult {
462
492
  interface VectorMaintenanceResult {
463
493
  /** This describes the named vector field. */
464
494
  fieldName: string;
465
- /** Tombstones make up this share of the graph's nodes, from 0 to 1. */
495
+ /**
496
+ * Tombstones make up this share of the graph's nodes, from 0 to 1. Before
497
+ * the first build, where {@link VectorMaintenanceResult.graphCount} reads 0,
498
+ * the engine divides by the number of stored vectors, because no graph
499
+ * exists yet.
500
+ */
466
501
  tombstoneRatio: number;
467
502
  /** The field holds this many HNSW graphs: 0 before the first build and 1 once a graph exists. */
468
503
  graphCount: number;
@@ -744,7 +779,12 @@ interface QueryParams {
744
779
  sort?: SortSpec;
745
780
  /** These settings collapse the hits into groups by field value. */
746
781
  group?: GroupConfig;
747
- /** The query returns this many hits, and 10 by default. */
782
+ /**
783
+ * The query returns this many hits, and 10 by default. Pass 0 to read the
784
+ * match count with no hits. The engine reads a value below 0 as 0. It falls
785
+ * back to the default for `NaN` and for an infinite value, so a page size
786
+ * that you compute from user input never fails the query.
787
+ */
748
788
  limit?: number;
749
789
  /** The query skips this many hits before returning. A deep offset costs more than a cursor. */
750
790
  offset?: number;
@@ -845,6 +885,16 @@ interface VectorQueryConfig {
845
885
  * value when omitted.
846
886
  */
847
887
  efSearch?: number;
888
+ /**
889
+ * How many times `limit` a quantized field re-scores against its
890
+ * full-precision vectors before it returns the best `limit`. A value below
891
+ * 1 or one that is not a finite number fails with `CONFIG_INVALID`. The
892
+ * engine ignores this on a field whose quantization is `none`. When a query
893
+ * omits it, the engine takes 3 for `osq1` and `osq2`, 2 for `osq8`, and 2
894
+ * for `osq4` at 1,024 dimensions and above, but 5 for `osq4` below 1,024,
895
+ * where a four-bit code ranks the true neighbours less reliably.
896
+ */
897
+ oversample?: number;
848
898
  }
849
899
  /**
850
900
  * How a hybrid query merges its keyword ranking with its vector ranking.
@@ -933,7 +983,12 @@ interface HighlightConfig {
933
983
  preTag?: string;
934
984
  /** This closes each match, and is `</mark>` by default. */
935
985
  postTag?: string;
936
- /** A snippet runs to this many characters before the engine trims it. */
986
+ /**
987
+ * The engine takes this many characters of the field around the densest run
988
+ * of matches, 200 by default. The snippet that comes back is longer than
989
+ * that number, because the engine then adds the opening and closing tags,
990
+ * and an ellipsis at each end where it cut the field.
991
+ */
937
992
  maxSnippetLength?: number;
938
993
  }
939
994
  /**
@@ -1073,4 +1128,4 @@ interface MemoryStats {
1073
1128
  }>;
1074
1129
  }
1075
1130
 
1076
- export { type ArrayFilter as A, type BatchResult as B, type ClientErrorCode as C, type DocumentProjection as D, type ErrorCode as E, type FacetConfig as F, type GeoFilter as G, type HighlightConfig as H, type IndexInfo as I, type ScoreComponents as J, type SearchMode as K, type ListParams as L, type MemoryStats as M, NarsilError as N, type SortField as O, type PartitionStatsResult as P, type QueryParams as Q, type SortSpec as R, type ServerErrorCode as S, type StringFilter as T, type TermMatchPolicy as U, type VectorMaintenanceResult as V, type VectorQueryConfig as W, type WorkerCopyReport as X, ClientErrorCodes as a, ErrorCodes as b, type NarsilErrorCode as c, ServerErrorCodes as d, type QueryResult as e, type IndexStats as f, type ListResult as g, type PreflightResult as h, type SuggestParams as i, type SuggestResult as j, type ComparisonFilter as k, type FacetResult as l, type FieldFilter as m, type FilterExpression as n, type GeoPolygonFilter as o, type GeoRadiusFilter as p, type GroupConfig as q, type GroupReducer as r, type GroupResult as s, type HighlightMatch as t, type Hit as u, type HybridConfig as v, type ListedDocument as w, type PresenceFilter as x, type ProcessMemoryReport as y, type QueryCoverage as z };
1131
+ export { type ArrayFilter as A, type BatchResult as B, type ClientErrorCode as C, type DocumentProjection as D, type ErrorCode as E, type FacetConfig as F, type GeoFilter as G, type HighlightConfig as H, type IndexInfo as I, type QueryCoverage as J, type ScoreComponents as K, type ListParams as L, type MemoryStats as M, NarsilError as N, type SearchMode as O, type PartitionStatsResult as P, type QueryParams as Q, type SortField as R, type ServerErrorCode as S, type SortSpec as T, type StringFilter as U, type VectorMaintenanceResult as V, type TermMatchPolicy as W, type VectorQueryConfig as X, type WorkerCopyReport as Y, ClientErrorCodes as a, ErrorCodes as b, type NarsilErrorCode as c, ServerErrorCodes as d, type QueryResult as e, type IndexStats as f, type ListResult as g, type PreflightResult as h, isNarsilError as i, type SuggestParams as j, type SuggestResult as k, type ComparisonFilter as l, type FacetResult as m, type FieldFilter as n, type FilterExpression as o, type GeoPolygonFilter as p, type GeoRadiusFilter as q, type GroupConfig as r, type GroupReducer as s, type GroupResult as t, type HighlightMatch as u, type Hit as v, type HybridConfig as w, type ListedDocument as x, type PresenceFilter as y, type ProcessMemoryReport as z };
@@ -1,4 +1,4 @@
1
- import { P as PartitionConfig, a as ScoringMode, V as VectorIndexConfig } from '../../schema-BqRx9t4E.js';
1
+ import { P as PartitionConfig, c as ScoringMode, V as VectorIndexConfig } from '../../schema-mLpXZBEh.js';
2
2
  import '../../adapters-79OIa4xm.js';
3
3
 
4
4
  interface IndexMetadata {
@@ -43,6 +43,119 @@ interface IndexEmbeddingMetadata {
43
43
  adapter?: string;
44
44
  fields: Record<string, string | string[]>;
45
45
  }
46
+ /**
47
+ * Persisted surface-form dictionary of one partition. Keys are the
48
+ * unstemmed display tokens; the value is the occurrence count when the
49
+ * surface equals its index token, or `[count, indexToken]` when stemming
50
+ * changed it.
51
+ */
52
+ type SerializedSurfaceForms = Record<string, number | [number, string]>;
53
+
54
+ interface SegmentPayload {
55
+ documentCount: number;
56
+ docIds: string[];
57
+ fieldNames: string[];
58
+ tokens: string[];
59
+ postingOffsets: Uint32Array;
60
+ postingDocIds: Uint32Array;
61
+ postingFrequencies: Uint16Array;
62
+ postingFieldIndices: Uint8Array;
63
+ positionOffsets: Uint32Array | null;
64
+ positionValues: Uint32Array | null;
65
+ fieldLengthNames: string[];
66
+ fieldLengthColumns: Uint32Array[];
67
+ totalFieldLengths: Record<string, number>;
68
+ docFrequencies: Record<string, number>;
69
+ surfaceForms: SerializedSurfaceForms | null;
70
+ numeric: Array<{
71
+ fieldPath: string;
72
+ docIds: Uint32Array;
73
+ values: Float64Array;
74
+ }>;
75
+ boolean: Array<{
76
+ fieldPath: string;
77
+ trueDocs: Uint32Array;
78
+ falseDocs: Uint32Array;
79
+ }>;
80
+ enums: Array<{
81
+ fieldPath: string;
82
+ values: string[];
83
+ offsets: Uint32Array;
84
+ docIds: Uint32Array;
85
+ }>;
86
+ geo: Array<{
87
+ fieldPath: string;
88
+ docIds: Uint32Array;
89
+ latitudes: Float64Array;
90
+ longitudes: Float64Array;
91
+ }>;
92
+ }
93
+
94
+ interface SegmentPostingColumns {
95
+ postingOffsets: Uint32Array;
96
+ postingDocIds: Uint32Array;
97
+ postingFrequencies: Uint16Array;
98
+ postingFieldIndices: Uint8Array;
99
+ positionOffsets: Uint32Array | null;
100
+ positionValues: Uint32Array | null;
101
+ }
102
+ interface SegmentColumns extends SegmentPostingColumns {
103
+ documentCount: number;
104
+ fieldNames: readonly string[];
105
+ fieldLengthNames: readonly string[];
106
+ fieldLengthColumns: readonly Uint32Array[];
107
+ totalFieldLengths: Readonly<Record<string, number>>;
108
+ numeric: SegmentPayload['numeric'];
109
+ boolean: SegmentPayload['boolean'];
110
+ enums: SegmentPayload['enums'];
111
+ geo: SegmentPayload['geo'];
112
+ surfaceForms: SerializedSurfaceForms | null;
113
+ }
114
+
115
+ interface EncodedDocumentTableData {
116
+ blob: Uint8Array;
117
+ offsets: Uint32Array;
118
+ }
119
+
120
+ interface ExternalIdTableData {
121
+ blob: Uint8Array;
122
+ offsets: Uint32Array;
123
+ sortedOrdinals: Uint32Array;
124
+ }
125
+
126
+ interface SurfaceTableData {
127
+ blob: Uint8Array;
128
+ offsets: Uint32Array;
129
+ counts: Uint32Array;
130
+ }
131
+
132
+ interface FrozenTokenTableData {
133
+ blob: Uint8Array;
134
+ offsets: Uint32Array;
135
+ payloadSlots: Uint32Array;
136
+ documentFrequencies: Uint32Array;
137
+ }
138
+
139
+ interface SharedSegmentSnapshot extends Omit<SegmentColumns, 'surfaceForms'> {
140
+ segmentId: string;
141
+ tokenTable: FrozenTokenTableData;
142
+ idTable: ExternalIdTableData;
143
+ documentTable: EncodedDocumentTableData;
144
+ /** The surface forms packed flat, or null where the segment holds none. */
145
+ surfaceTable: SurfaceTableData | null;
146
+ }
147
+
148
+ interface CapturedFrozenSegment {
149
+ snapshot: SharedSegmentSnapshot;
150
+ tombstonedDocIds: string[];
151
+ }
152
+ interface CapturedWholePartition {
153
+ partitionId: number;
154
+ totalPartitions: number;
155
+ docCount: number;
156
+ liveTail: Uint8Array | null;
157
+ frozen: CapturedFrozenSegment[];
158
+ }
46
159
 
47
160
  interface PartitionCheckpoint {
48
161
  partitionId: number;
@@ -50,20 +163,42 @@ interface PartitionCheckpoint {
50
163
  primaryTerm: number;
51
164
  }
52
165
 
166
+ interface SegmentRef {
167
+ id: number;
168
+ key: string;
169
+ docCount: number;
170
+ tombstoneCount: number;
171
+ }
172
+ interface PartitionManifestEntry {
173
+ partitionId: number;
174
+ nextSegmentId: number;
175
+ segments: SegmentRef[];
176
+ }
177
+
178
+ interface CheckpointSegmentsWritten {
179
+ checkpoint: PartitionCheckpoint[];
180
+ partitions: PartitionManifestEntry[];
181
+ }
182
+
53
183
  interface CheckpointWorkerRequest {
54
184
  root: string;
55
185
  metadata: IndexMetadata;
56
186
  targets: PartitionCheckpoint[];
57
187
  compactionThreshold: number;
188
+ capturedPartitions?: CapturedWholePartition[];
58
189
  }
59
190
  interface CheckpointWorkerSuccess {
60
191
  type: 'success';
192
+ segments: CheckpointSegmentsWritten;
61
193
  }
62
194
  interface CheckpointWorkerError {
63
195
  type: 'error';
64
196
  message: string;
65
197
  }
66
- type CheckpointWorkerMessage = CheckpointWorkerSuccess | CheckpointWorkerError;
198
+ interface CheckpointWorkerHeartbeat {
199
+ type: 'heartbeat';
200
+ }
201
+ type CheckpointWorkerMessage = CheckpointWorkerSuccess | CheckpointWorkerError | CheckpointWorkerHeartbeat;
67
202
  declare function handleRequest(raw: unknown): Promise<CheckpointWorkerSuccess>;
68
203
 
69
- export { type CheckpointWorkerError, type CheckpointWorkerMessage, type CheckpointWorkerRequest, type CheckpointWorkerSuccess, handleRequest };
204
+ export { type CheckpointWorkerError, type CheckpointWorkerHeartbeat, type CheckpointWorkerMessage, type CheckpointWorkerRequest, type CheckpointWorkerSuccess, handleRequest };
@@ -1,26 +1,27 @@
1
- import { createDurableDirectory, writeSegmentedCheckpoint } from '../../chunk-ND34I3SV.mjs';
2
- import '../../chunk-ZHUQKZBE.mjs';
1
+ import { CHECKPOINT_WORKER_HEARTBEAT_MS, createDurableDirectory, writeCheckpointSegments } from '../../chunk-BH5SYB5W.mjs';
3
2
  import '../../chunk-GCM3JFVA.mjs';
4
- import '../../chunk-PIWKZPP7.mjs';
5
- import '../../chunk-XE6XR2OE.mjs';
6
- import '../../chunk-BEIK3EOZ.mjs';
7
- import '../../chunk-CMVG2UEF.mjs';
3
+ import '../../chunk-4NVPQ6S5.mjs';
4
+ import '../../chunk-XNQAIO74.mjs';
8
5
  import '../../chunk-AV4IJKD2.mjs';
9
- import '../../chunk-CBLS46IE.mjs';
6
+ import '../../chunk-TVT5V4E7.mjs';
7
+ import '../../chunk-D2S642IV.mjs';
8
+ import '../../chunk-5T6AOR37.mjs';
9
+ import '../../chunk-L225SHNB.mjs';
10
10
  import '../../chunk-TGP5M5R7.mjs';
11
- import '../../chunk-PMBHH44R.mjs';
12
- import '../../chunk-X6YZO4MQ.mjs';
13
- import '../../chunk-RP23PWMV.mjs';
14
- import '../../chunk-KMMJMDUA.mjs';
11
+ import '../../chunk-U2AL3SON.mjs';
12
+ import '../../chunk-ZJ4CSAB2.mjs';
13
+ import '../../chunk-UTOFOJOR.mjs';
14
+ import '../../chunk-3L4U6EJQ.mjs';
15
+ import '../../chunk-IFBKLBGB.mjs';
15
16
  import '../../chunk-U2BKYEC7.mjs';
16
17
  import '../../chunk-2GWVQWGA.mjs';
17
- import '../../chunk-WYJXSLER.mjs';
18
- import '../../chunk-P4ELXVJQ.mjs';
18
+ import '../../chunk-POWOTUKJ.mjs';
19
+ import '../../chunk-FRQVMFY7.mjs';
19
20
 
20
21
  // src/persistence/durability/rebuild.ts
21
- async function rebuildSnapshotFromDurable(root, metadata, targets, compactionThreshold) {
22
+ async function rebuildSegmentsFromDurable(root, metadata, targets, compactionThreshold, capturedPartitions = []) {
22
23
  const directory = createDurableDirectory(root);
23
- await writeSegmentedCheckpoint({ directory, metadata, targets, compactionThreshold });
24
+ return writeCheckpointSegments({ directory, metadata, targets, compactionThreshold, capturedPartitions });
24
25
  }
25
26
 
26
27
  // src/persistence/durability/checkpoint-worker.ts
@@ -38,8 +39,17 @@ async function handleRequest(raw) {
38
39
  if (!Number.isInteger(request.compactionThreshold) || request.compactionThreshold <= 0) {
39
40
  throw new Error("Checkpoint request has an invalid compaction threshold");
40
41
  }
41
- await rebuildSnapshotFromDurable(request.root, request.metadata, request.targets, request.compactionThreshold);
42
- return { type: "success" };
42
+ if (request.capturedPartitions !== void 0 && !Array.isArray(request.capturedPartitions)) {
43
+ throw new Error("Checkpoint request names captured partitions in a shape the worker cannot read");
44
+ }
45
+ const segments = await rebuildSegmentsFromDurable(
46
+ request.root,
47
+ request.metadata,
48
+ request.targets,
49
+ request.compactionThreshold,
50
+ request.capturedPartitions
51
+ );
52
+ return { type: "success", segments };
43
53
  }
44
54
  async function setupAsync() {
45
55
  let parentPort = null;
@@ -54,10 +64,14 @@ async function setupAsync() {
54
64
  }
55
65
  const port = parentPort;
56
66
  port.on("message", (raw) => {
67
+ const heartbeat = setInterval(
68
+ () => port.postMessage({ type: "heartbeat" }),
69
+ CHECKPOINT_WORKER_HEARTBEAT_MS
70
+ );
57
71
  handleRequest(raw).then((result) => port.postMessage(result)).catch((err) => {
58
72
  const message = err instanceof Error ? err.message : String(err);
59
73
  port.postMessage({ type: "error", message });
60
- });
74
+ }).finally(() => clearInterval(heartbeat));
61
75
  });
62
76
  }
63
77
  function setupWorker() {
package/dist/react.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import { N as NarsilError, L as ListParams, g as ListResult, I as IndexInfo, f as IndexStats, Q as QueryParams, h as PreflightResult, e as QueryResult, i as SuggestParams, j as SuggestResult } from './memory-Bzd5xcEW.js';
2
- export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes } from './memory-Bzd5xcEW.js';
3
- import { e as TaskRecord, d as TaskProgress, b as ImportResult, c as TaskListQuery, T as TaskListPage } from './tasks-DT7L1p6w.js';
4
- export { I as ImportError, f as TaskStatus, g as TaskType } from './tasks-DT7L1p6w.js';
1
+ import { N as NarsilError, L as ListParams, g as ListResult, I as IndexInfo, f as IndexStats, Q as QueryParams, h as PreflightResult, e as QueryResult, j as SuggestParams, k as SuggestResult } from './memory-xrXOZMbw.js';
2
+ export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes, i as isNarsilError } from './memory-xrXOZMbw.js';
3
+ import { e as TaskRecord, d as TaskProgress, b as ImportResult, c as TaskListQuery, T as TaskListPage } from './tasks-Df73Tjgq.js';
4
+ export { I as ImportError, f as TaskStatus, g as TaskType } from './tasks-Df73Tjgq.js';
5
5
  import { ReactNode, ReactElement } from 'react';
6
- import { N as NarsilClient, I as ImportSource } from './client-B_X6_AbT.js';
7
- import { A as AnyDocument } from './schema-BqRx9t4E.js';
6
+ import { N as NarsilClient, I as ImportSource } from './client-CQUqt9Ir.js';
7
+ import { A as AnyDocument } from './schema-mLpXZBEh.js';
8
8
  import './adapters-79OIa4xm.js';
9
9
 
10
10
  /**
@@ -297,7 +297,7 @@ declare function useSuggest(indexName: string, params: SuggestParams, options?:
297
297
  *
298
298
  * @public
299
299
  */
300
- interface NarsilTaskOptions extends NarsilReadOptions {
300
+ interface NarsilTaskOptions extends Omit<NarsilReadOptions, 'refreshIntervalMs'> {
301
301
  /** The hook asks again this often while the task runs, and every 250 ms
302
302
  * unless you say otherwise, which is how often a running import writes its
303
303
  * progress. It stops once the task reaches a final status. */
@@ -306,10 +306,10 @@ interface NarsilTaskOptions extends NarsilReadOptions {
306
306
  /**
307
307
  * Follows one long-running operation, and stops asking once it finishes.
308
308
  *
309
- * The hook polls while the task is queued or running, pauses while the page is
310
- * hidden, and reads the figures once more as soon as the page comes back. A
311
- * failed task arrives as a record carrying its `error`, because a part-finished
312
- * import still reports what it indexed, so read the status you get.
309
+ * The hook polls while the task runs, pauses while the page is hidden, and
310
+ * reads the figures once more as soon as the page comes back. A failed task
311
+ * arrives as a record carrying its `error`, because a part-finished import
312
+ * still reports what it indexed, so read the status you get.
313
313
  *
314
314
  * @param taskId - This names the task to follow, and a nullish or empty id
315
315
  * switches the hook off.
package/dist/react.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createContext, useState, useEffect, createElement, useRef, useEffectEvent, useCallback, useMemo, useContext, useSyncExternalStore } from 'react';
2
2
 
3
3
  // src/errors.ts
4
+ var NARSIL_ERROR_MARKER = /* @__PURE__ */ Symbol.for("@delali/narsil.NarsilError");
4
5
  var ErrorCodes = {
5
6
  SCHEMA_INVALID_TYPE: "SCHEMA_INVALID_TYPE",
6
7
  SCHEMA_DEPTH_EXCEEDED: "SCHEMA_DEPTH_EXCEEDED",
@@ -18,6 +19,7 @@ var ErrorCodes = {
18
19
  WORKER_CRASHED: "WORKER_CRASHED",
19
20
  WORKER_BUSY: "WORKER_BUSY",
20
21
  WORKER_TIMEOUT: "WORKER_TIMEOUT",
22
+ WORKER_ACTION_FAILED: "WORKER_ACTION_FAILED",
21
23
  PERSISTENCE_SAVE_FAILED: "PERSISTENCE_SAVE_FAILED",
22
24
  PERSISTENCE_LOAD_FAILED: "PERSISTENCE_LOAD_FAILED",
23
25
  PERSISTENCE_DELETE_FAILED: "PERSISTENCE_DELETE_FAILED",
@@ -137,8 +139,12 @@ var NarsilError = class extends Error {
137
139
  this.name = "NarsilError";
138
140
  this.code = code;
139
141
  this.details = details ?? {};
142
+ Object.defineProperty(this, NARSIL_ERROR_MARKER, { value: true });
140
143
  }
141
144
  };
145
+ function isNarsilError(value) {
146
+ return typeof value === "object" && value !== null && NARSIL_ERROR_MARKER in value;
147
+ }
142
148
 
143
149
  // src/react/constants.ts
144
150
  var DEFAULT_KEEP_ALIVE_MS = 2e3;
@@ -148,7 +154,7 @@ var MAX_QUERY_KEY_DEPTH = 32;
148
154
 
149
155
  // src/react/failure.ts
150
156
  function asNarsilError(err, whatFailed) {
151
- if (err instanceof NarsilError) return err;
157
+ if (isNarsilError(err)) return err;
152
158
  const message = err instanceof Error ? err.message : String(err);
153
159
  return new NarsilError(ClientErrorCodes.CLIENT_UNEXPECTED_ERROR, `${whatFailed} failed unexpectedly: ${message}`);
154
160
  }
@@ -519,13 +525,19 @@ function useDocuments(indexName, params, options) {
519
525
  );
520
526
  }
521
527
 
528
+ // src/server/task-status.ts
529
+ var TERMINAL_TASK_STATUSES = /* @__PURE__ */ new Set(["succeeded", "failed", "cancelled"]);
530
+ function isTerminalTaskStatus(status) {
531
+ return TERMINAL_TASK_STATUSES.has(status);
532
+ }
533
+
522
534
  // src/react/task-state.ts
523
535
  function pollInterval(interval, failed) {
524
536
  return failed ? Math.max(interval, ERROR_RETRY_INTERVAL_MS) : interval;
525
537
  }
526
538
  function isTerminalTask(record) {
527
539
  if (record === null || record === void 0) return false;
528
- return record.status === "succeeded" || record.status === "failed" || record.status === "cancelled";
540
+ return isTerminalTaskStatus(record.status);
529
541
  }
530
542
 
531
543
  // src/react/import.ts
@@ -612,7 +624,7 @@ function useImport(indexName, options) {
612
624
  client.cancelTask(taskId, request.current).then((next) => {
613
625
  setProgress((prev) => prev.task?.id === taskId ? { task: next, error: void 0, starting: false } : prev);
614
626
  }).catch((err) => {
615
- if (err instanceof NarsilError && err.code === ServerErrorCodes.TASK_NOT_CANCELLABLE) return;
627
+ if (isNarsilError(err) && err.code === ServerErrorCodes.TASK_NOT_CANCELLABLE) return;
616
628
  setProgress((prev) => prev.task?.id === taskId ? { ...prev, error: asNarsilError(err, "The import") } : prev);
617
629
  });
618
630
  }, [client, taskId, running, progress.starting]);
@@ -686,4 +698,4 @@ function useTasks(query, options) {
686
698
  return useRead(["listTasks", query], (client, request) => client.listTasks(query, request), options);
687
699
  }
688
700
 
689
- export { ClientErrorCodes, ErrorCodes, NarsilError, NarsilProvider, ServerErrorCodes, useDocument, useDocuments, useImport, useIndexes, useNarsilClient, usePreflight, useQuery, useStats, useSuggest, useTask, useTasks };
701
+ export { ClientErrorCodes, ErrorCodes, NarsilError, NarsilProvider, ServerErrorCodes, isNarsilError, useDocument, useDocuments, useImport, useIndexes, useNarsilClient, usePreflight, useQuery, useStats, useSuggest, useTask, useTasks };