@lotargo/memory_plugin 1.6.2 → 1.6.4
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/CHANGELOG.md +82 -3
- package/README.md +78 -33
- package/mcp-server/admin/snapshot.js +93 -26
- package/mcp-server/cli/direct_commands.js +15 -4
- package/mcp-server/cli/handlers/storage_actions.js +3 -1
- package/mcp-server/cli.js +2 -1
- package/mcp-server/codex_config.js +171 -0
- package/mcp-server/codex_diagnostics.js +263 -0
- package/mcp-server/config/config_manager.js +0 -1
- package/mcp-server/db/migrations.js +26 -5
- package/mcp-server/db/sync_queue.js +118 -44
- package/mcp-server/graph/knowledge_linker.js +126 -19
- package/mcp-server/index.js +4 -2
- package/mcp-server/ingest/exporter.js +38 -9
- package/mcp-server/ingest/pipeline.js +146 -48
- package/mcp-server/prompt_manager.js +30 -25
- package/mcp-server/retrieval/retriever.js +62 -38
- package/mcp-server/setup.js +54 -32
- package/mcp-server/tools/core/memory_core.js +91 -39
- package/mcp-server/tools/identity_tools.js +21 -4
- package/mcp-server/tools/memory_tools.js +4 -2
- package/mcp-server/tools/rag_tools.js +114 -55
- package/opencode-plugin/index.js +199 -108
- package/package.json +5 -3
- package/skills/using-memory/SKILL.md +62 -31
package/CHANGELOG.md
CHANGED
|
@@ -3,9 +3,88 @@
|
|
|
3
3
|
All notable changes to `@lotargo/memory_plugin` are documented in this file.
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
-
|
|
8
|
-
## [
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [1.6.4] - 2026-08-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `memory_info` now reports whether the current Git identity is `Registry: linked`
|
|
15
|
+
or `Registry: unlinked`, enabling agents to register new repositories automatically.
|
|
16
|
+
- RAG documents now have explicit global/project scope associations. The default
|
|
17
|
+
project scope follows the current linked Git identity, while `scope: "all"`
|
|
18
|
+
retrieves only global knowledge plus the current project's knowledge. A source
|
|
19
|
+
shared by several scopes is stored once and associated with each scope.
|
|
20
|
+
- The native OpenCode plugin now exposes `batch_query_knowledge_base`, bringing it
|
|
21
|
+
to all 15 shared tools plus its two OpenCode-only helpers.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- OpenCode auto-injected memory now includes complete fact bodies for both global and
|
|
26
|
+
current-project stores without the previous ten-fact truncation and instructs the
|
|
27
|
+
agent to register an unlinked Git identity. Header-only initialization was removed
|
|
28
|
+
because it loses essential context.
|
|
29
|
+
- The bundled memory skill now defines full-body session recall, strict project
|
|
30
|
+
isolation, agent-resolved conflicts, automatic Git project registration, and
|
|
31
|
+
selective RAG curation for important web findings and current technical
|
|
32
|
+
documentation, including links from project facts to supporting sources.
|
|
33
|
+
- `recall` hides superseded facts by default and exposes history through
|
|
34
|
+
`includeSuperseded: true`. Filtered output keeps physical storage indices stable,
|
|
35
|
+
so a displayed number always targets the same fact in `forget`.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- Re-ingesting an existing path or URL now preserves its document ID, scope
|
|
40
|
+
associations, and fact links while rebuilding chunks, vectors, FTS rows, and
|
|
41
|
+
structural graph edges for changed content.
|
|
42
|
+
- Snapshot export/import and hybrid cloud synchronization now preserve vectors,
|
|
43
|
+
retrieval policies, policy provenance, document scopes, knowledge links, and
|
|
44
|
+
structural graph metadata. The hybrid sync worker also drains tasks queued during
|
|
45
|
+
an active flush instead of leaving them pending.
|
|
46
|
+
- Relinking a Git project now moves its RAG scope associations and fact-to-document
|
|
47
|
+
links together with Notebook facts.
|
|
48
|
+
- Environment-specific setup flags now update only their requested integration.
|
|
49
|
+
Codex setup also synchronizes the skill to both `~/.codex/skills` and the shared
|
|
50
|
+
`~/.agents/skills` location.
|
|
51
|
+
- Shared documents no longer expose fact-link metadata belonging to another project.
|
|
52
|
+
Document deletion now defaults to unlinking only the current project (or global
|
|
53
|
+
outside Git); broader `global` / `all` removal must be requested explicitly.
|
|
54
|
+
- Updating or forgetting a linked Notebook fact now keeps its knowledge-graph
|
|
55
|
+
projection and cloud payload consistent. Line-range graph edges are included in
|
|
56
|
+
per-document cloud sync, and superseding legacy facts without IDs assigns distinct
|
|
57
|
+
IDs to the old and new versions.
|
|
58
|
+
- README tool counts now match the implementations: 15 MCP tools, 17 native
|
|
59
|
+
OpenCode tools, and 17 unique tool names across both surfaces. The OpenCode tool
|
|
60
|
+
list documents all shared and OpenCode-only helpers explicitly.
|
|
61
|
+
|
|
62
|
+
## [1.6.3] - 2026-08-13
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
|
|
66
|
+
- `memory_plugin doctor --codex` validates the configured executable and Node.js
|
|
67
|
+
version, performs direct MCP `initialize` / `tools/list`, and calls both
|
|
68
|
+
`memory_info` and `recall(scope="all")`.
|
|
69
|
+
- Codex regression coverage for Windows paths with spaces, legacy config migration,
|
|
70
|
+
duplicate removal, standalone MCP protocol smoke testing, two-repository project
|
|
71
|
+
isolation, global-only recall outside Git, and prompt idempotency.
|
|
72
|
+
|
|
73
|
+
### Fixed
|
|
74
|
+
|
|
75
|
+
- Codex setup no longer launches the memory MCP through `npx` or a Windows `.cmd`
|
|
76
|
+
shim. It writes absolute paths for the active Node executable and packaged
|
|
77
|
+
`mcp-server/boot.js` entry point after validating Node.js >= 22.5.0.
|
|
78
|
+
- Existing plugin-owned `[mcp_servers.memory-agent]` sections, including the legacy
|
|
79
|
+
`opencode-memory-plugin` entry, are migrated in place without modifying unrelated
|
|
80
|
+
TOML sections or creating duplicates.
|
|
81
|
+
- Repeated prompt setup now collapses duplicate plugin-owned blocks while preserving
|
|
82
|
+
user-authored AGENTS.md / CLAUDE.md content.
|
|
83
|
+
- README tool counts match the v1.6.3 implementations: 15 MCP tools, 16 native
|
|
84
|
+
OpenCode tools, and 17 unique tool names across both surfaces. The OpenCode tool
|
|
85
|
+
list and the MCP-only status of `batch_query_knowledge_base` are documented explicitly.
|
|
86
|
+
|
|
87
|
+
## [1.6.2] - 2026-08-12
|
|
9
88
|
|
|
10
89
|
### Added
|
|
11
90
|
|
package/README.md
CHANGED
|
@@ -77,9 +77,29 @@ memory_plugin setup --opencode
|
|
|
77
77
|
# Claude Code
|
|
78
78
|
memory_plugin setup --claude
|
|
79
79
|
|
|
80
|
-
# Codex
|
|
81
|
-
memory_plugin setup --codex
|
|
82
|
-
```
|
|
80
|
+
# Codex
|
|
81
|
+
memory_plugin setup --codex
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Codex is configured with a direct executable chain (`node` → `mcp-server/boot.js`),
|
|
85
|
+
not `npx`. This avoids Windows stdio handshake failures caused by `.cmd` launchers.
|
|
86
|
+
Running setup again safely migrates legacy `npx` entries and preserves unrelated
|
|
87
|
+
sections in `~/.codex/config.toml`.
|
|
88
|
+
|
|
89
|
+
`memory_plugin setup --codex` updates only the Codex MCP registration, Codex prompt,
|
|
90
|
+
and the Codex-compatible skill locations (`~/.codex/skills` and the shared
|
|
91
|
+
`~/.agents/skills`). It does not modify Claude Code, OpenCode, or Antigravity files.
|
|
92
|
+
|
|
93
|
+
To verify registration, the Node runtime, MCP initialization, tool discovery, and
|
|
94
|
+
real `memory_info` / `recall(scope="all")` calls:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
memory_plugin doctor --codex
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The doctor checks the server process itself. If it passes but a fresh Codex Desktop
|
|
101
|
+
task still does not expose the tools, the remaining fault is in Desktop tool
|
|
102
|
+
exposure rather than the memory MCP launcher.
|
|
83
103
|
|
|
84
104
|
`setup` also accepts `--gemini` (alias for Antigravity) and `--local` (registers the MCP server in the project-local `.agents/` directory). Without a specific flag, all detected environments are configured.
|
|
85
105
|
|
|
@@ -106,10 +126,13 @@ memory_plugin setup --mode only-cloud
|
|
|
106
126
|
- **Fact Schema**: Every fact is formatted as `**Title** — body` with inline metadata badges (`[id]`, `[ttl]`, `[keep]`, `[tags]`, `[supersedes]`, `[inject]`).
|
|
107
127
|
- **Project Identity**: Project stores are bound to a **Git-based project identity** — the normalized remote URL (`git:github.com/owner/repo`) or `git:local:<repo basename>` — never to a directory path. Memories follow the repository across machines, OSes, and subdirectories. Legacy path/basename stores can be linked and merged via `link_project_memory`.
|
|
108
128
|
|
|
109
|
-
2. **Layer 2: RAG Knowledge Base (Technical Documents & Codebases)**
|
|
110
|
-
- **Tools**: `ingest_document`, `query_knowledge_base`, `manage_knowledge_base`, `reindex_knowledge_base`
|
|
111
|
-
- **Capabilities**: Ingests raw text files, Markdown, HTML, Web URLs, office documents (PDF, DOCX, XLSX, CSV), and codebases.
|
|
112
|
-
- **
|
|
129
|
+
2. **Layer 2: RAG Knowledge Base (Technical Documents & Codebases)**
|
|
130
|
+
- **Tools**: `ingest_document`, `query_knowledge_base`, `batch_query_knowledge_base`, `manage_knowledge_base`, `reindex_knowledge_base`
|
|
131
|
+
- **Capabilities**: Ingests raw text files, Markdown, HTML, Web URLs, office documents (PDF, DOCX, XLSX, CSV), and codebases.
|
|
132
|
+
- **Curation Model**: Stores only project-relevant sources likely to be reused—for example important web findings and current library/framework documentation that may be newer than model training. Ingest the useful document or excerpt, then link it to the project memory it supports; do not archive everything the agent encounters.
|
|
133
|
+
- **Scope Isolation**: New documents default to the current linked Git project. `scope: "all"` searches global sources plus the current project's sources; outside a Git repository it searches global sources only. Use `scope: "global"` only for genuinely cross-project material.
|
|
134
|
+
- **Stable Shared Sources**: Ingesting the same path or URL in another scope reuses one document and adds a scope association. Re-ingesting updated content preserves the document ID and its fact links; removing one scope does not delete a document still used by another scope.
|
|
135
|
+
- **Engine Components**: 3-tier hierarchy chunking (Big / Medium / Small), SQLite FTS5 BM25 search, ONNX dense vector embeddings (`multilingual-e5-small`), Reciprocal Rank Fusion (RRF / RSF), cross-encoder reranking (optional), and GraphRAG Lite code symbol extraction.
|
|
113
136
|
|
|
114
137
|
3. **Layer 3: Agent-Driven Knowledge Graph**
|
|
115
138
|
- **Tools**: `link_knowledge` (plus `docId`, `startLine`, `endLine` in `remember`)
|
|
@@ -147,22 +170,33 @@ Cloud authentication tokens are never written to `config.json`. They are stored
|
|
|
147
170
|
|
|
148
171
|
---
|
|
149
172
|
|
|
150
|
-
## Available
|
|
151
|
-
|
|
152
|
-
The
|
|
153
|
-
|
|
154
|
-
|
|
173
|
+
## Available Tools
|
|
174
|
+
|
|
175
|
+
The package currently exposes **17 unique tool names** across its two integration surfaces:
|
|
176
|
+
|
|
177
|
+
| Integration surface | Tool count | Composition |
|
|
178
|
+
| :------------------ | ---------: | :---------- |
|
|
179
|
+
| **MCP server** (Codex, Claude Code, Antigravity / Gemini CLI and other MCP clients) | **15** | 6 Notebook + 4 identity/graph + 5 RAG tools |
|
|
180
|
+
| **Native OpenCode plugin** | **17** | 15 shared memory/identity/RAG tools + 2 OpenCode-only helpers |
|
|
181
|
+
|
|
182
|
+
The two surfaces are intentionally counted separately. The OpenCode plugin exposes
|
|
183
|
+
all 15 shared tools, including `batch_query_knowledge_base`, and adds the native
|
|
184
|
+
`list-mcp-tools` and `mcp-reminder` helpers.
|
|
185
|
+
|
|
186
|
+
### MCP Server Tools (15)
|
|
187
|
+
|
|
188
|
+
#### 1. Memory Notebook Tools (Layer 1)
|
|
155
189
|
|
|
156
190
|
| Tool | Scope / Target | Key Parameters | Description |
|
|
157
191
|
| :--- | :------------- | :------------- | :---------- |
|
|
158
192
|
| `remember` | `project` / `global` | `fact`, `title`, `scope`, `docId`, `startLine`, `endLine`, `relationType`, `ttl`, `keep`, `tags`, `supersedes` | Save a durable fact or preference. Supports optional title, document linking, TTL, keep protection, tags, and version superseding. |
|
|
159
|
-
| `recall` | `all`, `project`, `global`, `list_projects` | `scope`, `project`, `query`, `tags`, `since`, `until`, `mode`, `offset`, `limit` | Display saved facts with metadata badges and linked docs.
|
|
193
|
+
| `recall` | `all`, `project`, `global`, `list_projects` | `scope`, `project`, `query`, `tags`, `since`, `until`, `mode`, `offset`, `limit`, `includeSuperseded` | Display saved facts with metadata badges and linked docs. Superseded facts are hidden by default; opt into history with `includeSuperseded: true`. Filtered results retain stable storage indices for safe `forget` operations. |
|
|
160
194
|
| `get_fact` | `all`, `project`, `global` | `id`, `scope` | Retrieve full text, raw line, and metadata of a single fact by its metadata ID (e.g. `"8f3a2c"`). |
|
|
161
195
|
| `update_fact` | `project` / `global` | `id`, `newText`, `title`, `scope` | Rewrite a fact (and optionally its `**Title**`) while preserving its original creation date, metadata, and knowledge links. |
|
|
162
196
|
| `forget` | `project` / `global` | `id` / `range` / `query`, `scope`, `force` | Remove a fact by index number, ID, range (e.g. `"3-30"`), or query. Requires `force: true` for protected (`[KEEP]`) facts. |
|
|
163
197
|
| `memory_info` | - | - | Show storage paths, fact counts, RAG statistics, git identity bindings, and package version. |
|
|
164
198
|
|
|
165
|
-
|
|
199
|
+
#### 2. Project Identity Tools
|
|
166
200
|
|
|
167
201
|
| Tool | Key Parameters | Description |
|
|
168
202
|
| :--- | :------------- | :---------- |
|
|
@@ -170,23 +204,32 @@ The MCP server registers **14 MCP tools** accessible across all connected AI env
|
|
|
170
204
|
| `unlink_project_memory` | `directory`, `purge` | Remove a path alias binding for a directory. Optionally purge the project identity entry if `purge: true`. |
|
|
171
205
|
| `relink_project_memory` | `directory`, `remote` | Switch a project's primary identity to a new remote URL and merge all stored facts into the target store with fact-text deduplication. |
|
|
172
206
|
|
|
173
|
-
|
|
207
|
+
#### 3. RAG Knowledge Base & Graph Tools (Layers 2 & 3)
|
|
174
208
|
|
|
175
209
|
| Tool | Key Parameters | Description |
|
|
176
210
|
| :--- | :------------- | :---------- |
|
|
177
|
-
| `ingest_document` | `content`, `type`, `title`, `path`, `generateEmbeddings` | Ingest local files, URLs, or raw text into the 3-tier index
|
|
178
|
-
| `query_knowledge_base` | `query`, `limit`, `instruction`, `generateEmbeddings` | Perform hybrid search (RSF/RRF BM25 + dense
|
|
179
|
-
| `batch_query_knowledge_base` | `queries` (array), `limit`, `instruction`, `generateEmbeddings` | Execute multiple queries in
|
|
180
|
-
| `manage_knowledge_base` | `action`, `docId`, `snapshotPath` | Inspect
|
|
211
|
+
| `ingest_document` | `content`, `type`, `title`, `path`, `scope`, `generateEmbeddings` | Ingest local files, URLs, or raw text into the 3-tier index. Defaults to the current linked Git project; use `scope: "global"` for intentionally shared knowledge. |
|
|
212
|
+
| `query_knowledge_base` | `query`, `scope`, `limit`, `instruction`, `generateEmbeddings` | Perform hybrid search (RSF/RRF BM25 + dense vectors). `all` means global plus the current project, while `project` and `global` restrict retrieval explicitly. |
|
|
213
|
+
| `batch_query_knowledge_base` | `queries` (array), `scope`, `limit`, `instruction`, `generateEmbeddings` | Execute multiple scoped queries in one call. All embeddings are computed in one ONNX pass, making this the preferred API for comparisons and multi-part research. |
|
|
214
|
+
| `manage_knowledge_base` | `action`, `scope`, `docId`, `snapshotPath` | Inspect, list, read, or unlink documents within the selected scope, or export/import complete snapshots. Delete defaults to the current project (global outside Git); broader removal requires explicit `global` or `all`. |
|
|
181
215
|
| `reindex_knowledge_base` | `model`, `dimension` | Re-embed all stored vectors with the active (or specified) embedding model and vector dimension. Use after switching the embedding model or vector dimension so previously indexed documents remain retrievable. Preserves documents, FTS index, graph edges, and fact links. |
|
|
182
216
|
| `link_knowledge` | `action`, `factText`, `docId`, `scope`, `startLine`, `endLine`, `relationType` | Create, list, or retrieve semantic graph links connecting Notebook facts to Knowledge Base documents, sections, or line ranges. Actions: `link`, `list_links`, `get_doc_links`. |
|
|
183
217
|
|
|
184
|
-
###
|
|
185
|
-
|
|
186
|
-
|
|
|
187
|
-
|
|
|
188
|
-
|
|
|
189
|
-
|
|
|
218
|
+
### Native OpenCode Plugin Tools (17)
|
|
219
|
+
|
|
220
|
+
| Group | Count | Tools |
|
|
221
|
+
| :---- | ----: | :---- |
|
|
222
|
+
| **Memory Notebook** | 6 | `remember`, `recall`, `get_fact`, `forget`, `update_fact`, `memory_info` |
|
|
223
|
+
| **Project Identity & Knowledge Graph** | 4 | `link_knowledge`, `link_project_memory`, `unlink_project_memory`, `relink_project_memory` |
|
|
224
|
+
| **RAG Knowledge Base** | 5 | `ingest_document`, `query_knowledge_base`, `batch_query_knowledge_base`, `manage_knowledge_base`, `reindex_knowledge_base` |
|
|
225
|
+
| **OpenCode-only helpers** | 2 | `list-mcp-tools`, `mcp-reminder` |
|
|
226
|
+
|
|
227
|
+
The OpenCode-only helpers have the following purpose:
|
|
228
|
+
|
|
229
|
+
| Tool | Key Parameters | Description |
|
|
230
|
+
| :--- | :------------- | :---------- |
|
|
231
|
+
| `list-mcp-tools` | - | Discover connected MCP servers and their intended use cases. |
|
|
232
|
+
| `mcp-reminder` | `task` | Recommend the appropriate MCP tool or server for a developer task. |
|
|
190
233
|
|
|
191
234
|
---
|
|
192
235
|
|
|
@@ -216,7 +259,8 @@ Both binaries accept the same commands. `memory_plugin` with **no** command star
|
|
|
216
259
|
| **`identity`** | `--dir <path>` | Inspects Git project identity key, primary remote, name, and toplevel path for a directory. |
|
|
217
260
|
| **`migrate_titles`** | `--key <key>` | Auto-generates `**Title**` prefixes for legacy facts without titles. |
|
|
218
261
|
| **`enable-prompt`** | - | Injects memory agent instructions into client agent files (`AGENTS.md`, `CLAUDE.md`). |
|
|
219
|
-
| **`disable-prompt`** | - | Removes memory agent instructions from client agent files. |
|
|
262
|
+
| **`disable-prompt`** | - | Removes memory agent instructions from client agent files. |
|
|
263
|
+
| **`doctor`** | `--codex` | Validates Codex config, direct Node runtime, MCP initialize/tools/list, and live `memory_info` + `recall` calls. |
|
|
220
264
|
| **`login`** | `--api-token`, `--from-env`, `--db-url <URL> --db-token`, `$TURSO_API_TOKEN`, `$TURSO_DB_TOKEN` | Authenticates with Turso Cloud via API token, direct DB token, or environment variables. Token values are read from the environment or a hidden stdin prompt. |
|
|
221
265
|
| **`logout`** | `--api-key` | Signs out of Turso Cloud or removes stored API key while retaining DB session. |
|
|
222
266
|
| **`auth-status`** | - | Displays authentication source, endpoint URL, username, organization, database, and sync mode. |
|
|
@@ -246,10 +290,12 @@ Use **Up / Down** arrows to navigate, **ENTER** to select, and **BACKSPACE** to
|
|
|
246
290
|
|
|
247
291
|
### Built-in Agent Skill (`using-memory`)
|
|
248
292
|
|
|
249
|
-
The plugin bundles a pre-configured Agent Skill located at [`skills/using-memory/SKILL.md`](./skills/using-memory/SKILL.md). When installed in supported environments (such as Antigravity / Gemini CLI or OpenCode), coding agents automatically read this skill to:
|
|
250
|
-
1. **Initialize Sessions**:
|
|
251
|
-
2. **
|
|
252
|
-
3. **
|
|
293
|
+
The plugin bundles a pre-configured Agent Skill located at [`skills/using-memory/SKILL.md`](./skills/using-memory/SKILL.md). When installed in supported environments (such as Antigravity / Gemini CLI or OpenCode), coding agents automatically read this skill to:
|
|
294
|
+
1. **Initialize Sessions**: Invoke full-body `recall(scope: "all")` first, loading global memory plus only the current Git project's memory (or global-only outside Git).
|
|
295
|
+
2. **Register Git Projects**: Inspect `memory_info` after recall and automatically call `link_project_memory` when the current Git identity reports `Registry: unlinked`.
|
|
296
|
+
3. **Proactively Save Context**: Automatically call `remember` whenever you share durable facts, tech stack choices, or coding guidelines.
|
|
297
|
+
4. **Curate and Use RAG Deliberately**: Preserve important web findings and current technical documentation only when they are likely to matter again. Store project-specific sources in the current project scope, reserve global scope for reusable cross-project material, query with concept-dense searches, and avoid low-value bulk ingestion.
|
|
298
|
+
5. **Architect Knowledge Graphs**: Use `link_knowledge` or `remember(docId, startLine, endLine)` to connect concise project memories to their supporting technical sources.
|
|
253
299
|
|
|
254
300
|
### Global System Prompt Synchronization
|
|
255
301
|
|
|
@@ -295,7 +341,7 @@ During `ingest_document`, code symbols are extracted from code blocks using fast
|
|
|
295
341
|
| Platform | Status | Configuration Mechanism |
|
|
296
342
|
| :--- | :--- | :--- |
|
|
297
343
|
| **Antigravity / Gemini CLI** | Supported | MCP Server (`~/.gemini/config/mcp_config.json` & `.agents/mcp_config.json`) |
|
|
298
|
-
| **OpenCode** | Native | Native plugin
|
|
344
|
+
| **OpenCode** | Native | Native plugin with 16 tools (`~/.config/opencode/opencode.json`) |
|
|
299
345
|
| **Claude Code** | Supported | MCP Server (`~/.claude.json`) |
|
|
300
346
|
| **Codex** | Supported | MCP Server (`~/.codex/config.toml`) |
|
|
301
347
|
| **Google Jules** | Supported | MCP Server via global install + setup (`memory_plugin setup`) |
|
|
@@ -321,7 +367,6 @@ The engine is configured through `<memory-dir>/config.json` (created with defaul
|
|
|
321
367
|
| `executionDevice` | `cpu` | `cpu` or `webgpu` (experimental) |
|
|
322
368
|
| `vectorScanLimit` | `50000` | Max micro-chunks scanned per vector query (`0` = unlimited) |
|
|
323
369
|
| `policyExpansion` | `true` | Expand table_summary/code_signature policy chunks for better recall (slight MRR trade-off). Disable for pure micro_chunk precision. |
|
|
324
|
-
| `injectLimit` | `10` | Max facts injected into the agent's system prompt |
|
|
325
370
|
| `conflictStrategy` | `merge` | Hybrid-sync conflict resolution: `merge`, `cloud-wins`, or `local-wins` |
|
|
326
371
|
| `tursoUrl` | `""` | Primary Turso endpoint URL (set by `login`) |
|
|
327
372
|
| `failoverUrl` | `""` | Secondary cloud endpoint for the circuit breaker; empty = failover disabled |
|
|
@@ -339,7 +384,7 @@ The engine is configured through `<memory-dir>/config.json` (created with defaul
|
|
|
339
384
|
To run the automated test suite and benchmarks locally, from the repository root:
|
|
340
385
|
|
|
341
386
|
```bash
|
|
342
|
-
# Unit + integration + cloud suites (
|
|
387
|
+
# Unit + integration + cloud suites (18 files) — fast and fully offline
|
|
343
388
|
npm test
|
|
344
389
|
|
|
345
390
|
# End-to-end smoke test with REAL ONNX embeddings — run before a release
|
|
@@ -72,8 +72,10 @@ export async function exportSnapshot({ customDb = null, customBlobDir = BLOBS_DI
|
|
|
72
72
|
const documents = await db.prepare("SELECT * FROM documents").all();
|
|
73
73
|
const sections = await db.prepare("SELECT * FROM sections").all();
|
|
74
74
|
const mediumChunks = await db.prepare("SELECT * FROM medium_chunks").all();
|
|
75
|
-
const rawMicroChunks = await db.prepare("SELECT * FROM micro_chunks").all();
|
|
76
|
-
const graphEdges = await db.prepare("SELECT * FROM graph_edges").all();
|
|
75
|
+
const rawMicroChunks = await db.prepare("SELECT * FROM micro_chunks").all();
|
|
76
|
+
const graphEdges = await db.prepare("SELECT * FROM graph_edges").all();
|
|
77
|
+
const knowledgeLinks = await db.prepare("SELECT * FROM knowledge_links").all();
|
|
78
|
+
const documentScopes = await db.prepare("SELECT * FROM document_scopes").all();
|
|
77
79
|
|
|
78
80
|
const microChunks = rawMicroChunks.map((mc) => {
|
|
79
81
|
let vecBase64 = "";
|
|
@@ -99,14 +101,16 @@ export async function exportSnapshot({ customDb = null, customBlobDir = BLOBS_DI
|
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
const snapshot = {
|
|
102
|
-
version:
|
|
104
|
+
version: 3,
|
|
103
105
|
created_at: new Date().toISOString(),
|
|
104
106
|
documents,
|
|
105
107
|
sections,
|
|
106
108
|
medium_chunks: mediumChunks,
|
|
107
109
|
micro_chunks: microChunks,
|
|
108
|
-
graph_edges: graphEdges,
|
|
109
|
-
|
|
110
|
+
graph_edges: graphEdges,
|
|
111
|
+
knowledge_links: knowledgeLinks,
|
|
112
|
+
document_scopes: documentScopes,
|
|
113
|
+
blobs,
|
|
110
114
|
};
|
|
111
115
|
|
|
112
116
|
const jsonStr = JSON.stringify(snapshot, null, 2);
|
|
@@ -187,14 +191,16 @@ export async function importSnapshot({ customDb = null, customBlobDir = BLOBS_DI
|
|
|
187
191
|
token_count=excluded.token_count
|
|
188
192
|
`);
|
|
189
193
|
|
|
190
|
-
const insertChunk = db.prepare(`
|
|
191
|
-
INSERT INTO micro_chunks (id, section_id, doc_id, content, vector, token_count, medium_id)
|
|
192
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
193
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
194
|
-
content=excluded.content,
|
|
195
|
-
vector=excluded.vector,
|
|
196
|
-
token_count=excluded.token_count,
|
|
197
|
-
medium_id=excluded.medium_id
|
|
194
|
+
const insertChunk = db.prepare(`
|
|
195
|
+
INSERT INTO micro_chunks (id, section_id, doc_id, content, vector, token_count, medium_id, retrieval_policy, policy_source_id)
|
|
196
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
197
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
198
|
+
content=excluded.content,
|
|
199
|
+
vector=excluded.vector,
|
|
200
|
+
token_count=excluded.token_count,
|
|
201
|
+
medium_id=excluded.medium_id,
|
|
202
|
+
retrieval_policy=excluded.retrieval_policy,
|
|
203
|
+
policy_source_id=excluded.policy_source_id
|
|
198
204
|
`);
|
|
199
205
|
|
|
200
206
|
const insertFts = db.prepare(`
|
|
@@ -204,11 +210,32 @@ export async function importSnapshot({ customDb = null, customBlobDir = BLOBS_DI
|
|
|
204
210
|
|
|
205
211
|
const deleteFts = db.prepare("DELETE FROM micro_chunks_fts WHERE id = ?");
|
|
206
212
|
|
|
207
|
-
const insertEdge = db.prepare(`
|
|
208
|
-
INSERT INTO graph_edges (source_id, target_id, relation_type)
|
|
209
|
-
VALUES (?, ?, ?)
|
|
210
|
-
ON CONFLICT(source_id, target_id, relation_type) DO
|
|
211
|
-
|
|
213
|
+
const insertEdge = db.prepare(`
|
|
214
|
+
INSERT INTO graph_edges (source_id, target_id, relation_type, metadata_json, created_at)
|
|
215
|
+
VALUES (?, ?, ?, ?, ?)
|
|
216
|
+
ON CONFLICT(source_id, target_id, relation_type) DO UPDATE SET
|
|
217
|
+
metadata_json=excluded.metadata_json,
|
|
218
|
+
created_at=excluded.created_at
|
|
219
|
+
`);
|
|
220
|
+
const insertScope = db.prepare(`
|
|
221
|
+
INSERT OR IGNORE INTO document_scopes (doc_id, scope_key, created_at)
|
|
222
|
+
VALUES (?, ?, ?)
|
|
223
|
+
`);
|
|
224
|
+
const insertLink = db.prepare(`
|
|
225
|
+
INSERT INTO knowledge_links
|
|
226
|
+
(id, fact_key, fact_text, doc_id, section_id, start_line, end_line, relation_type, metadata_json, created_at)
|
|
227
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
228
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
229
|
+
fact_key=excluded.fact_key,
|
|
230
|
+
fact_text=excluded.fact_text,
|
|
231
|
+
doc_id=excluded.doc_id,
|
|
232
|
+
section_id=excluded.section_id,
|
|
233
|
+
start_line=excluded.start_line,
|
|
234
|
+
end_line=excluded.end_line,
|
|
235
|
+
relation_type=excluded.relation_type,
|
|
236
|
+
metadata_json=excluded.metadata_json,
|
|
237
|
+
created_at=excluded.created_at
|
|
238
|
+
`);
|
|
212
239
|
|
|
213
240
|
await db.exec("BEGIN IMMEDIATE;");
|
|
214
241
|
try {
|
|
@@ -228,11 +255,23 @@ export async function importSnapshot({ customDb = null, customBlobDir = BLOBS_DI
|
|
|
228
255
|
}
|
|
229
256
|
}
|
|
230
257
|
|
|
231
|
-
if (Array.isArray(snapshot.sections)) {
|
|
258
|
+
if (Array.isArray(snapshot.sections)) {
|
|
232
259
|
for (const s of snapshot.sections) {
|
|
233
260
|
await insertSection.run(s.id, s.doc_id, s.heading, s.breadcrumbs, s.content, s.token_count);
|
|
234
261
|
}
|
|
235
|
-
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (Array.isArray(snapshot.document_scopes) && snapshot.document_scopes.length > 0) {
|
|
265
|
+
for (const scope of snapshot.document_scopes) {
|
|
266
|
+
await insertScope.run(scope.doc_id, scope.scope_key || "global", scope.created_at || Date.now());
|
|
267
|
+
}
|
|
268
|
+
} else if (Array.isArray(snapshot.documents)) {
|
|
269
|
+
// v1/v2 snapshots predate project-scoped RAG and retain their historical
|
|
270
|
+
// globally-visible behavior after import.
|
|
271
|
+
for (const d of snapshot.documents) {
|
|
272
|
+
await insertScope.run(d.id, "global", d.created_at || Date.now());
|
|
273
|
+
}
|
|
274
|
+
}
|
|
236
275
|
|
|
237
276
|
if (Array.isArray(snapshot.medium_chunks)) {
|
|
238
277
|
for (const m of snapshot.medium_chunks) {
|
|
@@ -246,7 +285,17 @@ export async function importSnapshot({ customDb = null, customBlobDir = BLOBS_DI
|
|
|
246
285
|
if (mc.vector) {
|
|
247
286
|
vecBuf = Buffer.from(mc.vector, "base64");
|
|
248
287
|
}
|
|
249
|
-
await insertChunk.run(
|
|
288
|
+
await insertChunk.run(
|
|
289
|
+
mc.id,
|
|
290
|
+
mc.section_id,
|
|
291
|
+
mc.doc_id,
|
|
292
|
+
mc.content,
|
|
293
|
+
vecBuf,
|
|
294
|
+
mc.token_count,
|
|
295
|
+
mc.medium_id || null,
|
|
296
|
+
mc.retrieval_policy || "micro_chunk",
|
|
297
|
+
mc.policy_source_id || null
|
|
298
|
+
);
|
|
250
299
|
|
|
251
300
|
try {
|
|
252
301
|
await deleteFts.run(mc.id);
|
|
@@ -255,10 +304,26 @@ export async function importSnapshot({ customDb = null, customBlobDir = BLOBS_DI
|
|
|
255
304
|
}
|
|
256
305
|
}
|
|
257
306
|
|
|
258
|
-
if (Array.isArray(snapshot.graph_edges)) {
|
|
259
|
-
for (const e of snapshot.graph_edges) {
|
|
260
|
-
await insertEdge.run(e.source_id, e.target_id, e.relation_type);
|
|
261
|
-
}
|
|
307
|
+
if (Array.isArray(snapshot.graph_edges)) {
|
|
308
|
+
for (const e of snapshot.graph_edges) {
|
|
309
|
+
await insertEdge.run(e.source_id, e.target_id, e.relation_type, e.metadata_json || null, e.created_at || null);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (Array.isArray(snapshot.knowledge_links)) {
|
|
313
|
+
for (const link of snapshot.knowledge_links) {
|
|
314
|
+
await insertLink.run(
|
|
315
|
+
link.id,
|
|
316
|
+
link.fact_key,
|
|
317
|
+
link.fact_text,
|
|
318
|
+
link.doc_id,
|
|
319
|
+
link.section_id || null,
|
|
320
|
+
link.start_line || null,
|
|
321
|
+
link.end_line || null,
|
|
322
|
+
link.relation_type || "LINKS_TO",
|
|
323
|
+
link.metadata_json || null,
|
|
324
|
+
link.created_at || Date.now()
|
|
325
|
+
);
|
|
326
|
+
}
|
|
262
327
|
}
|
|
263
328
|
await db.exec("COMMIT;");
|
|
264
329
|
} catch (err) {
|
|
@@ -271,7 +336,9 @@ export async function importSnapshot({ customDb = null, customBlobDir = BLOBS_DI
|
|
|
271
336
|
sections: snapshot.sections ? snapshot.sections.length : 0,
|
|
272
337
|
medium_chunks: snapshot.medium_chunks ? snapshot.medium_chunks.length : 0,
|
|
273
338
|
micro_chunks: snapshot.micro_chunks ? snapshot.micro_chunks.length : 0,
|
|
274
|
-
graph_edges: snapshot.graph_edges ? snapshot.graph_edges.length : 0,
|
|
339
|
+
graph_edges: snapshot.graph_edges ? snapshot.graph_edges.length : 0,
|
|
340
|
+
knowledge_links: snapshot.knowledge_links ? snapshot.knowledge_links.length : 0,
|
|
341
|
+
document_scopes: snapshot.document_scopes ? snapshot.document_scopes.length : 0,
|
|
275
342
|
blobs: blobCount,
|
|
276
343
|
};
|
|
277
344
|
}
|
|
@@ -11,7 +11,16 @@ import {
|
|
|
11
11
|
} from "../memory.js";
|
|
12
12
|
import { factBody } from "../fact_format.js";
|
|
13
13
|
|
|
14
|
-
export async function handleDirectCommands(cliArgs) {
|
|
14
|
+
export async function handleDirectCommands(cliArgs) {
|
|
15
|
+
if (cliArgs[0] === "doctor" && cliArgs.includes("--codex")) {
|
|
16
|
+
const { runCodexDoctor } = await import("../codex_diagnostics.js");
|
|
17
|
+
console.log("\nCodex memory-agent diagnostics\n");
|
|
18
|
+
const result = await runCodexDoctor();
|
|
19
|
+
console.log("");
|
|
20
|
+
if (!result.ok) process.exitCode = 1;
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
15
24
|
if (cliArgs[0] === "link") {
|
|
16
25
|
const dirIdx = cliArgs.indexOf("--dir");
|
|
17
26
|
const dir = dirIdx >= 0 && cliArgs[dirIdx + 1] ? cliArgs[dirIdx + 1] : process.cwd();
|
|
@@ -127,9 +136,11 @@ export async function handleDirectCommands(cliArgs) {
|
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
await writeMemory(targetKey, targetFacts);
|
|
130
|
-
await db
|
|
131
|
-
await
|
|
132
|
-
await
|
|
139
|
+
await upsertIdentity(db, { key: targetKey, name: sourceIdentity.name, primaryRemote: normalizeRemoteUrl(remote) });
|
|
140
|
+
await db.prepare("UPDATE project_aliases SET identity_key = ? WHERE identity_key = ?;").run(targetKey, sourceKey);
|
|
141
|
+
const { moveKnowledgeScope } = await import("../graph/knowledge_linker.js");
|
|
142
|
+
await moveKnowledgeScope(db, sourceKey, targetKey);
|
|
143
|
+
await removeIdentity(db, sourceKey);
|
|
133
144
|
|
|
134
145
|
try {
|
|
135
146
|
const sourceFp = storeFilePath(sourceKey);
|
|
@@ -405,8 +405,10 @@ export async function handleStorageAction(value, config, stats) {
|
|
|
405
405
|
}
|
|
406
406
|
|
|
407
407
|
await writeMemory(targetKey, targetFacts);
|
|
408
|
-
await db.prepare("UPDATE project_aliases SET identity_key = ? WHERE identity_key = ?;").run(targetKey, sourceKey);
|
|
409
408
|
await upsertIdentity(db, { key: targetKey, name: identity.name, primaryRemote: normalizeRemoteUrl(targetRemote) });
|
|
409
|
+
await db.prepare("UPDATE project_aliases SET identity_key = ? WHERE identity_key = ?;").run(targetKey, sourceKey);
|
|
410
|
+
const { moveKnowledgeScope } = await import("../../graph/knowledge_linker.js");
|
|
411
|
+
await moveKnowledgeScope(db, sourceKey, targetKey);
|
|
410
412
|
await removeIdentity(db, sourceKey);
|
|
411
413
|
|
|
412
414
|
try {
|
package/mcp-server/cli.js
CHANGED
|
@@ -23,7 +23,8 @@ Usage:
|
|
|
23
23
|
memory-cli auth-status
|
|
24
24
|
memory-cli link|unlink|relink|identity [--dir <path>] [--remote <url>]
|
|
25
25
|
memory-cli migrate_titles [--key <key>]
|
|
26
|
-
memory-cli enable-prompt | disable-prompt
|
|
26
|
+
memory-cli enable-prompt | disable-prompt
|
|
27
|
+
memory-cli doctor --codex
|
|
27
28
|
|
|
28
29
|
Options:
|
|
29
30
|
-h, --help Show this help text`);
|