albex 0.1.0 → 0.6.0

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 (72) hide show
  1. package/CHANGELOG.md +416 -0
  2. package/README.md +244 -112
  3. package/dist/albex-worker.d.ts +70 -0
  4. package/dist/albex-worker.d.ts.map +1 -0
  5. package/dist/albex-worker.js +153 -0
  6. package/dist/albex-worker.js.map +1 -0
  7. package/dist/albex.d.ts +508 -6
  8. package/dist/albex.d.ts.map +1 -1
  9. package/dist/albex.js +1911 -141
  10. package/dist/albex.js.map +1 -1
  11. package/dist/errors.d.ts +52 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +66 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/gpu/bloom-runtime.d.ts +60 -0
  16. package/dist/gpu/bloom-runtime.d.ts.map +1 -0
  17. package/dist/gpu/bloom-runtime.js +176 -0
  18. package/dist/gpu/bloom-runtime.js.map +1 -0
  19. package/dist/gpu/bloom-shader.wgsl.d.ts +19 -0
  20. package/dist/gpu/bloom-shader.wgsl.d.ts.map +1 -0
  21. package/dist/gpu/bloom-shader.wgsl.js +49 -0
  22. package/dist/gpu/bloom-shader.wgsl.js.map +1 -0
  23. package/dist/persistence.d.ts +21 -0
  24. package/dist/persistence.d.ts.map +1 -0
  25. package/dist/persistence.js +174 -0
  26. package/dist/persistence.js.map +1 -0
  27. package/dist/pool/coordinator.d.ts +98 -0
  28. package/dist/pool/coordinator.d.ts.map +1 -0
  29. package/dist/pool/coordinator.js +247 -0
  30. package/dist/pool/coordinator.js.map +1 -0
  31. package/dist/profile.d.ts +100 -0
  32. package/dist/profile.d.ts.map +1 -0
  33. package/dist/profile.js +200 -0
  34. package/dist/profile.js.map +1 -0
  35. package/dist/resource-manager.d.ts +56 -0
  36. package/dist/resource-manager.d.ts.map +1 -0
  37. package/dist/resource-manager.js +138 -0
  38. package/dist/resource-manager.js.map +1 -0
  39. package/dist/tiered-store.d.ts +98 -0
  40. package/dist/tiered-store.d.ts.map +1 -0
  41. package/dist/tiered-store.js +238 -0
  42. package/dist/tiered-store.js.map +1 -0
  43. package/dist/wasm-bindings.d.ts +180 -0
  44. package/dist/wasm-bindings.d.ts.map +1 -0
  45. package/dist/wasm-bindings.js +128 -0
  46. package/dist/wasm-bindings.js.map +1 -0
  47. package/dist/worker-protocol.d.ts +86 -0
  48. package/dist/worker-protocol.d.ts.map +1 -0
  49. package/dist/worker-protocol.js +20 -0
  50. package/dist/worker-protocol.js.map +1 -0
  51. package/dist/worker-runtime.d.ts +14 -0
  52. package/dist/worker-runtime.d.ts.map +1 -0
  53. package/dist/worker-runtime.js +109 -0
  54. package/dist/worker-runtime.js.map +1 -0
  55. package/package.json +60 -13
  56. package/src/albex-worker.ts +187 -0
  57. package/src/albex.ts +2136 -189
  58. package/src/errors.ts +76 -0
  59. package/src/gpu/bloom-runtime.ts +229 -0
  60. package/src/gpu/bloom-shader.wgsl.ts +48 -0
  61. package/src/persistence.ts +175 -0
  62. package/src/pool/coordinator.ts +324 -0
  63. package/src/profile.ts +280 -0
  64. package/src/resource-manager.ts +167 -0
  65. package/src/tiered-store.ts +259 -0
  66. package/src/wasm-bindings.ts +349 -0
  67. package/src/worker-protocol.ts +48 -0
  68. package/src/worker-runtime.ts +106 -0
  69. package/wasm/pkg/albex_pdf.wasm +0 -0
  70. package/wasm/pkg/albex_wasm.wasm +0 -0
  71. package/wasm/pkg/albex_wasm_bg.wasm +0 -0
  72. package/wasm/pkg/albex_wasm_simd.wasm +0 -0
package/dist/albex.d.ts CHANGED
@@ -13,11 +13,61 @@
13
13
  * const results = engine.search('contrato marco');
