@hasna/mementos 0.4.16 → 0.4.19

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 CHANGED
@@ -1,10 +1,10 @@
1
1
  # @hasna/mementos
2
2
 
3
- Universal memory system for AI agents. SQLite-backed with CLI, MCP server, and library API.
3
+ Universal memory system for AI agents. SQLite-backed with CLI, MCP server, REST API, and TypeScript library.
4
4
 
5
- Agents can save, recall, search, and share memories across sessions. Memories are scoped (global, shared, private), categorized, importance-ranked, and automatically injected into agent context.
5
+ Agents save, recall, search, and share memories across sessions. Memories are scoped (global/shared/private), categorized, importance-ranked, and injected into agent context on demand.
6
6
 
7
- ## Installation
7
+ ## Install
8
8
 
9
9
  ```bash
10
10
  bun add -g @hasna/mementos
@@ -14,261 +14,222 @@ bun add -g @hasna/mementos
14
14
 
15
15
  ```bash
16
16
  # Save a memory
17
- mementos save "preferred-language" "TypeScript" --scope global --importance 8
17
+ mementos save "project-stack" "Bun + TypeScript + SQLite" --scope shared --importance 8
18
18
 
19
19
  # Recall it
20
- mementos recall "preferred-language"
20
+ mementos recall "project-stack"
21
21
 
22
- # Search across all memories
23
- mementos search "typescript"
22
+ # Search
23
+ mementos search "typescript stack"
24
24
 
25
- # List memories with filters
26
- mementos list --scope global --importance-min 5
25
+ # Inject into agent context (compact = ~60% smaller)
26
+ mementos inject --format compact --project-id <id>
27
27
 
28
28
  # Get stats
29
29
  mementos stats
30
30
  ```
31
31
 
32
- ## Memory Scopes
33
-
34
- | Scope | Visibility | Use Case |
35
- |-------|-----------|----------|
36
- | `global` | All agents, all projects | Org-wide preferences, facts |
37
- | `shared` | All agents in a project | Project conventions, decisions |
38
- | `private` | Single agent only | Agent-specific context, history |
39
-
40
- ## Memory Categories
41
-
42
- | Category | Description |
43
- |----------|------------|
44
- | `preference` | Settings, choices, style preferences |
45
- | `fact` | Verified truths, known information |
46
- | `knowledge` | Learned patterns, insights, techniques |
47
- | `history` | Session context, conversation summaries |
48
-
49
- ## CLI Reference
32
+ ## MCP Server
50
33
 
51
- ### Global Options
34
+ ### Install into Claude Code (recommended)
52
35
 
53
- ```
54
- --project <path> Project context
55
- --json Output as JSON
56
- --agent <name> Agent identifier
57
- --session <id> Session context
36
+ ```bash
37
+ mementos mcp --claude
38
+ # Or manually:
39
+ claude mcp add --transport stdio --scope user mementos -- mementos-mcp
58
40
  ```
59
41
 
60
- ### Commands
42
+ ### Install into Codex / Gemini
61
43
 
62
44
  ```bash
63
- mementos save <key> <value> # Save a memory
64
- -s, --scope <scope> # global|shared|private (default: private)
65
- -c, --category <cat> # preference|fact|knowledge|history
66
- --importance <1-10> # Importance score (default: 5)
67
- --tags <t1,t2> # Comma-separated tags
68
- --summary <text> # Brief summary
69
- --ttl <ms> # Time-to-live in milliseconds
70
- --source <src> # user|agent|system|auto|imported
71
-
72
- mementos recall <key> # Get memory by key
73
- mementos list # List memories (with filters)
74
- mementos update <id> # Update memory fields
75
- mementos forget <key|id> # Delete a memory
76
- mementos search <query> # Full-text search
77
- mementos stats # Memory statistics
78
- mementos export # Export as JSON
79
- mementos import <file> # Import from JSON
80
- mementos clean # Remove expired + enforce quotas
81
- mementos inject # Output injection context
82
- mementos init <name> # Register agent
83
- mementos agents # List agents
84
- mementos projects # Manage projects
85
- mementos bulk <action> <ids> # Batch operations
45
+ mementos mcp --codex
46
+ mementos mcp --gemini
47
+ mementos mcp --all # all agents at once
86
48
  ```
