plugmem 0.1.3
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.
- package/README.md +136 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# plugmem-napi
|
|
2
|
+
|
|
3
|
+
> ⚠️ Experimental. plugmem is mostly an AI-built experiment — written with
|
|
4
|
+
> the help of a small local model (Qwen3.6-35B-A3B-UD-Q4_K_XL.gguf) and various
|
|
5
|
+
> Claude models, in roughly equal measure. Expect non-professional design
|
|
6
|
+
> choices, rough edges, broken behavior, or mistakes. Use it at your own risk.
|
|
7
|
+
|
|
8
|
+
`plugmem-napi` is the **native Node.js addon** for the plugmem
|
|
9
|
+
[temporal-memory engine](https://docs.rs/plugmem-core/latest) — it embeds
|
|
10
|
+
[`plugmem-host`](https://docs.rs/plugmem-host/latest) **in the Node process**
|
|
11
|
+
(real mmap, file locking, cross-process MVCC — the whole engine, unchanged) and
|
|
12
|
+
exposes it to **JavaScript / TypeScript** as a `Plugmem` class. It is published
|
|
13
|
+
to npm as **`plugmem`**.
|
|
14
|
+
|
|
15
|
+
Because it is native (not WebAssembly), there is no whole-file-in-RAM copy and no
|
|
16
|
+
4 GiB ceiling: the OS pages the snapshot in and out exactly as it does for the
|
|
17
|
+
Rust library. It loads in **Node, and any N-API host (Deno, Bun)**.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```console
|
|
22
|
+
$ npm install plugmem
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`npm i plugmem` pulls the meta package, which through `optionalDependencies`
|
|
26
|
+
installs only the prebuilt binary for your platform — one of
|
|
27
|
+
`plugmem-{linux-x64-gnu, linux-arm64-gnu, darwin-x64, darwin-arm64,
|
|
28
|
+
win32-x64-msvc, win32-arm64-msvc}`. No toolchain, no build step.
|
|
29
|
+
|
|
30
|
+
## Which door is this?
|
|
31
|
+
|
|
32
|
+
plugmem is **embedded-first, like SQLite**. Pick the door for your language:
|
|
33
|
+
|
|
34
|
+
| You are… | Use | Why |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| **writing JavaScript / TypeScript for Node** | **`plugmem-napi`** (this, npm `plugmem`) | The engine *in your Node process*, native speed, typed for TS. |
|
|
37
|
+
| **writing Rust** | [`plugmem-host`](https://docs.rs/plugmem-host/latest) | The engine in your process, like linking SQLite. |
|
|
38
|
+
| **an agent, or another language** (Python, Go…) | [`plugmem-mcp`](https://docs.rs/plugmem-mcp/latest) | A long-lived stdio JSON-RPC sidecar; language-independent. |
|
|
39
|
+
| a person at a **terminal / script** | [`plugmem-cli`](https://docs.rs/plugmem-cli/latest) | The human door. |
|
|
40
|
+
|
|
41
|
+
So: **Node/TS → napi; Rust → host; an agent or other language → MCP; a human →
|
|
42
|
+
the CLI.**
|
|
43
|
+
|
|
44
|
+
## Usage (TypeScript)
|
|
45
|
+
|
|
46
|
+
Every argument and result is typed — napi generates `index.d.ts`, so a TS host
|
|
47
|
+
gets full autocomplete and checking:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { Plugmem } from "plugmem";
|
|
51
|
+
|
|
52
|
+
const db = new Plugmem("agent.plugmem"); // or { readOnly: true }
|
|
53
|
+
|
|
54
|
+
const out = db.remember({
|
|
55
|
+
text: "prefers tokio",
|
|
56
|
+
entity: "user",
|
|
57
|
+
tags: ["pref"],
|
|
58
|
+
links: [{ rel: "works_at", entity: "acme" }],
|
|
59
|
+
metadata: { source: "chat", uri: "s3://bucket/note.txt" }, // opaque; a pointer
|
|
60
|
+
});
|
|
61
|
+
out.id; // number
|
|
62
|
+
out.similar; // Similar[] — the engine surfaces conflicts, you decide
|
|
63
|
+
|
|
64
|
+
const res = db.recall({ query: "runtime?", k: 5 });
|
|
65
|
+
res.rendered; // the prompt-ready block
|
|
66
|
+
res.facts; // RecalledFact[] — { id, score, entity, recordedAt, … }
|
|
67
|
+
|
|
68
|
+
const card = db.get(out.id);
|
|
69
|
+
card.metadata; // Record<string,string> — keys sorted, {} when none
|
|
70
|
+
|
|
71
|
+
db.revise(out.id, { text: "prefers async-std" });
|
|
72
|
+
db.link({ src: "user", rel: "works_at", dst: "acme" });
|
|
73
|
+
|
|
74
|
+
await db.checkpoint(); // async (see below)
|
|
75
|
+
db.close(); // release the file + lock explicitly
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Configuration & embeddings
|
|
79
|
+
|
|
80
|
+
The constructor resolves settings **exactly like the CLI and MCP server**: an
|
|
81
|
+
explicit `config` path wins, else `$PLUGMEM_CONFIG`, else
|
|
82
|
+
`$XDG_CONFIG_HOME/plugmem/config.toml`, else all defaults.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const db = new Plugmem("agent.plugmem", { config: "./plugmem.toml" });
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```toml
|
|
89
|
+
# plugmem.toml
|
|
90
|
+
[engine]
|
|
91
|
+
dim = 768 # embedding size (0 = vectors off)
|
|
92
|
+
|
|
93
|
+
[embedder] # optional — omit for lexical/tag/graph/time only
|
|
94
|
+
kind = "ollama" # or openai / lmstudio / vllm / llamacpp
|
|
95
|
+
url = "http://localhost:11434/v1/embeddings"
|
|
96
|
+
model = "nomic-embed-text"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
With an `[embedder]`, a text-only `remember`/`recall` **auto-embeds** — the
|
|
100
|
+
provider's HTTP call runs outside the engine lock. Without one, there is no
|
|
101
|
+
embedder and vector recall is skipped (lexical, tag, graph and time recall still
|
|
102
|
+
answer). The optional `dim` open option sets the embedding size when there is no
|
|
103
|
+
config; if the config configured an embedder, its dimension governs and `dim`
|
|
104
|
+
must agree. A `{ readOnly: true }` handle never auto-embeds — pass a vector.
|
|
105
|
+
|
|
106
|
+
## The verbs
|
|
107
|
+
|
|
108
|
+
Method names mirror `plugmem-host`'s `Database` one-to-one.
|
|
109
|
+
|
|
110
|
+
**Writer** (default): `remember`, `recall`, `revise(id, args)`, `forget(id)`,
|
|
111
|
+
`link`, `get(id)`, `stats`, `export`, `verify`, and the two **async** verbs
|
|
112
|
+
below. **Read-only** (`{ readOnly: true }`, observing another process's writer):
|
|
113
|
+
`recall`, `get`, `stats`, `export`, `verify`, plus `generation()` (the pinned
|
|
114
|
+
snapshot generation) and `refresh()` (advance to the writer's latest checkpoint);
|
|
115
|
+
the write verbs throw.
|
|
116
|
+
|
|
117
|
+
**No `import` verb** — bulk-loading a `backup.jsonl` reads a file on disk, which
|
|
118
|
+
is [`plugmem-cli import`](https://docs.rs/plugmem-cli/latest)'s job. An agent
|
|
119
|
+
remembers facts one at a time as the conversation goes.
|
|
120
|
+
|
|
121
|
+
## Async and concurrency (no tokio)
|
|
122
|
+
|
|
123
|
+
`maintain()` and `checkpoint()` do real disk I/O (compaction, HNSW build,
|
|
124
|
+
fsync), so they return a **`Promise`** and run on the **libuv** thread pool —
|
|
125
|
+
they never block the event loop. Every other verb is microsecond-fast in memory
|
|
126
|
+
and stays synchronous (a Promise there would be pure overhead). There is no async
|
|
127
|
+
runtime: the engine is CPU-bound, and the one thing that can wait — a remote
|
|
128
|
+
embedder's HTTP call — happens outside the engine lock.
|
|
129
|
+
|
|
130
|
+
`close()` releases the file and its lock; every verb afterwards throws, and it is
|
|
131
|
+
idempotent (the handle is also released on garbage collection, but `close()`
|
|
132
|
+
makes the moment explicit — e.g. before reopening the same file read-only).
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
MIT.
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "plugmem",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Native Node.js addon for plugmem: an embedded long-term memory engine for LLM agents (remember / recall / revise / forget over one local file).",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/m62624/plugmem.git"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"main": "index.js",
|
|
11
|
+
"types": "index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"index.js",
|
|
14
|
+
"index.d.ts"
|
|
15
|
+
],
|
|
16
|
+
"napi": {
|
|
17
|
+
"name": "plugmem",
|
|
18
|
+
"triples": {
|
|
19
|
+
"defaults": false,
|
|
20
|
+
"additional": [
|
|
21
|
+
"x86_64-unknown-linux-gnu",
|
|
22
|
+
"aarch64-unknown-linux-gnu",
|
|
23
|
+
"x86_64-apple-darwin",
|
|
24
|
+
"aarch64-apple-darwin",
|
|
25
|
+
"x86_64-pc-windows-msvc",
|
|
26
|
+
"aarch64-pc-windows-msvc"
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">= 16"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@napi-rs/cli": "^2.18.4"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "napi build --platform --release",
|
|
38
|
+
"build:debug": "napi build --platform",
|
|
39
|
+
"test": "node --test __test__/*.test.mjs"
|
|
40
|
+
},
|
|
41
|
+
"optionalDependencies": {
|
|
42
|
+
"plugmem-linux-x64-gnu": "0.1.3",
|
|
43
|
+
"plugmem-linux-arm64-gnu": "0.1.3",
|
|
44
|
+
"plugmem-darwin-x64": "0.1.3",
|
|
45
|
+
"plugmem-darwin-arm64": "0.1.3",
|
|
46
|
+
"plugmem-win32-x64-msvc": "0.1.3",
|
|
47
|
+
"plugmem-win32-arm64-msvc": "0.1.3"
|
|
48
|
+
}
|
|
49
|
+
}
|