14
14
  * ```
15
15
  */
16
+ import { type Tier } from './profile.js';
17
+ export { AlbexError, AlbexInitError, AlbexUnsupportedFormatError, AlbexParseError, AlbexCapacityError, } from './errors.js';
18
+ export { listPersisted, deletePersisted } from './persistence.js';
19
+ export { detectProfile, pickTier, pickWorkerCount, shouldUseGpu } from './profile.js';
20
+ export type { DeviceProfile, Tier } from './profile.js';
21
+ export { getResourceManager } from './resource-manager.js';
22
+ export type { ResourceState, ResourceMode } from './resource-manager.js';
23
+ export { AlbexPool } from './pool/coordinator.js';
24
+ export type { AlbexPoolOptions } from './pool/coordinator.js';
25
+ export { BloomGpu, packBloomsFromChunks } from './gpu/bloom-runtime.js';
26
+ export { TieredStore } from './tiered-store.js';
27
+ export type { TieredStoreOptions } from './tiered-store.js';
16
28
  export interface AlbexOptions {
17
- /** URL to albex_wasm_bg.wasm (required). */
18
- wasmUrl: string;
29
+ /**
30
+ * Explicit URL to the main WASM binary.
31
+ *
32
+ * If you want automatic tier selection (mini/std/pro chosen from
33
+ * `deviceMemory`), pass `wasmBaseUrl` instead — the engine will fetch
34
+ * `albex_wasm_<tier>.wasm` from that directory.
35
+ */
36
+ wasmUrl?: string;
37
+ /**
38
+ * Base directory containing tiered binaries (`albex_wasm_mini.wasm`,
39
+ * `_std.wasm`, `_pro.wasm`). Used when `wasmUrl` is omitted.
40
+ */
41
+ wasmBaseUrl?: string;
19
42
  /** URL to albex_pdf.wasm. Required only if you call indexFile() with PDFs. */
20
43
  pdfWasmUrl?: string;
44
+ /**
45
+ * Override the tier auto-detection. Pass `'auto'` (default), or an
46
+ * explicit tier when you know the constraints of your target environment.
47
+ */
48
+ /** @deprecated Removed in 0.5.0. Albex no longer has capacity tiers;
49
+ * pass `'auto'` or omit. Other values are accepted and ignored. */
50
+ tier?: 'auto' | 'mini' | 'std' | 'pro';
51
+ /**
52
+ * SIMD selection. When `'auto'` (default), Albex probes for v128 support
53
+ * and fetches the `_simd.wasm` variant when available. Pass `'off'` to
54
+ * stay on the baseline binary even on capable hosts (useful for
55
+ * regression testing or to align all clients in a corporate deployment).
56
+ */
57
+ simd?: 'auto' | 'on' | 'off';
58
+ /**
59
+ * GPU acceleration policy for the Bloom pre-filter.
60
+ * `'auto'` — enable when WebGPU is available AND chunk count is large
61
+ * `'on'` — force enable (fall back to CPU silently if GPU fails)
62
+ * `'off'` — never use GPU
63
+ * Default: `'auto'`.
64
+ */
65
+ gpu?: 'auto' | 'on' | 'off';
66
+ /**
67
+ * Minimum chunk count before `gpu: 'auto'` engages. Below this threshold
68
+ * the upload + dispatch overhead is bigger than the speedup. Default: 20_000.
69
+ */
70
+ gpuThreshold?: number;
21
71
  }
22
72
  export interface IndexedDocument {
23
73
  name: string;
@@ -25,6 +75,16 @@ export interface IndexedDocument {
25
75
  chunks: number;
26
76
  indexTimeMs: number;
27
77
  textBytes: number;
78
+ /** WASM-side stable identifier (also acts as a slot index after compact). */
79
+ docId: number;
80
+ /** 64-bit FNV-1a hex of the source file bytes. Stable across runs. */
81
+ contentHash: string;
82
+ }
83
+ export interface MatchSpan {
84
+ /** Byte offset within `snippet` where this matched token begins. */
85
+ start: number;
86
+ /** Byte offset within `snippet` where this matched token ends (exclusive). */
87
+ end: number;
28
88
  }
29
89
  export interface SearchResult {
30
90
  documentName: string;
@@ -32,12 +92,37 @@ export interface SearchResult {
32
92
  location: number;
33
93
  /** Relevance score 0–1000. */
34
94
  score: number;
35
- /** Raw snippet text (original, with accents). */
95
+ /** Snippet text. With `windowed` search options this is a substring with
96
+ * ASCII ellipsis sentinels (`"... "` / `" ..."`) the UI should render
97
+ * as `…`. Without windowing, the full chunk text. */
36
98
  snippet: string;
37
- /** Match start byte offset within snippet. */
99
+ /** Primary token match (kept for backwards compatibility). Equal to `matches[0]`. */
38
100
  matchStart: number;
39
- /** Match end byte offset within snippet (exclusive). */
40
101
  matchEnd: number;
102
+ /** All matched token spans within `snippet`, in query order. Length 1–4. */
103
+ matches: MatchSpan[];
104
+ }
105
+ /**
106
+ * Options that change how snippets are produced. Both fields are optional.
107
+ *
108
+ * `windowed` — when true, return a cropped window around the primary
109
+ * match instead of the full chunk text.
110
+ * `before/after` — bytes of context to include on each side of the primary
111
+ * match. Defaults: 60 before, 120 after.
112
+ */
113
+ export interface SearchOptions {
114
+ windowed?: boolean;
115
+ before?: number;
116
+ after?: number;
117
+ /**
118
+ * Frame budget in milliseconds for `searchCooperative`. The engine
119
+ * processes chunks until the budget is exhausted, then yields to the
120
+ * event loop via `scheduler.yield()` (or `requestAnimationFrame`
121
+ * fallback) before resuming. Lower = smoother UI; higher = lower latency.
122
+ *
123
+ * Default: 8 ms (half a 60 fps frame). Ignored by synchronous `search()`.
124
+ */
125
+ frameBudgetMs?: number;
41
126
  }
42
127
  export interface EngineStats {
43
128
  documents: number;
@@ -45,6 +130,12 @@ export interface EngineStats {
45
130
  textUsed: number;
46
131
  textCapacity: number;
47
132
  wasmMemoryBytes: number;
133
+ /** Tier loaded at init time (mini/std/pro). */
134
+ tier: Tier | null;
135
+ /** Compile-time chunk capacity for the loaded tier. */
136
+ maxChunks: number;
137
+ /** Compile-time document capacity for the loaded tier. */
138
+ maxDocs: number;
48
139
  }
49
140
  export interface SearchStats {
50
141
  query: string;
@@ -54,43 +145,355 @@ export interface SearchStats {
54
145
  bloomPassed: number;
55
146
  bitapMatched: number;
56
147
  }
148
+ /**
149
+ * One structured warning recorded by the engine during indexFile or
150
+ * load. Replaces the pre-0.5.0 pattern of scattered `console.warn`
151
+ * calls. Inspect via `engine.takeDiagnostics()` after the operation.
152
+ */
153
+ export interface AlbexDiagnostic {
154
+ /** Coarse kind. `'recovered'` means the engine handled the issue and
155
+ * kept going; `'skipped'` means content was dropped; `'fallback'` means
156
+ * an alternate code path was used (e.g. lopdf after pdf-extract trap). */
157
+ kind: 'recovered' | 'skipped' | 'fallback' | 'info';
158
+ /** Where in the pipeline this happened. Free-form short tag. */
159
+ stage: 'pdf' | 'ocr' | 'gpu' | 'persistence' | 'network';
160
+ /** Human-readable message safe to surface in a UI. */
161
+ message: string;
162
+ /** Optional file the issue belongs to. */
163
+ file?: string;
164
+ /** Optional page number (1-based for PDFs). */
165
+ page?: number;
166
+ }
167
+ /**
168
+ * Result shape returned by an attached OCR module. Kept structural here so
169
+ * the main package has no runtime dependency on `@albex/ocr` — the optional
170
+ * shape is just a contract.
171
+ */
172
+ export interface OcrAttachedResult {
173
+ text: string;
174
+ confidence: number;
175
+ timeMs: number;
176
+ }
177
+ export interface OcrAttachedOptions {
178
+ lang?: string;
179
+ hint?: string;
180
+ }
181
+ /**
182
+ * Contract the engine accepts from an OCR plugin. `@albex/ocr` is the
183
+ * canonical implementation, but any module that satisfies this interface
184
+ * can be attached via `engine.attachOcr(adapter)`.
185
+ */
186
+ export interface OcrAdapter {
187
+ /** Invoked by the engine to OCR a single image. Receives whatever the
188
+ * caller passes (Blob, ArrayBuffer, etc.); the adapter is responsible
189
+ * for accepting that input. Must return text + confidence. */
190
+ recognize(image: unknown, opts?: OcrAttachedOptions): Promise<OcrAttachedResult>;
191
+ /** Engine-side switches the adapter wants honoured. The only one
192
+ * defined today is `alwaysExtractEmbeddedImages`, which turns on the
193
+ * hybrid PDF OCR pass. New flags can be added without breaking the
194
+ * adapter interface. */
195
+ options?: {
196
+ /** When true, every PDF (native or scanned) is walked for embedded
197
+ * images and each qualifying image is sent to `recognize`. Off by
198
+ * default to keep performance predictable on native PDFs. */
199
+ alwaysExtractEmbeddedImages?: boolean;
200
+ };
201
+ }
202
+ /** Returned by `attachOcr`. Holds the lifecycle handles for the plugin.
203
+ * Calling `dispose()` removes the adapter from the engine; subsequent
204
+ * `engine.ocrImage` access returns `undefined` again. */
205
+ export interface OcrHandle {
206
+ /** Detach the plugin and tear down any resources it holds. After this,
207
+ * the engine reverts to "no OCR" — scanned PDFs go back to registering
208
+ * with zero chunks. */
209
+ dispose(): Promise<void>;
210
+ }
57
211
  export declare class AlbexEngine {
58
212
  private _wasm;
59
213
  private _mem;
214
+ /**
215
+ * OCR entry point installed by `@albex/ocr::enableOcr(engine)`. Undefined
216
+ * when the OCR module has not been wired. The main `albex` package has no
217
+ * runtime dependency on OCR — this is a structural slot that the optional
218
+ * companion package fills.
219
+ */
220
+ /**
221
+ * Public OCR entry point. Forwards to the attached OCR adapter installed
222
+ * via `attachOcr()`. Reading this property is a feature-detect for
223
+ * integrators: `if (engine.ocrImage) { ... OCR available ... }`. Writing
224
+ * to it directly is no longer supported in 0.5.0+ — use `attachOcr`.
225
+ */
226
+ get ocrImage(): ((image: unknown, opts?: OcrAttachedOptions) => Promise<OcrAttachedResult>) | undefined;
227
+ /** Private adapter slot. Holds the OCR plugin contract installed by
228
+ * `attachOcr()`. The engine reads `recognize` and `options` here; the
229
+ * caller never gets a reference to this object directly. */
230
+ private _ocrAdapter;
60
231
  private _pdfWasm;
61
232
  private _pdfMem;
62
233
  private _docs;
63
234
  private _lastSearch;
235
+ /** Structured diagnostics collected during the most recent operation.
236
+ * Drained by `takeDiagnostics()`. Capped at 256 entries to avoid
237
+ * unbounded memory growth in pathological cases (very corrupted
238
+ * corpora producing thousands of recovery warnings). */
239
+ private _diagnostics;
240
+ private _tier;
241
+ private _simd;
242
+ private _profile;
243
+ private _resources;
244
+ private _gpu;
245
+ private _gpuChunkCountUploaded;
246
+ private _unsubscribeResources;
64
247
  private readonly _opts;
248
+ private _opChain;
249
+ private _busy;
65
250
  constructor(opts: AlbexOptions);
251
+ /** Serialize an async engine operation behind any in-flight one. */
252
+ private _exclusive;
253
+ /** Guard a synchronous mutator/search: refuse to run mid-async-operation
254
+ * rather than silently corrupt the shared WASM state. */
255
+ private _assertIdle;
256
+ /** Compact opportunistically when tombstones pile up under text pressure,
257
+ * so repeated removeDocument/replaceDocument don't exhaust the pool. */
258
+ private _autoCompactIfNeeded;
66
259
  /** Load and initialise the main WASM module. Must be called before any other method. */
67
260
  init(): Promise<void>;
261
+ /**
262
+ * Decide which `.wasm` binary to fetch. Order of precedence:
263
+ * 1. `opts.wasmUrl` if provided — used verbatim.
264
+ * 2. `opts.tier` if explicit — joined with `wasmBaseUrl`.
265
+ * 3. `opts.wasmBaseUrl` + tier picked from the device profile.
266
+ *
267
+ * Order of precedence:
268
+ * 1. `opts.wasmUrl` literal → use verbatim
269
+ * 2. `opts.wasmBaseUrl` + tier suffix → fetched from that directory
270
+ * 3. zero-config default → `albex_wasm_bg.wasm` packaged
271
+ * next to this file, resolved
272
+ * via `import.meta.url`
273
+ *
274
+ * The zero-config default loads the std-baseline binary. Tier auto-detection
275
+ * is only active when `wasmBaseUrl` is given, because picking a tier in
276
+ * runtime would defeat any bundler's static asset rewriting. Users who want
277
+ * tier optimisation must serve the six variants themselves and pass the
278
+ * directory through `wasmBaseUrl`.
279
+ */
280
+ private _resolveWasmUrl;
281
+ /** The tier that was actually loaded. `null` until `init()` resolves. */
282
+ get tier(): Tier | null;
283
+ /** True if the SIMD-accelerated binary was loaded. */
284
+ get simdEnabled(): boolean;
285
+ /** True if a WebGPU device is acquired and the next search will use it. */
286
+ get gpuEngaged(): boolean;
287
+ /**
288
+ * Decide whether to use the GPU pre-filter for the upcoming search.
289
+ *
290
+ * Policy:
291
+ * - `gpu: 'off'` → never.
292
+ * - `gpu: 'on'` → always try (still fails over to CPU).
293
+ * - `gpu: 'auto'` (default) → only when WebGPU is available AND
294
+ * chunk count crosses `gpuThreshold`.
295
+ */
296
+ private _shouldEngageGpu;
297
+ /**
298
+ * Run the GPU Bloom scan and install the resulting candidate bitset into
299
+ * WASM. The next `searchBegin` will see the mask and `searchSlice` will
300
+ * restrict its Bitap pass to those candidates.
301
+ *
302
+ * No-op if the GPU device hasn't been acquired yet — first call attempts
303
+ * `init()` lazily; if that fails, the candidate path is permanently
304
+ * disabled for this engine instance.
305
+ */
306
+ private _gpuPreFilter;
68
307
  private _u8;
69
308
  private _writePad;
70
309
  private _writeStr;
71
310
  private _readPad;
72
311
  private _feedText;
312
+ /**
313
+ * Compute the FNV-1a 64-bit content hash of `bytes` via the WASM
314
+ * streaming API. Returns a 16-character hex string identical in shape
315
+ * to what the TS implementation in 0.3.x returned, so all callers
316
+ * stay unchanged. Single source of truth — same hash whether we use
317
+ * it for indexFile dedup, for snapshot v2 persistence, or anywhere
318
+ * else. Large inputs are chunked at FEED_SIZE just like _feedText.
319
+ */
320
+ private _contentHash;
73
321
  private _feedXmlBytes;
74
322
  private _ensurePdfWasm;
75
323
  private _indexDocx;
76
324
  private _indexXlsx;
77
325
  private _indexPdf;
326
+ /**
327
+ * Scanned-PDF OCR fallback. Called from `_indexPdf` when `extractPdf`
328
+ * returns `-2` (image-only PDF) AND `@albex/ocr` has been wired via
329
+ * `enableOcr(engine)`.
330
+ *
331
+ * Walks every page of the PDF, extracts embedded JPEG / JPEG2000 image
332
+ * XObjects, runs each through `engine.ocrImage`, and feeds the recognised
333
+ * text into the index — one paragraph per page so search snippets stay
334
+ * tied to the page they came from.
335
+ *
336
+ * Failure modes handled here (none re-thrown — the goal is best-effort
337
+ * indexing, not all-or-nothing):
338
+ *
339
+ * * A page's `extractPageImages` traps the WASM instance: the instance
340
+ * is discarded so the next PDF starts fresh, and we stop iterating
341
+ * (no more pages can be read from a poisoned instance). The doc is
342
+ * still committed with whatever text we got from earlier pages.
343
+ * * An individual image fails to OCR (Tesseract decode error, JP2 not
344
+ * supported in this browser, etc.): we skip that image and keep
345
+ * going. Partial coverage beats nothing.
346
+ * * A page yields no extractable images (e.g. uses Flate/CCITT/JBIG2):
347
+ * no paragraph is emitted; the page contributes 0 chunks.
348
+ */
349
+ private _indexPdfScanned;
350
+ /**
351
+ * Walk one page's embedded image XObjects, OCR each image, and return
352
+ * the joined recognised text for that page.
353
+ *
354
+ * Used by:
355
+ * - `_indexPdfScanned`: image-only PDFs (extractPdf returned -2).
356
+ * - `_indexPdf` hybrid path: when `ocrConfig.alwaysExtractEmbeddedImages`
357
+ * is set, every page goes through here on top of the normal text
358
+ * extraction.
359
+ *
360
+ * Returns:
361
+ * - The recognised text (possibly empty if the page has no qualifying
362
+ * images or every OCR call failed).
363
+ * - `null` if the PDF WASM trapped during extractPageImages — the
364
+ * caller should abort the remaining pages because the instance is
365
+ * now poisoned.
366
+ *
367
+ * Failure-handling philosophy: best-effort. An OCR failure on one image
368
+ * does not stop the page; a page with no images does not stop the doc;
369
+ * only a WASM trap stops the doc.
370
+ */
371
+ private _ocrPageEmbeddedImages;
372
+ /**
373
+ * Last-chance OCR path used when `extractPdf` itself trapped (pdf-extract
374
+ * crashed but lopdf may still be able to walk the file). Re-instantiates
375
+ * the PDF WASM, reloads the input bytes, and tries the image-extraction
376
+ * route directly — bypassing the text codec entirely.
377
+ *
378
+ * Returns:
379
+ * * the doc's chunk count on success (even 0 — that means lopdf could
380
+ * parse but no qualifying images existed, which still beats a hard
381
+ * parse error),
382
+ * * null if the recovery itself failed (binary lacks the image exports,
383
+ * re-instantiation failed, or lopdf also trapped). In the null case
384
+ * the caller throws AlbexParseError so the user sees a clear message.
385
+ */
386
+ private _indexPdfViaImagesOnly;
78
387
  private _indexTxt;
79
388
  private _indexXml;
389
+ private _indexMd;
390
+ private _indexHtml;
391
+ private _indexJson;
392
+ private _indexCsv;
393
+ private _indexEml;
394
+ /**
395
+ * Walk the multipart tree until a text/plain section is found. Returns
396
+ * the decoded body as a string, or null if no text/plain part exists.
397
+ *
398
+ * The function is called with the headers and body of the *current*
399
+ * MIME entity (the top-level message at first, then each multipart child
400
+ * on recursion). For single-part entities it inspects the entity's own
401
+ * Content-Transfer-Encoding and decodes accordingly.
402
+ */
403
+ private _extractEmlTextPlain;
404
+ private _indexRtf;
80
405
  private static readonly _INDEXERS;
81
406
  /**
82
407
  * Index a file. Supported formats: DOCX, XLSX, PDF, TXT, XML.
83
408
  * Throws for unsupported formats or parse errors.
84
409
  */
85
410
  indexFile(file: File): Promise<IndexedDocument>;
411
+ private _indexFileInner;
412
+ /**
413
+ * Mark a previously indexed document as removed. Searches no longer return
414
+ * its chunks. Storage is reclaimed only after `compact()`.
415
+ *
416
+ * `id` can be the file name or the contentHash returned by `indexFile`.
417
+ * Returns `true` if a matching document was found and tombstoned.
418
+ */
419
+ removeDocument(id: string): boolean;
420
+ private _removeDocumentInner;
421
+ /**
422
+ * Replace a previously indexed document with new content. Equivalent to
423
+ * `removeDocument(name)` + `indexFile(newFile)` but does not trigger the
424
+ * idempotency check (so re-indexing the *same* bytes after a remove works).
425
+ */
426
+ replaceDocument(name: string, newFile: File): Promise<IndexedDocument>;
427
+ /**
428
+ * Reclaim storage from previously removed documents. Compacts CHUNKS,
429
+ * TEXT_POOL, DOC_NAMES and NAME_POOL in place. Idempotent.
430
+ *
431
+ * Note: doc_ids of surviving documents are preserved, so any stored
432
+ * references (e.g. in a UI) remain valid.
433
+ */
434
+ compact(): void;
86
435
  /**
87
436
  * Search the index. Supports:
88
437
  * - Simple queries: `contrato` (AND of tokens, accent-insensitive)
89
438
  * - Phrase queries: `"contrato marco"` (must appear as phrase)
90
439
  * - OR queries: `contrato | acuerdo` (union of two searches)
440
+ *
441
+ * Pass `{ windowed: true }` to receive cropped snippets with ASCII ellipsis
442
+ * markers instead of full chunk text. Defaults: 60 bytes before, 120 after.
443
+ */
444
+ search(query: string, opts?: SearchOptions): SearchResult[];
445
+ /** Read the WASM-compiled tokens of branch `i` for phrase post-filter.
446
+ * The bytes returned are exactly what the WASM tokenizer produced —
447
+ * no TS re-tokenization. */
448
+ private _branchTokens;
449
+ /**
450
+ * Cooperative search. Processes the corpus in slices, yielding to the
451
+ * event loop between them so the host UI thread keeps a chance to paint
452
+ * even while a long scan is in flight.
453
+ *
454
+ * NOTE: this is NOT incremental streaming. Results are materialised
455
+ * once the search completes and then iterated out in score-descending
456
+ * order. The async iterator shape is preserved because the work that
457
+ * produces those results genuinely yields to the scheduler between
458
+ * slices — a future iteration may stream individual results before the
459
+ * heap sorts, but doing so today would deliver them in arbitrary order.
460
+ *
461
+ * Pass `opts.frameBudgetMs` to control the slice size (default 8 ms).
462
+ */
463
+ searchCooperative(query: string, opts?: SearchOptions): AsyncIterable<SearchResult>;
464
+ /** Materialise a cooperative search to a sorted result array. Runs inside
465
+ * the exclusivity lock. Frame-budget yielding lives in _runSearchBudgeted. */
466
+ private _searchCooperativeCollect;
467
+ /**
468
+ * @deprecated Renamed to `searchCooperative` in 0.3.0. The original name
469
+ * was misleading — this method does not stream incremental results, it
470
+ * yields to the scheduler between slices and returns a batch. The alias
471
+ * keeps existing integrations working; it will be removed in 0.4.0.
472
+ */
473
+ searchStream(query: string, opts?: SearchOptions): AsyncIterable<SearchResult>;
474
+ /**
475
+ * Drive a resumable search until done, yielding to the scheduler when the
476
+ * frame budget is exceeded. Returns the materialised result array.
477
+ *
478
+ * Heuristic: each call to `searchSlice` processes a chunk batch, then we
479
+ * check elapsed time. The batch size doubles up to a cap to amortise the
480
+ * JS<->WASM overhead on fast machines; on slow machines a single batch
481
+ * may eat the entire budget, which is also fine.
91
482
  */
92
- search(query: string): SearchResult[];
483
+ private _runSearchBudgeted;
484
+ /** Materialise results [0..count) into the public SearchResult shape.
485
+ * When `phraseTokens` is given, each result is kept only if those tokens
486
+ * appear adjacently in the FULL chunk text — independent of any display
487
+ * windowing — so phrase queries stay correct under `{ windowed: true }`. */
488
+ private _collectResults;
489
+ /** Run all OR branches and merge dedup-by-(doc, location, match). The
490
+ * branches are already compiled inside the WASM (by prepareQuery); we
491
+ * iterate them with selectQueryBranch. The "rawQuery" param is kept
492
+ * only for the lastSearch.query field. */
93
493
  private _searchOr;
494
+ /** Execute a single search using whichever query branch is currently
495
+ * active (set via selectQueryBranch). Returns the materialised
496
+ * SearchResult[]. Caller is responsible for activating a branch first. */
94
497
  private _runSearch;
95
498
  /** Returns current engine statistics. */
96
499
  getStats(): EngineStats;
@@ -104,7 +507,106 @@ export declare class AlbexEngine {
104
507
  setMaxErrors(errors: 0 | 1 | 2 | 3): void;
105
508
  setThreshold(threshold: number): void;
106
509
  setMaxResults(max: number): void;
510
+ /**
511
+ * Enable or disable query stemming.
512
+ *
513
+ * - `'off'` (default): tokens are used as-is. Strict matching.
514
+ * - `'es'`: Spanish stemmer applied to query tokens before search. A query
515
+ * for `"contratos"` matches `"contrato"` and vice versa.
516
+ *
517
+ * Indexed text is never stemmed, so snippets remain faithful to the
518
+ * source. Recall improvement comes from queries reducing to shared prefixes.
519
+ */
520
+ setLanguage(lang: 'off' | 'es'): void;
107
521
  /** Full reset — clears all indexed documents and chunks. */
108
522
  reset(): void;
523
+ private _resetInner;
524
+ /**
525
+ * Drain and return the diagnostics collected since the last call (or
526
+ * since the engine was created). Use this to surface recoverable
527
+ * issues to the caller after `indexFile`, `load`, or any other
528
+ * operation that may run into a "best-effort" path.
529
+ *
530
+ * Example diagnostics:
531
+ * - `{kind:'fallback', stage:'pdf', message:'pdf-extract crashed,
532
+ * attempting OCR-only fallback', file:'invoice.pdf'}`
533
+ * - `{kind:'skipped', stage:'ocr', message:'Tesseract abort on page
534
+ * 3 image 1; remaining images on this page skipped', file:'...',
535
+ * page:3}`
536
+ * - `{kind:'fallback', stage:'gpu', message:'GPU pre-filter failed,
537
+ * using CPU'}`
538
+ *
539
+ * The buffer is cleared on each call; callers should consume the
540
+ * returned array immediately (e.g. log to their telemetry, surface
541
+ * a UI banner). After `reset()` the buffer is also cleared.
542
+ */
543
+ takeDiagnostics(): AlbexDiagnostic[];
544
+ /** Internal: record a diagnostic. Capped at 256 to bound memory. */
545
+ private _diag;
546
+ /**
547
+ * Install an OCR adapter. Returns a handle whose `dispose()` removes the
548
+ * adapter from the engine.
549
+ *
550
+ * The contract: the adapter must provide `recognize(image, opts)` that
551
+ * returns `Promise<OcrAttachedResult>`. The engine validates the
552
+ * contract at attach time and refuses adapters that don't expose a
553
+ * recognise function. Only one adapter can be attached at a time; a
554
+ * second call to `attachOcr` while one is active throws — the caller
555
+ * must dispose the previous one first.
556
+ *
557
+ * @example
558
+ * ```ts
559
+ * import { enableOcr } from '@albex/ocr';
560
+ * const handle = enableOcr(engine); // internally calls attachOcr
561
+ * // ... later ...
562
+ * await handle.dispose();
563
+ * ```
564
+ *
565
+ * Direct use without the companion package:
566
+ * ```ts
567
+ * const handle = engine.attachOcr({
568
+ * recognize: async (blob) => myCustomOcr(blob),
569
+ * options: { alwaysExtractEmbeddedImages: false },
570
+ * });
571
+ * ```
572
+ */
573
+ attachOcr(adapter: OcrAdapter): OcrHandle;
574
+ /**
575
+ * Persist the current index to OPFS (or IndexedDB as fallback) under `name`.
576
+ *
577
+ * The snapshot includes every chunk, document name and text byte currently
578
+ * indexed. Subsequent `load(name)` calls restore the engine to this exact
579
+ * state in roughly O(total bytes), bypassing re-parsing.
580
+ */
581
+ save(name: string): Promise<void>;
582
+ private _saveInner;
583
+ /**
584
+ * Restore an index previously saved with `save(name)`. Returns `true` on
585
+ * success, `false` if the snapshot is missing or has an incompatible
586
+ * header (wrong magic, version, or struct sizes).
587
+ */
588
+ load(name: string): Promise<boolean>;
589
+ private _loadInner;
590
+ /**
591
+ * Convenience: load if the snapshot exists, otherwise leave the engine
592
+ * empty. Returns whether a load actually happened.
593
+ */
594
+ loadOrInit(name: string): Promise<boolean>;
595
+ /** Delete a previously persisted snapshot. */
596
+ deleteSnapshot(name: string): Promise<void>;
597
+ /** List names of persisted snapshots in the current origin. */
598
+ listSnapshots(): Promise<string[]>;
599
+ /**
600
+ * TC39 explicit-resource-management hook (Stage 3 in 2026). Lets the engine
601
+ * be used with `using` so the references are released deterministically:
602
+ *
603
+ * using engine = new AlbexEngine(opts); await engine.init();
604
+ *
605
+ * WebAssembly does not actually expose a way to release linear memory pages
606
+ * inside a Module instance, so we drop our references to the exports and
607
+ * the doc list. GC can then reclaim the engine, which in turn releases the
608
+ * WASM instance and its (typically 20 MB) backing memory.
609
+ */
610
+ [Symbol.dispose](): void;
109
611
  }
