plugmem 0.10.0 → 0.12.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 (3) hide show
  1. package/README.md +42 -58
  2. package/index.d.ts +56 -0
  3. package/package.json +7 -7
package/README.md CHANGED
@@ -233,6 +233,7 @@ only moves arguments and results across the boundary.
233
233
  | `rememberMany(args[])` | store a batch: one embedding round-trip, one journal sync |
234
234
  | `revise(id, args)` | close a fact and record its successor |
235
235
  | `forget(id)` | tombstone a fact; resolves with whether it was live |
236
+ | `forgetMany(ids[])` | tombstone a batch: one journal sync, one post-write pass |
236
237
  | `removeTag(tag)` | remove a tag from every current fact while preserving facts/history |
237
238
  | `link(args)` | upsert a typed edge, optionally with `provenance` |
238
239
  | `unlink(args)` | close the current edge; resolves with whether one was open |
@@ -446,72 +447,55 @@ the platform config directory, then defaults. The database path resolves from an
446
447
  explicit argument, then `$PLUGMEM_DB`, then `[database].path`, then the platform
447
448
  data directory.
448
449
 
449
- ```typescript
450
- const db = await Plugmem.open(undefined, { config: "./plugmem.toml" });
450
+ ```javascript
451
+ const db = await Plugmem.open("agent.plugmem", { config: "./plugmem.toml" });
451
452
  ```
452
453
 
453
454
  ```toml
454
455
  # plugmem.toml
455
- [database]
456
- path = "/path/to/memory.plugmem"
457
-
458
456
  [engine]
459
- dim = 768 # embedding size (0 = vectors off)
457
+ dim = 768 # 0 (the default) stores no vectors
460
458
 
461
- [recall] # optional every key has a tuned default
462
- w_vec = 2.0 # trust meaning over keywords in this memory
463
- half_life_days = 30 # and treat anything older than a month as stale
464
-
465
- [embedder] # optional — omit for lexical/tag/graph/time only
466
- enabled = true # false keeps settings but makes no embedder calls
467
- url = "http://localhost:11434/v1/embeddings"
459
+ [embedder] # omit for lexical, tag, graph and time only
460
+ url = "http://localhost:11434/v1/embeddings"
468
461
  model = "nomic-embed-text"
