@delali/narsil 0.2.0 → 0.2.1

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 (151) hide show
  1. package/dist/adapters/filesystem.d.ts +23 -1
  2. package/dist/adapters/filesystem.mjs +1 -1
  3. package/dist/adapters/indexeddb.d.ts +25 -1
  4. package/dist/adapters/indexeddb.mjs +1 -1
  5. package/dist/adapters/memory.d.ts +14 -1
  6. package/dist/adapters-CVqI5NBt.d.ts +149 -0
  7. package/dist/{chunk-S6IAXOBA.mjs → chunk-ASI6AOW2.mjs} +1 -1
  8. package/dist/{chunk-AUMKFYTG.mjs → chunk-FKK76OR7.mjs} +56 -55
  9. package/dist/{chunk-M2EDG55Y.mjs → chunk-UNJZ7ZDB.mjs} +10 -0
  10. package/dist/{chunk-XAKNSWIK.mjs → chunk-WLR5BFL3.mjs} +16 -14
  11. package/dist/config-CAjTHzkH.d.ts +256 -0
  12. package/dist/{direct-executor-2FV3MEDD.mjs → direct-executor-3W4QRA4E.mjs} +2 -2
  13. package/dist/distribution/coordinator/etcd.d.ts +44 -3
  14. package/dist/distribution/coordinator/etcd.mjs +2 -2
  15. package/dist/distribution/coordinator/in-memory.d.ts +14 -3
  16. package/dist/distribution.d.ts +312 -45
  17. package/dist/distribution.mjs +4 -4
  18. package/dist/embeddings/openai.d.ts +28 -1
  19. package/dist/embeddings/openai.mjs +1 -1
  20. package/dist/engine-CCrlfLyq.d.ts +431 -0
  21. package/dist/index.browser.mjs +24 -12
  22. package/dist/index.d.ts +173 -8
  23. package/dist/index.mjs +3 -3
  24. package/dist/invalidation/broadcast-channel.d.ts +20 -1
  25. package/dist/invalidation/filesystem.d.ts +24 -1
  26. package/dist/invalidation/noop.d.ts +14 -1
  27. package/dist/language-DB8KG1z5.d.ts +53 -0
  28. package/dist/languages/albanian.d.ts +11 -1
  29. package/dist/languages/amharic.d.ts +11 -1
  30. package/dist/languages/arabic.d.ts +10 -1
  31. package/dist/languages/armenian.d.ts +10 -1
  32. package/dist/languages/azerbaijani.d.ts +11 -1
  33. package/dist/languages/bambara.d.ts +11 -1
  34. package/dist/languages/basque.d.ts +10 -1
  35. package/dist/languages/belarusian.d.ts +11 -1
  36. package/dist/languages/bengali.d.ts +11 -1
  37. package/dist/languages/bosnian.d.ts +11 -1
  38. package/dist/languages/breton.d.ts +11 -1
  39. package/dist/languages/bulgarian.d.ts +10 -1
  40. package/dist/languages/burmese.d.ts +11 -1
  41. package/dist/languages/catalan.d.ts +10 -1
  42. package/dist/languages/chinese.d.ts +11 -1
  43. package/dist/languages/croatian.d.ts +11 -1
  44. package/dist/languages/czech.d.ts +10 -1
  45. package/dist/languages/dagbani.d.ts +11 -1
  46. package/dist/languages/danish.d.ts +10 -1
  47. package/dist/languages/dutch.d.ts +10 -1
  48. package/dist/languages/english.d.ts +10 -1
  49. package/dist/languages/esperanto.d.ts +10 -1
  50. package/dist/languages/estonian.d.ts +10 -1
  51. package/dist/languages/ewe.d.ts +11 -1
  52. package/dist/languages/faroese.d.ts +11 -1
  53. package/dist/languages/fijian.d.ts +11 -1
  54. package/dist/languages/finnish.d.ts +10 -1
  55. package/dist/languages/french.d.ts +10 -1
  56. package/dist/languages/ga.d.ts +11 -1
  57. package/dist/languages/galician.d.ts +11 -1
  58. package/dist/languages/georgian.d.ts +11 -1
  59. package/dist/languages/german.d.ts +10 -1
  60. package/dist/languages/greek.d.ts +10 -1
  61. package/dist/languages/guarani.d.ts +11 -1
  62. package/dist/languages/gujarati.d.ts +11 -1
  63. package/dist/languages/haitian-creole.d.ts +11 -1
  64. package/dist/languages/hausa.d.ts +11 -1
  65. package/dist/languages/hawaiian.d.ts +11 -1
  66. package/dist/languages/hebrew.d.ts +11 -1
  67. package/dist/languages/hindi.d.ts +10 -1
  68. package/dist/languages/hungarian.d.ts +10 -1
  69. package/dist/languages/icelandic.d.ts +11 -1
  70. package/dist/languages/igbo.d.ts +11 -1
  71. package/dist/languages/indonesian.d.ts +10 -1
  72. package/dist/languages/irish.d.ts +10 -1
  73. package/dist/languages/italian.d.ts +10 -1
  74. package/dist/languages/japanese.d.ts +11 -1
  75. package/dist/languages/kannada.d.ts +11 -1
  76. package/dist/languages/kazakh.d.ts +11 -1
  77. package/dist/languages/khmer.d.ts +11 -1
  78. package/dist/languages/kinyarwanda.d.ts +11 -1
  79. package/dist/languages/kirundi.d.ts +11 -1
  80. package/dist/languages/korean.d.ts +11 -1
  81. package/dist/languages/kurmanji.d.ts +11 -1
  82. package/dist/languages/kyrgyz.d.ts +11 -1
  83. package/dist/languages/lao.d.ts +11 -1
  84. package/dist/languages/latin.d.ts +11 -1
  85. package/dist/languages/latvian.d.ts +11 -1
  86. package/dist/languages/lingala.d.ts +11 -1
  87. package/dist/languages/lithuanian.d.ts +10 -1
  88. package/dist/languages/luxembourgish.d.ts +11 -1
  89. package/dist/languages/macedonian.d.ts +11 -1
  90. package/dist/languages/malagasy.d.ts +11 -1
  91. package/dist/languages/malay.d.ts +11 -1
  92. package/dist/languages/malayalam.d.ts +11 -1
  93. package/dist/languages/maltese.d.ts +11 -1
  94. package/dist/languages/maori.d.ts +11 -1
  95. package/dist/languages/marathi.d.ts +11 -1
  96. package/dist/languages/nepali.d.ts +10 -1
  97. package/dist/languages/norwegian.d.ts +10 -1
  98. package/dist/languages/oromo.d.ts +11 -1
  99. package/dist/languages/persian.d.ts +10 -1
  100. package/dist/languages/polish.d.ts +10 -1
  101. package/dist/languages/portuguese.d.ts +10 -1
  102. package/dist/languages/punjabi.d.ts +11 -1
  103. package/dist/languages/romanian.d.ts +10 -1
  104. package/dist/languages/russian.d.ts +10 -1
  105. package/dist/languages/samoan.d.ts +11 -1
  106. package/dist/languages/sanskrit.d.ts +10 -1
  107. package/dist/languages/scottish-gaelic.d.ts +11 -1
  108. package/dist/languages/serbian.d.ts +10 -1
  109. package/dist/languages/shona.d.ts +11 -1
  110. package/dist/languages/sinhala.d.ts +11 -1
  111. package/dist/languages/slovak.d.ts +11 -1
  112. package/dist/languages/slovenian.d.ts +10 -1
  113. package/dist/languages/sorani.d.ts +11 -1
  114. package/dist/languages/spanish.d.ts +10 -1
  115. package/dist/languages/swahili.d.ts +10 -1
  116. package/dist/languages/swedish.d.ts +10 -1
  117. package/dist/languages/tagalog.d.ts +11 -1
  118. package/dist/languages/tamil.d.ts +10 -1
  119. package/dist/languages/tatar.d.ts +11 -1
  120. package/dist/languages/telugu.d.ts +11 -1
  121. package/dist/languages/thai.d.ts +11 -1
  122. package/dist/languages/tibetan.d.ts +11 -1
  123. package/dist/languages/tigrinya.d.ts +11 -1
  124. package/dist/languages/tongan.d.ts +11 -1
  125. package/dist/languages/turkish.d.ts +10 -1
  126. package/dist/languages/twi.d.ts +11 -1
  127. package/dist/languages/ukrainian.d.ts +10 -1
  128. package/dist/languages/urdu.d.ts +11 -1
  129. package/dist/languages/vietnamese.d.ts +11 -1
  130. package/dist/languages/welsh.d.ts +11 -1
  131. package/dist/languages/wolof.d.ts +11 -1
  132. package/dist/languages/xhosa.d.ts +11 -1
  133. package/dist/languages/yoruba.d.ts +11 -1
  134. package/dist/languages/zulu.d.ts +11 -1
  135. package/dist/persistence/durability/checkpoint-worker.d.ts +2 -2
  136. package/dist/persistence/durability/checkpoint-worker.mjs +3 -3
  137. package/dist/schema-CE6S_aAr.d.ts +208 -0
  138. package/dist/search-CgQQIciB.d.ts +786 -0
  139. package/dist/server.d.ts +213 -12
  140. package/dist/server.mjs +29 -1
  141. package/dist/types-BV3nAKTL.d.ts +302 -0
  142. package/dist/vector/hnsw-build-worker.d.ts +68 -2
  143. package/dist/vector/hnsw-build-worker.mjs +0 -2
  144. package/dist/workers/entry.mjs +1 -1
  145. package/package.json +5 -2
  146. package/dist/adapters-Bo2JQg8b.d.ts +0 -37
  147. package/dist/config-P27AtSn4.d.ts +0 -502
  148. package/dist/language-CmJBHf1j.d.ts +0 -17
  149. package/dist/narsil-CMZRPDlQ.d.ts +0 -159
  150. package/dist/schema-BnvLvjRp.d.ts +0 -67
  151. package/dist/types-BRTcBgAp.d.ts +0 -73