110
612
  //# sourceMappingURL=albex.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"albex.d.ts","sourceRoot":"","sources":["../src/albex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAsLD,qBAAa,WAAW;IAEtB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,IAAI,CAAsB;IAGlC,OAAO,CAAC,QAAQ,CAAoC;IACpD,OAAO,CAAC,OAAO,CAAmC;IAElD,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;gBAEzB,IAAI,EAAE,YAAY;IAI9B,wFAAwF;IAClF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,aAAa;YAUP,cAAc;YAad,UAAU;YASV,UAAU;YAqBV,SAAS;YAuCT,SAAS;YAWT,SAAS;IAevB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAM/B;IAIF;;;OAGG;IACG,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC;IAmBrD;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,EAAE;IAgBrC,OAAO,CAAC,SAAS;IAmBjB,OAAO,CAAC,UAAU;IAiClB,yCAAyC;IACzC,QAAQ,IAAI,WAAW;IAUvB,0DAA0D;IAC1D,kBAAkB,IAAI,WAAW,GAAG,IAAI;IAIxC,6CAA6C;IAC7C,IAAI,SAAS,IAAI,SAAS,eAAe,EAAE,CAE1C;IAED,iCAAiC;IACjC,MAAM,KAAK,mBAAmB,IAAI,MAAM,EAAE,CAEzC;IAED,oCAAoC;IACpC,YAAY,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI;IAIzC,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAIrC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIhC,4DAA4D;IAC5D,KAAK,IAAI,IAAI;CAKd"}
1
+ {"version":3,"file":"albex.d.ts","sourceRoot":"","sources":["../src/albex.ts"],"names":[],"mappings":"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"}