87
49
 
88
- ## MCP Server
50
+ ### Available Tools (40+)
89
51
 
90
- ### Setup for Claude Code
52
+ **Memory:** `memory_save`, `memory_recall`, `memory_get`, `memory_list`, `memory_update`, `memory_pin`, `memory_archive`, `memory_forget`, `memory_search`, `memory_stats`, `memory_export`, `memory_import`, `memory_inject`, `memory_context`, `session_extract`
91
53
 
92
- Add to `~/.claude/.mcp.json`:
54
+ **Bulk:** `bulk_forget`, `bulk_update`
93
55
 
94
- ```json
95
- {
96
- "mcpServers": {
97
- "mementos": {
98
- "command": "mementos-mcp",
99
- "args": []
100
- }
101
- }
102
- }
103
- ```
56
+ **Agents:** `register_agent`, `list_agents`, `list_agents_by_project`, `get_agent`, `update_agent`
104
57
 
105
- ### Setup for Codex
58
+ **Projects:** `register_project`, `list_projects`, `get_project`
106
59
 
107
- Add to `.codex/mcp.json`:
60
+ **Knowledge Graph:** `entity_create`, `entity_get`, `entity_list`, `entity_delete`, `entity_merge`, `entity_link`, `relation_create`, `relation_delete`, `relation_list`, `graph_query`, `graph_path`, `graph_stats`
108
61
 
109
- ```json
110
- {
111
- "mcpServers": {
112
- "mementos": {
113
- "command": "mementos-mcp"
114
- }
115
- }
116
- }
62
+ **Meta:** `search_tools`, `describe_tools` (lean stubs — full docs on demand)
63
+
64
+ **Utility:** `clean_expired`
65
+
66
+ ## CLI Reference
67
+
68
+ ```bash
69
+ mementos save <key> <value> # Save/upsert a memory
70
+ mementos recall <key> # Get memory by key
71
+ mementos list # List memories (with filters)
72
+ mementos update <id> # Update memory fields
73
+ mementos pin <key|id> # Pin a memory
74
+ mementos forget <key|id> # Delete a memory
75
+ mementos search <query> # Full-text + fuzzy search
76
+ mementos stats # Memory statistics
77
+ mementos export # Export as JSON
78
+ mementos import <file> # Import from JSON
79
+ mementos clean # Remove expired + enforce quotas
80
+ mementos inject # Output injection context
81
+ mementos init <name> # Register agent
82
+ mementos agents # List agents
83
+ mementos projects # Manage projects
84
+ mementos bulk forget <ids> # Batch delete
85
+ mementos bulk update <ids> # Batch update
86
+ mementos diff <id> # Show memory version history
87
+ mementos doctor # Diagnose DB health
88
+
89
+ # Profiles — isolated DBs per context
90
+ mementos profile set work # Switch to work profile
91
+ mementos profile list # List all profiles
92
+ mementos profile get # Show active profile
93
+ mementos profile unset # Back to default
117
94
  ```
118
95
 
119
- ### Available Tools (19)
96
+ ## Profiles
120
97
 
121
- **Memory:** `memory_save`, `memory_recall`, `memory_list`, `memory_update`, `memory_forget`, `memory_search`, `memory_stats`, `memory_export`, `memory_import`, `memory_inject`
98
+ ```bash
99
+ # Each profile is an isolated DB: ~/.mementos/profiles/<name>.db
100
+ mementos profile set work
101
+ MEMENTOS_PROFILE=work mementos list # per-command
102
+ ```
122
103
 
123
- **Agents:** `register_agent`, `list_agents`, `get_agent`
104
+ ## REST API
124
105
 
125
- **Projects:** `register_project`, `list_projects`
106
+ ```bash
107
+ mementos-serve --port 19428
108
+ ```
126
109
 
127
- **Bulk:** `bulk_forget`, `bulk_update`
110
+ Default port: **19428**. Binds to `127.0.0.1` (localhost only). Override with `MEMENTOS_HOST=0.0.0.0`.
128
111
 
129
- **Utility:** `clean_expired`, `memory_context`
112
+ ### Key Endpoints
130
113
 
131
- ### Resources
114
+ | Method | Path | Description |
115
+ |--------|------|-------------|
116
+ | GET | `/api/memories?fields=key,value` | List memories (?fields, ?scope, ?session_id, ?status) |
117
+ | POST | `/api/memories` | Create/upsert memory |
118
+ | PATCH | `/api/memories/:id` | Update (version optional — auto-fetched) |
119
+ | DELETE | `/api/memories/:id` | Delete |
120
+ | POST | `/api/memories/search` | Full-text search |
121
+ | POST | `/api/memories/extract` | Auto-extract memories from session summary |
122
+ | POST | `/api/memories/bulk-forget` | Delete multiple |
123
+ | POST | `/api/memories/bulk-update` | Update multiple |
124
+ | GET | `/api/memories/stats` | Statistics |
125
+ | POST | `/api/memories/export` | Export with filters |
126
+ | GET | `/api/inject?format=compact` | Context injection (compact/markdown/json/xml) |
127
+ | GET/POST | `/api/agents` | Agent registry |
128
+ | PATCH | `/api/agents/:id` | Update agent (including active_project_id) |
129
+ | GET/POST | `/api/projects` | Project registry |
130
+ | GET | `/api/projects/:id/agents` | Agents active on a project |
131
+ | GET | `/api/profile` | Active profile info |
132
+ | GET | `/api/health` | Health check (includes profile, hostname) |
132
133
 
133
- - `mementos://memories` — All active memories
134
- - `mementos://agents` — Registered agents
135
- - `mementos://projects` — Registered projects
134
+ ## SDK
136
135
 