@@ -0,0 +1,786 @@
1
+ import { A as AnyDocument, b as SchemaDefinition, c as ScoringMode } from './schema-CE6S_aAr.js';
2
+
3
+ /**
4
+ * Every code a {@link NarsilError} carries, grouped by the part of the engine
5
+ * that raises it.
6
+ *
7
+ * Match on the code rather than on the message, because a code is stable and a
8
+ * message is not. The HTTP server maps each code to a status, so a code also
9
+ * tells you whether the caller or the engine is at fault.
10
+ *
11
+ * @public
12
+ */
13
+ declare const ErrorCodes: {
14
+ readonly SCHEMA_INVALID_TYPE: "SCHEMA_INVALID_TYPE";
15
+ readonly SCHEMA_MISSING_FIELD: "SCHEMA_MISSING_FIELD";
16
+ readonly SCHEMA_DEPTH_EXCEEDED: "SCHEMA_DEPTH_EXCEEDED";
17
+ readonly SCHEMA_INVALID_VECTOR_DIMENSION: "SCHEMA_INVALID_VECTOR_DIMENSION";
18
+ readonly SCHEMA_INVALID_GEOPOINT: "SCHEMA_INVALID_GEOPOINT";
19
+ readonly DOC_NOT_FOUND: "DOC_NOT_FOUND";
20
+ readonly DOC_ALREADY_EXISTS: "DOC_ALREADY_EXISTS";
21
+ readonly DOC_VALIDATION_FAILED: "DOC_VALIDATION_FAILED";
22
+ readonly INDEX_NOT_FOUND: "INDEX_NOT_FOUND";
23
+ readonly INDEX_ALREADY_EXISTS: "INDEX_ALREADY_EXISTS";
24
+ readonly PARTITION_CORRUPTED: "PARTITION_CORRUPTED";
25
+ readonly PARTITION_REBALANCING_BACKPRESSURE: "PARTITION_REBALANCING_BACKPRESSURE";
26
+ readonly WORKER_CRASHED: "WORKER_CRASHED";
27
+ readonly WORKER_BUSY: "WORKER_BUSY";
28
+ readonly WORKER_TIMEOUT: "WORKER_TIMEOUT";
29
+ readonly PERSISTENCE_SAVE_FAILED: "PERSISTENCE_SAVE_FAILED";
30
+ readonly PERSISTENCE_LOAD_FAILED: "PERSISTENCE_LOAD_FAILED";
31
+ readonly PERSISTENCE_DELETE_FAILED: "PERSISTENCE_DELETE_FAILED";
32
+ readonly PERSISTENCE_CRC_MISMATCH: "PERSISTENCE_CRC_MISMATCH";
33
+ readonly PERSISTENCE_WAL_CORRUPT: "PERSISTENCE_WAL_CORRUPT";
34
+ readonly PERSISTENCE_FSYNC_FAILED: "PERSISTENCE_FSYNC_FAILED";
35
+ readonly SEARCH_INVALID_FIELD: "SEARCH_INVALID_FIELD";
36
+ readonly SEARCH_INVALID_VECTOR_SIZE: "SEARCH_INVALID_VECTOR_SIZE";
37
+ readonly VECTOR_DIMENSION_MISMATCH: "VECTOR_DIMENSION_MISMATCH";
38
+ readonly SEARCH_INVALID_FILTER: "SEARCH_INVALID_FILTER";
39
+ readonly SEARCH_INVALID_MODE: "SEARCH_INVALID_MODE";
40
+ readonly SEARCH_INVALID_CURSOR: "SEARCH_INVALID_CURSOR";
41
+ readonly LANGUAGE_NOT_SUPPORTED: "LANGUAGE_NOT_SUPPORTED";
42
+ readonly ENVELOPE_VERSION_MISMATCH: "ENVELOPE_VERSION_MISMATCH";
43
+ readonly ENVELOPE_INVALID_MAGIC: "ENVELOPE_INVALID_MAGIC";
44
+ readonly PARTITION_CAPACITY_EXCEEDED: "PARTITION_CAPACITY_EXCEEDED";
45
+ readonly EMBEDDING_FAILED: "EMBEDDING_FAILED";
46
+ readonly EMBEDDING_DIMENSION_MISMATCH: "EMBEDDING_DIMENSION_MISMATCH";
47
+ readonly EMBEDDING_NO_SOURCE: "EMBEDDING_NO_SOURCE";
48
+ readonly EMBEDDING_CONFIG_INVALID: "EMBEDDING_CONFIG_INVALID";
49
+ readonly DOC_MISSING_REQUIRED_FIELD: "DOC_MISSING_REQUIRED_FIELD";
50
+ readonly CONFIG_INVALID: "CONFIG_INVALID";
51
+ readonly QUERY_ROUTING_FAILED: "QUERY_ROUTING_FAILED";
52
+ readonly QUERY_PARTIAL_FAILURE: "QUERY_PARTIAL_FAILURE";
53
+ readonly QUERY_NODE_TIMEOUT: "QUERY_NODE_TIMEOUT";
54
+ readonly QUERY_NO_ACTIVE_REPLICA: "QUERY_NO_ACTIVE_REPLICA";
55
+ readonly ALLOCATION_NO_DATA_NODES: "ALLOCATION_NO_DATA_NODES";
56
+ readonly ALLOCATION_INVALID_CONFIG: "ALLOCATION_INVALID_CONFIG";
57
+ readonly ALLOCATION_FAILED: "ALLOCATION_FAILED";
58
+ readonly CONTROLLER_LEASE_LOST: "CONTROLLER_LEASE_LOST";
59
+ readonly CONTROLLER_NOT_ACTIVE: "CONTROLLER_NOT_ACTIVE";
60
+ readonly CONTROLLER_METADATA_INVALID: "CONTROLLER_METADATA_INVALID";
61
+ readonly NODE_BOOTSTRAP_FAILED: "NODE_BOOTSTRAP_FAILED";
62
+ readonly NODE_ALREADY_JOINED: "NODE_ALREADY_JOINED";
63
+ readonly NODE_NOT_JOINED: "NODE_NOT_JOINED";
64
+ readonly COORDINATOR_DEPENDENCY_MISSING: "COORDINATOR_DEPENDENCY_MISSING";
65
+ readonly REPLICATION_ENTRY_INVALID: "REPLICATION_ENTRY_INVALID";
66
+ readonly REPLICATION_INSYNC_REMOVAL_FAILED: "REPLICATION_INSYNC_REMOVAL_FAILED";
67
+ readonly REPLICATION_ROLLBACK_FAILED: "REPLICATION_ROLLBACK_FAILED";
68
+ readonly REPLICATION_LOG_FULL: "REPLICATION_LOG_FULL";
69
+ readonly REPLICATION_ENTRY_CORRUPT: "REPLICATION_ENTRY_CORRUPT";
70
+ readonly REPLICATION_SNAPSHOT_CORRUPT: "REPLICATION_SNAPSHOT_CORRUPT";
71
+ readonly REPLICATION_TERM_MISMATCH: "REPLICATION_TERM_MISMATCH";
72
+ readonly REPLICATION_SYNC_FAILED: "REPLICATION_SYNC_FAILED";
73
+ readonly PARTITION_NOT_PRIMARY: "PARTITION_NOT_PRIMARY";
74
+ readonly PARTITION_UNASSIGNED: "PARTITION_UNASSIGNED";
75
+ readonly INSUFFICIENT_REPLICAS: "INSUFFICIENT_REPLICAS";
76
+ readonly SNAPSHOT_SYNC_UNAUTHORIZED: "SNAPSHOT_SYNC_UNAUTHORIZED";
77
+ readonly SNAPSHOT_SYNC_REQUEST_INVALID: "SNAPSHOT_SYNC_REQUEST_INVALID";
78
+ readonly SNAPSHOT_SYNC_INDEX_NOT_FOUND: "SNAPSHOT_SYNC_INDEX_NOT_FOUND";
79
+ readonly SNAPSHOT_SYNC_TOO_LARGE: "SNAPSHOT_SYNC_TOO_LARGE";
80
+ readonly SNAPSHOT_SYNC_CAPACITY_EXHAUSTED: "SNAPSHOT_SYNC_CAPACITY_EXHAUSTED";
81
+ readonly SNAPSHOT_SYNC_SNAPSHOT_FAILED: "SNAPSHOT_SYNC_SNAPSHOT_FAILED";
82
+ readonly SNAPSHOT_SYNC_DECODE_FAILED: "SNAPSHOT_SYNC_DECODE_FAILED";
83
+ readonly SNAPSHOT_SYNC_FRAME_INVALID: "SNAPSHOT_SYNC_FRAME_INVALID";
84
+ readonly SNAPSHOT_SYNC_HEADER_INVALID: "SNAPSHOT_SYNC_HEADER_INVALID";
85
+ readonly SNAPSHOT_SYNC_HEADER_MISMATCH: "SNAPSHOT_SYNC_HEADER_MISMATCH";
86
+ readonly SNAPSHOT_SYNC_CHUNK_OUT_OF_ORDER: "SNAPSHOT_SYNC_CHUNK_OUT_OF_ORDER";
87
+ readonly SNAPSHOT_SYNC_CHUNK_OVERFLOW: "SNAPSHOT_SYNC_CHUNK_OVERFLOW";
88
+ readonly SNAPSHOT_SYNC_CHUNK_SIZE_EXCEEDED: "SNAPSHOT_SYNC_CHUNK_SIZE_EXCEEDED";
89
+ readonly SNAPSHOT_SYNC_CHUNK_MISSING: "SNAPSHOT_SYNC_CHUNK_MISSING";
90
+ readonly SNAPSHOT_SYNC_END_MISSING: "SNAPSHOT_SYNC_END_MISSING";
91
+ readonly SNAPSHOT_SYNC_CHECKSUM_MISMATCH: "SNAPSHOT_SYNC_CHECKSUM_MISMATCH";
92
+ readonly SNAPSHOT_SYNC_PRIMARY_ERROR: "SNAPSHOT_SYNC_PRIMARY_ERROR";
93
+ readonly SNAPSHOT_SYNC_NO_TARGETS: "SNAPSHOT_SYNC_NO_TARGETS";
94
+ readonly SNAPSHOT_SYNC_TRANSPORT_FAILED: "SNAPSHOT_SYNC_TRANSPORT_FAILED";
95
+ readonly SNAPSHOT_SYNC_SCHEMA_UNAVAILABLE: "SNAPSHOT_SYNC_SCHEMA_UNAVAILABLE";
96
+ readonly SNAPSHOT_SYNC_RESTORE_FAILED: "SNAPSHOT_SYNC_RESTORE_FAILED";
97
+ readonly SNAPSHOT_SYNC_RESTORE_CLEANUP_FAILED: "SNAPSHOT_SYNC_RESTORE_CLEANUP_FAILED";
98
+ readonly SNAPSHOT_SYNC_TIMEOUT: "SNAPSHOT_SYNC_TIMEOUT";
99
+ readonly SNAPSHOT_SYNC_ALLOCATION_UNAVAILABLE: "SNAPSHOT_SYNC_ALLOCATION_UNAVAILABLE";
100
+ readonly SNAPSHOT_SYNC_NOT_ASSIGNED: "SNAPSHOT_SYNC_NOT_ASSIGNED";
101
+ readonly SNAPSHOT_SYNC_ABORTED: "SNAPSHOT_SYNC_ABORTED";
102
+ };
103
+ /**
104
+ * Any one of the codes in {@link ErrorCodes}, which is the type to narrow on
105
+ * when you branch on a failure.
106
+ *
107
+ * @public
108
+ */
109
+ type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
110
+ /**
111
+ * The error every part of the engine throws.
112
+ *
113
+ * Catch it, read {@link NarsilError.code} to decide what to do, and read
114
+ * {@link NarsilError.details} for the values that caused it. The engine lets
115
+ * this error propagate unchanged, so the code you catch is the code the
116
+ * failing operation raised.
117
+ *
118
+ * @public
119
+ */
120
+ declare class NarsilError extends Error {
121
+ /** This says which failure it is. */
122
+ readonly code: ErrorCode;
123
+ /** This carries the values behind the failure, such as the field, index, or limit involved. It is empty when the code says everything. */
124
+ readonly details: Record<string, unknown>;
125
+ /**
126
+ * Builds an error carrying a code the caller can branch on.
127
+ *
128
+ * @param code - The failure this error reports.
129
+ * @param message - Plain description, for a log or a person.
130
+ * @param details - Values behind the failure, which reach
131
+ * {@link NarsilError.details}.
132
+ */
133
+ constructor(code: ErrorCode, message: string, details?: Record<string, unknown>);
134
+ }
135
+
136
+ /**
137
+ * What {@link Narsil.query} returns: the ranked hits and everything the query
138
+ * asked for alongside them.
139
+ *
140
+ * @typeParam T - Shape of the stored documents, which flows through to each
141
+ * hit's `document`.
142
+ *
143
+ * @public
144
+ */
145
+ interface QueryResult<T = AnyDocument> {
146
+ /** These documents matched, best score first, cut to the query's `limit`. */
147
+ hits: Array<Hit<T>>;
148
+ /** This many documents matched in total, before `limit` and `offset` applied. */
149
+ count: number;
150
+ /** The engine spent this many milliseconds on the search. */
151
+ elapsed: number;
152
+ /** This opaque cursor reaches the next page. Pass it back as `searchAfter`. */
153
+ cursor?: string;
154
+ /** These facet counts are keyed by the field each facet was asked for. */
155
+ facets?: Record<string, FacetResult>;
156
+ /** These groups arrive when the query asked for grouping. */
157
+ groups?: GroupResult[];
158
+ /** This turns true when the index's terms came from an older analysis than its language module produces now. */
159
+ analysisStale?: boolean;
160
+ }
161
+ /**
162
+ * One matching document, with the score that ranked it.
163
+ *
164
+ * @typeParam T - Shape of the stored document.
165
+ *
166
+ * @public
167
+ */
168
+ interface Hit<T = AnyDocument> {
169
+ /** The document is stored under this id. */
170
+ id: string;
171
+ /** This score ranked the hit. Scores compare within one result set, never across searches. */
172
+ score: number;
173
+ /** This is the stored document. */
174
+ document: T;
175
+ /** These are the parts the score was built from, which arrive when the query asked for them. */
176
+ scoreComponents?: ScoreComponents;
177
+ /** These highlighted snippets are keyed by field, and arrive when the query asked for highlighting. */
178
+ highlights?: Record<string, HighlightMatch>;
179
+ }
180
+ /**
181
+ * The numbers BM25 combined into one hit's score, which is what you read when
182
+ * a ranking surprises you.
183
+ *
184
+ * @public
185
+ */
186
+ interface ScoreComponents {
187
+ /** Each query term appears in this document this often, keyed by term. */
188
+ termFrequencies: Record<string, number>;
189
+ /** Each field the query searched holds this many tokens, keyed by field. */
190
+ fieldLengths: Record<string, number>;
191
+ /** Each query term carries this inverse document frequency, which is what makes a rare term count for more. */
192
+ idf: Record<string, number>;
193
+ }
194
+ /**
195
+ * A highlighted field, ready to render.
196
+ *
197
+ * @public
198
+ */
199
+ interface HighlightMatch {
200
+ /** This is the field's text around the match, wrapped in the query's tags. */
201
+ snippet: string;
202
+ /** The match covers these character ranges in the original field, for rendering the highlight yourself. */
203
+ positions: Array<{
204
+ start: number;
205
+ end: number;
206
+ }>;
207
+ }
208
+ /**
209
+ * Counts for one faceted field.
210
+ *
211
+ * @public
212
+ */
213
+ interface FacetResult {
214
+ /** This many documents matched per value, keyed by value. */
215
+ values: Record<string, number>;
216
+ /** The field held this many distinct values across the matching documents. */
217
+ count: number;
218
+ }
219
+ /**
220
+ * One group of hits, produced by a query that grouped its results.
221
+ *
222
+ * @public
223
+ */
224
+ interface GroupResult {
225
+ /** Each grouping field holds this value for the group, keyed by field. */
226
+ values: Record<string, unknown>;
227
+ /** These hits fall in the group, cut to the query's `maxPerGroup`. */
228
+ hits: Array<Hit>;
229
+ }
230
+ /**
231
+ * What {@link Narsil.preflight} returns: how many documents a query matches,
232
+ * without building or ranking a single hit.
233
+ *
234
+ * @public
235
+ */
236
+ interface PreflightResult {
237
+ /** The query matches this many documents. */
238
+ count: number;
239
+ /** The count took this many milliseconds. */
240
+ elapsed: number;
241
+ /** This turns true when the index's terms came from an older analysis than its language module produces now. */
242
+ analysisStale?: boolean;
243
+ }
244
+ /**
245
+ * What a batch write returns. One bad document never abandons the rest, so
246
+ * read both lists.
247
+ *
248
+ * @public
249
+ */
250
+ interface BatchResult {
251
+ /** The engine wrote the documents under these ids. */
252
+ succeeded: string[];
253
+ /** The engine rejected each of these documents, and each entry carries the error that rejected it. */
254
+ failed: Array<{
255
+ docId: string;
256
+ error: NarsilError;
257
+ }>;
258
+ }
259
+ /**
260
+ * What {@link Narsil.getStats} returns about one index.
261
+ *
262
+ * @public
263
+ */
264
+ interface IndexStats {
265
+ /** The index holds this many documents. */
266
+ documentCount: number;
267
+ /** The index is spread across this many partitions. */
268
+ partitionCount: number;
269
+ /**
270
+ * Formula-based estimate of the index's main-thread memory footprint, summed
271
+ * across every partition and vector index for this index. Computed from
272
+ * structural counters (document count, posting counts, field-index sizes),
273
+ * not measured. Per-object V8 overhead (hidden classes, map transitions,
274
+ * GC headers) is not captured here, so this number routinely undershoots
275
+ * the real heap by a meaningful factor. Use {@link Narsil.getMemoryStats}
276
+ * when sizing host memory.
277
+ */
278
+ estimatedMemoryBytes: number;
279
+ /** The index analyses text with this language module. */
280
+ language: string;
281
+ /** The index was created with this field layout. */
282
+ schema: SchemaDefinition;
283
+ }
284
+ /**
285
+ * A summary of one index, as {@link Narsil.listIndexes} reports it.
286
+ *
287
+ * @public
288
+ */
289
+ interface IndexInfo {
290
+ /** The index was created under this name. */
291
+ name: string;
292
+ /** The index holds this many documents. */
293
+ documentCount: number;
294
+ /** The index is spread across this many partitions. */
295
+ partitionCount: number;
296
+ /** The index analyses text with this language module. */
297
+ language: string;
298
+ /** This turns true when the index's terms came from an older analysis than its language module produces now. */
299
+ analysisStale?: boolean;
300
+ }
301
+ /**
302
+ * What {@link Narsil.getPartitionStats} reports for one partition, which is
303
+ * where you look when an index grows unevenly.
304
+ *
305
+ * @public
306
+ */
307
+ interface PartitionStatsResult {
308
+ /** This identifies the partition within its index. */
309
+ partitionId: number;
310
+ /** The partition holds this many documents. */
311
+ documentCount: number;
312
+ /**
313
+ * Formula-based estimate of this partition's memory footprint. V8 has no
314
+ * per-object heap accounting API, so this number is derived from structural
315
+ * counters (document count, posting counts, field-index sizes) and does not
316
+ * include per-object overhead. Treat as an estimate, not a measurement.
317
+ */
318
+ estimatedMemoryBytes: number;
319
+ }
320
+ /**
321
+ * What {@link Narsil.suggest} returns: the indexed terms that complete a
322
+ * prefix, ready to offer as you-type suggestions.
323
+ *
324
+ * @public
325
+ */
326
+ interface SuggestResult {
327
+ /** These completions run most widely used first. */
328
+ terms: Array<{
329
+ /** This is the completed term, as the index holds it. */
330
+ term: string;
331
+ /** The term appears in this many documents, which is what ordered the list. */
332
+ documentFrequency: number;
333
+ }>;
334
+ /** The lookup took this many milliseconds. */
335
+ elapsed: number;
336
+ /** This turns true when the index's terms came from an older analysis than its language module produces now. */
337
+ analysisStale?: boolean;
338
+ }
339
+ /**
340
+ * Snapshot of V8 heap usage as reported by `process.memoryUsage()`. All values
341
+ * are bytes. `null` in environments that do not expose `process.memoryUsage`,
342
+ * such as browsers.
343
+ *
344
+ * @public
345
+ */
346
+ interface ProcessMemoryReport {
347
+ /** The process is using this much heap. */
348
+ heapUsed: number;
349
+ /** V8 has reserved this much heap. */
350
+ heapTotal: number;
351
+ /** The process holds this much outside the heap, such as buffers. */
352
+ external: number;
353
+ /** The process occupies this much physical memory in total. */
354
+ rss: number;
355
+ }
356
+ /**
357
+ * What {@link Narsil.getMemoryStats} returns, which is what you size a host
358
+ * from.
359
+ *
360
+ * @public
361
+ */
362
+ interface MemoryStats {
363
+ /**
364
+ * V8 heap usage for the host process at the moment the call was made. This
365
+ * is process-wide, not engine-wide; if multiple Narsil engines are running
366
+ * in the same process every engine's `getMemoryStats` returns the same
367
+ * `process` figures. `null` in browsers and any runtime where
368
+ * `process.memoryUsage` is unavailable.
369
+ */
370
+ process: ProcessMemoryReport | null;
371
+ /**
372
+ * Sum of every index's {@link IndexStats.estimatedMemoryBytes} held by this
373
+ * engine. Formula-based; treat as an estimate, not a measurement. Useful
374
+ * for cross-engine relative comparisons inside a single process where
375
+ * `process.heapUsed` cannot tell engines apart.
376
+ */
377
+ estimatedIndexBytes: number;
378
+ /**
379
+ * Per-worker V8 heap usage when the engine has been promoted to a worker
380
+ * pool. Empty when no workers are active.
381
+ */
382
+ workers: Array<{
383
+ /** This identifies the worker within the pool. */
384
+ workerId: number;
385
+ /** That worker is using this much heap. */
386
+ heapUsed: number;
387
+ /** V8 has reserved this much heap in that worker. */
388
+ heapTotal: number;
389
+ /** That worker holds this much outside its heap. */
390
+ external: number;
391
+ }>;
392
+ }
393
+ /**
394
+ * The state of one vector field, and what maintenance would cost, as
395
+ * {@link Narsil.vectorMaintenanceStatus} reports it.
396
+ *
397
+ * Removing a vector leaves a tombstone in the graph, and enough of them slow a
398
+ * search down. Read this to decide when compaction earns its cost.
399
+ *
400
+ * @public
401
+ */
402
+ interface VectorMaintenanceResult {
403
+ /** This describes the named vector field. */
404
+ fieldName: string;
405
+ /** Tombstones make up this share of the graph's nodes, from 0 to 1. */
406
+ tombstoneRatio: number;
407
+ /** The field's HNSW graph holds this many vectors. */
408
+ graphCount: number;
409
+ /** This many vectors wait outside the graph, which a search scans one by one. */
410
+ bufferSize: number;
411
+ /** This stays true while a graph build runs. */
412
+ building: boolean;
413
+ /** {@link Narsil.compactVectors} would take about this many milliseconds. */
414
+ estimatedCompactMs: number;
415
+ /** {@link Narsil.optimizeVectors} would take about this many milliseconds. */
416
+ estimatedOptimizeMs: number;
417
+ }
418
+
419
+ /**
420
+ * Compares one field against a value. Setting several keys narrows the match,
421
+ * because a document has to satisfy all of them.
422
+ *
423
+ * @public
424
+ */
425
+ type ComparisonFilter = {
426
+ /** This matches a field equal to the value. */
427
+ eq?: number | string | boolean;
428
+ /** This matches a field holding anything other than the value. */
429
+ ne?: number | string | boolean;
430
+ /** This matches a field greater than the number. */
431
+ gt?: number;
432
+ /** This matches a field less than the number. */
433
+ lt?: number;
434
+ /** This matches a field greater than or equal to the number. */
435
+ gte?: number;
436
+ /** This matches a field less than or equal to the number. */
437
+ lte?: number;
438
+ /** This matches a field inside the inclusive range, given as `[low, high]`. */
439
+ between?: [number, number];
440
+ };
441
+ /**
442
+ * Everything {@link ComparisonFilter} offers, with the set and prefix tests a
443
+ * string field also supports.
444
+ *
445
+ * @public
446
+ */
447
+ type StringFilter = ComparisonFilter & {
448
+ /** This matches a field equal to any value in the list. */
449
+ in?: string[];
450
+ /** This matches a field equal to none of the values in the list. */
451
+ nin?: string[];
452
+ /** This matches a field starting with the text. */
453
+ startsWith?: string;
454
+ /** This matches a field ending with the text. */
455
+ endsWith?: string;
456
+ };
457
+ /**
458
+ * Tests the contents of an array field.
459
+ *
460
+ * @public
461
+ */
462
+ type ArrayFilter = {
463
+ /** This matches an array holding every one of the values. */
464
+ containsAll?: (string | number | boolean)[];
465
+ /** This matches an array holding at least one of the values. */
466
+ matchesAny?: (string | number | boolean)[];
467
+ /** This compares the array's length. */
468
+ size?: ComparisonFilter;
469
+ };
470
+ /**
471
+ * Tests whether a field carries a value at all, without looking at what it
472
+ * holds.
473
+ *
474
+ * @public
475
+ */
476
+ type PresenceFilter = {
477
+ /** This matches a document where the field is present. */
478
+ exists?: boolean;
479
+ /** This matches a document where the field is absent. */
480
+ notExists?: boolean;
481
+ /** This matches an empty string or an empty array. */
482
+ isEmpty?: boolean;
483
+ /** This matches a string or array holding something. */
484
+ isNotEmpty?: boolean;
485
+ };
486
+ /**
487
+ * Matches a `geopoint` field against a circle drawn on the earth.
488
+ *
489
+ * @public
490
+ */
491
+ type GeoRadiusFilter = {
492
+ /** The filter tests the field against this circle. */
493
+ radius: {
494
+ /** The centre has this latitude, in degrees. */
495
+ lat: number;
496
+ /** The centre has this longitude, in degrees. */
497
+ lon: number;
498
+ /** The circle reaches this far, measured in `unit`. */
499
+ distance: number;
500
+ /** `distance` is given in kilometres, miles, or metres. */
501
+ unit: 'km' | 'mi' | 'm';
502
+ /** This keeps the points inside the circle. Set it to false to keep the points outside. It is true by default. */
503
+ inside?: boolean;
504
+ /** Setting this measures along the earth's curve instead of a flat approximation, which costs time and gains accuracy over long distances. */
505
+ highPrecision?: boolean;
506
+ };
507
+ };
508
+ /**
509
+ * Matches a `geopoint` field against a polygon drawn on the earth.
510
+ *
511
+ * @public
512
+ */
513
+ type GeoPolygonFilter = {
514
+ /** The filter tests the field against this polygon. */
515
+ polygon: {
516
+ /** These corners run in order. The engine closes the ring, so repeating the first point is unnecessary. */
517
+ points: Array<{
518
+ lat: number;
519
+ lon: number;
520
+ }>;
521
+ /** This keeps the points inside the polygon. Set it to false to keep the points outside. It is true by default. */
522
+ inside?: boolean;
523
+ };
524
+ };
525
+ /**
526
+ * Either shape a `geopoint` field is matched against.
527
+ *
528
+ * @public
529
+ */
530
+ type GeoFilter = GeoRadiusFilter | GeoPolygonFilter;
531
+ /**
532
+ * The filter one field accepts. Which of these forms applies follows from the
533
+ * field's declared type.
534
+ *
535
+ * @public
536
+ */
537
+ type FieldFilter = ComparisonFilter | StringFilter | ArrayFilter | PresenceFilter | GeoFilter;
538
+ /**
539
+ * The filter a query runs, built from per-field tests and the boolean
540
+ * operators that combine them.
541
+ *
542
+ * Nest the operators to whatever depth the query needs. The engine applies the
543
+ * filter before scoring, so a narrow filter makes a search cheaper.
544
+ *
545
+ * @public
546
+ */
547
+ type FilterExpression = {
548
+ /** These per-field tests are keyed by field name, and a document has to satisfy every entry. */
549
+ fields?: Record<string, FieldFilter>;
550
+ /** Every nested expression has to match. */
551
+ and?: FilterExpression[];
552
+ /** At least one nested expression has to match. */
553
+ or?: FilterExpression[];
554
+ /** The nested expression has to fail. */
555
+ not?: FilterExpression;
556
+ };
557
+
558
+ /**
559
+ * Which engine answers a query: keyword matching, vector similarity, or both
560
+ * merged into one ranking.
561
+ *
562
+ * @public
563
+ */
564
+ type SearchMode = 'fulltext' | 'vector' | 'hybrid';
565
+ /**
566
+ * How many of a query's terms a document has to carry. `all` demands every
567
+ * term, `any` accepts one, and a number demands that many.
568
+ *
569
+ * @public
570
+ */
571
+ type TermMatchPolicy = 'all' | 'any' | number;
572
+ /**
573
+ * Everything {@link Narsil.query} accepts.
574
+ *
575
+ * Every field is optional, so a query with nothing set returns the first page
576
+ * of the index. Set `term` for keyword search, `vector` for similarity
577
+ * search, and `mode` when you want both.
578
+ *
579
+ * @public
580
+ */
581
+ interface QueryParams {
582
+ /** The engine searches for this text, analysed with the index's own language module. */
583
+ term?: string;
584
+ /** The engine searches the term in these fields, and in every text field in the schema by default. */
585
+ fields?: string[];
586
+ /** This narrows the candidates before scoring. */
587
+ filters?: FilterExpression;
588
+ /** These multipliers raise or lower each field's contribution to the score, keyed by field. */
589
+ boost?: Record<string, number>;
590
+ /** The query gathers term statistics this way, and follows the index's `defaultScoring` otherwise. */
591
+ scoring?: ScoringMode;
592
+ /** The engine drops any hit scoring below this value. */
593
+ minScore?: number;
594
+ /** A document has to carry this many query terms. The engine accepts one by default. */
595
+ termMatch?: TermMatchPolicy;
596
+ /** A term may differ by this edit distance and still match, which is how a typo still finds its document. */
597
+ tolerance?: number;
598
+ /** This many leading characters have to match exactly before `tolerance` applies, which keeps fuzzy matching honest. */
599
+ prefixLength?: number;
600
+ /**
601
+ * Treat the last query token as an unfinished word so it also matches
602
+ * indexed terms that complete it ('secur' matches 'security'). Earlier
603
+ * tokens must match fully; `tolerance` keeps applying to them but not to
604
+ * the prefix token. Completions score against a shared document frequency
605
+ * and are demoted below full-word matches. Ignored when `exact` is true.
606
+ * Off by default.
607
+ */
608
+ prefix?: boolean;
609
+ /** Setting this matches the term as written, skipping stemming and fuzzy matching. */
610
+ exact?: boolean;
611
+ /** These settings name the fields the query counts values for, and control how each count is cut and sorted. */
612
+ facets?: FacetConfig;
613
+ /** This sorts the hits by field value, keyed by field, which replaces the relevance ranking. */
614
+ sort?: Record<string, 'asc' | 'desc'>;
615
+ /** These settings collapse the hits into groups by field value. */
616
+ group?: GroupConfig;
617
+ /** The query returns this many hits, and 10 by default. */
618
+ limit?: number;
619
+ /** The query skips this many hits before returning. A deep offset costs more than a cursor. */
620
+ offset?: number;
621
+ /** This cursor comes from a previous result's `cursor`, and pages without an offset's cost. */
622
+ searchAfter?: string;
623
+ /** These settings name the fields that come back with highlighted snippets. */
624
+ highlight?: HighlightConfig;
625
+ /** These documents take fixed positions, ahead of the ranking. */
626
+ pinned?: Array<{
627
+ docId: string;
628
+ position: number;
629
+ }>;
630
+ /** This picks which engine answers the query. Keyword search runs by default. */
631
+ mode?: SearchMode;
632
+ /** These vector-search inputs are required in `vector` and `hybrid` mode. */
633
+ vector?: VectorQueryConfig;
634
+ /** These settings control how the keyword and vector rankings merge in `hybrid` mode. */
635
+ hybrid?: HybridConfig;
636
+ /** Setting this returns the numbers behind each hit's score, which is what you read when a ranking surprises you. */
637
+ includeScoreComponents?: boolean;
638
+ }
639
+ /**
640
+ * Vector-search inputs passed under `QueryParams.vector`.
641
+ *
642
+ * Supply either a raw `value` array or a `text` string for auto-embedding;
643
+ * passing both throws `EMBEDDING_CONFIG_INVALID`. Result count is governed
644
+ * by the outer query's `limit`, not by any field on this object.
645
+ *
646
+ * @public
647
+ */
648
+ interface VectorQueryConfig {
649
+ /**
650
+ * Name of the schema field that holds the vector to compare against.
651
+ * Must reference a field declared as `vector[N]` in the index schema.
652
+ */
653
+ field: string;
654
+ /**
655
+ * Raw query vector. Length must match the indexed field's dimension or
656
+ * the search rejects the request with `VECTOR_DIMENSION_MISMATCH`.
657
+ */
658
+ value?: number[];
659
+ /**
660
+ * Text to embed at query time using the index or instance embedding
661
+ * adapter. Mutually exclusive with `value`; requires a configured adapter.
662
+ */
663
+ text?: string;
664
+ /**
665
+ * Score floor applied during ranking. Hits scoring below this value
666
+ * are dropped before `limit` is enforced, so the returned hit count
667
+ * can be smaller than `limit` even when more documents exist. The
668
+ * floor is interpreted in score space for every metric; for
669
+ * `euclidean`, distance is mapped to a similarity score of
670
+ * `1 / (1 + distance)` first. Defaults to no floor.
671
+ */
672
+ similarity?: number;
673
+ /**
674
+ * Similarity metric used for ranking. Defaults to `cosine`. Choose
675
+ * `dotProduct` for raw inner-product scoring on already-normalised
676
+ * vectors and `euclidean` for distance-based ordering.
677
+ */
678
+ metric?: 'cosine' | 'dotProduct' | 'euclidean';
679
+ /**
680
+ * HNSW exploration factor for approximate search. Higher values raise
681
+ * recall at the cost of latency. Ignored while the field is still
682
+ * served by the brute-force backend. Defaults to the engine's built-in
683
+ * value when omitted.
684
+ */
685
+ efSearch?: number;
686
+ }
687
+ /**
688
+ * How a hybrid query merges its keyword ranking with its vector ranking.
689
+ *
690
+ * `rrf` combines the two by rank alone, which needs no tuning and handles
691
+ * scores that live on different scales. `linear` blends the scores directly,
692
+ * which gives you control once you know what each side's scores look like.
693
+ *
694
+ * @public
695
+ */
696
+ interface HybridConfig {
697
+ /** The rankings merge this way, and by rank fusion by default. */
698
+ strategy?: 'rrf' | 'linear';
699
+ /** This rank-fusion constant softens the advantage of the top ranks, and `rrf` alone reads it. */
700
+ k?: number;
701
+ /** This weights the vector score, from 0 to 1, and `linear` alone reads it. */
702
+ alpha?: number;
703
+ }
704
+ /**
705
+ * Fields a query counts values for, keyed by field name.
706
+ *
707
+ * @public
708
+ */
709
+ interface FacetConfig {
710
+ /** Each key names a field the query counts values for. */
711
+ [field: string]: {
712
+ /** The facet returns this many values for the field, most frequent first. */
713
+ limit?: number;
714
+ /** This orders the returned values by their count. */
715
+ sort?: 'asc' | 'desc';
716
+ /** These ranges bucket a numeric field, instead of counting each value. */
717
+ ranges?: Array<{
718
+ from: number;
719
+ to: number;
720
+ }>;
721
+ };
722
+ }
723
+ /**
724
+ * How a query collapses its hits into groups.
725
+ *
726
+ * @public
727
+ */
728
+ interface GroupConfig {
729
+ /** The values of these fields define a group, and several fields group by their combination. */
730
+ fields: string[];
731
+ /** Each group keeps this many hits, and one by default, which is the collapse behaviour. */
732
+ maxPerGroup?: number;
733
+ /** This folds each group's hits into one value, such as a sum or an average. */
734
+ reduce?: GroupReducer;
735
+ }
736
+ /**
737
+ * Folds the hits of one group into a single value.
738
+ *
739
+ * @public
740
+ */
741
+ type GroupReducer = {
742
+ /**
743
+ * Folds one hit into the running value.
744
+ *
745
+ * @param accumulator - What the previous call returned, or what
746
+ * `initialValue` produced for the first hit.
747
+ * @param doc - The hit's stored document.
748
+ * @param score - The hit's relevance score.
749
+ * @returns The new running value.
750
+ */
751
+ reducer: (accumulator: unknown, doc: AnyDocument, score: number) => unknown;
752
+ /** Produces the starting value for each group. The engine calls it once per group. */
753
+ initialValue: () => unknown;
754
+ };
755
+ /**
756
+ * Which fields a query returns highlighted snippets for, and how those
757
+ * snippets are marked up.
758
+ *
759
+ * The index has to have been created with `trackPositions`, because
760
+ * highlighting reads the positions that setting records.
761
+ *
762
+ * @public
763
+ */
764
+ interface HighlightConfig {
765
+ /** The engine highlights these fields. */
766
+ fields: string[];
767
+ /** This opens each match, and is `<mark>` by default. */
768
+ preTag?: string;
769
+ /** This closes each match, and is `</mark>` by default. */
770
+ postTag?: string;
771
+ /** A snippet runs to this many characters before the engine trims it. */
772
+ maxSnippetLength?: number;
773
+ }
774
+ /**
775
+ * Everything {@link Narsil.suggest} accepts.
776
+ *
777
+ * @public
778
+ */
779
+ interface SuggestParams {
780
+ /** The returned terms complete this text. */
781
+ prefix: string;
782
+ /** The lookup returns this many completions, most widely used first, and 10 by default. */
783
+ limit?: number;
784
+ }
785
+
786
+ export { type ArrayFilter as A, type BatchResult as B, type ComparisonFilter as C, type ErrorCode as E, type FacetConfig as F, type GeoFilter as G, type HighlightConfig as H, type IndexInfo as I, type MemoryStats as M, NarsilError as N, type PartitionStatsResult as P, type QueryParams as Q, type ScoreComponents as S, type TermMatchPolicy as T, type VectorMaintenanceResult as V, ErrorCodes as a, type FacetResult as b, type FieldFilter as c, type FilterExpression as d, type GeoPolygonFilter as e, type GeoRadiusFilter as f, type GroupConfig as g, type GroupReducer as h, type GroupResult as i, type HighlightMatch as j, type Hit as k, type HybridConfig as l, type IndexStats as m, type PreflightResult as n, type PresenceFilter as o, type ProcessMemoryReport as p, type QueryResult as q, type SearchMode as r, type StringFilter as s, type SuggestParams as t, type SuggestResult as u, type VectorQueryConfig as v };