remem-mcp 0.5.17
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/LICENSE +21 -0
- package/README.md +235 -0
- package/dist/chunk-34TEZ5U4.js +1676 -0
- package/dist/chunk-34TEZ5U4.js.map +1 -0
- package/dist/chunk-RITPZHIB.js +475 -0
- package/dist/chunk-RITPZHIB.js.map +1 -0
- package/dist/engine-ZNZRRSBV.js +25 -0
- package/dist/engine-ZNZRRSBV.js.map +1 -0
- package/dist/index.js +12625 -0
- package/dist/index.js.map +1 -0
- package/dist/sdk.js +41 -0
- package/dist/sdk.js.map +1 -0
- package/dist/storage/schema.sql +292 -0
- package/package.json +82 -0
- package/scripts/bench-all.sh +147 -0
- package/scripts/cast-to-mp4.py +264 -0
- package/scripts/loop-bench.sh +179 -0
- package/scripts/loop-longmemeval.sh +159 -0
- package/scripts/loop-mem0-bench.sh +310 -0
- package/scripts/merge-casts.py +131 -0
- package/scripts/postinstall.js +51 -0
- package/skills/remem-mcp/SKILL.md +562 -0
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LocalEmbedder,
|
|
3
|
+
Memory,
|
|
4
|
+
SQLiteBackend,
|
|
5
|
+
findOutdatedPages,
|
|
6
|
+
getWikiPage,
|
|
7
|
+
ingestDirectory,
|
|
8
|
+
ingestFile,
|
|
9
|
+
searchWiki
|
|
10
|
+
} from "./chunk-34TEZ5U4.js";
|
|
11
|
+
import {
|
|
12
|
+
SUPPORTED_LANGUAGES,
|
|
13
|
+
detectLanguage,
|
|
14
|
+
findCallees,
|
|
15
|
+
findCallers,
|
|
16
|
+
impactAnalysis,
|
|
17
|
+
indexDirectory,
|
|
18
|
+
indexFile,
|
|
19
|
+
listSymbols,
|
|
20
|
+
searchSymbols
|
|
21
|
+
} from "./chunk-RITPZHIB.js";
|
|
22
|
+
export {
|
|
23
|
+
LocalEmbedder,
|
|
24
|
+
Memory,
|
|
25
|
+
SQLiteBackend,
|
|
26
|
+
SUPPORTED_LANGUAGES,
|
|
27
|
+
detectLanguage,
|
|
28
|
+
findCallees,
|
|
29
|
+
findCallers,
|
|
30
|
+
findOutdatedPages,
|
|
31
|
+
getWikiPage,
|
|
32
|
+
impactAnalysis,
|
|
33
|
+
indexDirectory,
|
|
34
|
+
indexFile,
|
|
35
|
+
listSymbols,
|
|
36
|
+
searchSymbols,
|
|
37
|
+
searchWiki,
|
|
38
|
+
ingestDirectory as wikiIngestDirectory,
|
|
39
|
+
ingestFile as wikiIngestFile
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=sdk.js.map
|
package/dist/sdk.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
-- Schema for tdai-memory-mcp
|
|
2
|
+
-- Version: 6
|
|
3
|
+
--
|
|
4
|
+
-- This file runs on the first start. It creates all tables, triggers, and indexes.
|
|
5
|
+
-- It uses CREATE TABLE IF NOT EXISTS and CREATE INDEX IF NOT EXISTS.
|
|
6
|
+
-- The migration is idempotent. You can run it more than once without side effects.
|
|
7
|
+
|
|
8
|
+
-- Schema version tracking
|
|
9
|
+
CREATE TABLE IF NOT EXISTS schema_version (
|
|
10
|
+
version INTEGER NOT NULL,
|
|
11
|
+
applied_at INTEGER NOT NULL
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
-- L0: Raw captures (always populated)
|
|
15
|
+
CREATE TABLE IF NOT EXISTS captures (
|
|
16
|
+
id TEXT PRIMARY KEY,
|
|
17
|
+
session_key TEXT NOT NULL,
|
|
18
|
+
agent_id TEXT NOT NULL,
|
|
19
|
+
type TEXT NOT NULL,
|
|
20
|
+
content TEXT NOT NULL,
|
|
21
|
+
content_hash TEXT,
|
|
22
|
+
tags TEXT,
|
|
23
|
+
created_at INTEGER NOT NULL,
|
|
24
|
+
metadata TEXT,
|
|
25
|
+
team_id TEXT,
|
|
26
|
+
user_id TEXT,
|
|
27
|
+
task_id TEXT,
|
|
28
|
+
deleted_at INTEGER,
|
|
29
|
+
trust_state TEXT NOT NULL DEFAULT 'candidate',
|
|
30
|
+
rejection_reason TEXT,
|
|
31
|
+
superseded_by TEXT REFERENCES captures(id)
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
-- L0 messages: role-based conversation messages linked to a capture.
|
|
35
|
+
-- Populated when capture is called with messages: [{role, content}].
|
|
36
|
+
CREATE TABLE IF NOT EXISTS messages (
|
|
37
|
+
id TEXT PRIMARY KEY,
|
|
38
|
+
capture_id TEXT NOT NULL REFERENCES captures(id) ON DELETE CASCADE,
|
|
39
|
+
role TEXT NOT NULL,
|
|
40
|
+
content TEXT NOT NULL,
|
|
41
|
+
seq INTEGER NOT NULL,
|
|
42
|
+
created_at INTEGER NOT NULL
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
-- L1: Atomic facts (populated by atom-extract pipeline, or CLI extract command)
|
|
46
|
+
CREATE TABLE IF NOT EXISTS atoms (
|
|
47
|
+
id TEXT PRIMARY KEY,
|
|
48
|
+
capture_id TEXT NOT NULL REFERENCES captures(id) ON DELETE CASCADE,
|
|
49
|
+
fact TEXT NOT NULL,
|
|
50
|
+
confidence REAL NOT NULL DEFAULT 1.0,
|
|
51
|
+
created_at INTEGER NOT NULL,
|
|
52
|
+
team_id TEXT,
|
|
53
|
+
agent_id TEXT,
|
|
54
|
+
user_id TEXT
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
-- L2: Scenario blocks (populated by scenario pipeline)
|
|
58
|
+
CREATE TABLE IF NOT EXISTS scenarios (
|
|
59
|
+
id TEXT PRIMARY KEY,
|
|
60
|
+
atom_ids TEXT NOT NULL,
|
|
61
|
+
summary TEXT NOT NULL,
|
|
62
|
+
persona_tags TEXT,
|
|
63
|
+
created_at INTEGER NOT NULL,
|
|
64
|
+
team_id TEXT,
|
|
65
|
+
agent_id TEXT,
|
|
66
|
+
user_id TEXT
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
-- L3: Persona (long-term user profile, one per team/agent/user)
|
|
70
|
+
CREATE TABLE IF NOT EXISTS persona (
|
|
71
|
+
team_id TEXT NOT NULL,
|
|
72
|
+
agent_id TEXT NOT NULL,
|
|
73
|
+
user_id TEXT NOT NULL,
|
|
74
|
+
content TEXT NOT NULL,
|
|
75
|
+
updated_at INTEGER NOT NULL,
|
|
76
|
+
PRIMARY KEY (team_id, agent_id, user_id)
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
-- Knowledge assets (wiki, code-graph) registered by the team
|
|
80
|
+
CREATE TABLE IF NOT EXISTS knowledge (
|
|
81
|
+
id TEXT PRIMARY KEY,
|
|
82
|
+
team_id TEXT NOT NULL,
|
|
83
|
+
name TEXT NOT NULL,
|
|
84
|
+
type TEXT NOT NULL,
|
|
85
|
+
summary TEXT,
|
|
86
|
+
service_url TEXT,
|
|
87
|
+
repo_url TEXT,
|
|
88
|
+
branch TEXT,
|
|
89
|
+
created_at INTEGER NOT NULL
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
-- Skills: reusable workflows extracted from conversations
|
|
93
|
+
CREATE TABLE IF NOT EXISTS skills (
|
|
94
|
+
id TEXT PRIMARY KEY,
|
|
95
|
+
team_id TEXT NOT NULL,
|
|
96
|
+
agent_id TEXT,
|
|
97
|
+
name TEXT NOT NULL,
|
|
98
|
+
description TEXT,
|
|
99
|
+
content TEXT,
|
|
100
|
+
version INTEGER NOT NULL DEFAULT 1,
|
|
101
|
+
created_at INTEGER NOT NULL,
|
|
102
|
+
updated_at INTEGER NOT NULL
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
-- Audit log
|
|
106
|
+
CREATE TABLE IF NOT EXISTS audit_log (
|
|
107
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
108
|
+
ts INTEGER NOT NULL,
|
|
109
|
+
tool TEXT NOT NULL,
|
|
110
|
+
args_hash TEXT NOT NULL,
|
|
111
|
+
result_len INTEGER,
|
|
112
|
+
quota_hit INTEGER NOT NULL DEFAULT 0,
|
|
113
|
+
redacted INTEGER NOT NULL DEFAULT 0
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
-- Full-text search (BM25 via FTS5)
|
|
117
|
+
-- External content table: the FTS5 index links to the captures table by rowid.
|
|
118
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS captures_fts USING fts5(
|
|
119
|
+
id UNINDEXED,
|
|
120
|
+
content,
|
|
121
|
+
tags,
|
|
122
|
+
type UNINDEXED,
|
|
123
|
+
content='captures',
|
|
124
|
+
content_rowid='rowid'
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
-- Vector search (sqlite-vec)
|
|
128
|
+
-- Dimension 384 for all-MiniLM-L6-v2. Change to 1536 for OpenAI text-embedding-3-small.
|
|
129
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS captures_vec USING vec0(
|
|
130
|
+
id TEXT PRIMARY KEY,
|
|
131
|
+
embedding float[384]
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
-- Triggers: keep FTS5 index in sync with captures table
|
|
135
|
+
-- FTS5 external content tables require the special 'delete' command syntax
|
|
136
|
+
-- to remove entries from the index.
|
|
137
|
+
CREATE TRIGGER IF NOT EXISTS captures_ai AFTER INSERT ON captures BEGIN
|
|
138
|
+
INSERT INTO captures_fts (rowid, id, content, tags, type)
|
|
139
|
+
VALUES (new.rowid, new.id, new.content, new.tags, new.type);
|
|
140
|
+
END;
|
|
141
|
+
|
|
142
|
+
CREATE TRIGGER IF NOT EXISTS captures_au AFTER UPDATE ON captures BEGIN
|
|
143
|
+
INSERT INTO captures_fts(captures_fts, rowid, content, tags, type) VALUES('delete', old.rowid, old.content, old.tags, old.type);
|
|
144
|
+
INSERT INTO captures_fts (rowid, id, content, tags, type)
|
|
145
|
+
VALUES (new.rowid, new.id, new.content, new.tags, new.type);
|
|
146
|
+
END;
|
|
147
|
+
|
|
148
|
+
CREATE TRIGGER IF NOT EXISTS captures_ad AFTER DELETE ON captures BEGIN
|
|
149
|
+
INSERT INTO captures_fts(captures_fts, rowid, content, tags, type) VALUES('delete', old.rowid, old.content, old.tags, old.type);
|
|
150
|
+
END;
|
|
151
|
+
|
|
152
|
+
-- ─────────────────────────────────────────────
|
|
153
|
+
-- CodeGraph: code symbols, call relationships, impact analysis
|
|
154
|
+
-- ─────────────────────────────────────────────
|
|
155
|
+
|
|
156
|
+
-- Symbols: functions, classes, methods, interfaces, etc.
|
|
157
|
+
CREATE TABLE IF NOT EXISTS symbols (
|
|
158
|
+
id TEXT PRIMARY KEY,
|
|
159
|
+
name TEXT NOT NULL,
|
|
160
|
+
kind TEXT NOT NULL, -- function, class, method, interface, type, variable, import
|
|
161
|
+
file_path TEXT NOT NULL,
|
|
162
|
+
line_start INTEGER NOT NULL,
|
|
163
|
+
line_end INTEGER NOT NULL,
|
|
164
|
+
language TEXT NOT NULL, -- typescript, javascript, python, go, rust, java, c, cpp, csharp
|
|
165
|
+
signature TEXT, -- function signature or type declaration
|
|
166
|
+
docstring TEXT, -- JSDoc, docstring, or comment above symbol
|
|
167
|
+
parent_id TEXT REFERENCES symbols(id), -- enclosing class or module
|
|
168
|
+
team_id TEXT,
|
|
169
|
+
repo_path TEXT, -- root path of the indexed repo
|
|
170
|
+
content_hash TEXT, -- hash of the symbol body for change detection
|
|
171
|
+
created_at INTEGER NOT NULL,
|
|
172
|
+
updated_at INTEGER NOT NULL
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
-- Call relationships: who calls whom
|
|
176
|
+
CREATE TABLE IF NOT EXISTS calls (
|
|
177
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
178
|
+
caller_id TEXT NOT NULL REFERENCES symbols(id) ON DELETE CASCADE,
|
|
179
|
+
callee_name TEXT NOT NULL, -- name of the called symbol (resolved later)
|
|
180
|
+
callee_id TEXT REFERENCES symbols(id), -- resolved callee (null if unresolved)
|
|
181
|
+
line INTEGER NOT NULL, -- line where the call occurs
|
|
182
|
+
kind TEXT NOT NULL DEFAULT 'call', -- call, import, reference
|
|
183
|
+
team_id TEXT
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
-- Import relationships: what a file imports
|
|
187
|
+
CREATE TABLE IF NOT EXISTS imports (
|
|
188
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
189
|
+
file_path TEXT NOT NULL,
|
|
190
|
+
symbol_name TEXT NOT NULL, -- imported symbol name
|
|
191
|
+
source_path TEXT, -- source module/path
|
|
192
|
+
line INTEGER NOT NULL,
|
|
193
|
+
language TEXT NOT NULL,
|
|
194
|
+
team_id TEXT,
|
|
195
|
+
repo_path TEXT
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
-- ─────────────────────────────────────────────
|
|
199
|
+
-- Wiki: structured documentation pages with link graph
|
|
200
|
+
-- ─────────────────────────────────────────────
|
|
201
|
+
|
|
202
|
+
-- Wiki pages: parsed from markdown/docs
|
|
203
|
+
CREATE TABLE IF NOT EXISTS wiki_pages (
|
|
204
|
+
id TEXT PRIMARY KEY,
|
|
205
|
+
title TEXT NOT NULL,
|
|
206
|
+
content TEXT NOT NULL, -- full page content (markdown)
|
|
207
|
+
source_file TEXT NOT NULL, -- original file path
|
|
208
|
+
section TEXT, -- heading path (e.g., "Getting Started > Install")
|
|
209
|
+
tags TEXT, -- comma-separated tags from frontmatter
|
|
210
|
+
frontmatter TEXT, -- JSON of frontmatter metadata
|
|
211
|
+
content_hash TEXT, -- hash for change detection
|
|
212
|
+
team_id TEXT,
|
|
213
|
+
created_at INTEGER NOT NULL,
|
|
214
|
+
updated_at INTEGER NOT NULL
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
-- Wiki links: adjacency list for the link graph
|
|
218
|
+
CREATE TABLE IF NOT EXISTS wiki_links (
|
|
219
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
220
|
+
from_page_id TEXT NOT NULL REFERENCES wiki_pages(id) ON DELETE CASCADE,
|
|
221
|
+
to_page_id TEXT REFERENCES wiki_pages(id), -- null if link target not found
|
|
222
|
+
to_title TEXT, -- target title (for unresolved links)
|
|
223
|
+
link_text TEXT, -- display text of the link
|
|
224
|
+
link_type TEXT NOT NULL DEFAULT 'wikilink', -- wikilink, markdown, heading
|
|
225
|
+
line INTEGER NOT NULL
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
-- FTS5 for wiki pages
|
|
229
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS wiki_fts USING fts5(
|
|
230
|
+
id UNINDEXED,
|
|
231
|
+
title,
|
|
232
|
+
content,
|
|
233
|
+
tags,
|
|
234
|
+
content='wiki_pages',
|
|
235
|
+
content_rowid='rowid'
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
-- Triggers: keep wiki FTS5 in sync
|
|
239
|
+
CREATE TRIGGER IF NOT EXISTS wiki_ai AFTER INSERT ON wiki_pages BEGIN
|
|
240
|
+
INSERT INTO wiki_fts (rowid, id, title, content, tags)
|
|
241
|
+
VALUES (new.rowid, new.id, new.title, new.content, new.tags);
|
|
242
|
+
END;
|
|
243
|
+
|
|
244
|
+
CREATE TRIGGER IF NOT EXISTS wiki_au AFTER UPDATE ON wiki_pages BEGIN
|
|
245
|
+
INSERT INTO wiki_fts(wiki_fts, rowid, title, content, tags) VALUES('delete', old.rowid, old.title, old.content, old.tags);
|
|
246
|
+
INSERT INTO wiki_fts (rowid, id, title, content, tags)
|
|
247
|
+
VALUES (new.rowid, new.id, new.title, new.content, new.tags);
|
|
248
|
+
END;
|
|
249
|
+
|
|
250
|
+
CREATE TRIGGER IF NOT EXISTS wiki_ad AFTER DELETE ON wiki_pages BEGIN
|
|
251
|
+
INSERT INTO wiki_fts(wiki_fts, rowid, title, content, tags) VALUES('delete', old.rowid, old.title, old.content, old.tags);
|
|
252
|
+
END;
|
|
253
|
+
|
|
254
|
+
-- Indexes
|
|
255
|
+
CREATE INDEX IF NOT EXISTS idx_captures_session ON captures (session_key, created_at DESC);
|
|
256
|
+
CREATE INDEX IF NOT EXISTS idx_captures_agent ON captures (agent_id, created_at DESC);
|
|
257
|
+
CREATE INDEX IF NOT EXISTS idx_captures_hash ON captures (content_hash);
|
|
258
|
+
CREATE INDEX IF NOT EXISTS idx_captures_team ON captures (team_id, created_at DESC);
|
|
259
|
+
CREATE INDEX IF NOT EXISTS idx_captures_user ON captures (team_id, user_id, created_at DESC);
|
|
260
|
+
CREATE INDEX IF NOT EXISTS idx_captures_task ON captures (task_id, created_at DESC);
|
|
261
|
+
CREATE INDEX IF NOT EXISTS idx_captures_trust ON captures (trust_state);
|
|
262
|
+
CREATE INDEX IF NOT EXISTS idx_captures_rejected_hash ON captures (content_hash) WHERE trust_state = 'rejected';
|
|
263
|
+
CREATE INDEX IF NOT EXISTS idx_atoms_capture ON atoms (capture_id);
|
|
264
|
+
CREATE INDEX IF NOT EXISTS idx_atoms_team ON atoms (team_id, created_at DESC);
|
|
265
|
+
CREATE INDEX IF NOT EXISTS idx_messages_capture ON messages (capture_id, seq);
|
|
266
|
+
CREATE INDEX IF NOT EXISTS idx_scenarios_team ON scenarios (team_id, created_at DESC);
|
|
267
|
+
CREATE INDEX IF NOT EXISTS idx_audit_ts ON audit_log (ts DESC);
|
|
268
|
+
CREATE INDEX IF NOT EXISTS idx_knowledge_team ON knowledge (team_id, created_at DESC);
|
|
269
|
+
CREATE INDEX IF NOT EXISTS idx_skills_team ON skills (team_id, updated_at DESC);
|
|
270
|
+
|
|
271
|
+
-- CodeGraph indexes
|
|
272
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_name ON symbols (name);
|
|
273
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_file ON symbols (file_path);
|
|
274
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_kind ON symbols (kind);
|
|
275
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_team ON symbols (team_id);
|
|
276
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_repo ON symbols (repo_path);
|
|
277
|
+
CREATE INDEX IF NOT EXISTS idx_symbols_parent ON symbols (parent_id);
|
|
278
|
+
CREATE INDEX IF NOT EXISTS idx_calls_caller ON calls (caller_id);
|
|
279
|
+
CREATE INDEX IF NOT EXISTS idx_calls_callee ON calls (callee_name);
|
|
280
|
+
CREATE INDEX IF NOT EXISTS idx_calls_callee_id ON calls (callee_id);
|
|
281
|
+
CREATE INDEX IF NOT EXISTS idx_calls_team ON calls (team_id);
|
|
282
|
+
CREATE INDEX IF NOT EXISTS idx_imports_file ON imports (file_path);
|
|
283
|
+
CREATE INDEX IF NOT EXISTS idx_imports_symbol ON imports (symbol_name);
|
|
284
|
+
CREATE INDEX IF NOT EXISTS idx_imports_team ON imports (team_id);
|
|
285
|
+
|
|
286
|
+
-- Wiki indexes
|
|
287
|
+
CREATE INDEX IF NOT EXISTS idx_wiki_pages_source ON wiki_pages (source_file);
|
|
288
|
+
CREATE INDEX IF NOT EXISTS idx_wiki_pages_team ON wiki_pages (team_id);
|
|
289
|
+
CREATE INDEX IF NOT EXISTS idx_wiki_pages_hash ON wiki_pages (content_hash);
|
|
290
|
+
CREATE INDEX IF NOT EXISTS idx_wiki_links_from ON wiki_links (from_page_id);
|
|
291
|
+
CREATE INDEX IF NOT EXISTS idx_wiki_links_to ON wiki_links (to_page_id);
|
|
292
|
+
CREATE INDEX IF NOT EXISTS idx_wiki_links_title ON wiki_links (to_title);
|
package/package.json
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "remem-mcp",
|
|
3
|
+
"mcpName": "io.github.tinhien11/remem-mcp",
|
|
4
|
+
"version": "0.5.17",
|
|
5
|
+
"description": "Long-term memory for AI coding agents. Memory + CodeGraph + Wiki in one SQLite file. Auto-recall, auto-capture, no API key, no cloud.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "tin",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/tinhien11/remem-mcp.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/tinhien11/remem-mcp#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/tinhien11/remem-mcp/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"model-context-protocol",
|
|
20
|
+
"memory",
|
|
21
|
+
"ai-agent",
|
|
22
|
+
"agent-memory",
|
|
23
|
+
"long-term-memory",
|
|
24
|
+
"claude-code",
|
|
25
|
+
"cursor",
|
|
26
|
+
"devin",
|
|
27
|
+
"codex",
|
|
28
|
+
"sqlite",
|
|
29
|
+
"sqlite-vec",
|
|
30
|
+
"local-first",
|
|
31
|
+
"codegraph",
|
|
32
|
+
"tree-sitter",
|
|
33
|
+
"knowledge-graph",
|
|
34
|
+
"persistent-memory",
|
|
35
|
+
"agent-context"
|
|
36
|
+
],
|
|
37
|
+
"bin": {
|
|
38
|
+
"remem-mcp": "dist/index.js"
|
|
39
|
+
},
|
|
40
|
+
"exports": {
|
|
41
|
+
".": {
|
|
42
|
+
"import": "./dist/sdk.js"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"dist",
|
|
47
|
+
"skills",
|
|
48
|
+
"scripts"
|
|
49
|
+
],
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=22"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsup && mkdir -p dist/storage && cp src/storage/schema.sql dist/storage/schema.sql",
|
|
55
|
+
"dev": "tsup --watch",
|
|
56
|
+
"test": "vitest run",
|
|
57
|
+
"test:watch": "vitest",
|
|
58
|
+
"lint": "biome check src",
|
|
59
|
+
"format": "biome format --write src",
|
|
60
|
+
"start": "node dist/index.js",
|
|
61
|
+
"postinstall": "node scripts/postinstall.js",
|
|
62
|
+
"prepublishOnly": "npm run build"
|
|
63
|
+
},
|
|
64
|
+
"dependencies": {
|
|
65
|
+
"@huggingface/transformers": "^4.2.0",
|
|
66
|
+
"@kreuzberg/tree-sitter-language-pack": "^1.10.9",
|
|
67
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
68
|
+
"better-sqlite3": "^13.0.3",
|
|
69
|
+
"gpt-tokenizer": "^3.4.0",
|
|
70
|
+
"sqlite-vec": "^0.1.9",
|
|
71
|
+
"tree-sitter": "^0.25.1",
|
|
72
|
+
"ulid": "^3.0.2"
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@biomejs/biome": "^2.5.7",
|
|
76
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
77
|
+
"@types/node": "^22.0.0",
|
|
78
|
+
"tsup": "^8.5.1",
|
|
79
|
+
"typescript": "^5.5.0",
|
|
80
|
+
"vitest": "^4.1.10"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# bench-all.sh — Run AMB L1-L3 + LoCoMo, output scores in parseable format.
|
|
3
|
+
# Usage: ./scripts/bench-all.sh [--quick]
|
|
4
|
+
# --quick: skip LoCoMo (AMB only, ~2 min)
|
|
5
|
+
#
|
|
6
|
+
# Output format (last line, parseable):
|
|
7
|
+
# BENCH_RESULT L1=<n> L2=<n> L3=<n> LOCOMO=<n>
|
|
8
|
+
#
|
|
9
|
+
# Exit 0 if all targets met, exit 1 if any below target.
|
|
10
|
+
|
|
11
|
+
set -uo pipefail
|
|
12
|
+
|
|
13
|
+
# ─── Targets ───────────────────────────────────────────────────
|
|
14
|
+
TARGET_L1="${TARGET_L1:-100}"
|
|
15
|
+
TARGET_L2="${TARGET_L2:-100}"
|
|
16
|
+
TARGET_L3="${TARGET_L3:-100}"
|
|
17
|
+
TARGET_LOCOMO="${TARGET_LOCOMO:-76}"
|
|
18
|
+
TARGET_PERSONAMEM="${TARGET_PERSONAMEM:-76}"
|
|
19
|
+
|
|
20
|
+
# ─── Paths ─────────────────────────────────────────────────────
|
|
21
|
+
PROJECT_ROOT="/data/projects/tdai-memory-mcp"
|
|
22
|
+
AMB_REPO="/tmp/amb-repo"
|
|
23
|
+
LOCOMO_BENCH="/tmp/locomo-bench"
|
|
24
|
+
LOCOMO_DATA="/tmp/locomo/data/locomo10.json"
|
|
25
|
+
AMB_RESULTS="/tmp/amb-results"
|
|
26
|
+
LOCOMO_RESULTS="$LOCOMO_BENCH/results.json"
|
|
27
|
+
PERSONAMEM_BENCH="/tmp/personamem"
|
|
28
|
+
PERSONAMEM_RESULTS="$PERSONAMEM_BENCH/results.json"
|
|
29
|
+
|
|
30
|
+
# ─── Helpers ───────────────────────────────────────────────────
|
|
31
|
+
log() { echo "[bench] $*" >&2; }
|
|
32
|
+
|
|
33
|
+
# ─── Build tdai-memory-mcp ─────────────────────────────────────
|
|
34
|
+
log "Building tdai-memory-mcp..."
|
|
35
|
+
cd "$PROJECT_ROOT"
|
|
36
|
+
npm run build 2>&1 | tail -1
|
|
37
|
+
log "Build OK"
|
|
38
|
+
|
|
39
|
+
# ─── AMB Layer 1 ───────────────────────────────────────────────
|
|
40
|
+
log "Running AMB Layer 1..."
|
|
41
|
+
cd "$AMB_REPO"
|
|
42
|
+
L1_OUTPUT=$(npx tsx src/cli.ts --provider tdai-memory --layer 1 --no-delay --verbose --output "$AMB_RESULTS" 2>&1)
|
|
43
|
+
L1=$(echo "$L1_OUTPUT" | grep '^🏆 Layer 1 Score:' | grep -oP 'Score: \K[0-9]+' || echo "0")
|
|
44
|
+
log "L1=$L1"
|
|
45
|
+
|
|
46
|
+
# ─── AMB Layer 2 ───────────────────────────────────────────────
|
|
47
|
+
log "Running AMB Layer 2..."
|
|
48
|
+
L2_OUTPUT=$(npx tsx src/cli.ts --provider tdai-memory --layer 2 --no-delay --verbose --output "$AMB_RESULTS" 2>&1)
|
|
49
|
+
L2=$(echo "$L2_OUTPUT" | grep '^🏆 Layer 2 Score:' | grep -oP 'Score: \K[0-9]+' || echo "0")
|
|
50
|
+
log "L2=$L2"
|
|
51
|
+
|
|
52
|
+
# ─── AMB Layer 3 ───────────────────────────────────────────────
|
|
53
|
+
log "Running AMB Layer 3 (1K memories)..."
|
|
54
|
+
L3_OUTPUT=$(npx tsx src/cli.ts --provider tdai-memory --layer 3 --no-delay --verbose --output "$AMB_RESULTS" 2>&1)
|
|
55
|
+
L3=$(echo "$L3_OUTPUT" | grep '^🏆 Layer 3 Score' | grep -oP 'Score.*?: \K[0-9]+' | head -1 || echo "0")
|
|
56
|
+
log "L3=$L3"
|
|
57
|
+
|
|
58
|
+
# ─── LoCoMo ────────────────────────────────────────────────────
|
|
59
|
+
LOCOMO="N/A"
|
|
60
|
+
if [ "${1:-}" != "--quick" ] && [ -f "$LOCOMO_DATA" ]; then
|
|
61
|
+
log "Running LoCoMo benchmark..."
|
|
62
|
+
cd "$LOCOMO_BENCH"
|
|
63
|
+
|
|
64
|
+
# Clean previous data to avoid stale memories
|
|
65
|
+
rm -rf "$LOCOMO_BENCH/tdai-data"
|
|
66
|
+
mkdir -p "$LOCOMO_BENCH/tdai-data"
|
|
67
|
+
|
|
68
|
+
# Run LoCoMo ingest + search
|
|
69
|
+
npx tsx run.ts 2>&1 | tail -5
|
|
70
|
+
|
|
71
|
+
# Judge results using simple keyword matching (fallback if no LLM judge)
|
|
72
|
+
if [ -f "$LOCOMO_RESULTS" ]; then
|
|
73
|
+
LOCOMO=$(python3 -c "
|
|
74
|
+
import json, sys
|
|
75
|
+
results = json.load(open('$LOCOMO_RESULTS'))
|
|
76
|
+
if not results:
|
|
77
|
+
print(0)
|
|
78
|
+
sys.exit()
|
|
79
|
+
correct = 0
|
|
80
|
+
for r in results:
|
|
81
|
+
gt = str(r.get('groundTruth', '')).lower()
|
|
82
|
+
hits = r.get('searchResults', [])
|
|
83
|
+
# Simple heuristic: if any search result contains a keyword from ground truth
|
|
84
|
+
gt_words = [w for w in gt.split() if len(w) > 3 and w not in ('what', 'when', 'where', 'which', 'about', 'because', 'would', 'could', 'should', 'their', 'there', 'these', 'those', 'after', 'before')]
|
|
85
|
+
found = False
|
|
86
|
+
for h in hits:
|
|
87
|
+
content = h.get('content', '').lower()
|
|
88
|
+
if any(w in content for w in gt_words[:3]):
|
|
89
|
+
found = True
|
|
90
|
+
break
|
|
91
|
+
if found:
|
|
92
|
+
correct += 1
|
|
93
|
+
score = round(correct / len(results) * 100)
|
|
94
|
+
print(score)
|
|
95
|
+
" 2>/dev/null || echo "0")
|
|
96
|
+
log "LOCOMO=$LOCOMO (keyword heuristic — for LLM judge, set BENCH_LLM_JUDGE=1)"
|
|
97
|
+
fi
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# ─── PersonaMem ────────────────────────────────────────────────
|
|
101
|
+
PERSONAMEM="N/A"
|
|
102
|
+
if [ "${1:-}" != "--quick" ] && [ -f "$PERSONAMEM_BENCH/personamem-bench.ts" ]; then
|
|
103
|
+
log "Running PersonaMem benchmark..."
|
|
104
|
+
cd "$PERSONAMEM_BENCH"
|
|
105
|
+
PERSONAMEM_SAMPLE="${PERSONAMEM_SAMPLE:-50}"
|
|
106
|
+
npx tsx personamem-bench.ts --sample=$PERSONAMEM_SAMPLE 2>&1 | tail -20
|
|
107
|
+
PERSONAMEM=$(grep "PERSONAMEM_SCORE" /tmp/personamem-bench-output.log 2>/dev/null | grep -oP '\d+' || echo "0")
|
|
108
|
+
# Parse from results.json if score line not captured
|
|
109
|
+
if [ "$PERSONAMEM" = "0" ] && [ -f "$PERSONAMEM_RESULTS" ]; then
|
|
110
|
+
PERSONAMEM=$(python3 -c "import json; print(json.load(open('$PERSONAMEM_RESULTS'))['score'])" 2>/dev/null || echo "0")
|
|
111
|
+
fi
|
|
112
|
+
log "PERSONAMEM=$PERSONAMEM (sample=$PERSONAMEM_SAMPLE, TencentDB=76)"
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# ─── Output ────────────────────────────────────────────────────
|
|
116
|
+
echo ""
|
|
117
|
+
echo "═══════════════════════════════════════════════════════════"
|
|
118
|
+
echo " BENCHMARK RESULTS — tdai-memory-mcp"
|
|
119
|
+
echo "═══════════════════════════════════════════════════════════"
|
|
120
|
+
echo " AMB Layer 1: $L1 / 100 (target: $TARGET_L1)"
|
|
121
|
+
echo " AMB Layer 2: $L2 / 100 (target: $TARGET_L2)"
|
|
122
|
+
echo " AMB Layer 3: $L3 / 100 (target: $TARGET_L3)"
|
|
123
|
+
echo " LoCoMo: $LOCOMO / 100 (target: $TARGET_LOCOMO)"
|
|
124
|
+
echo " PersonaMem: $PERSONAMEM / 100 (target: $TARGET_PERSONAMEM, TencentDB=76)"
|
|
125
|
+
echo "═══════════════════════════════════════════════════════════"
|
|
126
|
+
echo ""
|
|
127
|
+
echo "BENCH_RESULT L1=$L1 L2=$L2 L3=$L3 LOCOMO=$LOCOMO PERSONAMEM=$PERSONAMEM"
|
|
128
|
+
|
|
129
|
+
# ─── Check targets ─────────────────────────────────────────────
|
|
130
|
+
PASS=true
|
|
131
|
+
[ "${L1:-0}" -lt "$TARGET_L1" ] && PASS=false && echo "FAIL: L1=$L1 < target=$TARGET_L1"
|
|
132
|
+
[ "${L2:-0}" -lt "$TARGET_L2" ] && PASS=false && echo "FAIL: L2=$L2 < target=$TARGET_L2"
|
|
133
|
+
[ "${L3:-0}" -lt "$TARGET_L3" ] && PASS=false && echo "FAIL: L3=$L3 < target=$TARGET_L3"
|
|
134
|
+
if [ "$LOCOMO" != "N/A" ]; then
|
|
135
|
+
[ "${LOCOMO:-0}" -lt "$TARGET_LOCOMO" ] && PASS=false && echo "FAIL: LOCOMO=$LOCOMO < target=$TARGET_LOCOMO"
|
|
136
|
+
fi
|
|
137
|
+
if [ "$PERSONAMEM" != "N/A" ]; then
|
|
138
|
+
[ "${PERSONAMEM:-0}" -lt "$TARGET_PERSONAMEM" ] && PASS=false && echo "FAIL: PERSONAMEM=$PERSONAMEM < target=$TARGET_PERSONAMEM"
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
if [ "$PASS" = true ]; then
|
|
142
|
+
echo "ALL PASS ✓"
|
|
143
|
+
exit 0
|
|
144
|
+
else
|
|
145
|
+
echo "SOME FAIL ✗"
|
|
146
|
+
exit 1
|
|
147
|
+
fi
|