137
- ## Library API
136
+ ```bash
137
+ bun add @hasna/mementos-sdk
138
+ ```
138
139
 
139
140
  ```typescript
140
- import {
141
- createMemory,
142
- getMemoryByKey,
143
- listMemories,
144
- searchMemories,
145
- MemoryInjector,
146
- } from "@hasna/mementos";
141
+ import { MementosClient } from "@hasna/mementos-sdk";
147
142
 
148
- // Save a memory
149
- const memory = createMemory({
150
- key: "db-convention",
151
- value: "Always use snake_case for column names",
152
- scope: "shared",
153
- category: "preference",
154
- importance: 8,
155
- tags: ["database", "conventions"],
156
- });
143
+ const client = new MementosClient({ baseUrl: "http://localhost:19428" });
157
144
 
158
- // Recall
159
- const recalled = getMemoryByKey("db-convention", "shared");
145
+ // Save memory
146
+ await client.saveMemory({ key: "db-convention", value: "snake_case", scope: "shared" });
160
147
 
161
148
  // Search
162
- const results = searchMemories("database");
163
-
164
- // List with filters
165
- const memories = listMemories({
166
- scope: "global",
167
- category: "fact",
168
- min_importance: 5,
169
- limit: 20,
170
- });
149
+ const { results } = await client.searchMemories("database conventions");
150
+
151
+ // Context injection (compact format — 60% smaller)
152
+ const { context } = await client.getContext({ project_id: "...", format: "compact" });
171
153
 
172
- // Inject into agent context
173
- const injector = new MemoryInjector();
174
- const context = injector.getInjectionContext({
175
- agent_id: "my-agent",
176
- project_id: "my-project",
177
- max_tokens: 500,
154
+ // Sessions mementos integration
155
+ await client.extractFromSession({
156
+ session_id: "abc123",
157
+ title: "Fix auth middleware",
158
+ key_topics: ["jwt", "compliance"],
159
+ project_id: "...",
178
160
  });
179
161
  ```
180
162
 
181
- ## REST API
163
+ ## Agent-Project Binding
164
+
165
+ Track which agent is working on which project:
182
166
 