469
- space_id = "nomic-embed-text@v1" # optional; defaults to model
470
- api_key_env = "OPENAI_API_KEY" # env var holding the bearer token
471
-
472
- [maintenance]
473
- fsync = "each_op" # or "on_snapshot": faster, loses the journal tail on an OS crash
474
- ```
475
-
476
- `[engine]` is what a database is *built* with; changing one of those on an
477
- existing file is refused. `[recall]` and `[index]` are the opposite — reopening
478
- with different weights is how you change the ranking, so tune them freely. All
479
- of them are in the [full settings reference](https://github.com/m62624/plugmem/blob/main/crates/plugmem-host/SETTINGS.md).
480
-
481
- ### When a key is misspelled
482
-
483
- Unknown keys and sections do not stop anything, but they are not swallowed
484
- either — a misspelled `w_vec` changes no behaviour, and silence would leave you
485
- believing you had tuned something. **Read them once after opening**, because a
486
- native addon has nowhere sensible to print:
487
-
488
- ```javascript
489
- const db = await Plugmem.open("agent.plugmem", { config: "./plugmem.toml" });
490
- for (const warning of db.configWarnings()) console.warn(warning);
491
- // unknown setting [recall].w_vector — did you mean `w_vec`?
462
+ on_error = "degrade" # keep answering when the provider is down
492
463
  ```
493
464
 
494
- With an `[embedder]`, a text-only `remember`/`recall` embeds automatically, and
495
- the provider's HTTP call happens outside the engine lock. The `dim` open option
496
- sets the embedding size when there is no config; if the config built an
497
- embedder, its dimension governs and `dim` must agree.
498
-
499
- The host uses one `OpenAiCompatEmbedder` implementation for OpenAI, Ollama,
500
- LM Studio, vLLM and other OpenAI-compatible servers. `url` is the complete
501
- embeddings endpoint exactly as provided (nothing is appended), and `model` is
502
- the model name understood by that server. `space_id` optionally identifies the
503
- exact semantic space and defaults to `model`; it is never discovered over the
504
- network. Set `enabled = false` to keep the
505
- settings without creating or calling the embedder; `$PLUGMEM_EMBEDDER_ENABLED`
506
- overrides it with `true` or `false`.
507
-
508
- A read-only handle cannot embed inside the engine — writing into a zero-copy
509
- mapping is exactly what read-only exists to avoid so this binding embeds the
510
- query itself before the read. A text `recall` reaches the vector source in both
511
- modes.
512
-
513
- The [full settings reference](https://github.com/m62624/plugmem/blob/main/crates/plugmem-host/SETTINGS.md)
514
- lists every field and the OS-specific paths.
465
+ Every other key, its default and what it costs live in one place:
466
+
467
+ - [`config.example.toml`](https://github.com/m62624/plugmem/blob/main/config.example.toml) every key with its default, commented
468
+ out, ready to copy.
469
+ - [SETTINGS.md](https://github.com/m62624/plugmem/blob/main/crates/plugmem-host/SETTINGS.md) — the reference: what each key is for, which
470
+ sections are safe to change on an existing database, and the OS-specific
471
+ paths.
472
+ - `settingsHelp()` the same catalogue from the addon you have loaded.
473
+
474
+ What is specific to this binding:
475
+
476
+ - **`dim` is an open option too**, for callers with no config file. If the
477
+ config built an embedder, that embedder's dimension governs and `dim` must
478
+ agree with it.
479
+ - **A text-only `remember`/`recall` embeds automatically**, and the provider's
480
+ HTTP call happens outside the engine lockincluding on a read-only handle,
481
+ which embeds its query out here because the engine cannot embed into a
482
+ zero-copy mapping.
483
+ - **`embedderState()`** answers `'absent' | 'active' | 'suspended'`, and
484
+ `suspendEmbedder()` / `resumeEmbedder()` are the manual switches, for when you
485
+ already know the provider is gone. With `on_error = "degrade"` the addon does
486
+ this for itself: a failed call costs the vector and suspends the embedder
487
+ rather than failing the verb, and `reembed()` fills the missing vectors in
488
+ later. A `WorkspaceMemory` has the same three, as promises: one shared
489
+ provider, but a gate per memory, so suspending one leaves its siblings
490
+ answering with vectors.
491
+ - **Unknown keys are returned, not printed.** A native addon has nowhere
492
+ sensible to write, so read them once after opening:
493
+
494
+ ```javascript
495
+ const db = await Plugmem.open("agent.plugmem", { config: "./plugmem.toml" });
496
+ for (const warning of db.configWarnings()) console.warn(warning);
497
+ // unknown setting [recall].w_vector — did you mean `w_vec`?
498
+ ```
515
499
 
516
500
  ## Async and the event loop
517
501
 
@@ -521,7 +505,7 @@ callback in the process. Anything that can do that runs on a libuv worker and
521
505
  returns a promise instead.
522
506
 
523
507
  Promises: `Plugmem.open`, `remember`, `rememberGuarded`, `rememberMany`, `revise`, `recall`,
524
- `forget`, `removeTag`, `listTags`, `link`, `unlink`, `export`, `exportPage`, `verify`, `maintain`,
508
+ `forget`, `forgetMany`, `removeTag`, `listTags`, `link`, `unlink`, `export`, `exportPage`, `verify`, `maintain`,
525
509
  `checkpoint`, every database verb on `WorkspaceMemory`, and every registry
526
510
  verb on `Workspace`.
527
511
 
package/index.d.ts CHANGED
@@ -731,6 +731,15 @@ export declare class Plugmem {
731
731
  * @throws synchronously in read-only mode.
732
732
  */
733
733
  forget(id: number): Promise<boolean>
734
+ /**
735
+ * Tombstones many facts at once. Equivalent to [`forget`](Plugmem::forget)
736
+ * on each id in order, but under **one** journal sync and **one**
737
+ * post-write policy pass instead of N — the same batching
738
+ * [`rememberMany`](Plugmem::remember_many) does for writes. Resolves with
739
+ * one boolean per id, in the same order, `true` when that id was live.
740
+ * @throws synchronously in read-only mode.
741
+ */
742
+ forgetMany(ids: Array<number>): Promise<boolean[]>
734
743
  /**
735
744
  * Upserts a typed edge `src -rel-> dst`. **Async** for the same reason as
736
745
  * [`forget`](Plugmem::forget). @throws synchronously in read-only mode.
@@ -878,6 +887,32 @@ export declare class Plugmem {
878
887
  * but `close()` makes the moment explicit — e.g. before a read-only reopen.)
879
888
  */
880
889
  close(): void
890
+ /**
891
+ * Whether this handle has an embedder, and whether it is usable now.
892
+ *
893
+ * `"absent"` when none is configured, `"active"` when it is being called,
894
+ * `"suspended"` when it is not — either because `suspendEmbedder()` said
895
+ * so, or because it failed under `on_error = "degrade"`. A suspended
896
+ * memory still remembers, still recalls and still forgets; what it does
897
+ * not do is meaning-based ranking.
898
+ */
899
+ embedderState(): 'absent' | 'active' | 'suspended'
900
+ /**
901
+ * Stops calling the embedder until `resumeEmbedder()`.
902
+ *
903
+ * For when the caller knows the provider is gone — the machine went
904
+ * offline, the model was unloaded — and would rather not pay one failed
905
+ * request per verb to rediscover it. Writes made meanwhile store no
906
+ * vector; `reembed()` fills them in later. Idempotent, and a no-op
907
+ * without an embedder. Works on a read-only handle too, which is the one
908
+ * that embeds its own queries.
909
+ */
910
+ suspendEmbedder(): void
911
+ /**
912
+ * Calls the embedder again. Nothing is verified here: the next verb that
913
+ * needs a vector finds out, and suspends it again if it is still down.
914
+ */
915
+ resumeEmbedder(): void
881
916
  }
882
917
  /**
883
918
  * A resumable byte-level check of one snapshot generation.
@@ -936,6 +971,7 @@ export declare class WorkspaceMemory {
936
971
  revise(id: number, args: RememberArgs): Promise<RememberOutcome>
937
972
  recall(args?: RecallArgs | undefined | null): Promise<RecallResult>
938
973
  forget(id: number): Promise<boolean>
974
+ forgetMany(ids: Array<number>): Promise<boolean[]>
939
975
  link(args: LinkArgs): Promise<void>
940
976
  unlink(args: LinkArgs): Promise<boolean>
941
977
  get(id: number): Promise<FactSnapshot | null>
@@ -951,6 +987,26 @@ export declare class WorkspaceMemory {
951
987
  maintain(mode?: 'auto' | 'compact' | 'reindex-text' | 'optimize-vectors' | 'full'): Promise<MaintainReport>
952
988
  reembed(batchSize?: number | undefined | null): Promise<ReembedReport>
953
989
  checkpoint(): Promise<void>
990
+ /**
991
+ * Whether this memory has an embedder, and whether it is usable now:
992
+ * `"absent"`, `"active"` or `"suspended"`.
993
+ *
994
+ * A workspace shares one provider between its memories, but each memory
995
+ * keeps its own gate — so this answers for this memory alone. A sibling
996
+ * that has not called the dead endpoint yet still reports `"active"`.
997
+ */
998
+ embedderState(): Promise<'absent' | 'active' | 'suspended'>
999
+ /**
1000
+ * Stops calling this memory's embedder until `resumeEmbedder()`. Writes
1001
+ * made meanwhile store no vector; `reembed()` fills them in later.
1002
+ */
1003
+ suspendEmbedder(): Promise<void>
1004
+ /**
1005
+ * Calls this memory's embedder again. Nothing is verified here: the next
1006
+ * verb that needs a vector finds out, and suspends it again if it is
1007
+ * still down.
1008
+ */
1009
+ resumeEmbedder(): Promise<void>
954
1010
  }
955
1011
  export declare class Workspace {
956
1012
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plugmem",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "Native Node.js addon for plugmem: an embedded bitemporal memory and retrieval engine for local-first applications and agents (remember / recall / revise / forget over one local database).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -43,11 +43,11 @@
43
43
  "typecheck": "tsc -p tsconfig.json"
44
44
  },
45
45
  "optionalDependencies": {
46
- "plugmem-linux-x64-gnu": "0.10.0",
47
- "plugmem-linux-arm64-gnu": "0.10.0",
48
- "plugmem-darwin-x64": "0.10.0",
49
- "plugmem-darwin-arm64": "0.10.0",
50
- "plugmem-win32-x64-msvc": "0.10.0",
51
- "plugmem-win32-arm64-msvc": "0.10.0"
46
+ "plugmem-linux-x64-gnu": "0.12.0",
47
+ "plugmem-linux-arm64-gnu": "0.12.0",
48
+ "plugmem-darwin-x64": "0.12.0",
49
+ "plugmem-darwin-arm64": "0.12.0",
50
+ "plugmem-win32-x64-msvc": "0.12.0",
51
+ "plugmem-win32-arm64-msvc": "0.12.0"
52
52
  }
53
53
  }