plugmem 0.3.0 → 0.5.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 (4) hide show
  1. package/README.md +426 -145
  2. package/index.d.ts +746 -0
  3. package/index.js +323 -0
  4. package/package.json +7 -7
package/index.d.ts ADDED
@@ -0,0 +1,746 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ /** Options for [`Plugmem::new`]. */
7
+ export interface OpenOptions {
8
+ /**
9
+ * Embedding dimension (`Config::dim`). Omit or 0 to keep vectors off. When
10
+ * the config file configures an `[embedder]`, that embedder's dimension is
11
+ * authoritative and this — if given — must agree with it.
12
+ */
13
+ dim?: number
14
+ /**
15
+ * Open read-only over another process's writer (requires a checkpointed
16
+ * database). The write verbs then throw; `generation`/`refresh` appear.
17
+ *
18
+ * A text `recall` still reaches the vector source: the engine cannot embed
19
+ * on a read-only handle (replaying into it would defeat the zero-copy
20
+ * open), so this binding embeds the query itself before asking — the same
21
+ * thing the CLI and the MCP server do for their read-only paths.
22
+ */
23
+ readOnly?: boolean
24
+ /**
25
+ * Path to a `config.toml` (`[database]` / `[engine]` / `[embedder]` /
26
+ * `[maintenance]`). When the constructor path is omitted, `[database].path`
27
+ * participates in database-path resolution.
28
+ * Omitted, the standard discovery applies — `$PLUGMEM_CONFIG`, then
29
+ * `$XDG_CONFIG_HOME/plugmem/config.toml` — exactly as the CLI and MCP
30
+ * server resolve it. The `[embedder]` section is what makes a text-only
31
+ * `remember`/`recall` auto-embed; with no config there is no embedder
32
+ * (lexical, tag, graph and time recall still answer).
33
+ */
34
+ config?: string
35
+ }
36
+ /** One typed edge on a remembered fact: `entity` gains relation `rel`. */
37
+ export interface LinkRef {
38
+ /** The relation name. */
39
+ rel: string
40
+ /** The target entity name. */
41
+ entity: string
42
+ }
43
+ /** Arguments for [`Plugmem::remember`] / [`Plugmem::revise`]. */
44
+ export interface RememberArgs {
45
+ /** The fact text (required). */
46
+ text: string
47
+ /** Subject entity name. */
48
+ entity?: string
49
+ /** Tag strings. */
50
+ tags?: Array<string>
51
+ /** Typed edges to attach. */
52
+ links?: Array<LinkRef>
53
+ /**
54
+ * Opaque metadata as a key→value map (a URI to the real payload, a mime
55
+ * type, an external key). The engine never interprets it.
56
+ */
57
+ metadata?: Record<string, string>
58
+ /** Validity start, unix milliseconds (default: the fact's record time). */
59
+ validFrom?: number
60
+ /**
61
+ * A precomputed embedding. Its length must equal the configured `dim`.
62
+ *
63
+ * Given, it **replaces** the embedder: nothing is sent to the provider.
64
+ * That is the host's own precedence — it embeds only when this is absent —
65
+ * and it is the route for a vector you already have, or for a model that
66
+ * is not an OpenAI-shaped HTTP endpoint.
67
+ */
68
+ vector?: Array<number>
69
+ }
70
+ /**
71
+ * Arguments for [`Plugmem::recall`] — every field optional; lexical/tag/graph/
72
+ * time still answer with no query vector.
73
+ */
74
+ export interface RecallArgs {
75
+ /** Free-text query (embedded by the engine when an embedder is configured). */
76
+ query?: string
77
+ /** Restrict to facts carrying all these tags. */
78
+ tags?: Array<string>
79
+ /** Anchor entities for the graph source. */
80
+ entities?: Array<string>
81
+ /** "What was true at" this instant, unix milliseconds (bitemporal as-of). */
82
+ asOf?: number
83
+ /** Time window `[from, to)` over `recorded_at`, unix milliseconds. */
84
+ range?: Array<number>
85
+ /** Max facts to return (0 = engine default). */
86
+ k?: number
87
+ /** Include closed revisions (default false). */
88
+ closed?: boolean
89
+ /**
90
+ * Token budget of the `rendered` block (default 512). That block is what
91
+ * goes into a prompt, so this is the knob deciding how much of the
92
+ * context window a recall may spend.
93
+ */
94
+ tokenBudget?: number
95
+ /**
96
+ * HNSW beam width for the vector source (default: the configured
97
+ * `hnsw_ef_search`). Higher is more accurate and slower; ignored while
98
+ * the engine is still in the flat regime, below `flat_to_hnsw`.
99
+ */
100
+ ef?: number
101
+ /**
102
+ * A precomputed embedding. Its length must equal the configured `dim`.
103
+ *
104
+ * Given, it **replaces** the embedder: nothing is sent to the provider.
105
+ * That is the host's own precedence — it embeds only when this is absent —
106
+ * and it is the route for a vector you already have, or for a model that
107
+ * is not an OpenAI-shaped HTTP endpoint.
108
+ */
109
+ vector?: Array<number>
110
+ }
111
+ /** Arguments for [`Plugmem::link`]. */
112
+ export interface LinkArgs {
113
+ /** Source entity name. */
114
+ src: string
115
+ /** Relation name. */
116
+ rel: string
117
+ /** Destination entity name. */
118
+ dst: string
119
+ /**
120
+ * The fact this edge follows from, recorded on the edge and returned by
121
+ * graph recall — the answer to "why is this edge here". Ignored by
122
+ * `unlink`, which closes an edge rather than opening one.
123
+ */
124
+ provenance?: number
125
+ }
126
+ /** One similar / potentially-conflicting live fact surfaced by `remember`. */
127
+ export interface Similar {
128
+ /** The existing fact's id. */
129
+ id: number
130
+ /** Match strength (higher = closer). */
131
+ score: number
132
+ /** What triggered the hint: `"LexicalOverlap"` or `"VectorCosine"`. */
133
+ reason: string
134
+ }
135
+ /** The result of `remember` / `revise`. */
136
+ export interface RememberOutcome {
137
+ /** The new fact's id. */
138
+ id: number
139
+ /** The subject entity id, if one was named. */
140
+ entity?: number
141
+ /**
142
+ * Similar / potentially-conflicting live facts (best first; the engine
143
+ * never merges on its own — the caller decides).
144
+ */
145
+ similar: Array<Similar>
146
+ }
147
+ /** One recalled fact. */
148
+ export interface RecalledFact {
149
+ /** The fact id. */
150
+ id: number
151
+ /** Fused score (reciprocal-rank fusion + recency). */
152
+ score: number
153
+ /** Bit set of the sources that surfaced it. */
154
+ sources: number
155
+ /** Subject entity id (a sentinel when none). */
156
+ entity: number
157
+ /** Knowledge axis: when the memory learned it (unix ms). */
158
+ recordedAt: number
159
+ /** Truth axis start (unix ms). */
160
+ validFrom: number
161
+ /** Truth axis end (unix ms), or the open sentinel — see the module note. */
162
+ validTo: number
163
+ }
164
+ /** One edge walked by the graph source. */
165
+ export interface RecalledEdge {
166
+ /** Source entity id. */
167
+ src: number
168
+ /** Relation term id. */
169
+ rel: number
170
+ /** Destination entity id. */
171
+ dst: number
172
+ /** Provenance fact id (a sentinel when none). */
173
+ provenance: number
174
+ }
175
+ /** A recall response: the structured hits plus the prompt-ready block. */
176
+ export interface RecallResult {
177
+ /** Selected facts, descending fused score. */
178
+ facts: Array<RecalledFact>
179
+ /** Edges the graph source walked (deduplicated). */
180
+ edges: Array<RecalledEdge>
181
+ /** The compact prompt block (empty when nothing was found). */
182
+ rendered: string
183
+ /** `true` when selection stopped at `k`/the token budget with more left. */
184
+ truncated: boolean
185
+ }
186
+ /** Engine size counters. */
187
+ export interface Stats {
188
+ /** Fact records stored (live, closed and tombstoned-awaiting-maintain). */
189
+ facts: number
190
+ /** Entities. */
191
+ entities: number
192
+ /** Interned terms (tokens, tags, relations, names). */
193
+ terms: number
194
+ /** Directed edges. */
195
+ edges: number
196
+ /** Historical edge versions, including closed versions. */
197
+ edgeVersions: number
198
+ /** Quantized vector slots. */
199
+ vectors: number
200
+ /** Tombstoned fact records awaiting physical purge. */
201
+ tombstones: number
202
+ /** Vector slots covered by HNSW. */
203
+ hnswIndexed: number
204
+ /** The next fact id to be assigned. */
205
+ nextFact: number
206
+ /** The next entity id to be assigned. */
207
+ nextEntity: number
208
+ /** The next edge-version id to be assigned. */
209
+ nextEdge: number
210
+ /** Total bytes held by the engine's pools. */
211
+ poolBytes: number
212
+ }
213
+ /**
214
+ * The raw record behind a [`FactSnapshot`] — temporality and flags. (Internal
215
+ * pointers — the blob/vector slots and the reserved `kind` — are omitted.)
216
+ */
217
+ export interface FactRecord {
218
+ /** The fact id. */
219
+ id: number
220
+ /** Subject entity id (a sentinel when none). */
221
+ entity: number
222
+ /** Bit set of fact flags (tombstone / closed / has-vector). */
223
+ flags: number
224
+ /** Predecessor in the revision chain (a sentinel when none). */
225
+ revises: number
226
+ /** Knowledge axis: when the memory learned it (unix ms). */
227
+ recordedAt: number
228
+ /** Truth axis start (unix ms). */
229
+ validFrom: number
230
+ /** Truth axis end (unix ms), or the open sentinel — see the module note. */
231
+ validTo: number
232
+ }
233
+ /** One fact's full card (from `get`). */
234
+ export interface FactSnapshot {
235
+ /** The raw record (temporality, flags, references). */
236
+ record: FactRecord
237
+ /** The fact text. */
238
+ text: string
239
+ /**
240
+ * The fact's metadata as a key→value map (empty when it has none). Opaque
241
+ * to the engine — a URI to the real payload, a mime type, an external key.
242
+ */
243
+ metadata: Record<string, string>
244
+ }
245
+ /** One exported fact — the id-free, import-ready shape. */
246
+ export interface ExportedFact {
247
+ /**
248
+ * The fact's id in the database it came from. Informational: an import
249
+ * assigns fresh ids. Present because edges name their provenance fact by
250
+ * id, so a dump carrying edges needs something for them to point at.
251
+ */
252
+ id: number
253
+ /** The fact text. */
254
+ text: string
255
+ /** Subject entity name, if any. */
256
+ entity?: string
257
+ /** Tag strings. */
258
+ tags: Array<string>
259
+ /** Metadata as a key→value map (empty when none); preserved on import. */
260
+ metadata: Record<string, string>
261
+ /** When the memory learned it (unix ms; informational). */
262
+ recordedAt: number
263
+ /** Validity start (unix ms; preserved on import). */
264
+ validFrom: number
265
+ }
266
+ /** One bounded page returned by `exportPage`. */
267
+ export interface ExportPage {
268
+ /** Open facts in fact-id order; never longer than the native page bound. */
269
+ facts: Array<ExportedFact>
270
+ /** Pass this opaque cursor to the next call; absent when the scan is done. */
271
+ nextCursor?: number
272
+ }
273
+ /** The report of a `maintain` pass. */
274
+ export interface MaintainReport {
275
+ /** Tombstoned facts physically removed by this pass. */
276
+ purged: number
277
+ /** On-disk image bytes before the pass. */
278
+ bytesBefore: number
279
+ /** On-disk image bytes after the pass. */
280
+ bytesAfter: number
281
+ /** No storage/index rewrite was needed. */
282
+ noOp: boolean
283
+ /** Tombstones present before the pass. */
284
+ tombstonesBefore: number
285
+ /** Fact records before the pass. */
286
+ factsBefore: number
287
+ /** Fact records after the pass. */
288
+ factsAfter: number
289
+ /** Vector slots before the pass. */
290
+ vectorsBefore: number
291
+ /** Vector slots after the pass. */
292
+ vectorsAfter: number
293
+ /** HNSW coverage before the pass. */
294
+ hnswIndexedBefore: number
295
+ /** HNSW coverage after the pass. */
296
+ hnswIndexedAfter: number
297
+ /** Physical compaction ran. */
298
+ structuralCompacted: boolean
299
+ /** BM25 was compacted from existing postings. */
300
+ bm25Compacted: boolean
301
+ /** BM25 was rebuilt from text. */
302
+ bm25Reindexed: boolean
303
+ /** HNSW was rebuilt from empty. */
304
+ hnswRebuilt: boolean
305
+ /** HNSW was carried/remapped. */
306
+ hnswRemapped: boolean
307
+ /** Vector slots inserted into HNSW. */
308
+ hnswInserted: number
309
+ /**
310
+ * The edge arenas were rewritten page-dense (`full` only). No edge
311
+ * version is ever dropped, so the version count is unchanged — only the
312
+ * bytes shrink.
313
+ */
314
+ edgesCompacted: boolean
315
+ /** Current edges before the pass. */
316
+ edgesBefore: number
317
+ /** Historical edge versions before the pass. */
318
+ edgeVersionsBefore: number
319
+ }
320
+ /** How much work a `maintain` pass should do. */
321
+ export const enum MaintainMode {
322
+ /**
323
+ * Only pending work: purge tombstones, refresh a stale text index, and
324
+ * advance the vector graph within a bounded budget. Cheap to run often.
325
+ */
326
+ Auto = 'auto',
327
+ /** Physically purge tombstoned facts and compact storage and indexes. */
328
+ Compact = 'compact',
329
+ /** Rebuild the text index by re-reading and re-tokenizing every fact. */
330
+ ReindexText = 'reindex-text',
331
+ /** Build or advance the vector graph without compacting anything else. */
332
+ OptimizeVectors = 'optimize-vectors',
333
+ /**
334
+ * Rebuild every rebuildable structure, fully optimize vectors and repack
335
+ * the edge arenas. O(database) work; no history is ever dropped.
336
+ */
337
+ Full = 'full'
338
+ }
339
+ /**
340
+ * One memory as the workspace registry knows it.
341
+ *
342
+ * Hand-mapped rather than serde-round-tripped like the rest of this file:
343
+ * `DbEntry` carries a `DbName`, which is a validated newtype with no serde
344
+ * derive, and giving one to a public host type only so a wrapper could
345
+ * round-trip it would be the wrong direction of dependency.
346
+ */
347
+ export interface DbEntry {
348
+ /** The memory's name — its identity, and what `Workspace.open` takes. */
349
+ db: string
350
+ /** What it is for. */
351
+ description: string
352
+ /** Its tags. */
353
+ tags: Array<string>
354
+ /** Its owner, if recorded. */
355
+ owner?: string
356
+ /** Whether it is labelled archived. */
357
+ archived: boolean
358
+ }
359
+ /** What a `Workspace.reindex()` pass did. */
360
+ export interface ReindexReport {
361
+ /** Memories whose own description was copied into the registry. */
362
+ indexed: Array<string>
363
+ /**
364
+ * Memories nobody has described. Not a fault — a memory works without a
365
+ * description; it just cannot be found by one.
366
+ */
367
+ undescribed: Array<string>
368
+ /**
369
+ * Memories another process holds open, so this pass could not read them.
370
+ * Named rather than skipped silently: the registry is knowingly incomplete.
371
+ */
372
+ busy: Array<string>
373
+ }
374
+ /** Something `Workspace.verify()` found. Reported, never repaired. */
375
+ export interface WorkspaceProblem {
376
+ /** The memory it concerns (empty for a kind this binding does not know). */
377
+ db: string
378
+ /**
379
+ * What kind: `"missing"`, `"undescribed"`, `"stale"`, `"unreadable"`,
380
+ * `"ambiguous-self"`. The same vocabulary the CLI prints in `--json`.
381
+ */
382
+ issue: string
383
+ /** More detail, where the kind carries any. */
384
+ detail?: string
385
+ }
386
+ /** Options for [`Workspace::new`]. */
387
+ export interface WorkspaceOptions {
388
+ /**
389
+ * Embedding dimension, as in [`crate::db::OpenOptions`]. Applies to every
390
+ * memory in the workspace and to the registry.
391
+ */
392
+ dim?: number
393
+ /**
394
+ * Path to a `config.toml`. Resolution is the standard one when omitted.
395
+ * Its `[workspace]` section supplies the pool defaults below.
396
+ */
397
+ config?: string
398
+ /**
399
+ * Memories kept open at once; the least recently used is closed to make
400
+ * room. Defaults to `[workspace].max_open`, else 16.
401
+ */
402
+ maxOpen?: number
403
+ /**
404
+ * Milliseconds a memory may sit unused before `closeIdle()` closes it.
405
+ * `0` disables the sweep. Defaults to `[workspace].idle_timeout_ms`, else
406
+ * 60000.
407
+ *
408
+ * This is a liveness setting, not a memory one: an open memory holds the
409
+ * file's exclusive lock, so a long-running process that never let go would
410
+ * make its memories unreachable from anything else on the machine.
411
+ */
412
+ idleTimeoutMs?: number
413
+ }
414
+ /** What to record about a memory — the argument of [`Workspace::describe`]. */
415
+ export interface DescribeArgs {
416
+ /**
417
+ * What this memory is for, in the words someone would search with. This is
418
+ * the text `find` matches.
419
+ */
420
+ description: string
421
+ /** Tags to filter by. */
422
+ tags?: Array<string>
423
+ /**
424
+ * Who it belongs to. Recorded as a graph edge, so `find("ann")` returns
425
+ * what Ann owns even though no description mentions her.
426
+ */
427
+ owner?: string
428
+ }
429
+ /**
430
+ * The engine/package version (the workspace version; the npm package tracks
431
+ * it release-for-release).
432
+ */
433
+ export declare function version(): string
434
+ /** A short, version-free description pointing the caller at the skill. */
435
+ export declare function about(): string
436
+ /** One config.toml setting returned by [`settings_help`]. */
437
+ export interface SettingHelpItem {
438
+ /** TOML section name. */
439
+ section: string
440
+ /** TOML key name. */
441
+ key: string
442
+ /** Human-readable value type. */
443
+ valueType: string
444
+ /** Displayed default value. */
445
+ defaultValue: string
446
+ /** Setting behavior. */
447
+ description: string
448
+ /** Owning surface: shared, CLI or MCP. */
449
+ scope: string
450
+ }
451
+ /** Complete config.toml help returned by [`settings_help`]. */
452
+ export interface SettingsHelpResult {
453
+ /** Config discovery order from highest to lowest precedence. */
454
+ configPathPrecedence: Array<string>
455
+ /** Resolved platform default config path, if the OS exposes a user home. */
456
+ defaultConfigPath?: string
457
+ /** Every supported config.toml setting. */
458
+ settings: Array<SettingHelpItem>
459
+ }
460
+ /** Return the complete settings catalogue without opening a database. */
461
+ export declare function settingsHelp(): SettingsHelpResult
462
+ /**
463
+ * The companion skill for napi consumers: the canonical `SKILL.md` with the
464
+ * CLI/MCP "Run it" appendix removed (a napi host has one transport and always
465
+ * ships skill and engine from the same release, so that ceremony never applies).
466
+ */
467
+ export declare function skill(): string
468
+ /** The canonical, unstripped `SKILL.md` (what CLI/MCP consumers read). */
469
+ export declare function skillFull(): string
470
+ /**
471
+ * The `<!-- skill-version: X.Y.Z -->` marker value from the canonical skill
472
+ * (read from the raw text, so the marker living inside the stripped block is
473
+ * still visible here).
474
+ */
475
+ export declare function skillVersion(): string
476
+ /**
477
+ * A memory over one plugmem file — the napi mirror of [`plugmem_host::Database`]
478
+ * (writer) or [`plugmem_host::ReadOnlyDatabase`] (with `{ readOnly: true }`).
479
+ * Construct it, call the verbs, and `close()` it to release the file when done.
480
+ */
481
+ export declare class Plugmem {
482
+ /**
483
+ * Opens (or creates) the memory at `path` and resolves with the handle. If
484
+ * `path` is omitted, resolution is `PLUGMEM_DB` > `[database].path` > the
485
+ * platform data path — and [`path()`](Plugmem::path) reports what that was.
486
+ *
487
+ * **A static method, not a constructor, and that is the point.** Opening
488
+ * takes the file's exclusive lock, replays the journal and maps the
489
+ * snapshot — work proportional to what is on disk. A JavaScript
490
+ * constructor must evaluate to its object immediately, so `new` has no way
491
+ * to hand that to a worker: it would run on the one thread that executes
492
+ * JavaScript and freeze the process for the length of the replay. A static
493
+ * method can return a `Promise`, so it does.
494
+ *
495
+ * @throws synchronously on a config error (the file is read before any
496
+ * work is scheduled); rejects if another writer holds the lock
497
+ * (`PLUGMEM_LOCKED`), if `readOnly` is set on a database with no published
498
+ * snapshot (`PLUGMEM_NEEDS_CHECKPOINT`), or on an IO error.
499
+ */
500
+ static open(path?: string | undefined | null, options?: OpenOptions | undefined | null): Promise<Plugmem>
501
+ /**
502
+ * The file this memory is open on.
503
+ *
504
+ * Worth having because the constructor may resolve the path rather than be
505
+ * given one — `PLUGMEM_DB`, then `[database].path`, then the platform data
506
+ * path — and `new Plugmem()` with no argument otherwise leaves the caller
507
+ * unable to say which file it just wrote to.
508
+ */
509
+ path(): string
510
+ /**
511
+ * Stores a fact and resolves with its id plus similar/conflicting live
512
+ * facts.
513
+ *
514
+ * **Async** (returns a `Promise`): with an `[embedder]` configured this
515
+ * makes an HTTP call to the provider, and a write waits for the journal's
516
+ * durability policy. Both are blocking work, and Node has exactly one
517
+ * thread that runs JavaScript — doing them on it would freeze every timer,
518
+ * socket and callback in the process for the whole round trip. It runs on
519
+ * a libuv worker instead. Arguments are still checked synchronously, so a
520
+ * refused one throws here rather than rejecting later.
521
+ * @throws synchronously in read-only mode.
522
+ */
523
+ remember(args: RememberArgs): Promise<RememberOutcome>
524
+ /**
525
+ * Stores a batch of facts and resolves with one outcome per input.
526
+ *
527
+ * A batch may call a remote embedder and always performs one journal sync,
528
+ * so it runs on napi-rs' libuv worker pool.
529
+ */
530
+ rememberMany(args: Array<RememberArgs>): Promise<RememberOutcome[]>
531
+ /**
532
+ * Closes fact `id`, records `args` as its successor, and resolves with the
533
+ * outcome. **Async** for the same reasons as
534
+ * [`remember`](Plugmem::remember).
535
+ * @throws synchronously in read-only mode.
536
+ */
537
+ revise(id: number, args: RememberArgs): Promise<RememberOutcome>
538
+ /**
539
+ * Ranked, fused recall. Resolves with the structured result (its `rendered`
540
+ * field is the prompt-ready block; `facts`/`edges` are the structured hits).
541
+ *
542
+ * **Async** (returns a `Promise`): a text query with an `[embedder]`
543
+ * configured costs an HTTP round trip, and blocking the one thread that
544
+ * runs JavaScript for it would stall the whole process. The query shape is
545
+ * still validated synchronously.
546
+ */
547
+ recall(args?: RecallArgs | undefined | null): Promise<RecallResult>
548
+ /**
549
+ * Tombstones fact `id` (physically purged at the next `maintain`) and
550
+ * resolves with whether it was a live fact.
551
+ *
552
+ * **Async**: every write syncs the journal, and the host's post-write
553
+ * policy can fire a whole maintenance pass or a reshard from here — work
554
+ * proportional to the database, which the JS thread must not be holding.
555
+ * @throws synchronously in read-only mode.
556
+ */
557
+ forget(id: number): Promise<boolean>
558
+ /**
559
+ * Upserts a typed edge `src -rel-> dst`. **Async** for the same reason as
560
+ * [`forget`](Plugmem::forget). @throws synchronously in read-only mode.
561
+ */
562
+ link(args: LinkArgs): Promise<void>
563
+ /**
564
+ * Closes the current typed edge `src -rel-> dst`, resolving with whether
565
+ * one was open. **Async** for the same reason as
566
+ * [`forget`](Plugmem::forget). @throws synchronously in read-only mode.
567
+ */
568
+ unlink(args: LinkArgs): Promise<boolean>
569
+ /** One fact's full card by `id`, or `null` if unknown/tombstoned. */
570
+ get(id: number): FactSnapshot | null
571
+ /** Engine size counters. */
572
+ stats(): Stats
573
+ /**
574
+ * Every currently-open fact, as one array (id-free, import-ready).
575
+ *
576
+ * **Async, but still unbounded, in two ways.** The scan runs on a worker,
577
+ * yet the whole memory is materialized into a single array before it
578
+ * resolves, so peak memory is the whole export. And `resolve` runs on the
579
+ * JS thread by definition, so building one JavaScript object per fact
580
+ * stalls it: measured at ~244 ms of a 289 ms call over 100 000 facts,
581
+ * against 0 ms for the same data through `exportPage`. A promise hides
582
+ * neither cost. Prefer `exportPage` for anything but a small memory or a
583
+ * script.
584
+ */
585
+ export(): Promise<ExportedFact[]>
586
+ /**
587
+ * Returns at most 128 inspected fact ids' open facts on a libuv worker
588
+ * thread. A sparse page can be empty and still carry `nextCursor`.
589
+ *
590
+ * Pass `nextCursor` back as `cursor` until it is absent. Each Promise owns
591
+ * exactly one bounded page and resolves only after its native scan has
592
+ * completed; there is no callback queue and no database lock held while JS
593
+ * processes the result. A writer may change between page calls, so do not
594
+ * mutate it during a snapshot-style backup; a read-only handle is stable.
595
+ */
596
+ exportPage(cursor?: number | undefined | null): Promise<ExportPage>
597
+ /** One fact's tags, or an empty array for an unknown or tombstoned id. */
598
+ tagsOf(id: number): Array<string>
599
+ /**
600
+ * Content-integrity check; rejects on the first inconsistency found.
601
+ *
602
+ * **Async**: this is a full sweep — every fact's text and metadata, the
603
+ * vector mapping, and both directions of every edge. On a large memory
604
+ * that is seconds of work, and it belongs on a worker.
605
+ */
606
+ verify(): Promise<void>
607
+ /**
608
+ * Runs policy-driven maintenance; resolves with the before/after report.
609
+ * **Async** (returns a `Promise`): the pass may do disk I/O (compaction,
610
+ * HNSW work), so it runs on a libuv worker thread and never blocks the
611
+ * event loop. @throws synchronously in read-only mode.
612
+ *
613
+ * `mode` defaults to `auto`, which does only what is pending. `full`
614
+ * rebuilds everything and repacks the edge arenas — O(database) work, and
615
+ * the only mode that reclaims edge-history page slack.
616
+ */
617
+ maintain(mode?: 'auto' | 'compact' | 'reindex-text' | 'optimize-vectors' | 'full'): Promise<MaintainReport>
618
+ /**
619
+ * Flushes the journal into a fresh snapshot. **Async** (returns a `Promise`):
620
+ * it writes and fsyncs a snapshot file, so it runs on a libuv worker thread.
621
+ * @throws synchronously in read-only mode.
622
+ */
623
+ checkpoint(): Promise<void>
624
+ /**
625
+ * The pinned snapshot generation (read-only mode only).
626
+ * @throws on a writer.
627
+ */
628
+ generation(): number
629
+ /**
630
+ * Advance to the writer's latest published checkpoint (read-only mode only);
631
+ * returns whether a newer generation was adopted. @throws on a writer.
632
+ */
633
+ refresh(): boolean
634
+ /**
635
+ * Releases the file and its lock. Every verb afterwards throws; calling it
636
+ * again is a no-op. (The handle is also released when the object is GC'd,
637
+ * but `close()` makes the moment explicit — e.g. before a read-only reopen.)
638
+ */
639
+ close(): void
640
+ }
641
+ /**
642
+ * A directory of named memories — the napi mirror of
643
+ * [`plugmem_host::Workspace`].
644
+ */
645
+ export declare class Workspace {
646
+ /**
647
+ * Opens the workspace rooted at `root`. Creates nothing: the directories
648
+ * appear when a memory is first written.
649
+ *
650
+ * @throws on a config error.
651
+ */
652
+ constructor(root: string, options?: WorkspaceOptions | undefined | null)
653
+ /**
654
+ * Opens the memory named `db` and returns it as a [`Plugmem`] — the same
655
+ * class, and the same verbs, as a memory opened by path.
656
+ *
657
+ * `create` defaults to `true`: a first use of an unused name brings that
658
+ * memory into being, which is what makes a new conversation need no
659
+ * registration step. Pass `false` to require that it already exists, which
660
+ * is what a read should do so a misspelled name is diagnosed rather than
661
+ * answered with nothing.
662
+ *
663
+ * @throws if the name is not a usable memory name, if it does not exist and
664
+ * `create` is false, or if another process holds it.
665
+ * **Async**: a first open replays the memory's journal and maps its
666
+ * snapshot, and making room in the pool closes another memory — file work
667
+ * that the one thread running JavaScript must not be holding.
668
+ */
669
+ open(db: string, create?: boolean | undefined | null): Promise<Plugmem>
670
+ /**
671
+ * Every memory in the directory, sorted by name.
672
+ *
673
+ * Reads the filesystem, not the registry: a memory that exists but was
674
+ * never described still appears.
675
+ * **Async**: it reads the directory.
676
+ */
677
+ list(): Promise<string[]>
678
+ /**
679
+ * Every described memory, sorted by name.
680
+ *
681
+ * **Async**: the registry is itself a memory, so this opens and reads a
682
+ * database.
683
+ */
684
+ entries(): Promise<DbEntry[]>
685
+ /**
686
+ * The memories whose descriptions best match `query`, best first.
687
+ *
688
+ * This is the answer to "I do not know the name": ask in words, get names
689
+ * back, then open by name. A person's name works too — an owner is a graph
690
+ * edge, and the graph source reaches it.
691
+ * **Async**: this is a full recall against the registry memory — the same
692
+ * hybrid retrieval any other recall runs.
693
+ */
694
+ find(query: string, k?: number | undefined | null): Promise<DbEntry[]>
695
+ /**
696
+ * Records what a memory is for — in the memory itself and in the registry,
697
+ * so the registry can always be rebuilt from the memories. Creates the
698
+ * memory if it does not exist.
699
+ *
700
+ * Called again for the same memory this revises rather than duplicating,
701
+ * so the history of what it used to be for is kept.
702
+ * **Async**: it writes twice — into the memory itself and into the
703
+ * registry — and each write syncs a journal.
704
+ */
705
+ describe(db: string, args: DescribeArgs): Promise<void>
706
+ /**
707
+ * Labels a memory archived, keeping its description. Returns whether
708
+ * anything changed. Archiving does not close, move or delete anything.
709
+ *
710
+ * @throws if the memory has no registry record to archive.
711
+ * **Async**: a registry write.
712
+ */
713
+ archive(db: string): Promise<boolean>
714
+ /**
715
+ * Rebuilds the registry from the memories' own descriptions.
716
+ *
717
+ * Runs on a libuv thread: it opens and reads every memory in the
718
+ * directory, which is not work for the main thread. A memory another
719
+ * process holds open cannot be read and is named in the report rather than
720
+ * skipped silently.
721
+ */
722
+ reindex(): Promise<ReindexReport>
723
+ /**
724
+ * Checks the registry against the directory. Reports every disagreement
725
+ * and repairs nothing — a workspace is a directory a person can edit, and
726
+ * guessing at their intent is how a consistency check loses data.
727
+ */
728
+ verify(): Promise<WorkspaceProblem[]>
729
+ /**
730
+ * Closes every memory unused for longer than the idle timeout, returning
731
+ * how many were closed. Call it on a timer: nothing else releases the file
732
+ * lock on a memory nobody is asking about.
733
+ */
734
+ closeIdle(): number
735
+ /** How many memories are open right now. */
736
+ openCount(): number
737
+ /**
738
+ * Closes every pooled memory and the registry, releasing their file locks,
739
+ * and closes the workspace. Every method then throws.
740
+ *
741
+ * A [`Plugmem`] handed out by `open()` is **not** closed by this: it is its
742
+ * own handle and holds its own lock until it is closed or garbage
743
+ * collected.
744
+ */
745
+ close(): void
746
+ }