183
- Start the server:
167
+ ```typescript
168
+ // On session start
169
+ await client.updateAgent("my-agent", { active_project_id: "project-uuid" });
170
+
171
+ // Query: who's on this project?
172
+ const { agents } = await client.getProjectAgents("open-mementos");
173
+ ```
174
+
175
+ ## Context Injection
184
176
 
185
177
  ```bash
186
- mementos-serve --port 19428
178
+ # 60% smaller with compact format
179
+ mementos inject --format compact --project-id <id> --max-tokens 400
187
180
  ```
188
181
 
189
- ### Endpoints
182
+ MCP: `memory_inject(project_id="...", format="compact", max_tokens=400)`
190
183
 
191
- | Method | Path | Description |
192
- |--------|------|-------------|
193
- | GET | `/api/memories` | List memories |
194
- | POST | `/api/memories` | Create memory |
195
- | GET | `/api/memories/:id` | Get memory |
196
- | PATCH | `/api/memories/:id` | Update memory |
197
- | DELETE | `/api/memories/:id` | Delete memory |
198
- | POST | `/api/memories/search` | Search |
199
- | GET | `/api/memories/stats` | Statistics |
200
- | POST | `/api/memories/export` | Export |
201
- | POST | `/api/memories/import` | Import |
202
- | POST | `/api/memories/clean` | Cleanup |
203
- | GET/POST | `/api/agents` | Agents |
204
- | GET/POST | `/api/projects` | Projects |
205
- | GET | `/api/inject` | Injection context |
184
+ ## Sessions Integration
206
185
 
207
- ## Configuration
186
+ After ingesting a session (open-sessions):
208
187
 
209
- Config file: `~/.mementos/config.json`
188
+ ```bash
189
+ sessions remember <session-id> --mementos-url http://localhost:19428
190
+ # Creates: session-summary (history), session-topics (knowledge), session-notes (knowledge)
191
+ ```
210
192
 
193
+ REST:
211
194
  ```json
212
- {
213
- "default_scope": "private",
214
- "default_category": "knowledge",
215
- "default_importance": 5,
216
- "max_entries": 1000,
217
- "max_entries_per_scope": {
218
- "global": 500,
219
- "shared": 300,
220
- "private": 200
221
- },
222
- "injection": {
223
- "max_tokens": 500,
224
- "min_importance": 5,
225
- "categories": ["preference", "fact"],
226
- "refresh_interval": 5
227
- },
228
- "sync_agents": ["claude", "codex", "gemini"],
229
- "auto_cleanup": {
230
- "enabled": true,
231
- "expired_check_interval": 3600
232
- }
233
- }
195
+ POST /api/memories/extract
196
+ { "session_id": "abc", "title": "Fix auth", "key_topics": ["jwt"] }
234
197
  ```
235
198
 
236
- ### Environment Variables
199
+ ## Environment Variables
237
200
 
238
- | Variable | Description |
239
- |----------|------------|
240
- | `MEMENTOS_DB_PATH` | Override database path |
241
- | `MEMENTOS_DB_SCOPE` | Set to `project` for project-level DB |
242
- | `MEMENTOS_DEFAULT_SCOPE` | Default memory scope |
201
+ | Variable | Purpose | Default |
202
+ |----------|---------|---------|
203
+ | `MEMENTOS_DB_PATH` | Override DB path (bypasses profiles) | `~/.mementos/mementos.db` |
204
+ | `MEMENTOS_PROFILE` | Named profile → `~/.mementos/profiles/<name>.db` | none |
205
+ | `MEMENTOS_DB_SCOPE` | `project` = git root `.mementos/mementos.db` | global |
206
+ | `MEMENTOS_HOST` | Server bind address | `127.0.0.1` |
207
+ | `PORT` | Server port | `19428` |
243
208
 
244
- ## Database
209
+ ## Library
245
210
 
246
- SQLite with WAL mode. Path resolution:
247
-
248
- 1. `MEMENTOS_DB_PATH` environment variable
249
- 2. Nearest `.mementos/mementos.db` (walking up from cwd)
250
- 3. `~/.mementos/mementos.db` (global fallback)
211
+ ```typescript
212
+ import {
213
+ createMemory, getMemoryByKey, listMemories, searchMemories,
214
+ registerAgent, updateAgent, listAgentsByProject,
215
+ registerProject, getProject,
216
+ getActiveProfile, setActiveProfile,
217
+ MemoryInjector,
218
+ } from "@hasna/mementos";
219
+ ```
251
220
 
252
221
  ## Architecture
253
222
 
254
223
  ```
255
224
  src/
256
- ├── types/index.ts # Type definitions, enums, errors
257
- ├── db/
258
- │ ├── database.ts # SQLite setup, migrations, utilities
259
- │ ├── memories.ts # Memory CRUD with optimistic locking
260
- │ ├── agents.ts # Agent registration (8-char UUIDs)
261
- │ └── projects.ts # Project registry
262
- ├── lib/
263
- │ ├── config.ts # Configuration loading
264
- │ ├── search.ts # Full-text search engine
265
- │ ├── injector.ts # Context injection system
266
- │ ├── retention.ts # Auto-cleanup & quota enforcement
267
- │ └── sync.ts # Multi-agent memory sync
268
- ├── cli/index.tsx # CLI (Commander.js + chalk)
269
- ├── mcp/index.ts # MCP server (19 tools, 3 resources)
270
- ├── server/index.ts # REST API server
271
- └── index.ts # Library exports
225
+ cli/ Commander.js + Ink TUI — 20+ commands
226
+ mcp/ MCP server — 40+ tools (lean stubs)
227
+ server/ REST API 37+ endpoints (Bun.serve)
228
+ db/ SQLite (bun:sqlite) — memories, agents, projects, entities, relations
229
+ lib/ FTS5 search, injection, extraction, retention, config, profiles
230
+ types/ TypeScript interfaces and errors
231
+ sdk/ @hasna/mementos-sdk — zero-dep fetch client
232
+ dashboard/ React+Vite web UI
272
233
  ```
273
234
 
274
235
  ## License
package/dist/mcp/index.js CHANGED
@@ -6357,6 +6357,49 @@ server.tool("memory_stats", "Get aggregate statistics about stored memories", {}
6357
6357
  return { content: [{ type: "text", text: formatError(e) }], isError: true };
6358
6358
  }
6359
6359
  });
6360
+ server.tool("memory_activity", "Get daily memory creation activity over N days.", {
6361
+ days: exports_external.coerce.number().optional(),
6362
+ scope: exports_external.enum(["global", "shared", "private"]).optional(),
6363
+ agent_id: exports_external.string().optional(),
6364
+ project_id: exports_external.string().optional()
6365
+ }, async (args) => {
6366
+ try {
6367
+ const days = Math.min(args.days || 30, 365);
6368
+ const db = getDatabase();
6369
+ const conditions = ["status = 'active'"];
6370
+ const params = [];
6371
+ if (args.scope) {
6372
+ conditions.push("scope = ?");
6373
+ params.push(args.scope);
6374
+ }
6375
+ if (args.agent_id) {
6376
+ conditions.push("agent_id = ?");
6377
+ params.push(args.agent_id);
6378
+ }
6379
+ if (args.project_id) {
6380
+ conditions.push("project_id = ?");
6381
+ params.push(args.project_id);
6382
+ }
6383
+ const where = conditions.slice(1).map((c) => `AND ${c}`).join(" ");
6384
+ const rows = db.query(`
6385
+ SELECT date(created_at) AS date, COUNT(*) AS memories_created
6386
+ FROM memories
6387
+ WHERE status = 'active' AND date(created_at) >= date('now', '-${days} days') ${where}
6388
+ GROUP BY date(created_at)
6389
+ ORDER BY date ASC
6390
+ `).all(...params);
6391
+ if (rows.length === 0) {
6392
+ return { content: [{ type: "text", text: `No memory activity in last ${days} days.` }] };
6393
+ }
6394
+ const total = rows.reduce((s, r) => s + r.memories_created, 0);
6395
+ const lines = rows.map((r) => `${r.date}: ${r.memories_created} memor${r.memories_created === 1 ? "y" : "ies"}`);
6396
+ return { content: [{ type: "text", text: `Memory activity (last ${days} days \u2014 ${total} total):
6397
+ ${lines.join(`
6398
+ `)}` }] };
6399
+ } catch (e) {
6400
+ return { content: [{ type: "text", text: formatError(e) }], isError: true };
6401
+ }
6402
+ });
6360
6403
  server.tool("memory_export", "Export memories as JSON", {
6361
6404
  scope: exports_external.enum(["global", "shared", "private"]).optional(),
6362
6405
  category: exports_external.enum(["preference", "fact", "knowledge", "history"]).optional(),
@@ -7146,6 +7189,17 @@ var FULL_SCHEMAS = {
7146
7189
  },
7147
7190
  example: '{"query":"typescript","scope":"global","limit":10}'
7148
7191
  },
7192
+ memory_activity: {
7193
+ description: "Get daily memory creation counts over N days (max 365). Like 'git log --stat' for memories.",
7194
+ category: "memory",
7195
+ params: {
7196
+ days: { type: "number", description: "Number of days to look back (default 30)" },
7197
+ scope: { type: "string", description: "Filter by scope", enum: ["global", "shared", "private"] },
7198
+ agent_id: { type: "string", description: "Filter by agent" },
7199
+ project_id: { type: "string", description: "Filter by project" }
7200
+ },
7201
+ example: '{"days":14,"project_id":"proj-uuid"}'
7202
+ },
7149
7203
  memory_stats: {
7150
7204
  description: "Aggregate statistics: total, by scope, by category, pinned, expired counts.",
7151
7205
  category: "memory",
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAulCH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkH9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAynCH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAkH9C"}
@@ -2217,6 +2217,43 @@ addRoute("GET", "/api/memories/stats", (_req) => {
2217
2217
  stats.by_agent[row.agent_id] = row.c;
2218
2218
  return json(stats);
2219
2219
  });
2220
+ addRoute("GET", "/api/activity", (_req, url) => {
2221
+ const q = getSearchParams(url);
2222
+ const days = Math.min(parseInt(q["days"] || "30", 10), 365);
2223
+ const scope = q["scope"];
2224
+ const agentId = q["agent_id"];
2225
+ const projectId = q["project_id"];
2226
+ const db = getDatabase();
2227
+ const conditions = ["status = 'active'"];
2228
+ const params = [];
2229
+ if (scope) {
2230
+ conditions.push("scope = ?");
2231
+ params.push(scope);
2232
+ }
2233
+ if (agentId) {
2234
+ conditions.push("agent_id = ?");
2235
+ params.push(agentId);
2236
+ }
2237
+ if (projectId) {
2238
+ conditions.push("project_id = ?");
2239
+ params.push(projectId);
2240
+ }
2241
+ const where = conditions.map((c) => `AND ${c}`).join(" ");
2242
+ const rows = db.query(`
2243
+ SELECT
2244
+ date(created_at) AS date,
2245
+ COUNT(*) AS memories_created,
2246
+ SUM(CASE WHEN scope = 'global' THEN 1 ELSE 0 END) AS global_count,
2247
+ SUM(CASE WHEN scope = 'shared' THEN 1 ELSE 0 END) AS shared_count,
2248
+ SUM(CASE WHEN scope = 'private' THEN 1 ELSE 0 END) AS private_count,
2249
+ AVG(importance) AS avg_importance
2250
+ FROM memories
2251
+ WHERE date(created_at) >= date('now', '-${days} days') ${where}
2252
+ GROUP BY date(created_at)
2253
+ ORDER BY date ASC
2254
+ `).all(...params);
2255
+ return json({ activity: rows, days, total: rows.reduce((s, r) => s + r.memories_created, 0) });
2256
+ });
2220
2257
  addRoute("POST", "/api/memories/search", async (req) => {
2221
2258
  const body = await readJson(req);
2222
2259
  if (!body || typeof body["query"] !== "string") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/mementos",
3
- "version": "0.4.16",
3
+ "version": "0.4.19",
4
4
  "description": "Universal memory system for AI agents - CLI + MCP server + library API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",